diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..5496de7f45 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +# Ignore 3rd party js code +spec/3rd-party/ +spec/helpers/jasmine-jsreporter.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000..3254f2cddd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,71 @@ +{ + "env": { + "browser": true, + "es6": true, + "node": true + }, + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "extends": "eslint:recommended", + "rules": { + "no-useless-escape": "off", + "no-console": "off", + "camelcase": "error", + "curly": "error", + "eqeqeq": "error", + "no-extend-native": "error", + "wrap-iife": ["error", "any"], + "indent": ["error", 4, { + "SwitchCase": 1, + "MemberExpression": "off", + "CallExpression": {"arguments": "first"}, + "ArrayExpression": "first", + "flatTernaryExpressions": true + } + ], + "no-caller": "error", + "no-new": "error", + "no-unused-vars": ["error", {"args": "none"}], + "max-params": ["error", 5], + "max-depth": ["error", 4], + "complexity": ["error", 10], + "max-len": ["error", 140], + "quotes": ["error", "single"], + "no-var": "error", + "prefer-const": "error", + "no-shadow": "error", + "prefer-arrow-callback": "error", + "arrow-body-style": "error", + "implicit-arrow-linebreak": "error", + "arrow-parens": ["error", "as-needed"], + "space-before-function-paren": ["error", "always"], + "no-useless-concat": "error", + "prefer-template": "error", + "template-curly-spacing": "error", + "valid-jsdoc": ["error", {"requireParamDescription": false, "requireReturnDescription": false}] + }, + "overrides": [ + { + "files": ["spec/**/*.js", "web-src/**/*.js"], + "globals": { + "crossfilter": false, + "d3": false, + "dc": false + } + }, + { + "files": ["spec/**/*.js"], + "globals": { + "jasmine": false, + "expect": false, + "describe": false, + "it": false, + "beforeEach": false, + "afterEach": false, + "spyOn": false + } + } + ] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..176a458f94 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000000..450b6dad0b --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,17 @@ +name: MacOS Test + +on: [push, pull_request] + +jobs: + build: + + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - run: npm ci + - run: npx grunt ci-macos diff --git a/.github/workflows/ubuntu-d3-v5.yml b/.github/workflows/ubuntu-d3-v5.yml new file mode 100644 index 0000000000..179782a5da --- /dev/null +++ b/.github/workflows/ubuntu-d3-v5.yml @@ -0,0 +1,18 @@ +name: Ubuntu d3@5 + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - run: npm ci + - run: npm i d3@5 + - run: npx grunt ci-pull diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml new file mode 100644 index 0000000000..c2db1883de --- /dev/null +++ b/.github/workflows/ubuntu.yml @@ -0,0 +1,17 @@ +name: Ubuntu Test + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - run: npm ci + - run: npx grunt ci-pull diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000000..e1f9631aac --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,17 @@ +name: Windows Test + +on: [push, pull_request] + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '12.x' + - run: npm ci + - run: npx grunt ci-windows diff --git a/.gitignore b/.gitignore index d21edced7f..af0526579c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ *.log *~ +# distribution files no longer checked in as of version 4 +dist + # local files node_modules bower_components @@ -39,3 +42,8 @@ web/docs/public # html docs are only checked into gh-pages branch web/docs/html +# Ignore, needed only for Github pages +web/ + +# Igonore, copied from npm modules +spec/3rd-party/ diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index f114fb4be5..0000000000 --- a/.jscsrc +++ /dev/null @@ -1,31 +0,0 @@ -{ - "preset": "google", - "maximumLineLength": { - "value": 140 - }, - "validateIndentation": 4, - "disallowMultipleVarDecl": null, - "requireSpacesInFunctionExpression": { - "beforeOpeningRoundBrace": true, - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunctionDeclaration": { - "beforeOpeningRoundBrace": true, - "beforeOpeningCurlyBrace": true - }, - "disallowSpacesInFunctionExpression": null, - "disallowSpacesInAnonymousFunctionExpression": null, - "disallowSpacesInFunctionDeclaration": null, - "jsDoc": { - "checkAnnotations": "jsdoc3", - "checkParamNames": true, - "requireParamTypes": true, - "checkRedundantParams": true, - "checkReturnTypes": true, - "checkRedundantReturns": true, - "requireReturnTypes": true, - "checkTypes": "capitalizedNativeCase", - "checkRedundantAccess": true - }, - "esnext": true -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index a7b70bf85b..0000000000 --- a/.jshintrc +++ /dev/null @@ -1,78 +0,0 @@ -{ - "bitwise": false, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "forin": false, - "freeze": true, - "immed": true, - "indent": 4, - "latedef": true, - "newcap": true, - "noarg": true, - "nonbsp": true, - "nonew": true, - "noempty": true, - "plusplus": false, - "undef": true, - "unused": "vars", - "strict": false, - "maxparams": 5, - "maxdepth": 4, - "maxstatements": false, - "maxcomplexity": 10, - "maxlen": 140, - "quotmark": "single", - "asi": false, - "boss": false, - "debug": false, - "eqnull": false, - "esnext": true, - "evil": false, - "expr": false, - "funcscope": false, - "globalstrict": false, - "iterator": false, - "lastsemic": false, - "loopfunc": false, - "maxerr": 50, - "multistr": false, - "notypeof": false, - "proto": false, - "scripturl": false, - "shadow": false, - "supernew": false, - "sub": true, - "validthis": false, - "noyield": false, - "browser": true, - "couch": false, - "devel": false, - "dojo": false, - "jquery": false, - "mootools": false, - "node": true, - "nonstandard": false, - "prototypejs": false, - "rhino": false, - "worker": false, - "wsh": false, - "yui": false, - "globals": { - "console": false, - "crossfilter": false, - "d3": false, - "dc": false, - "global": false, - "module": false, - "process": false, - "require": false, - "jasmine": false, - "expect": false, - "describe": false, - "it": false, - "beforeEach": false, - "afterEach": false, - "spyOn": false - } -} \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000000..d4b0b29dba --- /dev/null +++ b/.npmignore @@ -0,0 +1,19 @@ + +# Ignore everything +* + +# selectively include +!package.json +!README.md +!LICENSE +!dist/**/* + +# ES6 modules +!src/**/* + +# Exclude index-with-version from ES6 modules +src/index-with-version.js + +# ignore the source map files, these have no use without source files +# gw: these may still help +# dist/**/*.map diff --git a/.travis.yml b/.travis.yml index b296a57f3d..f4cba02ec7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ -sudo: false language: node_js node_js: - - '0.12' + - '12' + script: - - 'if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then grunt ci; else grunt ci-pull; fi' -env: - global: - - secure: Kt+5IJDJRVwr28xRnmR5YDsJceXDcDR21/JUBfk6DYFixPbIq7LCPnZUmiSZQs8akU95ucXwB5hsirUAdEhXdYKilec6go70lticVlZBLy8IdJ+Di1uPwMOeMHvalC2P0woIRJSMzP8u5E+e+5ASggTjsXID7/p1rE0jXtoOueQ= - - secure: TED5eLMxEsyIGzKP8xxhyRDbKlIX9POzj1qgan40a8rkwIVzkdglkviLAXJJeP0ilc1GeGz1ctXyA6NAZt7RHB79mdQbH9iV1AsR29ItH4jdBs7eWRybDRKYRlmOntH0n7zlJDB4qQMxvNdI8BKYrPQymgZ3jtRJ/INOvLerg1g= + - npx grunt ci-pull diff --git a/AUTHORS b/AUTHORS index bcfdc6e58b..4c896d93c6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -32,7 +32,7 @@ James King Matt Hull Neal Ruggles Matt Traynham -Xavier Dutoit +Xavier Dutoit Siddharth Gupta David Long Austin Lyons @@ -59,7 +59,7 @@ Johnny Peck Kevin Kirsche Meyfarth Ion Alberdi -Marcel Pfeiffer +Marcel Pfeiffer Rob Hardwick Jonathan Munz Chris Alvino @@ -71,15 +71,51 @@ Mohamed Gazal Indri Muska Reese Sam Dunster -Mike Vashevko +Mike Vashevko3 koefoed Yuval Greenfield Xaser Acheron Adrián de la Rosa Cathy Nangini Timothy Pfafman -Sebastian Gröhn +Sebastian Gröhn Wei Ding Michael Dougherty Paul Mach Fil +Mauricio Bustos +Anders Dalvander +Alexander Stillesjö +Steffen Dienst +Ganesh Iyer +Daniel Gall +Renoth +Alexander Bouriakov +Kyle Doherty +Macy Abbey +Sandeep Fatangare +James Tindall +Victor Parpoil +Deepak Kumar +Keith Dahlby +Blair Nilsson +Sean Micklethwaite +Amelia Ireland +David Long +Ramesh Rajagopalan +Chris Wolcott +R Manzano +Brendan Heberton +Leung CHAN +Alex Campana +Frozenlock +Sudeep Mandal +Davide Arcuri +Lou Moxy +Sven Hertling +Tahirhan Yıldızoğlu +hofmeister +German Priks +Maxime Rouyrre +BERÉNYI Attila +Patrik Kullman diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 865575da2e..43527ea47a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,51 +2,74 @@ ## Issue Submission Guidelines -* Because of the volume of requests, we do not use the issue tracker for support questions. If you are trying to get a particular effect or you have a problem with your code, please ask your question on stackoverflow.com or the [user group](https://groups.google.com/forum/?fromgroups#!forum/dc-js-user-group) -* It will be far, far easier for others to understand your problem or bug if you demonstrate it with a short example on http://jsfiddle.net/ or on http://bl.ocks.org/ (http://blockbuilder.org/ is a great way to edit bl.ocks!). Here are some examples you can fork to get started: - * [example jsFiddle](http://jsfiddle.net/gordonwoodhull/os27xcg2/) with some data and a chart. - * [blank jsFiddle](http://jsfiddle.net/gordonwoodhull/u57bfje8/) using the latest dc.js from github.io - * the same example [as a bl.ock](http://bl.ocks.org/gordonwoodhull/ecce8e32d64c662cffd5); [on blockbuilder.org](http://blockbuilder.org/gordonwoodhull/ecce8e32d64c662cffd5) - * a blank template bl.ock [on blockbuilder.org](http://blockbuilder.org/gordonwoodhull/9ab997c9a8d7d3380364) -* For bugs and feature requests submit a [github issue](http://github.com/dc-js/dc.js/issues) +If you are trying to get a particular effect or you have a problem with your code, please ask your question [on stackoverflow.com](http://stackoverflow.com/questions/tagged/dc.js) or the [user group](https://groups.google.com/forum/?fromgroups#!forum/dc-js-user-group). We use the issue tracker for bug reports and feature requests only. + +Get help faster with a working example! Fork these to get started:
+[blank jsFiddle](https://jsfiddle.net/gordonwoodhull/rL82bguk/1) - [example jsFiddle](https://jsfiddle.net/gordonwoodhull/5ztavmjy/2) - [blank bl.ock](https://blockbuilder.org/gordonwoodhull/f6bab3d2f5b34018548207014b4056bf) - [example bl.ock](https://blockbuilder.org/gordonwoodhull/bcf9eaa0bfc2c84373cffac06d5755e5) + +For bug reports and feature requests submit a [github issue](http://github.com/dc-js/dc.js/issues) * Please include the version of DC you are using * If you can, please try the latest version of DC on the [master](https://raw.github.com/dc-js/dc.js/master/dc.js) branch to see if your issue has already been addressed or is otherwise affected by recent changes. -## Pull Request Guidelines +## Development Guidelines -* Fork the repository. -* As with all pull requests, put your changes in a branch. For contributions that change the dc.js API, create your branch off of `develop`. If your contribution does not change the API, branch off of `master` instead. -* Make changes to the files in `src/` not dc.js +* Code is written and distributed as ES6 modules. +* `src/` folder is directly exposed for ES6 module users. + In addition, a `rollup` generated UMD bundle is placed in `dist/`. +* Please try to follow the existing code formatting. +* Make changes to the files in `src/` not `dc.js`. * Add tests to `spec/`. Feel free to create a new file if needed. -* Run `grunt server` and go to http://localhost:8888/spec to develop your tests. -* If your changes might affect transitions, go to the relevant transition tests in http://localhost:8888/web/transitions and watch them by eye to see if they make sense -* Run `grunt lint` to confirm that your code meets the dc.js style guidelines. -* Run `grunt test` to confirm that all tests will pass on phantomjs. -* Commit your changes to `src/*` and `spec/*` but not any build artifacts. (Build artifacts include `dc.*js*`, `web/docs/*`, `web/js/*`) -* Submit a pull request. -* If you merge `develop` or `master` into your patchset, please rebase against develop. (It's okay to rewrite history for PRs, because these branches are temporary and it's unlikely that anyone is tracking your feature branch.) -* The DC maintainer team will review and build the artifacts when merging. -* If you continue making changes to your fork of `dc.js`, create a separate branch for each pull request and keep the changes separate. - -#### Coding Conventions - -* Avoid tabs and trailing whitespace -* Please try to follow the existing code formatting -* We use jshint and jscs to verify most of our coding conventions + `spec/index.html` is a generated file, no need to manually update. +* Please add adequate tests. Many good PRs are not merged for the + lack of test cases. +* Please use `.transitionDuration(0)` for all chart tests. +* If you have made significant changes or added a new chart type, + please consider adding a new example in `web-src/examples/`. +* Source for `dc.css` is maintained in `style/dc.scss`. +* All files in `web/` and `dist/` are generated. + Do not make direct changes to these. +* Run `grunt test` to run all tests using Karma and Jasmine on headless Firefox, + or see [Testing](#Testing) for other methods +* We use eslint to check coding guidelines and conventions. + Run `grunt lint` to confirm that your code meets the dc.js style guidelines. + See `.eslintrc` for current rules. +* The default grunt task will install a git pre-commit hook + `.git/hooks/pre-commit` to help verify the coding conventions. + Run `grunt` without any arguments to install the hook. + You only need to do it once. +* Commit your changes to `src/*`, `spec/*`, and `web-src/*`; exclude build artifacts. + (Build artifacts include `dist/*` and `web/*`). -It helps keep on top of the conventions if you create a git pre-commit hook `.git/hooks/pre-commit`: -``` -#!/usr/bin/env sh +## Testing +* `grunt test` will run will all tests using Karma and Jasmine on headless Firefox. + `grunt ci` tests headless Chrome as well. + Some IDEs facilitate executing tests from the IDE itself. +* Running `grunt server` starts a server at http://localhost:8888/ which serves + the current directory as root. +* Tests can also be run on the browser by going to http://localhost:8888/spec when + server is running. +* With the server running, go to http://localhost:8888/web to check the stocks example. + You can also go to the examples sub folder to test specific examples. +* During development, you can run `grunt test-n-serve`. + It will start the server and in addition keep a watch for changes to + run build/test as needed. +* If your changes might affect animated transitions, + go to the relevant transition tests in + http://localhost:8888/web/transitions and watch them by eye to see if they make + sense, or add another one if needed. There are no automated tests for transitions. -grunt jshint -grunt jscs -``` - -(You also need to make it executable with `chmod u+x .git/hooks/pre-commit`) - -Or you can just run the commands manually before committing. - -#### Testing Notes +## Pull Request Guidelines -Running `grunt server` will host the jasmine specs at http://localhost:8888/spec. -Please use `.transitionDuration(0)` for all chart tests. +* Fork the repository. +* As with all pull requests, put your changes in a branch. + For contributions that change the dc.js API, create your branch off of `develop`. + If your contribution does not change the API, branch off of `master` instead. +* Make your changes. +* Submit a pull request. +* Travis CI is linked to PRs, so, all tests will get executed on creation/updation of a PR. + The status is visible on the GitHub PR page. +* If you need to merge `develop` or `master` into your patchset, + instead of merging please use git rebase. +* The DC maintainer team will review and build the artifacts when merging. +* If you continue making changes to your fork of `dc.js`, + please create a separate branch for each pull request and keep the changes separate. diff --git a/Changelog.md b/Changelog.md index ecf508583d..16df65535a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,311 @@ +## 4.2.7 +* Remove lax `d3compat.eventHandler` workarounds, not necessary if code consistently uses d3@5 or d3@6 event handler signatures +* Remove extra `d3compat.eventHandler` identified with strict event handler +* Fix event handling in focus ordinal bar example ([#1826](https://github.com/dc-js/dc.js/issues/1826)) +* Change composite bar line example to illustrate using `xAxisPadding` with `centerBar` to draw compoisite bar/line properly ([#1827](https://github.com/dc-js/dc.js/issues/1827)) + +## 4.2.6 +* Isolate D3 compatibility layers, allowing more efficient module imports, by Patrik Kullman ([#1822](https://github.com/dc-js/dc.js/issues/1822) / [#1823](https://github.com/dc-js/dc.js/issues/1823) / [#1824](https://github.com/dc-js/dc.js/issues/1824)) + +## 4.2.5 +* Option [useTopXAxis](https://dc-js.github.io/dc.js/docs/html/CoordinateGridMixin.html#useTopXAxis) to show coordinate grid X axis at top of chart, by BERÉNYI Attila ([#1815](https://github.com/dc-js/dc.js/issues/1815) / [#1816](https://github.com/dc-js/dc.js/pull/1816)) +* Add source for bar colors example ([#1817](https://github.com/dc-js/dc.js/issues/1817)) + +## 4.2.4 +* Fix use of `d3.mouse` removed in d3@6, by Deepak Kumar ([#1807](https://github.com/dc-js/dc.js/issues/1807) / [#1808](https://github.com/dc-js/dc.js/pull/1808)) +* Simpler example of ordinal brushing, by Deepak Kumar ([#1809](https://github.com/dc-js/dc.js/pull/1809)) + +## 4.2.3 +* Fix undefined this on SeriesChart redraw, by Maxime Rouyrre ([#1800](https://github.com/dc-js/dc.js/pull/1800)) +* Export d3 compat functions allowing it to be used to simplify d3@6 compatibility in examples. + Fixes [#1787](https://github.com/dc-js/dc.js/issues/1787). + +## 4.2.2 +* Add [linked filter example](https://dc-js.github.io/dc.js/examples/linked-filter.html), had been floating around as a jsfiddle answer to [SO question](https://stackoverflow.com/questions/59461538/dc-js-how-to-mirror-brush-across-multiple-charts) for a while. + +## 4.2.1 +* Text filter widget should redraw chart's group - thanks @kriddy! ([#1678](https://github.com/dc-js/dc.js/pull/1678) / [#14978](https://github.com/dc-js/dc.js/issues/14978)) +* Pareto chart example was not correctly sorted, and scatter series chart displayed brush when zoomed ([#1780](https://github.com/dc-js/dc.js/pull/1780) / [#1772](https://github.com/dc-js/dc.js/issues/1772)) + +## 4.2.0 +* Accessibility features BaseMixin.svgDescription and BaseMixin.keyboardAccessible, by German Priks. Demo here. ([#1738](https://github.com/dc-js/dc.js/pull/1738) / [#1185](https://github.com/dc-js/dc.js/issues/1185)) + +## 4.1.1 +* The [brush ordinal example](https://dc-js.github.io/dc.js/examples/brush-ordinal.html) did not filter correctly when row chart was clicked ([#1770](https://github.com/dc-js/dc.js/issues/1770)) +* Some examples were broken by the move to d3@6 ([#1769](https://github.com/dc-js/dc.js/issues/1769)) + +## 4.1.0 +* Compatible with d3@6 while preserving compatibility with d3@5, by Deepak Kumar ([#1749](https://github.com/dc-js/dc.js/pull/1749) / [#1748](https://github.com/dc-js/dc.js/issues/1748)) + +## 4.0.5 +* Remove accidental references to global `d3`, `dc` in sources (discussion [here](https://github.com/dc-js/dc.js/commit/902736ad4436dbcad1d57badce14a5e485c59d7a#commitcomment-40208686)) + +## 4.0.4 +* Fix ordinal (string) ordering ([#1690](https://github.com/dc-js/dc.js/issues/1690)) +* Bubble mixin should exclude zeros when calculating elastic radius; [excludeElasticZero](https://dc-js.github.io/dc.js/docs/html/BubbleMixin.html#excludeElasticZero) can be set false if old behavior is desired ([#1688](https://github.com/dc-js/dc.js/pull/1688)) +* Add a simple [linear regression example](http://dc-js.github.io/dc.js/examples/regression.html). +* Add a [horizon chart example](http://dc-js.github.io/dc.js/examples/horizon-chart.html) which shows how to add a custom chart with group data. Rename the old custom chart example which displays a groupAll to [color swatch](http://dc-js.github.io/dc.js/examples/color-swatch.html). + +## 4.0.3 +* Remove a `filterHandler` special case, and improve the performance of the default filter handler, by Deepak Kumar ([#1660](https://github.com/dc-js/dc.js/pull/1660)) +* Merge sunburst rounding error fixes from 3.2.1 + +## 4.0.2 +Fix bugs in previous version + +## 4.0.1 +Merges sunburst charts from 3.2.0 + +## 4.0.0 +* Thanks to the diligent and careful effort of Deepak Kumar, dc.js has been ported to ES6 modules, classes and syntax. + +IE is no longer supported. dc.js will not support transpilation. Stick with dc@3 for IE support. + +The API is mostly compatible, but there are a few breaking changes - see the [v4 upgrade guide](https://github.com/dc-js/dc.js/blob/develop/docs/dc-v4-upgrade-guide.md) for details. + +## 3.2.1 +* Fix rounding issue with equal ring sizes, by hofmeister ([#1662](https://github.com/dc-js/dc.js/pull/1662) / ([#1661](https://github.com/dc-js/dc.js/issues/1661)) + + +## 3.2.0 +* Support for general customizable ring sizes on the sunburst chart, by hofmeister ([#1625](https://github.com/dc-js/dc.js/pull/1655) / ([#1511](https://github.com/dc-js/dc.js/issues/1511)) +* Sort sunburst wedges according to `baseMixin.ordering()`, by hofmeister ([#1625](https://github.com/dc-js/dc.js/pull/1655) / ([#1511](https://github.com/dc-js/dc.js/issues/1511)) + +## 3.1.9 +* `highlightSelected` implemented for SVG legend, by Tahirhan Yıldızoğlu ([#1625](https://github.com/dc-js/dc.js/pull/1625) / ([#600](https://github.com/dc-js/dc.js/issues/600)) +* [Pareto chart example](http://dc-js.github.io/dc.js/examples/pareto-chart.html) + +## 3.1.8 +Special **Goodbye IE** Edition! dc.js 4.0 will remove support for Internet Explorer, as it has been translated into ES6 by Deepak Kumar. For one last trip down memory lane, here are some IE patches. +* Do not use `Array.from()` yet in base mixin +* Use polyfills and don't use ES6 in examples. All examples work in IE11 except where IE is too slow or its CSS too weird to both with. +* Fully tested with crossfilter 1.4.8, the last crossfilter to support IE + +## 3.1.7 +* Updating `bower.json` to D3v5, with apologies for [#1458](https://github.com/dc-js/dc.js/issues/1458). Bower support will be dropped in dc.js version 4.0 - please specify dc version `3.x` if you are using bower + +## 3.1.6 +* allow resizing of canvas-based scatter plots ([#1596](https://github.com/dc-js/dc.js/issues/1596)) + +## 3.1.5 +* Composite chart properties should pass through regardless of when compose is called, by Keith Dahlby. ([#1365](https://github.com/dc-js/dc.js/pull/1365) / [#554](https://github.com/dc-js/dc.js/issues/554) / [#611](https://github.com/dc-js/dc.js/issues/611) / [#1003](https://github.com/dc-js/dc.js/issues/1003)) + +## 3.1.4 +* Example of [drawing a contour map as a background](http://dc-js.github.io/dc.js/examples/background-drawing.html), by Sven Hertling +* Example of [capping and sorting by different criteria](https://dc-js.github.io/dc.js/examples/cap-and-sort-differently.html) ([#1474](https://github.com/dc-js/dc.js/issues/1474) + +## 3.1.3 +* Canvas-based scatter plot, by Sudeep Mandal ([#1361](https://github.com/dc-js/dc.js/pull/1361)) +* Better use of data in scatter example +* Missing inheritance link in class hierarchy diagram + +## 3.1.2 +* Stop using [crossfilter.quicksort.by](https://github.com/crossfilter/crossfilter/wiki/API-Reference#quicksort_by) and use [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) instead, by Deepak Kumar. Crossfilter is now just a `devDependency`. ([#1560](https://github.com/dc-js/dc.js/pull/1560) / ([#1559](https://github.com/dc-js/dc.js/issues/1559)) +* Example of [updating data in a range-focus chart](http://dc-js.github.io/dc.js/examples/focus-dynamic-data.html). + +## 3.1.1 +* Update [replacing data](https://dc-js.github.io/dc.js/examples/replacing-data.html) and [series](https://dc-js.github.io/dc.js/examples/series.html) examples with the robust way to replace data as of crossfilter 1.4 ([#1536](https://github.com/dc-js/dc.js/issues/1536)) +* The [focus ordinal bar example](https://dc-js.github.io/dc.js/examples/focus-ordinal-bar.html) demonstrates scrolling through a wide bar chart using a range chart. +* The [brush ordinal example](https://dc-js.github.io/dc.js/examples/brush-ordinal.html) demonstrates using a range brush on ordinal data, by transforming the data to a linear scale. +* Remove leftover debugging logs, thanks Adrián de la Rosa! ([#1534](https://github.com/dc-js/dc.js/pull/1534)) + +## 3.1.0 +* Remove `float: left` from dc.css; add it to individual examples where needed. + +It's not appropriate to set this in the library, because charts will be used in all sorts of different layouts, and this sometimes required people to use `div.dc-chart { float: none!important; }` which is horrible. ([#673](https://github.com/dc-js/dc.js/issues/673)) + +Fixing this will break a lot of dashboard layouts, thus the version bump. Add + +```css +div.dc-chart { + float: left; +} +``` +to your page CSS to restore the old layout! +* Fix mixed content loading, by Rohan Shewale ([#1529](https://github.com/dc-js/dc.js/pull/1529)) +* Update all dependencies and move to eslint, to eliminate npm security audit complaints + +## 3.0.13 +* Keep track of individual values efficiently in boxplot examples ([#543](https://github.com/dc-js/dc.js/issues/543)) +* Series progression [example](https://dc-js.github.io/dc.js/transitions/series-progression.html) + +## 3.0.12 +* heatmap takes ordinary filter objects and conversion of coordinates is deprecated ([#1515](https://github.com/dc-js/dc.js/issues/1515)) +* [Example](http://dc-js.github.io/dc.js/examples/compare-unfiltered.html) of comparing the current filters against the unfiltered values [using a fake group to copy original values](https://github.com/dc-js/dc.js/wiki/FAQ#static-copy-of-a-group). Thanks to Jason Aizkalns for the [SO](https://stackoverflow.com/questions/55066391/display-original-conditional-brushed-unbrushed-crossfilter-bars-with-dc-js-wit) and [CodeReview](https://codereview.stackexchange.com/questions/215041/dc-js-and-crossfilter-app-to-display-multiple-charts) questions and the example! +* Provide alternate, more descriptive names for properties so that the meaning is not overloaded, to reduce confusion and improve code clarity: + * `dataTable.group` and `dataGrid.group` took a nesting function, not a crossfilter group, so they are replaced with a new property called `section` ([#855](https://github.com/dc-js/dc.js/issues/855)). Additionally, `dataTable.section` is no longer mandatory and defaults to the empty string. + * `dataCount.dimension` took a crossfilter instance, and `dataCount.group` really took a groupAll object, so they are replaced with properties with those names ([#1499](https://github.com/dc-js/dc.js/issues/1499)) +The old property names are still supported, but they emit an informational message recommending the better name. They could be deprecated in the future (but there is probably no need). + +## 3.0.11 +* Remove the deprecation on `colorMixin.colorCalculator`, and implement it in a reasonable way ([#1493](https://github.com/dc-js/dc.js/issues/1493)) + +## 3.0.10 +This mostly updates examples and tests, and updates compatiblity polyfills for IE. +* Compatible with d3 5.8 +* Various test failures across all browsers fixed, due to changes in D3 and browsers +* New [row targets](http://dc-js.github.io/dc.js/examples/row-targets.html) example shows how to superimpose lines on individual row chart items +* [Focus dynamic interval](http://dc-js.github.io/dc.js/examples/focus-dynamic-interval.html) example builds on [switching time intervals](http://dc-js.github.io/dc.js/examples/switching-time-intervals.html) to show how to change the aggregation in response to brushing on a range chart +* Many examples were mistitled +* Removed arrow functions and polyfilled missing functions (eg Fetch) for IE. Note that IE support won't last forever since D3v6 will no longer support it! +* Fixed typo, thanks Rimian Perkins! + +## 3.0.9 +* Updated Table Pagination example, with filtering, by Sudeep Mandal and Arcuri Davide ([#1492](https://github.com/dc-js/dc.js/pull/1492)) +* Fade-in and correct opacity for grid lines, by Lou Moxy ([#1501](https://github.com/dc-js/dc.js/pull/1501) / [#1500](https://github.com/dc-js/dc.js/issues/1500)) +* Thanks to Rohan Shewale for a doc typo fix + +## 3.0.8 +* Sunburst was not centering responsively on redraw, by Frozenlock ([#1491](https://github.com/dc-js/dc.js/pull/1491) / [#1490](https://github.com/dc-js/dc.js/issues/1490)) +* Composite chart with no `id` was not clipping its children, by Frozenlock ([#1488](https://github.com/dc-js/dc.js/issues/1488)) + +## 3.0.7 +* Sunburst has animated transitions, by Amelia Ireland ([#1481](https://github.com/dc-js/dc.js/pull/1481)) +* Filter printer now prints more than 2 elements, by Amelia Ireland ([#1475](https://github.com/dc-js/dc.js/pull/1475)) +* `controlsUseVisibility` was incorrectly documented as defaulting true, by Amelia Ireland ([#1474](https://github.com/dc-js/dc.js/issues/1474)) +* Pie charts and row charts should always use `cappedValueAccessor` or custom `valueAccessor` will crash by Alex Campana ([#1335](https://github.com/dc-js/dc.js/pull/1335)) +* Title tooltips were not shown on heatmap the first time ([#1482](https://github.com/dc-js/dc.js/issues/1482)) +* Simpler, improved method for "bar single select" example, by Leung Chan ([#1477](https://github.com/dc-js/dc.js/pull/1477) + +## 3.0.6 +* Enable the stroke for line chart dots, making it possible to actually use `strokeOpacity` ([#1449](https://github.com/dc-js/dc.js/pull/1449) / [#1447](https://github.com/dc-js/dc.js/issues/1447)) +* Fix an error when horizontal grid lines were drawn on a chart with an ordinal Y scale, by the3ver ([#1448](https://github.com/dc-js/dc.js/pull/1448) / [#539](https://github.com/dc-js/dc.js/issues/539)) +* Bubbles were not disappearing when bins were removed from the group, by Brendan Heberton ([#1466](https://github.com/dc-js/dc.js/pull/1466)) +* Protect value accessor from `sunburstChart`'s virtual parent nodes, by Deepak Kumar ([#1444](https://github.com/dc-js/dc.js/pull/1444) / [#1440](https://github.com/dc-js/dc.js/issues/1440)) + +## 3.0.5 +* Scatter plot symbols were not getting removed when group changed size, by Deepak Kumar. ([#1463](https://github.com/dc-js/dc.js/pull/1463) / [#1460](https://github.com/dc-js/dc.js/issues/1460)) +* Use Chrome and Firefox headless at Travis CI, by Deepak Kumar. See ([#1452](https://github.com/dc-js/dc.js/pull/1452)), an attempt to resolve ([#1451](https://github.com/dc-js/dc.js/pull/1451)) + +## 3.0.4 +* Box plot enhancements: jittered data points, data point tooltips, bold outliers, by Chris Wolcott. Also implements `yRangePadding` to fix problems with not enough/too much space for labels in box plots. ([#1439](https://github.com/dc-js/dc.js/pull/1439) / [#1370](https://github.com/dc-js/dc.js/issues/1370) / [#1120](https://github.com/dc-js/dc.js/issues/1120)) +* Code cleanup - replaced `.rangesEqual` with `dc.utils.arraysEqual`, by Deepak Kumar ([#1436](https://github.com/dc-js/dc.js/pull/1436) / [#1405](https://github.com/dc-js/dc.js/issues/1405)) +* New tests for range filters with dates, by Deepak Kumar. ([#1437](https://github.com/dc-js/dc.js/pull/1437) / [#1432](https://github.com/dc-js/dc.js/issues/1432)) +* Fix readme references to 3.0, by Deepak Kumar. ([#1441](https://github.com/dc-js/dc.js/pull/1441)) +* Propagate filters on composite chart to children, by Deepak Kumar ([#1435](https://github.com/dc-js/dc.js/pull/1435)). Fixes remaining parts of ([#390](https://github.com/dc-js/dc.js/issues/390) / [#706](https://github.com/dc-js/dc.js/issues/706)). +* Listen to rangeChart's filtered event with a namespace, by Keith Dahlby ([#1366](https://github.com/dc-js/dc.js/pull/1366)) + +## 3.0.3 +* Update versions and release new fiddles and blocks pegged to dc@3 and d3@5 + +## 3.0.2 +* Allow row chart `.xAxis` to be settable. Since the type of axis can't be detected by the chart, provide [example](https://dc-js.github.io/dc.js/examples/row-top-axis.html) of setting the position of axis and grid lines manually. +* In a composite chart, the brush is only applied on the parent, by Deepak Kumar. This fixes many composite chart brushing issues, but let us know if it broke any of your use cases! ([#1408](https://github.com/dc-js/dc.js/pull/1408) / [#1424](https://github.com/dc-js/dc.js/issues/1424) / [#479](https://github.com/dc-js/dc.js/issues/479) / [#390](https://github.com/dc-js/dc.js/issues/390) / [#706](https://github.com/dc-js/dc.js/issues/706) / [#878](https://github.com/dc-js/dc.js/issues/878)) + +## 3.0.1 +* Test compatibility with D3v4 as well as D3v5, by Deepak Kumar ([#1430](https://github.com/dc-js/dc.js/pull/1430)) +* Add new charts/widgets to class hierarchy in documentation + +## 3.0.0 +* Sunburst chart, by Blair Nilsson, with contributions by Sean Micklethwaite and Deepak Kumar ([#781](https://github.com/dc-js/dc.js/issues/781) / [#907](https://github.com/dc-js/dc.js/pull/907) / [#1337](https://github.com/dc-js/dc.js/pull/1337) /[#1388](https://github.com/dc-js/dc.js/pull/1388)) +* Text filter widget, by Xavier Dutoit ([#383](https://github.com/dc-js/dc.js/issues/383) / [#936](https://github.com/dc-js/dc.js/pull/936) / [#1387](https://github.com/dc-js/dc.js/pull/1387)) +* Checkbox/radio button filtering, by Amelia Ireland, with contributions by Deepak Kumar ([#1348](https://github.com/dc-js/dc.js/pull/1348) / [#1389](https://github.com/dc-js/dc.js/pull/1389)) +* HTML Legend, by David Long and Ramesh Rajagopalon, with contributions by Deepak Kumar ([#1325](https://github.com/dc-js/dc.js/issues/1325) / [#577](https://github.com/dc-js/dc.js/pull/577) / [#1329](https://github.com/dc-js/dc.js/pull/1329) / [#1392](https://github.com/dc-js/dc.js/pull/1392)) + +## 3.0.0 beta 2 +* declare `pkg.main` for compatibility with some bundlers (and hopefully Observable) + +## 3.0.0 beta 1 +* First NPM release of dc.js, compatible with D3 versions 4 and 5. Thanks to Deepak Kumar for all his effort on the port! We've made every effort to keep the library backward-compatible, but see [the 3.0 changes in the wiki](https://github.com/dc-js/dc.js/wiki/Changes-in-dc.js-version-3.0). +* `fadeDeselectedArea` checks if brushing is enabled for the chart. Restores backward compatibility. By Deepak Kumar. ([#1422](https://github.com/dc-js/dc.js/pull/1422) / [#1401](https://github.com/dc-js/dc.js/issues/1401)) +* Rename `selection` --> `brushSelection`. By Deepak Kumar.([#1423](https://github.com/dc-js/dc.js/issues/1423) / [#1398](https://github.com/dc-js/dc.js/issues/1398)) + +## 3.0.0 alpha 12 +* Use `d3.stack` from d3v4+, transforming the data from/to the old layer/stack objects. Remove `d3v3-compat.js` ([#1375](https://github.com/dc-js/dc.js/issues/1375) + +## 3.0.0 alpha 11 +* xAxisPaddingUnit should be the d3 interval not the name of it ([#1320](https://github.com/dc-js/dc.js/issues/1320), [#1326](https://github.com/dc-js/dc.js/issues/1326), [#1420](https://github.com/dc-js/dc.js/issues/1420)) + +## 3.0.0 alpha 10 +* Streamlined creation of YAxis in coordinate grid charts, by Deepak Kumar ([#1416](https://github.com/dc-js/dc.js/pull/1416)) +* Updated XAxis and YAxis documentation, by Deepak Kumar ([#1416](https://github.com/dc-js/dc.js/pull/1416)) +* `dc.config.defaultColors` is a mechanism to change default color scheme for all ordinal charts, by Deepak Kumar ([#1409](https://github.com/dc-js/dc.js/pull/1409)). +* deprecate use of default color scheme `d3.schemeCategory20c`, which has been [removed in D3v5](https://github.com/d3/d3/blob/master/CHANGES.md#changes-in-d3-50). Provide a temporary copy of the old colors for backward compatibility, but the defaults will change in DCv3.1. By Deepak Kumar ([#1409](https://github.com/dc-js/dc.js/pull/1409)). +* more cleanup from d3v4 refactor, by Deepak Kumar. Warn before converting from `d3.scaleOrdinal` to `d3.scaleBands` ([#1414](https://github.com/dc-js/dc.js/pull/1414), [#1417](https://github.com/dc-js/dc.js/pull/1417), [#1418](https://github.com/dc-js/dc.js/pull/1418)) + +## 3.0.0 alpha 9 +* `numberDisplay` uses [d3.easeQuad](https://github.com/d3/d3-ease/blob/master/README.md#easeQuad) instead of [quad-out-in](https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md#d3_ease), which didn't make sense. ([#1413](https://github.com/dc-js/dc.js/pull/1413)) +* `dc.units.ordinal` is now purely a placeholder or magic value, and not called as a function. Previously dc.js would call the `xUnits` function with three arguments: the start, end, and domain array, but this was not compliant with d3 range functions. Now these functions are called with only the start and end, and `dc.units.ordinal` is detected with `===`. ([#1410](https://github.com/dc-js/dc.js/pull/1410)) +* cleanup from d3v4 refactor, by Deepak Kumar ([#1412](https://github.com/dc-js/dc.js/pull/1412)) + +## 3.0.0 alpha 8 +* don't show brush handles on scatter plot, by Deepak Kumar ([#1407](https://github.com/dc-js/dc.js/pull/1407) / [#1406](https://github.com/dc-js/dc.js/issues/1406)) +* remove `d3.functor`. [`d3.functor` was removed in d3 version 4]( https://github.com/d3/d3/blob/master/CHANGES.md#internals); to replace it, use `typeof x === "function" ? x : dc.utils.constant(x)` ([#1374](https://github.com/dc-js/dc.js/issues/1374)) + +## 3.0.0 alpha 7 +* `elasticY` should look only at points within the X domain, even with `evadeDomainFilter` enabled, by Keith Dahlby ([#1367](https://github.com/dc-js/dc.js/pull/1367)) +* fixes to animated resizing of brush when chart resizes, by Deepak Kumar ([#1402](https://github.com/dc-js/dc.js/pull/1402) / [#1376](https://github.com/dc-js/dc.js/issues/1399) + +## 3.0.0 alpha 6 +* initialize all positions for entering objects, since d3.transition will now start them at zero if you don't ([#1400](https://github.com/dc-js/dc.js/issues/1400)) + +## 3.0.0 alpha 5 +* d3v5 support: all examples upgraded to d3-fetch. `schemeCategory20c` is patched into `d3` temporarily, by Deepak Kumar, but see [#1403](https://github.com/dc-js/dc.js/issues/1403) + +## 3.0.0 alpha 4 +* switch to Karma for testing across browsers, by Deepak Kumar ([#1393](https://github.com/dc-js/dc.js/pull/1393)) + +## 3.0.0 alpha 3 +* improved integration with `d3.zoom`, by Deepak Kumar. Since the d3v4 implementation is a lot more powerful, this eliminates a lot of custom zoom code. ([#1385](https://github.com/dc-js/dc.js/pull/1385)) + +## 3.0.0 alpha 2 +* backward compatibility for `dc.lineChart.interpolate` and `dc.geoChoroplethChart.projection`, by Deepak Kumar ([#1381](https://github.com/dc-js/dc.js/pull/1381) / [#1376](https://github.com/dc-js/dc.js/issues/1376), [#1382](https://github.com/dc-js/dc.js/pull/1382) / [#1379](https://github.com/dc-js/dc.js/issues/1379)) +* Fixed test cases for Edge/IE, by Deepak Kumar ([#1378](https://github.com/dc-js/dc.js/pull/1378) / [#1373](https://github.com/dc-js/dc.js/issues/1373) +* lint ([#1372](https://github.com/dc-js/dc.js/pull/1372)) + +## 3.0.0 alpha 1 +* first pass of d3v4 support, by Deepak Kumar ([#1363](https://github.com/dc-js/dc.js/pull/1363)) +* until more stable, releases will be github-only (no npm/cdnjs) +* all [axis.tickArguments()](https://github.com/d3/d3-axis/blob/master/README.md#axis_tickArguments) are applied to `scale.ticks()` to produce horizontal & vertical gridlines, not just the first argument. + +## 3.0 +dc.js 3.0 is compatible with d3 versions 4 and 5! Thanks to Deepak Kumar for his tireless effort on making this finally happen. + +New features will only be added to 3.0; however, 2.1 will be maintained for a limited time for those who still need compatibility with d3 version 3. + + +## 2.1.10 +* Update dependencies, including crossfilter2 v1.4 +* Example of adding a vertical line to a row chart + +## 2.1.9 +* Fix selectMenu crashing IE11 on Windows 8 and below, by Victor Parpoil ([#1338](https://github.com/dc-js/dc.js/pull/1338) / [#1334](https://github.com/dc-js/dc.js/issues/1334)) + +## 2.1.8 +(see 2.0.5) + +## 2.1.7 +* viewBox-based resizing of charts, by James Tindall ([#1312](https://github.com/dc-js/dc.js/pull/1312)) +* workaround for [issue #949](https://github.com/dc-js/dc.js/issues/949) merged from 2.0.4 +* remove pointless and confusing optimization from number display - it now uses `computeOrderedGroups` like everything else. + +## 2.1.6 +* fix test syntax for Microsoft browsers + +## 2.1.5 +* crossfilter is loaded by its module name (crossfilter2), not its filename (crossfilter). This is intended to help webpack and other automatic module loaders. This is likely to break requireJS configurations; see [#1304](https://github.com/dc-js/dc.js/issues/1304) for details. ([#1213](https://github.com/dc-js/dc.js/issues/1213), [#1214](https://github.com/dc-js/dc.js/issues/1214), [#1261](https://github.com/dc-js/dc.js/issues/1261), [#1293](https://github.com/dc-js/dc.js/issues/1293), [#1302](https://github.com/dc-js/dc.js/issues/1302)) + * Default capMixin.ordering to sort decreasing by value, to emulate old group.top(N) + * `numberDisplay` should pick the highest value in the case where it is given a regular group + +## 2.1.4 + * Simplified `capMixin.othersGrouper` default implementation by passing the rest of the items as well as those before the cap. This is possible because of [#934](https://github.com/dc-js/dc.js/issues/934) relying on sorting of `group.all()` instead of `group.top()`. The default implementation is now easy to understand and it should be easier to customize (if anyone should want to). + * Added example filtering segments of stack ([#657](https://github.com/dc-js/dc.js/issues/657)) + +## 2.1.3 + * 2.1.2 did not observe the common convention of having the rows/pie slices ordered from greatest to least - now we take from the front by default. ([#1296](https://github.com/dc-js/dc.js/issues/1296) + * Add [`takeFront`](http://dc-js.github.io/dc.js/docs/html/dc.capMixin.html#takeFront) option, defaulted true, in case you want to take from the back isntead. + * Remove `component.json`, since [component-js has been deprecated for a long time](https://github.com/componentjs/component/issues/639) (actually it got deprecated immediately after we added this in [#860](https://github.com/dc-js/dc.js/pull/860)) + +## 2.1.2 + * Lift `elasticRadius` from `bubbleChart` to `bubbleMixin`, making it available to `bubbleOverlay` ([#661](https://github.com/dc-js/dc.js/issues/661)) +Stop using `group.top()` in favor of `group.all()` sorting and slicing. ([#934](https://github.com/dc-js/dc.js/issues/934)) + * Eliminate use of `group.top()` in cap mixin, by Macy Abbey ([#1184](https://github.com/dc-js/dc.js/pull/1184)). It already had to agree with `chart.ordering()` for the results to make sense. + * Eliminate `group.top()` in number display. This one is more problematic but probably less common. Although the number display now defaults ordering to `function (kv) { return kv.value; }`, applications which use a group with multiple bins with the number display, which were using `group.order()` to specify which bin should be displayed, must now specify `numberDisplay.ordering()` instead. + * Eliminate `group.top()` in bubble mixin, which was used to draw the bubbles in descending order of size, when the `group.order()` specified the radius. The bubble chart's `sortBubbleSize` is more general and is lifted to the mixin. + +## 2.1.1 + * Merges 2.0.1 + ## 2.1.0 * `dc.selectMenu`, implementing a `` menu. The menu can be optionally turned into a multiselect. - * @class selectMenu - * @memberof dc - * @mixes dc.baseMixin - * @example - * // create a select menu under #select-container using the default global chart group - * var select = dc.selectMenu('#select-container') - * .dimension(states) - * .group(stateGroup); - * // the option text can be set via the title() function - * // by default the option text is '`key`: `value`' - * select.title(function (d){ - * return 'STATE: ' + d.key; - * }) - * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid - * [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this widget should be placed in. - * Interaction with the widget will only trigger events and redraws within its group. - * @returns {selectMenu} - **/ -dc.selectMenu = function (parent, chartGroup) { - var SELECT_CSS_CLASS = 'dc-select-menu'; - var OPTION_CSS_CLASS = 'dc-select-option'; - - var _chart = dc.baseMixin({}); - - var _select; - var _promptText = 'Select all'; - var _multiple = false; - var _promptValue = null; - var _numberVisible = null; - var _order = function (a, b) { - return _chart.keyAccessor()(a) > _chart.keyAccessor()(b) ? - 1 : _chart.keyAccessor()(b) > _chart.keyAccessor()(a) ? - -1 : 0; - }; - - var _filterDisplayed = function (d) { - return _chart.valueAccessor()(d) > 0; - }; - - _chart.data(function (group) { - return group.all().filter(_filterDisplayed); - }); - - _chart._doRender = function () { - _chart.select('select').remove(); - _select = _chart.root().append('select') - .classed(SELECT_CSS_CLASS, true); - _select.append('option').text(_promptText).attr('value', ''); - - _chart._doRedraw(); - return _chart; - }; - - _chart._doRedraw = function () { - setAttributes(); - renderOptions(); - // select the option(s) corresponding to current filter(s) - if (_chart.hasFilter() && _multiple) { - _select.selectAll('option') - .property('selected', function (d) { - return d && _chart.filters().indexOf(String(_chart.keyAccessor()(d))) >= 0; - }); - } else if (_chart.hasFilter()) { - _select.property('value', _chart.filter()); - } else { - _select.property('value', ''); - } - return _chart; - }; - - function renderOptions () { - var options = _select.selectAll('option.' + OPTION_CSS_CLASS) - .data(_chart.data(), function (d) { return _chart.keyAccessor()(d); }); - - options.enter() - .append('option') - .classed(OPTION_CSS_CLASS, true) - .attr('value', function (d) { return _chart.keyAccessor()(d); }); - - options.text(_chart.title()); - options.exit().remove(); - _select.selectAll('option.' + OPTION_CSS_CLASS).sort(_order); - - _select.on('change', onChange); - return options; - } - - function onChange (d, i) { - var values; - var target = d3.event.target; - if (target.selectedOptions) { - var selectedOptions = Array.prototype.slice.call(target.selectedOptions); - values = selectedOptions.map(function (d) { - return d.value; - }); - } else { // IE and other browsers do not support selectedOptions - // adapted from this polyfill: https://gist.github.com/brettz9/4212217 - var options = [].slice.call(d3.event.target.options); - values = options.filter(function (option) { - return option.selected; - }).map(function (option) { - return option.value; - }); - } - // console.log(values); - // check if only prompt option is selected - if (values.length === 1 && values[0] === '') { - values = _promptValue || null; - } else if (!_multiple && values.length === 1) { - values = values[0]; - } - _chart.onChange(values); - } - - _chart.onChange = function (val) { - if (val && _multiple) { - _chart.replaceFilter([val]); - } else if (val) { - _chart.replaceFilter(val); - } else { - _chart.filterAll(); - } - dc.events.trigger(function () { - _chart.redrawGroup(); - }); - }; - - function setAttributes () { - if (_multiple) { - _select.attr('multiple', true); - } else { - _select.attr('multiple', null); - } - if (_numberVisible !== null) { - _select.attr('size', _numberVisible); - } else { - _select.attr('size', null); - } - } - - /** - * Get or set the function that controls the ordering of option tags in the - * select menu. By default options are ordered by the group key in ascending - * order. - * @name order - * @memberof dc.selectMenu - * @instance - * @param {Function} [order] - * @example - * // order by the group's value - * chart.order(function (a,b) { - * return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; - * }); - **/ - _chart.order = function (order) { - if (!arguments.length) { - return _order; - } - _order = order; - return _chart; - }; - - /** - * Get or set the text displayed in the options used to prompt selection. - * @name promptText - * @memberof dc.selectMenu - * @instance - * @param {String} [promptText='Select all'] - * @example - * chart.promptText('All states'); - **/ - _chart.promptText = function (_) { - if (!arguments.length) { - return _promptText; - } - _promptText = _; - return _chart; - }; - - /** - * Get or set the function that filters option tags prior to display. By default options - * with a value of < 1 are not displayed. - * @name filterDisplayed - * @memberof dc.selectMenu - * @instance - * @param {function} [filterDisplayed] - * @example - * // display all options override the `filterDisplayed` function: - * chart.filterDisplayed(function () { - * return true; - * }); - **/ - _chart.filterDisplayed = function (filterDisplayed) { - if (!arguments.length) { - return _filterDisplayed; - } - _filterDisplayed = filterDisplayed; - return _chart; - }; - - /** - * Controls the type of select menu. Setting it to true converts the underlying - * HTML tag into a multiple select. - * @name multiple - * @memberof dc.selectMenu - * @instance - * @param {boolean} [multiple=false] - * @example - * chart.multiple(true); - **/ - _chart.multiple = function (multiple) { - if (!arguments.length) { - return _multiple; - } - _multiple = multiple; - - return _chart; - }; - - /** - * Controls the default value to be used for - * [dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) - * when only the prompt value is selected. If `null` (the default), no filtering will occur when - * just the prompt is selected. - * @name promptValue - * @memberof dc.selectMenu - * @instance - * @param {?*} [promptValue=null] - **/ - _chart.promptValue = function (promptValue) { - if (!arguments.length) { - return _promptValue; - } - _promptValue = promptValue; - - return _chart; - }; - - /** - * Controls the number of items to show in the select menu, when `.multiple()` is true. This - * controls the [`size` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Attributes) of - * the `select` element. If `null` (the default), uses the browser's default height. - * @name numberItems - * @memberof dc.selectMenu - * @instance - * @param {?number} [numberVisible=null] - * @example - * chart.numberVisible(10); - **/ - _chart.numberVisible = function (numberVisible) { - if (!arguments.length) { - return _numberVisible; - } - _numberVisible = numberVisible; - - return _chart; - }; - - _chart.size = dc.logger.deprecate(_chart.numberVisible, 'selectMenu.size is ambiguous - use numberVisible instead'); - - return _chart.anchor(parent, chartGroup); -}; - -// Renamed functions - -dc.abstractBubbleChart = dc.bubbleMixin; -dc.baseChart = dc.baseMixin; -dc.capped = dc.capMixin; -dc.colorChart = dc.colorMixin; -dc.coordinateGridChart = dc.coordinateGridMixin; -dc.marginable = dc.marginMixin; -dc.stackableChart = dc.stackMixin; - -// Expose d3 and crossfilter, so that clients in browserify -// case can obtain them if they need them. -dc.d3 = d3; -dc.crossfilter = crossfilter; - -return dc;} - if(typeof define === "function" && define.amd) { - define(["d3", "crossfilter"], _dc); - } else if(typeof module === "object" && module.exports) { - var _d3 = require('d3'); - var _crossfilter = require('crossfilter2'); - // When using npm + browserify, 'crossfilter' is a function, - // since package.json specifies index.js as main function, and it - // does special handling. When using bower + browserify, - // there's no main in bower.json (in fact, there's no bower.json), - // so we need to fix it. - if (typeof _crossfilter !== "function") { - _crossfilter = _crossfilter.crossfilter; - } - module.exports = _dc(_d3, _crossfilter); - } else { - this.dc = _dc(d3, crossfilter); - } -} -)(); - -//# sourceMappingURL=dc.js.map \ No newline at end of file diff --git a/dc.js.map b/dc.js.map deleted file mode 100644 index 0577b70546..0000000000 --- a/dc.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["src/banner.js","src/core.js","src/errors.js","src/utils.js","src/logger.js","src/events.js","src/filters.js","src/base-mixin.js","src/margin-mixin.js","src/color-mixin.js","src/coordinate-grid-mixin.js","src/stack-mixin.js","src/cap-mixin.js","src/bubble-mixin.js","src/pie-chart.js","src/bar-chart.js","src/line-chart.js","src/data-count.js","src/data-table.js","src/data-grid.js","src/bubble-chart.js","src/composite-chart.js","src/series-chart.js","src/geo-choropleth-chart.js","src/bubble-overlay.js","src/row-chart.js","src/legend.js","src/scatter-plot.js","src/number-display.js","src/heatmap.js","src/d3.box.js","src/box-plot.js","src/select-menu.js","src/footer.js"],"names":[],"mappings":"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","file":"dc.js","sourcesContent":["(function() { function _dc(d3, crossfilter) {\n'use strict';\n","/**\n * The entire dc.js library is scoped under the **dc** name space. It does not introduce\n * anything else into the global name space.\n *\n * Most `dc` functions are designed to allow function chaining, meaning they return the current chart\n * instance whenever it is appropriate. The getter forms of functions do not participate in function\n * chaining because they return values that are not the chart, although some,\n * such as {@link dc.baseMixin#svg .svg} and {@link dc.coordinateGridMixin#xAxis .xAxis},\n * return values that are themselves chainable d3 objects.\n * @namespace dc\n * @version 2.1.0-dev\n * @example\n * // Example chaining\n * chart.width(300)\n * .height(300)\n * .filter('sunday');\n */\n/*jshint -W079*/\nvar dc = {\n version: '2.1.0-dev',\n constants: {\n CHART_CLASS: 'dc-chart',\n DEBUG_GROUP_CLASS: 'debug',\n STACK_CLASS: 'stack',\n DESELECTED_CLASS: 'deselected',\n SELECTED_CLASS: 'selected',\n NODE_INDEX_NAME: '__index__',\n GROUP_INDEX_NAME: '__group_index__',\n DEFAULT_CHART_GROUP: '__default_chart_group__',\n EVENT_DELAY: 40,\n NEGLIGIBLE_NUMBER: 1e-10\n },\n _renderlet: null\n};\n/*jshint +W079*/\n\n/**\n * The dc.chartRegistry object maintains sets of all instantiated dc.js charts under named groups\n * and the default group.\n *\n * A chart group often corresponds to a crossfilter instance. It specifies\n * the set of charts which should be updated when a filter changes on one of the charts or when the\n * global functions {@link dc.filterAll dc.filterAll}, {@link dc.refocusAll dc.refocusAll},\n * {@link dc.renderAll dc.renderAll}, {@link dc.redrawAll dc.redrawAll}, or chart functions\n * {@link dc.baseMixin#renderGroup baseMixin.renderGroup},\n * {@link dc.baseMixin#redrawGroup baseMixin.redrawGroup} are called.\n *\n * @namespace chartRegistry\n * @memberof dc\n * @type {{has, register, deregister, clear, list}}\n */\ndc.chartRegistry = (function () {\n // chartGroup:string => charts:array\n var _chartMap = {};\n\n function initializeChartGroup (group) {\n if (!group) {\n group = dc.constants.DEFAULT_CHART_GROUP;\n }\n\n if (!_chartMap[group]) {\n _chartMap[group] = [];\n }\n\n return group;\n }\n\n return {\n /**\n * Determine if a given chart instance resides in any group in the registry.\n * @method has\n * @memberof dc.chartRegistry\n * @param {Object} chart dc.js chart instance\n * @returns {Boolean}\n */\n has: function (chart) {\n for (var e in _chartMap) {\n if (_chartMap[e].indexOf(chart) >= 0) {\n return true;\n }\n }\n return false;\n },\n\n /**\n * Add given chart instance to the given group, creating the group if necessary.\n * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used.\n * @method register\n * @memberof dc.chartRegistry\n * @param {Object} chart dc.js chart instance\n * @param {String} [group] Group name\n */\n register: function (chart, group) {\n group = initializeChartGroup(group);\n _chartMap[group].push(chart);\n },\n\n /**\n * Remove given chart instance from the given group, creating the group if necessary.\n * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used.\n * @method deregister\n * @memberof dc.chartRegistry\n * @param {Object} chart dc.js chart instance\n * @param {String} [group] Group name\n */\n deregister: function (chart, group) {\n group = initializeChartGroup(group);\n for (var i = 0; i < _chartMap[group].length; i++) {\n if (_chartMap[group][i].anchorName() === chart.anchorName()) {\n _chartMap[group].splice(i, 1);\n break;\n }\n }\n },\n\n /**\n * Clear given group if one is provided, otherwise clears all groups.\n * @method clear\n * @memberof dc.chartRegistry\n * @param {String} group Group name\n */\n clear: function (group) {\n if (group) {\n delete _chartMap[group];\n } else {\n _chartMap = {};\n }\n },\n\n /**\n * Get an array of each chart instance in the given group.\n * If no group is provided, the charts in the default group are returned.\n * @method list\n * @memberof dc.chartRegistry\n * @param {String} [group] Group name\n * @returns {Array}\n */\n list: function (group) {\n group = initializeChartGroup(group);\n return _chartMap[group];\n }\n };\n})();\n\n/**\n * Add given chart instance to the given group, creating the group if necessary.\n * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used.\n * @memberof dc\n * @method registerChart\n * @param {Object} chart dc.js chart instance\n * @param {String} [group] Group name\n */\ndc.registerChart = function (chart, group) {\n dc.chartRegistry.register(chart, group);\n};\n\n/**\n * Remove given chart instance from the given group, creating the group if necessary.\n * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used.\n * @memberof dc\n * @method deregisterChart\n * @param {Object} chart dc.js chart instance\n * @param {String} [group] Group name\n */\ndc.deregisterChart = function (chart, group) {\n dc.chartRegistry.deregister(chart, group);\n};\n\n/**\n * Determine if a given chart instance resides in any group in the registry.\n * @memberof dc\n * @method hasChart\n * @param {Object} chart dc.js chart instance\n * @returns {Boolean}\n */\ndc.hasChart = function (chart) {\n return dc.chartRegistry.has(chart);\n};\n\n/**\n * Clear given group if one is provided, otherwise clears all groups.\n * @memberof dc\n * @method deregisterAllCharts\n * @param {String} group Group name\n */\ndc.deregisterAllCharts = function (group) {\n dc.chartRegistry.clear(group);\n};\n\n/**\n * Clear all filters on all charts within the given chart group. If the chart group is not given then\n * only charts that belong to the default chart group will be reset.\n * @memberof dc\n * @method filterAll\n * @param {String} [group]\n */\ndc.filterAll = function (group) {\n var charts = dc.chartRegistry.list(group);\n for (var i = 0; i < charts.length; ++i) {\n charts[i].filterAll();\n }\n};\n\n/**\n * Reset zoom level / focus on all charts that belong to the given chart group. If the chart group is\n * not given then only charts that belong to the default chart group will be reset.\n * @memberof dc\n * @method refocusAll\n * @param {String} [group]\n */\ndc.refocusAll = function (group) {\n var charts = dc.chartRegistry.list(group);\n for (var i = 0; i < charts.length; ++i) {\n if (charts[i].focus) {\n charts[i].focus();\n }\n }\n};\n\n/**\n * Re-render all charts belong to the given chart group. If the chart group is not given then only\n * charts that belong to the default chart group will be re-rendered.\n * @memberof dc\n * @method renderAll\n * @param {String} [group]\n */\ndc.renderAll = function (group) {\n var charts = dc.chartRegistry.list(group);\n for (var i = 0; i < charts.length; ++i) {\n charts[i].render();\n }\n\n if (dc._renderlet !== null) {\n dc._renderlet(group);\n }\n};\n\n/**\n * Redraw all charts belong to the given chart group. If the chart group is not given then only charts\n * that belong to the default chart group will be re-drawn. Redraw is different from re-render since\n * when redrawing dc tries to update the graphic incrementally, using transitions, instead of starting\n * from scratch.\n * @memberof dc\n * @method redrawAll\n * @param {String} [group]\n */\ndc.redrawAll = function (group) {\n var charts = dc.chartRegistry.list(group);\n for (var i = 0; i < charts.length; ++i) {\n charts[i].redraw();\n }\n\n if (dc._renderlet !== null) {\n dc._renderlet(group);\n }\n};\n\n/**\n * If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen\n * immediately\n * @memberof dc\n * @method disableTransitions\n * @type {Boolean}\n * @default false\n */\ndc.disableTransitions = false;\n\ndc.transition = function (selections, duration, callback, name) {\n if (duration <= 0 || duration === undefined || dc.disableTransitions) {\n return selections;\n }\n\n var s = selections\n .transition(name)\n .duration(duration);\n\n if (typeof(callback) === 'function') {\n callback(s);\n }\n\n return s;\n};\n\n/* somewhat silly, but to avoid duplicating logic */\ndc.optionalTransition = function (enable, duration, callback, name) {\n if (enable) {\n return function (selection) {\n return dc.transition(selection, duration, callback, name);\n };\n } else {\n return function (selection) {\n return selection;\n };\n }\n};\n\n// See http://stackoverflow.com/a/20773846\ndc.afterTransition = function (transition, callback) {\n if (transition.empty() || !transition.duration) {\n callback.call(transition);\n } else {\n var n = 0;\n transition\n .each(function () { ++n; })\n .each('end', function () {\n if (!--n) {\n callback.call(transition);\n }\n });\n }\n};\n\n/**\n * @namespace units\n * @memberof dc\n * @type {{}}\n */\ndc.units = {};\n\n/**\n * The default value for {@link dc.coordinateGridMixin#xUnits .xUnits} for the\n * {@link dc.coordinateGridMixin Coordinate Grid Chart} and should\n * be used when the x values are a sequence of integers.\n * It is a function that counts the number of integers in the range supplied in its start and end parameters.\n * @method integers\n * @memberof dc.units\n * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits}\n * @example\n * chart.xUnits(dc.units.integers) // already the default\n * @param {Number} start\n * @param {Number} end\n * @return {Number}\n */\ndc.units.integers = function (start, end) {\n return Math.abs(end - start);\n};\n\n/**\n * This argument can be passed to the {@link dc.coordinateGridMixin#xUnits .xUnits} function of the to\n * specify ordinal units for the x axis. Usually this parameter is used in combination with passing\n * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales d3.scale.ordinal} to\n * {@link dc.coordinateGridMixin#x .x}.\n * It just returns the domain passed to it, which for ordinal charts is an array of all values.\n * @method ordinal\n * @memberof dc.units\n * @see {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales d3.scale.ordinal}\n * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits}\n * @see {@link dc.coordinateGridMixin#x coordinateGridMixin.x}\n * @example\n * chart.xUnits(dc.units.ordinal)\n * .x(d3.scale.ordinal())\n * @param {*} start\n * @param {*} end\n * @param {Array} domain\n * @return {Array}\n */\ndc.units.ordinal = function (start, end, domain) {\n return domain;\n};\n\n/**\n * @namespace fp\n * @memberof dc.units\n * @type {{}}\n */\ndc.units.fp = {};\n/**\n * This function generates an argument for the {@link dc.coordinateGridMixin Coordinate Grid Chart}\n * {@link dc.coordinateGridMixin#xUnits .xUnits} function specifying that the x values are floating-point\n * numbers with the given precision.\n * The returned function determines how many values at the given precision will fit into the range\n * supplied in its start and end parameters.\n * @method precision\n * @memberof dc.units.fp\n * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits}\n * @example\n * // specify values (and ticks) every 0.1 units\n * chart.xUnits(dc.units.fp.precision(0.1)\n * // there are 500 units between 0.5 and 1 if the precision is 0.001\n * var thousandths = dc.units.fp.precision(0.001);\n * thousandths(0.5, 1.0) // returns 500\n * @param {Number} precision\n * @return {Function} start-end unit function\n */\ndc.units.fp.precision = function (precision) {\n var _f = function (s, e) {\n var d = Math.abs((e - s) / _f.resolution);\n if (dc.utils.isNegligible(d - Math.floor(d))) {\n return Math.floor(d);\n } else {\n return Math.ceil(d);\n }\n };\n _f.resolution = precision;\n return _f;\n};\n\ndc.round = {};\ndc.round.floor = function (n) {\n return Math.floor(n);\n};\ndc.round.ceil = function (n) {\n return Math.ceil(n);\n};\ndc.round.round = function (n) {\n return Math.round(n);\n};\n\ndc.override = function (obj, functionName, newFunction) {\n var existingFunction = obj[functionName];\n obj['_' + functionName] = existingFunction;\n obj[functionName] = newFunction;\n};\n\ndc.renderlet = function (_) {\n if (!arguments.length) {\n return dc._renderlet;\n }\n dc._renderlet = _;\n return dc;\n};\n\ndc.instanceOfChart = function (o) {\n return o instanceof Object && o.__dcFlag__ && true;\n};\n","dc.errors = {};\n\ndc.errors.Exception = function (msg) {\n var _msg = msg || 'Unexpected internal error';\n\n this.message = _msg;\n\n this.toString = function () {\n return _msg;\n };\n this.stack = (new Error()).stack;\n};\ndc.errors.Exception.prototype = Object.create(Error.prototype);\ndc.errors.Exception.prototype.constructor = dc.errors.Exception;\n\ndc.errors.InvalidStateException = function () {\n dc.errors.Exception.apply(this, arguments);\n};\n\ndc.errors.InvalidStateException.prototype = Object.create(dc.errors.Exception.prototype);\ndc.errors.InvalidStateException.prototype.constructor = dc.errors.InvalidStateException;\n\ndc.errors.BadArgumentException = function () {\n dc.errors.Exception.apply(this, arguments);\n};\n\ndc.errors.BadArgumentException.prototype = Object.create(dc.errors.Exception.prototype);\ndc.errors.BadArgumentException.prototype.constructor = dc.errors.BadArgumentException;\n","/**\n * The default date format for dc.js\n * @name dateFormat\n * @memberof dc\n * @type {Function}\n * @default d3.time.format('%m/%d/%Y')\n */\ndc.dateFormat = d3.time.format('%m/%d/%Y');\n\n/**\n * @namespace printers\n * @memberof dc\n * @type {{}}\n */\ndc.printers = {};\n\n/**\n * Converts a list of filters into a readable string\n * @method filters\n * @memberof dc.printers\n * @param {Array} filters\n * @returns {String}\n */\ndc.printers.filters = function (filters) {\n var s = '';\n\n for (var i = 0; i < filters.length; ++i) {\n if (i > 0) {\n s += ', ';\n }\n s += dc.printers.filter(filters[i]);\n }\n\n return s;\n};\n\n/**\n * Converts a filter into a readable string\n * @method filter\n * @memberof dc.printers\n * @param {dc.filters|any|Array} filter\n * @returns {String}\n */\ndc.printers.filter = function (filter) {\n var s = '';\n\n if (typeof filter !== 'undefined' && filter !== null) {\n if (filter instanceof Array) {\n if (filter.length >= 2) {\n s = '[' + dc.utils.printSingleValue(filter[0]) + ' -> ' + dc.utils.printSingleValue(filter[1]) + ']';\n } else if (filter.length >= 1) {\n s = dc.utils.printSingleValue(filter[0]);\n }\n } else {\n s = dc.utils.printSingleValue(filter);\n }\n }\n\n return s;\n};\n\n/**\n * Returns a function that given a string property name, can be used to pluck the property off an object. A function\n * can be passed as the second argument to also alter the data being returned. This can be a useful shorthand method to create\n * accessor functions.\n * @method pluck\n * @memberof dc\n * @example\n * var xPluck = dc.pluck('x');\n * var objA = {x: 1};\n * xPluck(objA) // 1\n * @example\n * var xPosition = dc.pluck('x', function (x, i) {\n * // `this` is the original datum,\n * // `x` is the x property of the datum,\n * // `i` is the position in the array\n * return this.radius + x;\n * });\n * dc.selectAll('.circle').data(...).x(xPosition);\n * @param {String} n\n * @param {Function} [f]\n * @returns {Function}\n */\ndc.pluck = function (n, f) {\n if (!f) {\n return function (d) { return d[n]; };\n }\n return function (d, i) { return f.call(d, d[n], i); };\n};\n\n/**\n * @namespace utils\n * @memberof dc\n * @type {{}}\n */\ndc.utils = {};\n\n/**\n * Print a single value filter\n * @method printSingleValue\n * @memberof dc.utils\n * @param {any} filter\n * @returns {String}\n */\ndc.utils.printSingleValue = function (filter) {\n var s = '' + filter;\n\n if (filter instanceof Date) {\n s = dc.dateFormat(filter);\n } else if (typeof(filter) === 'string') {\n s = filter;\n } else if (dc.utils.isFloat(filter)) {\n s = dc.utils.printSingleValue.fformat(filter);\n } else if (dc.utils.isInteger(filter)) {\n s = Math.round(filter);\n }\n\n return s;\n};\ndc.utils.printSingleValue.fformat = d3.format('.2f');\n\n/**\n * Arbitrary add one value to another.\n * @method add\n * @memberof dc.utils\n * @todo\n * These assume than any string r is a percentage (whether or not it includes %).\n * They also generate strange results if l is a string.\n * @param {String|Date|Number} l\n * @param {Number} r\n * @returns {String|Date|Number}\n */\ndc.utils.add = function (l, r) {\n if (typeof r === 'string') {\n r = r.replace('%', '');\n }\n\n if (l instanceof Date) {\n if (typeof r === 'string') {\n r = +r;\n }\n var d = new Date();\n d.setTime(l.getTime());\n d.setDate(l.getDate() + r);\n return d;\n } else if (typeof r === 'string') {\n var percentage = (+r / 100);\n return l > 0 ? l * (1 + percentage) : l * (1 - percentage);\n } else {\n return l + r;\n }\n};\n\n/**\n * Arbitrary subtract one value from another.\n * @method subtract\n * @memberof dc.utils\n * @todo\n * These assume than any string r is a percentage (whether or not it includes %).\n * They also generate strange results if l is a string.\n * @param {String|Date|Number} l\n * @param {Number} r\n * @returns {String|Date|Number}\n */\ndc.utils.subtract = function (l, r) {\n if (typeof r === 'string') {\n r = r.replace('%', '');\n }\n\n if (l instanceof Date) {\n if (typeof r === 'string') {\n r = +r;\n }\n var d = new Date();\n d.setTime(l.getTime());\n d.setDate(l.getDate() - r);\n return d;\n } else if (typeof r === 'string') {\n var percentage = (+r / 100);\n return l < 0 ? l * (1 + percentage) : l * (1 - percentage);\n } else {\n return l - r;\n }\n};\n\n/**\n * Is the value a number?\n * @method isNumber\n * @memberof dc.utils\n * @param {any} n\n * @returns {Boolean}\n */\ndc.utils.isNumber = function (n) {\n return n === +n;\n};\n\n/**\n * Is the value a float?\n * @method isFloat\n * @memberof dc.utils\n * @param {any} n\n * @returns {Boolean}\n */\ndc.utils.isFloat = function (n) {\n return n === +n && n !== (n | 0);\n};\n\n/**\n * Is the value an integer?\n * @method isInteger\n * @memberof dc.utils\n * @param {any} n\n * @returns {Boolean}\n */\ndc.utils.isInteger = function (n) {\n return n === +n && n === (n | 0);\n};\n\n/**\n * Is the value very close to zero?\n * @method isNegligible\n * @memberof dc.utils\n * @param {any} n\n * @returns {Boolean}\n */\ndc.utils.isNegligible = function (n) {\n return !dc.utils.isNumber(n) || (n < dc.constants.NEGLIGIBLE_NUMBER && n > -dc.constants.NEGLIGIBLE_NUMBER);\n};\n\n/**\n * Ensure the value is no greater or less than the min/max values. If it is return the boundary value.\n * @method clamp\n * @memberof dc.utils\n * @param {any} val\n * @param {any} min\n * @param {any} max\n * @returns {any}\n */\ndc.utils.clamp = function (val, min, max) {\n return val < min ? min : (val > max ? max : val);\n};\n\n/**\n * Using a simple static counter, provide a unique integer id.\n * @method uniqueId\n * @memberof dc.utils\n * @returns {Number}\n */\nvar _idCounter = 0;\ndc.utils.uniqueId = function () {\n return ++_idCounter;\n};\n\n/**\n * Convert a name to an ID.\n * @method nameToId\n * @memberof dc.utils\n * @param {String} name\n * @returns {String}\n */\ndc.utils.nameToId = function (name) {\n return name.toLowerCase().replace(/[\\s]/g, '_').replace(/[\\.']/g, '');\n};\n\n/**\n * Append or select an item on a parent element\n * @method appendOrSelect\n * @memberof dc.utils\n * @param {d3.selection} parent\n * @param {String} selector\n * @param {String} tag\n * @returns {d3.selection}\n */\ndc.utils.appendOrSelect = function (parent, selector, tag) {\n tag = tag || selector;\n var element = parent.select(selector);\n if (element.empty()) {\n element = parent.append(tag);\n }\n return element;\n};\n\n/**\n * Return the number if the value is a number; else 0.\n * @method safeNumber\n * @memberof dc.utils\n * @param {Number|any} n\n * @returns {Number}\n */\ndc.utils.safeNumber = function (n) { return dc.utils.isNumber(+n) ? +n : 0;};\n","dc.logger = {};\n\ndc.logger.enableDebugLog = false;\n\ndc.logger.warn = function (msg) {\n if (console) {\n if (console.warn) {\n console.warn(msg);\n } else if (console.log) {\n console.log(msg);\n }\n }\n\n return dc.logger;\n};\n\ndc.logger.debug = function (msg) {\n if (dc.logger.enableDebugLog && console) {\n if (console.debug) {\n console.debug(msg);\n } else if (console.log) {\n console.log(msg);\n }\n }\n\n return dc.logger;\n};\n\ndc.logger.deprecate = function (fn, msg) {\n // Allow logging of deprecation\n var warned = false;\n function deprecated () {\n if (!warned) {\n dc.logger.warn(msg);\n warned = true;\n }\n return fn.apply(this, arguments);\n }\n return deprecated;\n};\n","dc.events = {\n current: null\n};\n\n/**\n * This function triggers a throttled event function with a specified delay (in milli-seconds). Events\n * that are triggered repetitively due to user interaction such brush dragging might flood the library\n * and invoke more renders than can be executed in time. Using this function to wrap your event\n * function allows the library to smooth out the rendering by throttling events and only responding to\n * the most recent event.\n * @name events.trigger\n * @memberof dc\n * @example\n * chart.on('renderlet', function(chart) {\n * // smooth the rendering through event throttling\n * dc.events.trigger(function(){\n * // focus some other chart to the range selected by user on this chart\n * someOtherChart.focus(chart.filter());\n * });\n * })\n * @param {Function} closure\n * @param {Number} [delay]\n */\ndc.events.trigger = function (closure, delay) {\n if (!delay) {\n closure();\n return;\n }\n\n dc.events.current = closure;\n\n setTimeout(function () {\n if (closure === dc.events.current) {\n closure();\n }\n }, delay);\n};\n","/**\n * The dc.js filters are functions which are passed into crossfilter to chose which records will be\n * accumulated to produce values for the charts. In the crossfilter model, any filters applied on one\n * dimension will affect all the other dimensions but not that one. dc always applies a filter\n * function to the dimension; the function combines multiple filters and if any of them accept a\n * record, it is filtered in.\n *\n * These filter constructors are used as appropriate by the various charts to implement brushing. We\n * mention below which chart uses which filter. In some cases, many instances of a filter will be added.\n *\n * Each of the dc.js filters is an object with the following properties:\n * * `isFiltered` - a function that returns true if a value is within the filter\n * * `filterType` - a string identifying the filter, here the name of the constructor\n *\n * Currently these filter objects are also arrays, but this is not a requirement. Custom filters\n * can be used as long as they have the properties above.\n * @namespace filters\n * @memberof dc\n * @type {{}}\n */\ndc.filters = {};\n\n/**\n * RangedFilter is a filter which accepts keys between `low` and `high`. It is used to implement X\n * axis brushing for the {@link dc.coordinateGridMixin coordinate grid charts}.\n *\n * Its `filterType` is 'RangedFilter'\n * @name RangedFilter\n * @memberof dc.filters\n * @param {Number} low\n * @param {Number} high\n * @return {Array}\n * @constructor\n */\ndc.filters.RangedFilter = function (low, high) {\n var range = new Array(low, high);\n range.isFiltered = function (value) {\n return value >= this[0] && value < this[1];\n };\n range.filterType = 'RangedFilter';\n\n return range;\n};\n\n/**\n * TwoDimensionalFilter is a filter which accepts a single two-dimensional value. It is used by the\n * {@link dc.heatMap heat map chart} to include particular cells as they are clicked. (Rows and columns are\n * filtered by filtering all the cells in the row or column.)\n *\n * Its `filterType` is 'TwoDimensionalFilter'\n * @name TwoDimensionalFilter\n * @memberof dc.filters\n * @param {Array} filter\n * @return {Array}\n * @constructor\n */\ndc.filters.TwoDimensionalFilter = function (filter) {\n if (filter === null) { return null; }\n\n var f = filter;\n f.isFiltered = function (value) {\n return value.length && value.length === f.length &&\n value[0] === f[0] && value[1] === f[1];\n };\n f.filterType = 'TwoDimensionalFilter';\n\n return f;\n};\n\n/**\n * The RangedTwoDimensionalFilter allows filtering all values which fit within a rectangular\n * region. It is used by the {@link dc.scatterPlot scatter plot} to implement rectangular brushing.\n *\n * It takes two two-dimensional points in the form `[[x1,y1],[x2,y2]]`, and normalizes them so that\n * `x1 <= x2` and `y1 <= y2`. It then returns a filter which accepts any points which are in the\n * rectangular range including the lower values but excluding the higher values.\n *\n * If an array of two values are given to the RangedTwoDimensionalFilter, it interprets the values as\n * two x coordinates `x1` and `x2` and returns a filter which accepts any points for which `x1 <= x <\n * x2`.\n *\n * Its `filterType` is 'RangedTwoDimensionalFilter'\n * @name RangedTwoDimensionalFilter\n * @memberof dc.filters\n * @param {Array>} filter\n * @return {Array>}\n * @constructor\n */\ndc.filters.RangedTwoDimensionalFilter = function (filter) {\n if (filter === null) { return null; }\n\n var f = filter;\n var fromBottomLeft;\n\n if (f[0] instanceof Array) {\n fromBottomLeft = [\n [Math.min(filter[0][0], filter[1][0]), Math.min(filter[0][1], filter[1][1])],\n [Math.max(filter[0][0], filter[1][0]), Math.max(filter[0][1], filter[1][1])]\n ];\n } else {\n fromBottomLeft = [[filter[0], -Infinity], [filter[1], Infinity]];\n }\n\n f.isFiltered = function (value) {\n var x, y;\n\n if (value instanceof Array) {\n if (value.length !== 2) {\n return false;\n }\n x = value[0];\n y = value[1];\n } else {\n x = value;\n y = fromBottomLeft[0][1];\n }\n\n return x >= fromBottomLeft[0][0] && x < fromBottomLeft[1][0] &&\n y >= fromBottomLeft[0][1] && y < fromBottomLeft[1][1];\n };\n f.filterType = 'RangedTwoDimensionalFilter';\n\n return f;\n};\n","/**\n * `dc.baseMixin` is an abstract functional object representing a basic `dc` chart object\n * for all chart and widget implementations. Methods from the {@link #dc.baseMixin dc.baseMixin} are inherited\n * and available on all chart implementations in the `dc` library.\n * @name baseMixin\n * @memberof dc\n * @mixin\n * @param {Object} _chart\n * @return {dc.baseMixin}\n */\ndc.baseMixin = function (_chart) {\n _chart.__dcFlag__ = dc.utils.uniqueId();\n\n var _dimension;\n var _group;\n\n var _anchor;\n var _root;\n var _svg;\n var _isChild;\n\n var _minWidth = 200;\n var _defaultWidthCalc = function (element) {\n var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width;\n return (width && width > _minWidth) ? width : _minWidth;\n };\n var _widthCalc = _defaultWidthCalc;\n\n var _minHeight = 200;\n var _defaultHeightCalc = function (element) {\n var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height;\n return (height && height > _minHeight) ? height : _minHeight;\n };\n var _heightCalc = _defaultHeightCalc;\n var _width, _height;\n\n var _keyAccessor = dc.pluck('key');\n var _valueAccessor = dc.pluck('value');\n var _label = dc.pluck('key');\n\n var _ordering = dc.pluck('key');\n var _orderSort;\n\n var _renderLabel = false;\n\n var _title = function (d) {\n return _chart.keyAccessor()(d) + ': ' + _chart.valueAccessor()(d);\n };\n var _renderTitle = true;\n var _controlsUseVisibility = false;\n\n var _transitionDuration = 750;\n\n var _filterPrinter = dc.printers.filters;\n\n var _mandatoryAttributes = ['dimension', 'group'];\n\n var _chartGroup = dc.constants.DEFAULT_CHART_GROUP;\n\n var _listeners = d3.dispatch(\n 'preRender',\n 'postRender',\n 'preRedraw',\n 'postRedraw',\n 'filtered',\n 'zoomed',\n 'renderlet',\n 'pretransition');\n\n var _legend;\n var _commitHandler;\n\n var _filters = [];\n var _filterHandler = function (dimension, filters) {\n if (filters.length === 0) {\n dimension.filter(null);\n } else if (filters.length === 1 && !filters[0].isFiltered) {\n // single value and not a function-based filter\n dimension.filterExact(filters[0]);\n } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') {\n // single range-based filter\n dimension.filterRange(filters[0]);\n } else {\n dimension.filterFunction(function (d) {\n for (var i = 0; i < filters.length; i++) {\n var filter = filters[i];\n if (filter.isFiltered && filter.isFiltered(d)) {\n return true;\n } else if (filter <= d && filter >= d) {\n return true;\n }\n }\n return false;\n });\n }\n return filters;\n };\n\n var _data = function (group) {\n return group.all();\n };\n\n /**\n * Set or get the height attribute of a chart. The height is applied to the SVGElement generated by\n * the chart when rendered (or re-rendered). If a value is given, then it will be used to calculate\n * the new height and the chart returned for method chaining. The value can either be a numeric, a\n * function, or falsy. If no value is specified then the value of the current height attribute will\n * be returned.\n *\n * By default, without an explicit height being given, the chart will select the width of its\n * anchor element. If that isn't possible it defaults to 200 (provided by the\n * {@link dc.baseMixin#minHeight minHeight} property). Setting the value falsy will return\n * the chart to the default behavior.\n * @method height\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#minHeight minHeight}\n * @example\n * // Default height\n * chart.height(function (element) {\n * var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height;\n * return (height && height > chart.minHeight()) ? height : chart.minHeight();\n * });\n *\n * chart.height(250); // Set the chart's height to 250px;\n * chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function\n * chart.height(null); // reset the height to the default auto calculation\n * @param {Number|Function} [height]\n * @return {Number}\n * @return {dc.baseMixin}\n */\n _chart.height = function (height) {\n if (!arguments.length) {\n if (!dc.utils.isNumber(_height)) {\n // only calculate once\n _height = _heightCalc(_root.node());\n }\n return _height;\n }\n _heightCalc = d3.functor(height || _defaultHeightCalc);\n _height = undefined;\n return _chart;\n };\n\n /**\n * Set or get the width attribute of a chart.\n * @method width\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#height height}\n * @see {@link dc.baseMixin#minWidth minWidth}\n * @example\n * // Default width\n * chart.width(function (element) {\n * var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width;\n * return (width && width > chart.minWidth()) ? width : chart.minWidth();\n * });\n * @param {Number|Function} [width]\n * @return {Number}\n * @return {dc.baseMixin}\n */\n _chart.width = function (width) {\n if (!arguments.length) {\n if (!dc.utils.isNumber(_width)) {\n // only calculate once\n _width = _widthCalc(_root.node());\n }\n return _width;\n }\n _widthCalc = d3.functor(width || _defaultWidthCalc);\n _width = undefined;\n return _chart;\n };\n\n /**\n * Set or get the minimum width attribute of a chart. This only has effect when used with the default\n * {@link dc.baseMixin#width width} function.\n * @method minWidth\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#width width}\n * @param {Number} [minWidth=200]\n * @return {Number}\n * @return {dc.baseMixin}\n */\n _chart.minWidth = function (minWidth) {\n if (!arguments.length) {\n return _minWidth;\n }\n _minWidth = minWidth;\n return _chart;\n };\n\n /**\n * Set or get the minimum height attribute of a chart. This only has effect when used with the default\n * {@link dc.baseMixin#height height} function.\n * @method minHeight\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#height height}\n * @param {Number} [minHeight=200]\n * @return {Number}\n * @return {dc.baseMixin}\n */\n _chart.minHeight = function (minHeight) {\n if (!arguments.length) {\n return _minHeight;\n }\n _minHeight = minHeight;\n return _chart;\n };\n\n /**\n * **mandatory**\n *\n * Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid [crossfilter\n * dimension](https://github.com/square/crossfilter/wiki/API-Reference#wiki-dimension).\n *\n * If a value is given, then it will be used as the new dimension. If no value is specified then\n * the current dimension will be returned.\n * @method dimension\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension crossfilter.dimension}\n * @example\n * var index = crossfilter([]);\n * var dimension = index.dimension(dc.pluck('key'));\n * chart.dimension(dimension);\n * @param {crossfilter.dimension} [dimension]\n * @return {crossfilter.dimension}\n * @return {dc.baseMixin}\n */\n _chart.dimension = function (dimension) {\n if (!arguments.length) {\n return _dimension;\n }\n _dimension = dimension;\n _chart.expireCache();\n return _chart;\n };\n\n /**\n * Set the data callback or retrieve the chart's data set. The data callback is passed the chart's\n * group and by default will return\n * {@link https://github.com/square/crossfilter/wiki/API-Reference#group_all group.all}.\n * This behavior may be modified to, for instance, return only the top 5 groups.\n * @method data\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // Default data function\n * chart.data(function (group) { return group.all(); });\n *\n * chart.data(function (group) { return group.top(5); });\n * @param {Function} [callback]\n * @return {*}\n * @return {dc.baseMixin}\n */\n _chart.data = function (callback) {\n if (!arguments.length) {\n return _data.call(_chart, _group);\n }\n _data = d3.functor(callback);\n _chart.expireCache();\n return _chart;\n };\n\n /**\n * **mandatory**\n *\n * Set or get the group attribute of a chart. In `dc` a group is a\n * {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter group}.\n * Usually the group should be created from the particular dimension associated with the same chart. If a value is\n * given, then it will be used as the new group.\n *\n * If no value specified then the current group will be returned.\n * If `name` is specified then it will be used to generate legend label.\n * @method group\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group}\n * @example\n * var index = crossfilter([]);\n * var dimension = index.dimension(dc.pluck('key'));\n * chart.dimension(dimension);\n * chart.group(dimension.group(crossfilter.reduceSum()));\n * @param {crossfilter.group} [group]\n * @param {String} [name]\n * @return {crossfilter.group}\n * @return {dc.baseMixin}\n */\n _chart.group = function (group, name) {\n if (!arguments.length) {\n return _group;\n }\n _group = group;\n _chart._groupName = name;\n _chart.expireCache();\n return _chart;\n };\n\n /**\n * Get or set an accessor to order ordinal dimensions. The chart uses\n * {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by}\n * to sort elements; this accessor returns the value to order on.\n * @method ordering\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by}\n * @example\n * // Default ordering accessor\n * _chart.ordering(dc.pluck('key'));\n * @param {Function} [orderFunction]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.ordering = function (orderFunction) {\n if (!arguments.length) {\n return _ordering;\n }\n _ordering = orderFunction;\n _orderSort = crossfilter.quicksort.by(_ordering);\n _chart.expireCache();\n return _chart;\n };\n\n _chart._computeOrderedGroups = function (data) {\n var dataCopy = data.slice(0);\n\n if (dataCopy.length <= 1) {\n return dataCopy;\n }\n\n if (!_orderSort) {\n _orderSort = crossfilter.quicksort.by(_ordering);\n }\n\n return _orderSort(dataCopy, 0, dataCopy.length);\n };\n\n /**\n * Clear all filters associated with this chart\n *\n * The same can be achieved by calling {@link dc.baseMixin#filter chart.filter(null)}.\n * @method filterAll\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.filterAll = function () {\n return _chart.filter(null);\n };\n\n /**\n * Execute d3 single selection in the chart's scope using the given selector and return the d3\n * selection.\n *\n * This function is **not chainable** since it does not return a chart instance; however the d3\n * selection result can be chained to d3 function calls.\n * @method select\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection}\n * @example\n * // Similar to:\n * d3.select('#chart-id').select(selector);\n * @return {d3.selection}\n */\n _chart.select = function (s) {\n return _root.select(s);\n };\n\n /**\n * Execute in scope d3 selectAll using the given selector and return d3 selection result.\n *\n * This function is **not chainable** since it does not return a chart instance; however the d3\n * selection result can be chained to d3 function calls.\n * @method selectAll\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection}\n * @example\n * // Similar to:\n * d3.select('#chart-id').selectAll(selector);\n * @return {d3.selection}\n */\n _chart.selectAll = function (s) {\n return _root ? _root.selectAll(s) : null;\n };\n\n /**\n * Set the root SVGElement to either be an existing chart's root; or any valid [d3 single\n * selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom\n * block element such as a div; or a dom element or d3 selection. Optionally registers the chart\n * within the chartGroup. This class is called internally on chart initialization, but be called\n * again to relocate the chart. However, it will orphan any previously created SVGElements.\n * @method anchor\n * @memberof dc.baseMixin\n * @instance\n * @param {anchorChart|anchorSelector|anchorNode} [parent]\n * @param {String} [chartGroup]\n * @return {String|node|d3.selection}\n * @return {dc.baseMixin}\n */\n _chart.anchor = function (parent, chartGroup) {\n if (!arguments.length) {\n return _anchor;\n }\n if (dc.instanceOfChart(parent)) {\n _anchor = parent.anchor();\n _root = parent.root();\n _isChild = true;\n } else if (parent) {\n if (parent.select && parent.classed) { // detect d3 selection\n _anchor = parent.node();\n } else {\n _anchor = parent;\n }\n _root = d3.select(_anchor);\n _root.classed(dc.constants.CHART_CLASS, true);\n dc.registerChart(_chart, chartGroup);\n _isChild = false;\n } else {\n throw new dc.errors.BadArgumentException('parent must be defined');\n }\n _chartGroup = chartGroup;\n return _chart;\n };\n\n /**\n * Returns the DOM id for the chart's anchored location.\n * @method anchorName\n * @memberof dc.baseMixin\n * @instance\n * @return {String}\n */\n _chart.anchorName = function () {\n var a = _chart.anchor();\n if (a && a.id) {\n return a.id;\n }\n if (a && a.replace) {\n return a.replace('#', '');\n }\n return 'dc-chart' + _chart.chartID();\n };\n\n /**\n * Returns the root element where a chart resides. Usually it will be the parent div element where\n * the SVGElement was created. You can also pass in a new root element however this is usually handled by\n * dc internally. Resetting the root element on a chart outside of dc internals may have\n * unexpected consequences.\n * @method root\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement HTMLElement}\n * @param {HTMLElement} [rootElement]\n * @return {HTMLElement}\n * @return {dc.baseMixin}\n */\n _chart.root = function (rootElement) {\n if (!arguments.length) {\n return _root;\n }\n _root = rootElement;\n return _chart;\n };\n\n /**\n * Returns the top SVGElement for this specific chart. You can also pass in a new SVGElement,\n * however this is usually handled by dc internally. Resetting the SVGElement on a chart outside\n * of dc internals may have unexpected consequences.\n * @method svg\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement}\n * @param {SVGElement|d3.selection} [svgElement]\n * @return {SVGElement|d3.selection}\n * @return {dc.baseMixin}\n */\n _chart.svg = function (svgElement) {\n if (!arguments.length) {\n return _svg;\n }\n _svg = svgElement;\n return _chart;\n };\n\n /**\n * Remove the chart's SVGElements from the dom and recreate the container SVGElement.\n * @method resetSvg\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement}\n * @return {SVGElement}\n */\n _chart.resetSvg = function () {\n _chart.select('svg').remove();\n return generateSvg();\n };\n\n function sizeSvg () {\n if (_svg) {\n _svg\n .attr('width', _chart.width())\n .attr('height', _chart.height());\n }\n }\n\n function generateSvg () {\n _svg = _chart.root().append('svg');\n sizeSvg();\n return _svg;\n }\n\n /**\n * Set or get the filter printer function. The filter printer function is used to generate human\n * friendly text for filter value(s) associated with the chart instance. By default dc charts use a\n * default filter printer `dc.printers.filter` that provides simple printing support for both\n * single value and ranged filters.\n * @method filterPrinter\n * @memberof dc.baseMixin\n * @instance\n * @param {Function} [filterPrinterFunction=dc.printers.filter]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.filterPrinter = function (filterPrinterFunction) {\n if (!arguments.length) {\n return _filterPrinter;\n }\n _filterPrinter = filterPrinterFunction;\n return _chart;\n };\n\n /**\n * If set, use the `visibility` attribute instead of the `display` attribute for showing/hiding\n * chart reset and filter controls, for less disruption to the layout.\n * @method controlsUseVisibility\n * @memberof dc.baseMixin\n * @instance\n * @param {Boolean} [controlsUseVisibility=false]\n * @return {Boolean}\n * @return {dc.baseMixin}\n **/\n _chart.controlsUseVisibility = function (useVisibility) {\n if (!arguments.length) {\n return _controlsUseVisibility;\n }\n _controlsUseVisibility = useVisibility;\n return _chart;\n };\n\n /**\n * Turn on optional control elements within the root element. dc currently supports the\n * following html control elements.\n * * root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type\n * of control element is usually used to store a reset link to allow user to reset filter on a\n * certain chart. This element will be turned off automatically if the filter is cleared.\n * * root.selectAll('.filter') elements are turned on if the chart has an active filter. The text\n * content of this element is then replaced with the current filter value using the filter printer\n * function. This type of element will be turned off automatically if the filter is cleared.\n * @method turnOnControls\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.turnOnControls = function () {\n if (_root) {\n var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display';\n _chart.selectAll('.reset').style(attribute, null);\n _chart.selectAll('.filter').text(_filterPrinter(_chart.filters())).style(attribute, null);\n }\n return _chart;\n };\n\n /**\n * Turn off optional control elements within the root element.\n * @method turnOffControls\n * @memberof dc.baseMixin\n * @see {@link dc.baseMixin#turnOnControls turnOnControls}\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.turnOffControls = function () {\n if (_root) {\n var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display';\n var value = _chart.controlsUseVisibility() ? 'hidden' : 'none';\n _chart.selectAll('.reset').style(attribute, value);\n _chart.selectAll('.filter').style(attribute, value).text(_chart.filter());\n }\n return _chart;\n };\n\n /**\n * Set or get the animation transition duration (in milliseconds) for this chart instance.\n * @method transitionDuration\n * @memberof dc.baseMixin\n * @instance\n * @param {Number} [duration=750]\n * @return {Number}\n * @return {dc.baseMixin}\n */\n _chart.transitionDuration = function (duration) {\n if (!arguments.length) {\n return _transitionDuration;\n }\n _transitionDuration = duration;\n return _chart;\n };\n\n _chart._mandatoryAttributes = function (_) {\n if (!arguments.length) {\n return _mandatoryAttributes;\n }\n _mandatoryAttributes = _;\n return _chart;\n };\n\n function checkForMandatoryAttributes (a) {\n if (!_chart[a] || !_chart[a]()) {\n throw new dc.errors.InvalidStateException('Mandatory attribute chart.' + a +\n ' is missing on chart[#' + _chart.anchorName() + ']');\n }\n }\n\n /**\n * Invoking this method will force the chart to re-render everything from scratch. Generally it\n * should only be used to render the chart for the first time on the page or if you want to make\n * sure everything is redrawn from scratch instead of relying on the default incremental redrawing\n * behaviour.\n * @method render\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.render = function () {\n _height = _width = undefined; // force recalculate\n _listeners.preRender(_chart);\n\n if (_mandatoryAttributes) {\n _mandatoryAttributes.forEach(checkForMandatoryAttributes);\n }\n\n var result = _chart._doRender();\n\n if (_legend) {\n _legend.render();\n }\n\n _chart._activateRenderlets('postRender');\n\n return result;\n };\n\n _chart._activateRenderlets = function (event) {\n _listeners.pretransition(_chart);\n if (_chart.transitionDuration() > 0 && _svg) {\n _svg.transition().duration(_chart.transitionDuration())\n .each('end', function () {\n _listeners.renderlet(_chart);\n if (event) {\n _listeners[event](_chart);\n }\n });\n } else {\n _listeners.renderlet(_chart);\n if (event) {\n _listeners[event](_chart);\n }\n }\n };\n\n /**\n * Calling redraw will cause the chart to re-render data changes incrementally. If there is no\n * change in the underlying data dimension then calling this method will have no effect on the\n * chart. Most chart interaction in dc will automatically trigger this method through internal\n * events (in particular {@link dc.redrawAll dc.redrawAll}); therefore, you only need to\n * manually invoke this function if data is manipulated outside of dc's control (for example if\n * data is loaded in the background using\n * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add}.\n * @method redraw\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.redraw = function () {\n sizeSvg();\n _listeners.preRedraw(_chart);\n\n var result = _chart._doRedraw();\n\n if (_legend) {\n _legend.render();\n }\n\n _chart._activateRenderlets('postRedraw');\n\n return result;\n };\n\n /**\n * Gets/sets the commit handler. If the chart has a commit handler, the handler will be called when\n * the chart's filters have changed, in order to send the filter data asynchronously to a server.\n *\n * Unlike other functions in dc.js, the commit handler is asynchronous. It takes two arguments:\n * a flag indicating whether this is a render (true) or a redraw (false), and a callback to be\n * triggered once the commit is filtered. The callback has the standard node.js continuation signature\n * with error first and result second.\n * @method commitHandler\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.commitHandler = function (commitHandler) {\n if (!arguments.length) {\n return _commitHandler;\n }\n _commitHandler = commitHandler;\n return _chart;\n };\n\n /**\n * Redraws all charts in the same group as this chart, typically in reaction to a filter\n * change. If the chart has a {@link dc.baseMixin.commitFilter commitHandler}, it will\n * be executed and waited for.\n * @method redrawGroup\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.redrawGroup = function () {\n if (_commitHandler) {\n _commitHandler(false, function (error, result) {\n if (error) {\n console.log(error);\n } else {\n dc.redrawAll(_chart.chartGroup());\n }\n });\n } else {\n dc.redrawAll(_chart.chartGroup());\n }\n return _chart;\n };\n\n /**\n * Renders all charts in the same group as this chart. If the chart has a\n * {@link dc.baseMixin.commitFilter commitHandler}, it will be executed and waited for\n * @method renderGroup\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.renderGroup = function () {\n if (_commitHandler) {\n _commitHandler(false, function (error, result) {\n if (error) {\n console.log(error);\n } else {\n dc.renderAll(_chart.chartGroup());\n }\n });\n } else {\n dc.renderAll(_chart.chartGroup());\n }\n return _chart;\n };\n\n _chart._invokeFilteredListener = function (f) {\n if (f !== undefined) {\n _listeners.filtered(_chart, f);\n }\n };\n\n _chart._invokeZoomedListener = function () {\n _listeners.zoomed(_chart);\n };\n\n var _hasFilterHandler = function (filters, filter) {\n if (filter === null || typeof(filter) === 'undefined') {\n return filters.length > 0;\n }\n return filters.some(function (f) {\n return filter <= f && filter >= f;\n });\n };\n\n /**\n * Set or get the has-filter handler. The has-filter handler is a function that checks to see if\n * the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows\n * you to change the way filters are checked for and replaced.\n * @method hasFilterHandler\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default has-filter handler\n * chart.hasFilterHandler(function (filters, filter) {\n * if (filter === null || typeof(filter) === 'undefined') {\n * return filters.length > 0;\n * }\n * return filters.some(function (f) {\n * return filter <= f && filter >= f;\n * });\n * });\n *\n * // custom filter handler (no-op)\n * chart.hasFilterHandler(function(filters, filter) {\n * return false;\n * });\n * @param {Function} [hasFilterHandler]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.hasFilterHandler = function (hasFilterHandler) {\n if (!arguments.length) {\n return _hasFilterHandler;\n }\n _hasFilterHandler = hasFilterHandler;\n return _chart;\n };\n\n /**\n * Check whether any active filter or a specific filter is associated with particular chart instance.\n * This function is **not chainable**.\n * @method hasFilter\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#hasFilterHandler hasFilterHandler}\n * @param {*} [filter]\n * @return {Boolean}\n */\n _chart.hasFilter = function (filter) {\n return _hasFilterHandler(_filters, filter);\n };\n\n var _removeFilterHandler = function (filters, filter) {\n for (var i = 0; i < filters.length; i++) {\n if (filters[i] <= filter && filters[i] >= filter) {\n filters.splice(i, 1);\n break;\n }\n }\n return filters;\n };\n\n /**\n * Set or get the remove filter handler. The remove filter handler is a function that removes a\n * filter from the chart's current filters. Using a custom remove filter handler allows you to\n * change how filters are removed or perform additional work when removing a filter, e.g. when\n * using a filter server other than crossfilter.\n *\n * The handler should return a new or modified array as the result.\n * @method removeFilterHandler\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default remove filter handler\n * chart.removeFilterHandler(function (filters, filter) {\n * for (var i = 0; i < filters.length; i++) {\n * if (filters[i] <= filter && filters[i] >= filter) {\n * filters.splice(i, 1);\n * break;\n * }\n * }\n * return filters;\n * });\n *\n * // custom filter handler (no-op)\n * chart.removeFilterHandler(function(filters, filter) {\n * return filters;\n * });\n * @param {Function} [removeFilterHandler]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.removeFilterHandler = function (removeFilterHandler) {\n if (!arguments.length) {\n return _removeFilterHandler;\n }\n _removeFilterHandler = removeFilterHandler;\n return _chart;\n };\n\n var _addFilterHandler = function (filters, filter) {\n filters.push(filter);\n return filters;\n };\n\n /**\n * Set or get the add filter handler. The add filter handler is a function that adds a filter to\n * the chart's filter list. Using a custom add filter handler allows you to change the way filters\n * are added or perform additional work when adding a filter, e.g. when using a filter server other\n * than crossfilter.\n *\n * The handler should return a new or modified array as the result.\n * @method addFilterHandler\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default add filter handler\n * chart.addFilterHandler(function (filters, filter) {\n * filters.push(filter);\n * return filters;\n * });\n *\n * // custom filter handler (no-op)\n * chart.addFilterHandler(function(filters, filter) {\n * return filters;\n * });\n * @param {Function} [addFilterHandler]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.addFilterHandler = function (addFilterHandler) {\n if (!arguments.length) {\n return _addFilterHandler;\n }\n _addFilterHandler = addFilterHandler;\n return _chart;\n };\n\n var _resetFilterHandler = function (filters) {\n return [];\n };\n\n /**\n * Set or get the reset filter handler. The reset filter handler is a function that resets the\n * chart's filter list by returning a new list. Using a custom reset filter handler allows you to\n * change the way filters are reset, or perform additional work when resetting the filters,\n * e.g. when using a filter server other than crossfilter.\n *\n * The handler should return a new or modified array as the result.\n * @method resetFilterHandler\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default remove filter handler\n * function (filters) {\n * return [];\n * }\n *\n * // custom filter handler (no-op)\n * chart.resetFilterHandler(function(filters) {\n * return filters;\n * });\n * @param {Function} [resetFilterHandler]\n * @return {dc.baseMixin}\n */\n _chart.resetFilterHandler = function (resetFilterHandler) {\n if (!arguments.length) {\n return _resetFilterHandler;\n }\n _resetFilterHandler = resetFilterHandler;\n return _chart;\n };\n\n function applyFilters (filters) {\n if (_chart.dimension() && _chart.dimension().filter) {\n var fs = _filterHandler(_chart.dimension(), filters);\n if (fs) {\n filters = fs;\n }\n }\n return filters;\n }\n\n /**\n * Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)`\n *\n * @method replaceFilter\n * @memberof dc.baseMixin\n * @instance\n * @param {*} [filter]\n * @return {dc.baseMixin}\n **/\n _chart.replaceFilter = function (filter) {\n _filters = _resetFilterHandler(_filters);\n _chart.filter(filter);\n };\n\n /**\n * Filter the chart by the given parameter, or return the current filter if no input parameter\n * is given.\n *\n * The filter parameter can take one of these forms:\n * * A single value: the value will be toggled (added if it is not present in the current\n * filters, removed if it is present)\n * * An array containing a single array of values (`[[value,value,value]]`): each value is\n * toggled\n * * When appropriate for the chart, a {@link dc.filters dc filter object} such as\n * * {@link dc.filters.RangedFilter `dc.filters.RangedFilter`} for the\n * {@link dc.coordinateGridMixin dc.coordinateGridMixin} charts\n * * {@link dc.filters.TwoDimensionalFilter `dc.filters.TwoDimensionalFilter`} for the\n * {@link dc.heatMap heat map}\n * * {@link dc.filters.RangedTwoDimensionalFilter `dc.filters.RangedTwoDimensionalFilter`}\n * for the {@link dc.scatterPlot scatter plot}\n * * `null`: the filter will be reset using the\n * {@link dc.baseMixin#resetFilterHandler resetFilterHandler}\n *\n * Note that this is always a toggle (even when it doesn't make sense for the filter type). If\n * you wish to replace the current filter, either call `chart.filter(null)` first, or\n * equivalently, call {@link dc.baseMixin#replaceFilter `chart.replaceFilter(filter)`} instead.\n *\n * Each toggle is executed by checking if the value is already present using the\n * {@link dc.baseMixin#hasFilterHandler hasFilterHandler}; if it is not present, it is added\n * using the {@link dc.baseMixin#addFilterHandler addFilterHandler}; if it is already present,\n * it is removed using the {@link dc.baseMixin#removeFilterHandler removeFilterHandler}.\n *\n * Once the filters array has been updated, the filters are applied to the\n * crossfilter dimension, using the {@link dc.baseMixin#filterHandler filterHandler}.\n *\n * Once you have set the filters, call {@link dc.baseMixin#redrawGroup `chart.redrawGroup()`}\n * (or {@link dc.redrawAll `dc.redrawAll()`}) to redraw the chart's group.\n * @method filter\n * @memberof dc.baseMixin\n * @instance\n * @see {@link dc.baseMixin#addFilterHandler addFilterHandler}\n * @see {@link dc.baseMixin#removeFilterHandler removeFilterHandler}\n * @see {@link dc.baseMixin#resetFilterHandler resetFilterHandler}\n * @see {@link dc.baseMixin#filterHandler filterHandler}\n * @example\n * // filter by a single string\n * chart.filter('Sunday');\n * // filter by a single age\n * chart.filter(18);\n * // filter by a set of states\n * chart.filter([['MA', 'TX', 'ND', 'WA']]);\n * // filter by range -- note the use of dc.filters.RangedFilter, which is different\n * // from the syntax for filtering a crossfilter dimension directly, dimension.filter([15,20])\n * chart.filter(dc.filters.RangedFilter(15,20));\n * @param {*} [filter]\n * @return {dc.baseMixin}\n */\n _chart.filter = function (filter) {\n if (!arguments.length) {\n return _filters.length > 0 ? _filters[0] : null;\n }\n var filters = _filters;\n if (filter instanceof Array && filter[0] instanceof Array && !filter.isFiltered) {\n // toggle each filter\n filter[0].forEach(function (f) {\n if (_hasFilterHandler(filters, f)) {\n filters = _removeFilterHandler(filters, f);\n } else {\n filters = _addFilterHandler(filters, f);\n }\n });\n } else if (filter === null) {\n filters = _resetFilterHandler(filters);\n } else {\n if (_hasFilterHandler(filters, filter)) {\n filters = _removeFilterHandler(filters, filter);\n } else {\n filters = _addFilterHandler(filters, filter);\n }\n }\n _filters = applyFilters(filters);\n _chart._invokeFilteredListener(filter);\n\n if (_root !== null && _chart.hasFilter()) {\n _chart.turnOnControls();\n } else {\n _chart.turnOffControls();\n }\n\n return _chart;\n };\n\n /**\n * Returns all current filters. This method does not perform defensive cloning of the internal\n * filter array before returning, therefore any modification of the returned array will effect the\n * chart's internal filter storage.\n * @method filters\n * @memberof dc.baseMixin\n * @instance\n * @return {Array<*>}\n */\n _chart.filters = function () {\n return _filters;\n };\n\n _chart.highlightSelected = function (e) {\n d3.select(e).classed(dc.constants.SELECTED_CLASS, true);\n d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);\n };\n\n _chart.fadeDeselected = function (e) {\n d3.select(e).classed(dc.constants.SELECTED_CLASS, false);\n d3.select(e).classed(dc.constants.DESELECTED_CLASS, true);\n };\n\n _chart.resetHighlight = function (e) {\n d3.select(e).classed(dc.constants.SELECTED_CLASS, false);\n d3.select(e).classed(dc.constants.DESELECTED_CLASS, false);\n };\n\n /**\n * This function is passed to d3 as the onClick handler for each chart. The default behavior is to\n * filter on the clicked datum (passed to the callback) and redraw the chart group.\n * @method onClick\n * @memberof dc.baseMixin\n * @instance\n * @param {*} datum\n */\n _chart.onClick = function (datum) {\n var filter = _chart.keyAccessor()(datum);\n dc.events.trigger(function () {\n _chart.filter(filter);\n _chart.redrawGroup();\n });\n };\n\n /**\n * Set or get the filter handler. The filter handler is a function that performs the filter action\n * on a specific dimension. Using a custom filter handler allows you to perform additional logic\n * before or after filtering.\n * @method filterHandler\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension_filter crossfilter.dimension.filter}\n * @example\n * // default filter handler\n * chart.filterHandler(function (dimension, filters) {\n * dimension.filter(null);\n * if (filters.length === 0) {\n * dimension.filter(null);\n * } else {\n * dimension.filterFunction(function (d) {\n * for (var i = 0; i < filters.length; i++) {\n * var filter = filters[i];\n * if (filter.isFiltered && filter.isFiltered(d)) {\n * return true;\n * } else if (filter <= d && filter >= d) {\n * return true;\n * }\n * }\n * return false;\n * });\n * }\n * return filters;\n * });\n *\n * // custom filter handler\n * chart.filterHandler(function(dimension, filter){\n * var newFilter = filter + 10;\n * dimension.filter(newFilter);\n * return newFilter; // set the actual filter value to the new value\n * });\n * @param {Function} [filterHandler]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.filterHandler = function (filterHandler) {\n if (!arguments.length) {\n return _filterHandler;\n }\n _filterHandler = filterHandler;\n return _chart;\n };\n\n // abstract function stub\n _chart._doRender = function () {\n // do nothing in base, should be overridden by sub-function\n return _chart;\n };\n\n _chart._doRedraw = function () {\n // do nothing in base, should be overridden by sub-function\n return _chart;\n };\n\n _chart.legendables = function () {\n // do nothing in base, should be overridden by sub-function\n return [];\n };\n\n _chart.legendHighlight = function () {\n // do nothing in base, should be overridden by sub-function\n };\n\n _chart.legendReset = function () {\n // do nothing in base, should be overridden by sub-function\n };\n\n _chart.legendToggle = function () {\n // do nothing in base, should be overriden by sub-function\n };\n\n _chart.isLegendableHidden = function () {\n // do nothing in base, should be overridden by sub-function\n return false;\n };\n\n /**\n * Set or get the key accessor function. The key accessor function is used to retrieve the key\n * value from the crossfilter group. Key values are used differently in different charts, for\n * example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart.\n * @method keyAccessor\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default key accessor\n * chart.keyAccessor(function(d) { return d.key; });\n * // custom key accessor for a multi-value crossfilter reduction\n * chart.keyAccessor(function(p) { return p.value.absGain; });\n * @param {Function} [keyAccessor]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.keyAccessor = function (keyAccessor) {\n if (!arguments.length) {\n return _keyAccessor;\n }\n _keyAccessor = keyAccessor;\n return _chart;\n };\n\n /**\n * Set or get the value accessor function. The value accessor function is used to retrieve the\n * value from the crossfilter group. Group values are used differently in different charts, for\n * example values correspond to slice sizes in a pie chart and y axis positions in a grid\n * coordinate chart.\n * @method valueAccessor\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default value accessor\n * chart.valueAccessor(function(d) { return d.value; });\n * // custom value accessor for a multi-value crossfilter reduction\n * chart.valueAccessor(function(p) { return p.value.percentageGain; });\n * @param {Function} [valueAccessor]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.valueAccessor = function (valueAccessor) {\n if (!arguments.length) {\n return _valueAccessor;\n }\n _valueAccessor = valueAccessor;\n return _chart;\n };\n\n /**\n * Set or get the label function. The chart class will use this function to render labels for each\n * child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every\n * chart supports the label function, for example line chart does not use this function\n * at all. By default, enables labels; pass false for the second parameter if this is not desired.\n * @method label\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default label function just return the key\n * chart.label(function(d) { return d.key; });\n * // label function has access to the standard d3 data binding and can get quite complicated\n * chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; });\n * @param {Function} [labelFunction]\n * @param {Boolean} [enableLabels=true]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.label = function (labelFunction, enableLabels) {\n if (!arguments.length) {\n return _label;\n }\n _label = labelFunction;\n if ((enableLabels === undefined) || enableLabels) {\n _renderLabel = true;\n }\n return _chart;\n };\n\n /**\n * Turn on/off label rendering\n * @method renderLabel\n * @memberof dc.baseMixin\n * @instance\n * @param {Boolean} [renderLabel=false]\n * @return {Boolean}\n * @return {dc.baseMixin}\n */\n _chart.renderLabel = function (renderLabel) {\n if (!arguments.length) {\n return _renderLabel;\n }\n _renderLabel = renderLabel;\n return _chart;\n };\n\n /**\n * Set or get the title function. The chart class will use this function to render the SVGElement title\n * (usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice\n * in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function;\n * however in grid coordinate charts you need to turn off the brush in order to see titles, because\n * otherwise the brush layer will block tooltip triggering.\n * @method title\n * @memberof dc.baseMixin\n * @instance\n * @example\n * // default title function shows \"key: value\"\n * chart.title(function(d) { return d.key + ': ' + d.value; });\n * // title function has access to the standard d3 data binding and can get quite complicated\n * chart.title(function(p) {\n * return p.key.getFullYear()\n * + '\\n'\n * + 'Index Gain: ' + numberFormat(p.value.absGain) + '\\n'\n * + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\\n'\n * + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%';\n * });\n * @param {Function} [titleFunction]\n * @return {Function}\n * @return {dc.baseMixin}\n */\n _chart.title = function (titleFunction) {\n if (!arguments.length) {\n return _title;\n }\n _title = titleFunction;\n return _chart;\n };\n\n /**\n * Turn on/off title rendering, or return the state of the render title flag if no arguments are\n * given.\n * @method renderTitle\n * @memberof dc.baseMixin\n * @instance\n * @param {Boolean} [renderTitle=true]\n * @return {Boolean}\n * @return {dc.baseMixin}\n */\n _chart.renderTitle = function (renderTitle) {\n if (!arguments.length) {\n return _renderTitle;\n }\n _renderTitle = renderTitle;\n return _chart;\n };\n\n /**\n * A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added\n * to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked\n * right after the chart finishes its transitions, giving you a way to modify the SVGElements.\n * Renderlet functions take the chart instance as the only input parameter and you can\n * use the dc API or use raw d3 to achieve pretty much any effect.\n *\n * Use {@link dc.baseMixin#on on} with a 'renderlet' prefix.\n * Generates a random key for the renderlet, which makes it hard to remove.\n * @method renderlet\n * @memberof dc.baseMixin\n * @instance\n * @deprecated\n * @example\n * // do this instead of .renderlet(function(chart) { ... })\n * chart.on(\"renderlet\", function(chart){\n * // mix of dc API and d3 manipulation\n * chart.select('g.y').style('display', 'none');\n * // its a closure so you can also access other chart variable available in the closure scope\n * moveChart.filter(chart.filter());\n * });\n * @param {Function} renderletFunction\n * @return {dc.baseMixin}\n */\n _chart.renderlet = dc.logger.deprecate(function (renderletFunction) {\n _chart.on('renderlet.' + dc.utils.uniqueId(), renderletFunction);\n return _chart;\n }, 'chart.renderlet has been deprecated. Please use chart.on(\"renderlet.\", renderletFunction)');\n\n /**\n * Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn\n * together since it is expected they share the same underlying crossfilter data set.\n * @method chartGroup\n * @memberof dc.baseMixin\n * @instance\n * @param {String} [chartGroup]\n * @return {String}\n * @return {dc.baseMixin}\n */\n _chart.chartGroup = function (chartGroup) {\n if (!arguments.length) {\n return _chartGroup;\n }\n if (!_isChild) {\n dc.deregisterChart(_chart, _chartGroup);\n }\n _chartGroup = chartGroup;\n if (!_isChild) {\n dc.registerChart(_chart, _chartGroup);\n }\n return _chart;\n };\n\n /**\n * Expire the internal chart cache. dc charts cache some data internally on a per chart basis to\n * speed up rendering and avoid unnecessary calculation; however it might be useful to clear the\n * cache if you have changed state which will affect rendering. For example if you invoke the\n * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add}\n * function or reset group or dimension after rendering it is a good idea to\n * clear the cache to make sure charts are rendered properly.\n * @method expireCache\n * @memberof dc.baseMixin\n * @instance\n * @return {dc.baseMixin}\n */\n _chart.expireCache = function () {\n // do nothing in base, should be overridden by sub-function\n return _chart;\n };\n\n /**\n * Attach a dc.legend widget to this chart. The legend widget will automatically draw legend labels\n * based on the color setting and names associated with each group.\n * @method legend\n * @memberof dc.baseMixin\n * @instance\n * @example\n * chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5))\n * @param {dc.legend} [legend]\n * @return {dc.legend}\n * @return {dc.baseMixin}\n */\n _chart.legend = function (legend) {\n if (!arguments.length) {\n return _legend;\n }\n _legend = legend;\n _legend.parent(_chart);\n return _chart;\n };\n\n /**\n * Returns the internal numeric ID of the chart.\n * @method chartID\n * @memberof dc.baseMixin\n * @instance\n * @return {String}\n */\n _chart.chartID = function () {\n return _chart.__dcFlag__;\n };\n\n /**\n * Set chart options using a configuration object. Each key in the object will cause the method of\n * the same name to be called with the value to set that attribute for the chart.\n * @method options\n * @memberof dc.baseMixin\n * @instance\n * @example\n * chart.options({dimension: myDimension, group: myGroup});\n * @param {{}} opts\n * @return {dc.baseMixin}\n */\n _chart.options = function (opts) {\n var applyOptions = [\n 'anchor',\n 'group',\n 'xAxisLabel',\n 'yAxisLabel',\n 'stack',\n 'title',\n 'point',\n 'getColor',\n 'overlayGeoJson'\n ];\n\n for (var o in opts) {\n if (typeof(_chart[o]) === 'function') {\n if (opts[o] instanceof Array && applyOptions.indexOf(o) !== -1) {\n _chart[o].apply(_chart, opts[o]);\n } else {\n _chart[o].call(_chart, opts[o]);\n }\n } else {\n dc.logger.debug('Not a valid option setter name: ' + o);\n }\n }\n return _chart;\n };\n\n /**\n * All dc chart instance supports the following listeners.\n * Supports the following events:\n * * `renderlet` - This listener function will be invoked after transitions after redraw and render. Replaces the\n * deprecated {@link dc.baseMixin#renderlet renderlet} method.\n * * `pretransition` - Like `.on('renderlet', ...)` but the event is fired before transitions start.\n * * `preRender` - This listener function will be invoked before chart rendering.\n * * `postRender` - This listener function will be invoked after chart finish rendering including\n * all renderlets' logic.\n * * `preRedraw` - This listener function will be invoked before chart redrawing.\n * * `postRedraw` - This listener function will be invoked after chart finish redrawing\n * including all renderlets' logic.\n * * `filtered` - This listener function will be invoked after a filter is applied, added or removed.\n * * `zoomed` - This listener function will be invoked after a zoom is triggered.\n * @method on\n * @memberof dc.baseMixin\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Internals#dispatch_on d3.dispatch.on}\n * @example\n * .on('renderlet', function(chart, filter){...})\n * .on('pretransition', function(chart, filter){...})\n * .on('preRender', function(chart){...})\n * .on('postRender', function(chart){...})\n * .on('preRedraw', function(chart){...})\n * .on('postRedraw', function(chart){...})\n * .on('filtered', function(chart, filter){...})\n * .on('zoomed', function(chart, filter){...})\n * @param {String} event\n * @param {Function} listener\n * @return {dc.baseMixin}\n */\n _chart.on = function (event, listener) {\n _listeners.on(event, listener);\n return _chart;\n };\n\n return _chart;\n};\n","/**\n * Margin is a mixin that provides margin utility functions for both the Row Chart and Coordinate Grid\n * Charts.\n * @name marginMixin\n * @memberof dc\n * @mixin\n * @param {Object} _chart\n * @return {dc.marginMixin}\n */\ndc.marginMixin = function (_chart) {\n var _margin = {top: 10, right: 50, bottom: 30, left: 30};\n\n /**\n * Get or set the margins for a particular coordinate grid chart instance. The margins is stored as\n * an associative Javascript array.\n * @method margins\n * @memberof dc.marginMixin\n * @instance\n * @example\n * var leftMargin = chart.margins().left; // 30 by default\n * chart.margins().left = 50;\n * leftMargin = chart.margins().left; // now 50\n * @param {{top: Number, right: Number, left: Number, bottom: Number}} [margins={top: 10, right: 50, bottom: 30, left: 30}]\n * @return {{top: Number, right: Number, left: Number, bottom: Number}}\n * @return {dc.marginMixin}\n */\n _chart.margins = function (margins) {\n if (!arguments.length) {\n return _margin;\n }\n _margin = margins;\n return _chart;\n };\n\n _chart.effectiveWidth = function () {\n return _chart.width() - _chart.margins().left - _chart.margins().right;\n };\n\n _chart.effectiveHeight = function () {\n return _chart.height() - _chart.margins().top - _chart.margins().bottom;\n };\n\n return _chart;\n};\n","/**\n * The Color Mixin is an abstract chart functional class providing universal coloring support\n * as a mix-in for any concrete chart implementation.\n * @name colorMixin\n * @memberof dc\n * @mixin\n * @param {Object} _chart\n * @return {dc.colorMixin}\n */\ndc.colorMixin = function (_chart) {\n var _colors = d3.scale.category20c();\n var _defaultAccessor = true;\n\n var _colorAccessor = function (d) { return _chart.keyAccessor()(d); };\n\n /**\n * Retrieve current color scale or set a new color scale. This methods accepts any function that\n * operates like a d3 scale.\n * @method colors\n * @memberof dc.colorMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale}\n * @example\n * // alternate categorical scale\n * chart.colors(d3.scale.category20b());\n * // ordinal scale\n * chart.colors(d3.scale.ordinal().range(['red','green','blue']));\n * // convenience method, the same as above\n * chart.ordinalColors(['red','green','blue']);\n * // set a linear scale\n * chart.linearColors([\"#4575b4\", \"#ffffbf\", \"#a50026\"]);\n * @param {d3.scale} [colorScale=d3.scale.category20c()]\n * @return {d3.scale}\n * @return {dc.colorMixin}\n */\n _chart.colors = function (colorScale) {\n if (!arguments.length) {\n return _colors;\n }\n if (colorScale instanceof Array) {\n _colors = d3.scale.quantize().range(colorScale); // deprecated legacy support, note: this fails for ordinal domains\n } else {\n _colors = d3.functor(colorScale);\n }\n return _chart;\n };\n\n /**\n * Convenience method to set the color scale to\n * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#ordinal d3.scale.ordinal} with\n * range `r`.\n * @method ordinalColors\n * @memberof dc.colorMixin\n * @instance\n * @param {Array} r\n * @return {dc.colorMixin}\n */\n _chart.ordinalColors = function (r) {\n return _chart.colors(d3.scale.ordinal().range(r));\n };\n\n /**\n * Convenience method to set the color scale to an Hcl interpolated linear scale with range `r`.\n * @method linearColors\n * @memberof dc.colorMixin\n * @instance\n * @param {Array} r\n * @return {dc.colorMixin}\n */\n _chart.linearColors = function (r) {\n return _chart.colors(d3.scale.linear()\n .range(r)\n .interpolate(d3.interpolateHcl));\n };\n\n /**\n * Set or the get color accessor function. This function will be used to map a data point in a\n * crossfilter group to a color value on the color scale. The default function uses the key\n * accessor.\n * @method colorAccessor\n * @memberof dc.colorMixin\n * @instance\n * @example\n * // default index based color accessor\n * .colorAccessor(function (d, i){return i;})\n * // color accessor for a multi-value crossfilter reduction\n * .colorAccessor(function (d){return d.value.absGain;})\n * @param {Function} [colorAccessor]\n * @return {Function}\n * @return {dc.colorMixin}\n */\n _chart.colorAccessor = function (colorAccessor) {\n if (!arguments.length) {\n return _colorAccessor;\n }\n _colorAccessor = colorAccessor;\n _defaultAccessor = false;\n return _chart;\n };\n\n // what is this?\n _chart.defaultColorAccessor = function () {\n return _defaultAccessor;\n };\n\n /**\n * Set or get the current domain for the color mapping function. The domain must be supplied as an\n * array.\n *\n * Note: previously this method accepted a callback function. Instead you may use a custom scale\n * set by {@link dc.colorMixin#colors .colors}.\n * @method colorDomain\n * @memberof dc.colorMixin\n * @instance\n * @param {Array} [domain]\n * @return {Array}\n * @return {dc.colorMixin}\n */\n _chart.colorDomain = function (domain) {\n if (!arguments.length) {\n return _colors.domain();\n }\n _colors.domain(domain);\n return _chart;\n };\n\n /**\n * Set the domain by determining the min and max values as retrieved by\n * {@link dc.colorMixin#colorAccessor .colorAccessor} over the chart's dataset.\n * @method calculateColorDomain\n * @memberof dc.colorMixin\n * @instance\n * @return {dc.colorMixin}\n */\n _chart.calculateColorDomain = function () {\n var newDomain = [d3.min(_chart.data(), _chart.colorAccessor()),\n d3.max(_chart.data(), _chart.colorAccessor())];\n _colors.domain(newDomain);\n return _chart;\n };\n\n /**\n * Get the color for the datum d and counter i. This is used internally by charts to retrieve a color.\n * @method getColor\n * @memberof dc.colorMixin\n * @instance\n * @param {*} d\n * @param {Number} [i]\n * @return {String}\n */\n _chart.getColor = function (d, i) {\n return _colors(_colorAccessor.call(this, d, i));\n };\n\n /**\n * Get the color for the datum d and counter i. This is used internally by charts to retrieve a color.\n * @method colorCalculator\n * @memberof dc.colorMixin\n * @instance\n * @param {*} [colorCalculator]\n * @return {*}\n */\n _chart.colorCalculator = function (colorCalculator) {\n if (!arguments.length) {\n return _chart.getColor;\n }\n _chart.getColor = colorCalculator;\n return _chart;\n };\n\n return _chart;\n};\n","/**\n * Coordinate Grid is an abstract base chart designed to support a number of coordinate grid based\n * concrete chart types, e.g. bar chart, line chart, and bubble chart.\n * @name coordinateGridMixin\n * @memberof dc\n * @mixin\n * @mixes dc.colorMixin\n * @mixes dc.marginMixin\n * @mixes dc.baseMixin\n * @param {Object} _chart\n * @return {dc.coordinateGridMixin}\n */\ndc.coordinateGridMixin = function (_chart) {\n var GRID_LINE_CLASS = 'grid-line';\n var HORIZONTAL_CLASS = 'horizontal';\n var VERTICAL_CLASS = 'vertical';\n var Y_AXIS_LABEL_CLASS = 'y-axis-label';\n var X_AXIS_LABEL_CLASS = 'x-axis-label';\n var DEFAULT_AXIS_LABEL_PADDING = 12;\n\n _chart = dc.colorMixin(dc.marginMixin(dc.baseMixin(_chart)));\n\n _chart.colors(d3.scale.category10());\n _chart._mandatoryAttributes().push('x');\n\n function zoomHandler () {\n _refocused = true;\n if (_zoomOutRestrict) {\n _chart.x().domain(constrainRange(_chart.x().domain(), _xOriginalDomain));\n if (_rangeChart) {\n _chart.x().domain(constrainRange(_chart.x().domain(), _rangeChart.x().domain()));\n }\n }\n\n var domain = _chart.x().domain();\n var domFilter = dc.filters.RangedFilter(domain[0], domain[1]);\n\n _chart.replaceFilter(domFilter);\n _chart.rescale();\n _chart.redraw();\n\n if (_rangeChart && !rangesEqual(_chart.filter(), _rangeChart.filter())) {\n dc.events.trigger(function () {\n _rangeChart.replaceFilter(domFilter);\n _rangeChart.redraw();\n });\n }\n\n _chart._invokeZoomedListener();\n\n dc.events.trigger(function () {\n _chart.redrawGroup();\n }, dc.constants.EVENT_DELAY);\n\n _refocused = !rangesEqual(domain, _xOriginalDomain);\n }\n\n var _parent;\n var _g;\n var _chartBodyG;\n\n var _x;\n var _xOriginalDomain;\n var _xAxis = d3.svg.axis().orient('bottom');\n var _xUnits = dc.units.integers;\n var _xAxisPadding = 0;\n var _xElasticity = false;\n var _xAxisLabel;\n var _xAxisLabelPadding = 0;\n var _lastXDomain;\n\n var _y;\n var _yAxis = d3.svg.axis().orient('left');\n var _yAxisPadding = 0;\n var _yElasticity = false;\n var _yAxisLabel;\n var _yAxisLabelPadding = 0;\n\n var _brush = d3.svg.brush();\n var _brushOn = true;\n var _round;\n\n var _renderHorizontalGridLine = false;\n var _renderVerticalGridLine = false;\n\n var _refocused = false, _resizing = false;\n var _unitCount;\n\n var _zoomScale = [1, Infinity];\n var _zoomOutRestrict = true;\n\n var _zoom = d3.behavior.zoom().on('zoom', zoomHandler);\n var _nullZoom = d3.behavior.zoom().on('zoom', null);\n var _hasBeenMouseZoomable = false;\n\n var _rangeChart;\n var _focusChart;\n\n var _mouseZoomable = false;\n var _clipPadding = 0;\n\n var _outerRangeBandPadding = 0.5;\n var _rangeBandPadding = 0;\n\n var _useRightYAxis = false;\n\n /**\n * When changing the domain of the x or y scale, it is necessary to tell the chart to recalculate\n * and redraw the axes. (`.rescale()` is called automatically when the x or y scale is replaced\n * with {@link dc.coordinateGridMixin+x .x()} or {@link dc.coordinateGridMixin#y .y()}, and has\n * no effect on elastic scales.)\n * @method rescale\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {dc.coordinateGridMixin}\n */\n _chart.rescale = function () {\n _unitCount = undefined;\n _resizing = true;\n return _chart;\n };\n\n _chart.resizing = function () {\n return _resizing;\n };\n\n /**\n * Get or set the range selection chart associated with this instance. Setting the range selection\n * chart using this function will automatically update its selection brush when the current chart\n * zooms in. In return the given range chart will also automatically attach this chart as its focus\n * chart hence zoom in when range brush updates.\n *\n * Usually the range and focus charts will share a dimension. The range chart will set the zoom\n * boundaries for the focus chart, so its dimension values must be compatible with the domain of\n * the focus chart.\n *\n * See the [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) example for this effect in action.\n * @method rangeChart\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {dc.coordinateGridMixin} [rangeChart]\n * @return {dc.coordinateGridMixin}\n */\n _chart.rangeChart = function (rangeChart) {\n if (!arguments.length) {\n return _rangeChart;\n }\n _rangeChart = rangeChart;\n _rangeChart.focusChart(_chart);\n return _chart;\n };\n\n /**\n * Get or set the scale extent for mouse zooms.\n * @method zoomScale\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Array} [extent=[1, Infinity]]\n * @return {Array}\n * @return {dc.coordinateGridMixin}\n */\n _chart.zoomScale = function (extent) {\n if (!arguments.length) {\n return _zoomScale;\n }\n _zoomScale = extent;\n return _chart;\n };\n\n /**\n * Get or set the zoom restriction for the chart. If true limits the zoom to origional domain of the chart.\n * @method zoomOutRestrict\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [zoomOutRestrict=true]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.zoomOutRestrict = function (zoomOutRestrict) {\n if (!arguments.length) {\n return _zoomOutRestrict;\n }\n _zoomScale[0] = zoomOutRestrict ? 1 : 0;\n _zoomOutRestrict = zoomOutRestrict;\n return _chart;\n };\n\n _chart._generateG = function (parent) {\n if (parent === undefined) {\n _parent = _chart.svg();\n } else {\n _parent = parent;\n }\n\n var href = window.location.href.split('#')[0];\n\n _g = _parent.append('g');\n\n _chartBodyG = _g.append('g').attr('class', 'chart-body')\n .attr('transform', 'translate(' + _chart.margins().left + ', ' + _chart.margins().top + ')')\n .attr('clip-path', 'url('http://github.com/+%20href%20+%20'#'%20+%20getClipPathId() + ')');\n\n return _g;\n };\n\n /**\n * Get or set the root g element. This method is usually used to retrieve the g element in order to\n * overlay custom svg drawing programatically. **Caution**: The root g element is usually generated\n * by dc.js internals, and resetting it might produce unpredictable result.\n * @method g\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {SVGElement} [gElement]\n * @return {SVGElement}\n * @return {dc.coordinateGridMixin}\n */\n _chart.g = function (gElement) {\n if (!arguments.length) {\n return _g;\n }\n _g = gElement;\n return _chart;\n };\n\n /**\n * Set or get mouse zoom capability flag (default: false). When turned on the chart will be\n * zoomable using the mouse wheel. If the range selector chart is attached zooming will also update\n * the range selection brush on the associated range selector chart.\n * @method mouseZoomable\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [mouseZoomable=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.mouseZoomable = function (mouseZoomable) {\n if (!arguments.length) {\n return _mouseZoomable;\n }\n _mouseZoomable = mouseZoomable;\n return _chart;\n };\n\n /**\n * Retrieve the svg group for the chart body.\n * @method chartBodyG\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {SVGElement} [chartBodyG]\n * @return {SVGElement}\n */\n _chart.chartBodyG = function (chartBodyG) {\n if (!arguments.length) {\n return _chartBodyG;\n }\n _chartBodyG = chartBodyG;\n return _chart;\n };\n\n /**\n * **mandatory**\n *\n * Get or set the x scale. The x scale can be any d3\n * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale} or\n * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales ordinal scale}.\n * @method x\n * @memberof dc.coordinateGridMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale}\n * @example\n * // set x to a linear scale\n * chart.x(d3.scale.linear().domain([-2500, 2500]))\n * // set x to a time scale to generate histogram\n * chart.x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)]))\n * @param {d3.scale} [xScale]\n * @return {d3.scale}\n * @return {dc.coordinateGridMixin}\n */\n _chart.x = function (xScale) {\n if (!arguments.length) {\n return _x;\n }\n _x = xScale;\n _xOriginalDomain = _x.domain();\n _chart.rescale();\n return _chart;\n };\n\n _chart.xOriginalDomain = function () {\n return _xOriginalDomain;\n };\n\n /**\n * Set or get the xUnits function. The coordinate grid chart uses the xUnits function to calculate\n * the number of data projections on x axis such as the number of bars for a bar chart or the\n * number of dots for a line chart. This function is expected to return a Javascript array of all\n * data points on x axis, or the number of points on the axis. [d3 time range functions\n * d3.time.days, d3.time.months, and\n * d3.time.years](https://github.com/mbostock/d3/wiki/Time-Intervals#aliases) are all valid xUnits\n * function. dc.js also provides a few units function, see the {@link dc.utils Utilities} section for\n * a list of built-in units functions. The default xUnits function is dc.units.integers.\n * @method xUnits\n * @memberof dc.coordinateGridMixin\n * @instance\n * @todo Add docs for utilities\n * @example\n * // set x units to count days\n * chart.xUnits(d3.time.days);\n * // set x units to count months\n * chart.xUnits(d3.time.months);\n *\n * // A custom xUnits function can be used as long as it follows the following interface:\n * // units in integer\n * function(start, end, xDomain) {\n * // simply calculates how many integers in the domain\n * return Math.abs(end - start);\n * };\n *\n * // fixed units\n * function(start, end, xDomain) {\n * // be aware using fixed units will disable the focus/zoom ability on the chart\n * return 1000;\n * @param {Function} [xUnits]\n * @return {Function}\n * @return {dc.coordinateGridMixin}\n */\n _chart.xUnits = function (xUnits) {\n if (!arguments.length) {\n return _xUnits;\n }\n _xUnits = xUnits;\n return _chart;\n };\n\n /**\n * Set or get the x axis used by a particular coordinate grid chart instance. This function is most\n * useful when x axis customization is required. The x axis in dc.js is an instance of a [d3\n * axis object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis); therefore it supports any\n * valid d3 axis manipulation. **Caution**: The x axis is usually generated internally by dc;\n * resetting it may cause unexpected results.\n * @method xAxis\n * @memberof dc.coordinateGridMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis}\n * @example\n * // customize x axis tick format\n * chart.xAxis().tickFormat(function(v) {return v + '%';});\n * // customize x axis tick values\n * chart.xAxis().tickValues([0, 100, 200, 300]);\n * @param {d3.svg.axis} [xAxis=d3.svg.axis().orient('bottom')]\n * @return {d3.svg.axis}\n * @return {dc.coordinateGridMixin}\n */\n _chart.xAxis = function (xAxis) {\n if (!arguments.length) {\n return _xAxis;\n }\n _xAxis = xAxis;\n return _chart;\n };\n\n /**\n * Turn on/off elastic x axis behavior. If x axis elasticity is turned on, then the grid chart will\n * attempt to recalculate the x axis range whenever a redraw event is triggered.\n * @method elasticX\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [elasticX=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.elasticX = function (elasticX) {\n if (!arguments.length) {\n return _xElasticity;\n }\n _xElasticity = elasticX;\n return _chart;\n };\n\n /**\n * Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x\n * axis if elasticX is turned on; otherwise it is ignored.\n *\n * padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to\n * number or date x axes. When padding a date axis, an integer represents number of days being padded\n * and a percentage string will be treated the same as an integer.\n * @method xAxisPadding\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Number|String} [padding=0]\n * @return {Number|String}\n * @return {dc.coordinateGridMixin}\n */\n _chart.xAxisPadding = function (padding) {\n if (!arguments.length) {\n return _xAxisPadding;\n }\n _xAxisPadding = padding;\n return _chart;\n };\n\n /**\n * Returns the number of units displayed on the x axis using the unit measure configured by\n * .xUnits.\n * @method xUnitCount\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {Number}\n */\n _chart.xUnitCount = function () {\n if (_unitCount === undefined) {\n var units = _chart.xUnits()(_chart.x().domain()[0], _chart.x().domain()[1], _chart.x().domain());\n\n if (units instanceof Array) {\n _unitCount = units.length;\n } else {\n _unitCount = units;\n }\n }\n\n return _unitCount;\n };\n\n /**\n * Gets or sets whether the chart should be drawn with a right axis instead of a left axis. When\n * used with a chart in a composite chart, allows both left and right Y axes to be shown on a\n * chart.\n * @method useRightYAxis\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [useRightYAxis=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.useRightYAxis = function (useRightYAxis) {\n if (!arguments.length) {\n return _useRightYAxis;\n }\n _useRightYAxis = useRightYAxis;\n return _chart;\n };\n\n /**\n * Returns true if the chart is using ordinal xUnits ({@link dc.units.ordinal dc.units.ordinal}, or false\n * otherwise. Most charts behave differently with ordinal data and use the result of this method to\n * trigger the appropriate logic.\n * @method isOrdinal\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {Boolean}\n */\n _chart.isOrdinal = function () {\n return _chart.xUnits() === dc.units.ordinal;\n };\n\n _chart._useOuterPadding = function () {\n return true;\n };\n\n _chart._ordinalXDomain = function () {\n var groups = _chart._computeOrderedGroups(_chart.data());\n return groups.map(_chart.keyAccessor());\n };\n\n function compareDomains (d1, d2) {\n return !d1 || !d2 || d1.length !== d2.length ||\n d1.some(function (elem, i) { return (elem && d2[i]) ? elem.toString() !== d2[i].toString() : elem === d2[i]; });\n }\n\n function prepareXAxis (g, render) {\n if (!_chart.isOrdinal()) {\n if (_chart.elasticX()) {\n _x.domain([_chart.xAxisMin(), _chart.xAxisMax()]);\n }\n } else { // _chart.isOrdinal()\n if (_chart.elasticX() || _x.domain().length === 0) {\n _x.domain(_chart._ordinalXDomain());\n }\n }\n\n // has the domain changed?\n var xdom = _x.domain();\n if (render || compareDomains(_lastXDomain, xdom)) {\n _chart.rescale();\n }\n _lastXDomain = xdom;\n\n // please can't we always use rangeBands for bar charts?\n if (_chart.isOrdinal()) {\n _x.rangeBands([0, _chart.xAxisLength()], _rangeBandPadding,\n _chart._useOuterPadding() ? _outerRangeBandPadding : 0);\n } else {\n _x.range([0, _chart.xAxisLength()]);\n }\n\n _xAxis = _xAxis.scale(_chart.x());\n\n renderVerticalGridLines(g);\n }\n\n _chart.renderXAxis = function (g) {\n var axisXG = g.selectAll('g.x');\n\n if (axisXG.empty()) {\n axisXG = g.append('g')\n .attr('class', 'axis x')\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart._xAxisY() + ')');\n }\n\n var axisXLab = g.selectAll('text.' + X_AXIS_LABEL_CLASS);\n if (axisXLab.empty() && _chart.xAxisLabel()) {\n axisXLab = g.append('text')\n .attr('class', X_AXIS_LABEL_CLASS)\n .attr('transform', 'translate(' + (_chart.margins().left + _chart.xAxisLength() / 2) + ',' +\n (_chart.height() - _xAxisLabelPadding) + ')')\n .attr('text-anchor', 'middle');\n }\n if (_chart.xAxisLabel() && axisXLab.text() !== _chart.xAxisLabel()) {\n axisXLab.text(_chart.xAxisLabel());\n }\n\n dc.transition(axisXG, _chart.transitionDuration())\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart._xAxisY() + ')')\n .call(_xAxis);\n dc.transition(axisXLab, _chart.transitionDuration())\n .attr('transform', 'translate(' + (_chart.margins().left + _chart.xAxisLength() / 2) + ',' +\n (_chart.height() - _xAxisLabelPadding) + ')');\n };\n\n function renderVerticalGridLines (g) {\n var gridLineG = g.selectAll('g.' + VERTICAL_CLASS);\n\n if (_renderVerticalGridLine) {\n if (gridLineG.empty()) {\n gridLineG = g.insert('g', ':first-child')\n .attr('class', GRID_LINE_CLASS + ' ' + VERTICAL_CLASS)\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')');\n }\n\n var ticks = _xAxis.tickValues() ? _xAxis.tickValues() :\n (typeof _x.ticks === 'function' ? _x.ticks(_xAxis.ticks()[0]) : _x.domain());\n\n var lines = gridLineG.selectAll('line')\n .data(ticks);\n\n // enter\n var linesGEnter = lines.enter()\n .append('line')\n .attr('x1', function (d) {\n return _x(d);\n })\n .attr('y1', _chart._xAxisY() - _chart.margins().top)\n .attr('x2', function (d) {\n return _x(d);\n })\n .attr('y2', 0)\n .attr('opacity', 0);\n dc.transition(linesGEnter, _chart.transitionDuration())\n .attr('opacity', 1);\n\n // update\n dc.transition(lines, _chart.transitionDuration())\n .attr('x1', function (d) {\n return _x(d);\n })\n .attr('y1', _chart._xAxisY() - _chart.margins().top)\n .attr('x2', function (d) {\n return _x(d);\n })\n .attr('y2', 0);\n\n // exit\n lines.exit().remove();\n } else {\n gridLineG.selectAll('line').remove();\n }\n }\n\n _chart._xAxisY = function () {\n return (_chart.height() - _chart.margins().bottom);\n };\n\n _chart.xAxisLength = function () {\n return _chart.effectiveWidth();\n };\n\n /**\n * Set or get the x axis label. If setting the label, you may optionally include additional padding to\n * the margin to make room for the label. By default the padded is set to 12 to accomodate the text height.\n * @method xAxisLabel\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {String} [labelText]\n * @param {Number} [padding=12]\n * @return {String}\n */\n _chart.xAxisLabel = function (labelText, padding) {\n if (!arguments.length) {\n return _xAxisLabel;\n }\n _xAxisLabel = labelText;\n _chart.margins().bottom -= _xAxisLabelPadding;\n _xAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding;\n _chart.margins().bottom += _xAxisLabelPadding;\n return _chart;\n };\n\n _chart._prepareYAxis = function (g) {\n if (_y === undefined || _chart.elasticY()) {\n if (_y === undefined) {\n _y = d3.scale.linear();\n }\n var min = _chart.yAxisMin() || 0,\n max = _chart.yAxisMax() || 0;\n _y.domain([min, max]).rangeRound([_chart.yAxisHeight(), 0]);\n }\n\n _y.range([_chart.yAxisHeight(), 0]);\n _yAxis = _yAxis.scale(_y);\n\n if (_useRightYAxis) {\n _yAxis.orient('right');\n }\n\n _chart._renderHorizontalGridLinesForAxis(g, _y, _yAxis);\n };\n\n _chart.renderYAxisLabel = function (axisClass, text, rotation, labelXPosition) {\n labelXPosition = labelXPosition || _yAxisLabelPadding;\n\n var axisYLab = _chart.g().selectAll('text.' + Y_AXIS_LABEL_CLASS + '.' + axisClass + '-label');\n var labelYPosition = (_chart.margins().top + _chart.yAxisHeight() / 2);\n if (axisYLab.empty() && text) {\n axisYLab = _chart.g().append('text')\n .attr('transform', 'translate(' + labelXPosition + ',' + labelYPosition + '),rotate(' + rotation + ')')\n .attr('class', Y_AXIS_LABEL_CLASS + ' ' + axisClass + '-label')\n .attr('text-anchor', 'middle')\n .text(text);\n }\n if (text && axisYLab.text() !== text) {\n axisYLab.text(text);\n }\n dc.transition(axisYLab, _chart.transitionDuration())\n .attr('transform', 'translate(' + labelXPosition + ',' + labelYPosition + '),rotate(' + rotation + ')');\n };\n\n _chart.renderYAxisAt = function (axisClass, axis, position) {\n var axisYG = _chart.g().selectAll('g.' + axisClass);\n if (axisYG.empty()) {\n axisYG = _chart.g().append('g')\n .attr('class', 'axis ' + axisClass)\n .attr('transform', 'translate(' + position + ',' + _chart.margins().top + ')');\n }\n\n dc.transition(axisYG, _chart.transitionDuration())\n .attr('transform', 'translate(' + position + ',' + _chart.margins().top + ')')\n .call(axis);\n };\n\n _chart.renderYAxis = function () {\n var axisPosition = _useRightYAxis ? (_chart.width() - _chart.margins().right) : _chart._yAxisX();\n _chart.renderYAxisAt('y', _yAxis, axisPosition);\n var labelPosition = _useRightYAxis ? (_chart.width() - _yAxisLabelPadding) : _yAxisLabelPadding;\n var rotation = _useRightYAxis ? 90 : -90;\n _chart.renderYAxisLabel('y', _chart.yAxisLabel(), rotation, labelPosition);\n };\n\n _chart._renderHorizontalGridLinesForAxis = function (g, scale, axis) {\n var gridLineG = g.selectAll('g.' + HORIZONTAL_CLASS);\n\n if (_renderHorizontalGridLine) {\n var ticks = axis.tickValues() ? axis.tickValues() : scale.ticks(axis.ticks()[0]);\n\n if (gridLineG.empty()) {\n gridLineG = g.insert('g', ':first-child')\n .attr('class', GRID_LINE_CLASS + ' ' + HORIZONTAL_CLASS)\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')');\n }\n\n var lines = gridLineG.selectAll('line')\n .data(ticks);\n\n // enter\n var linesGEnter = lines.enter()\n .append('line')\n .attr('x1', 1)\n .attr('y1', function (d) {\n return scale(d);\n })\n .attr('x2', _chart.xAxisLength())\n .attr('y2', function (d) {\n return scale(d);\n })\n .attr('opacity', 0);\n dc.transition(linesGEnter, _chart.transitionDuration())\n .attr('opacity', 1);\n\n // update\n dc.transition(lines, _chart.transitionDuration())\n .attr('x1', 1)\n .attr('y1', function (d) {\n return scale(d);\n })\n .attr('x2', _chart.xAxisLength())\n .attr('y2', function (d) {\n return scale(d);\n });\n\n // exit\n lines.exit().remove();\n } else {\n gridLineG.selectAll('line').remove();\n }\n };\n\n _chart._yAxisX = function () {\n return _chart.useRightYAxis() ? _chart.width() - _chart.margins().right : _chart.margins().left;\n };\n\n /**\n * Set or get the y axis label. If setting the label, you may optionally include additional padding\n * to the margin to make room for the label. By default the padded is set to 12 to accomodate the\n * text height.\n * @method yAxisLabel\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {String} [labelText]\n * @param {Number} [padding=12]\n * @return {String}\n * @return {dc.coordinateGridMixin}\n */\n _chart.yAxisLabel = function (labelText, padding) {\n if (!arguments.length) {\n return _yAxisLabel;\n }\n _yAxisLabel = labelText;\n _chart.margins().left -= _yAxisLabelPadding;\n _yAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding;\n _chart.margins().left += _yAxisLabelPadding;\n return _chart;\n };\n\n /**\n * Get or set the y scale. The y scale is typically automatically determined by the chart implementation.\n * @method y\n * @memberof dc.coordinateGridMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale}\n * @param {d3.scale} [yScale]\n * @return {d3.scale}\n * @return {dc.coordinateGridMixin}\n */\n _chart.y = function (yScale) {\n if (!arguments.length) {\n return _y;\n }\n _y = yScale;\n _chart.rescale();\n return _chart;\n };\n\n /**\n * Set or get the y axis used by the coordinate grid chart instance. This function is most useful\n * when y axis customization is required. The y axis in dc.js is simply an instance of a [d3 axis\n * object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis); therefore it supports any\n * valid d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc;\n * resetting it may cause unexpected results.\n * @method yAxis\n * @memberof dc.coordinateGridMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis}\n * @example\n * // customize y axis tick format\n * chart.yAxis().tickFormat(function(v) {return v + '%';});\n * // customize y axis tick values\n * chart.yAxis().tickValues([0, 100, 200, 300]);\n * @param {d3.svg.axis} [yAxis=d3.svg.axis().orient('left')]\n * @return {d3.svg.axis}\n * @return {dc.coordinateGridMixin}\n */\n _chart.yAxis = function (yAxis) {\n if (!arguments.length) {\n return _yAxis;\n }\n _yAxis = yAxis;\n return _chart;\n };\n\n /**\n * Turn on/off elastic y axis behavior. If y axis elasticity is turned on, then the grid chart will\n * attempt to recalculate the y axis range whenever a redraw event is triggered.\n * @method elasticY\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [elasticY=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.elasticY = function (elasticY) {\n if (!arguments.length) {\n return _yElasticity;\n }\n _yElasticity = elasticY;\n return _chart;\n };\n\n /**\n * Turn on/off horizontal grid lines.\n * @method renderHorizontalGridLines\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [renderHorizontalGridLines=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.renderHorizontalGridLines = function (renderHorizontalGridLines) {\n if (!arguments.length) {\n return _renderHorizontalGridLine;\n }\n _renderHorizontalGridLine = renderHorizontalGridLines;\n return _chart;\n };\n\n /**\n * Turn on/off vertical grid lines.\n * @method renderVerticalGridLines\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [renderVerticalGridLines=false]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.renderVerticalGridLines = function (renderVerticalGridLines) {\n if (!arguments.length) {\n return _renderVerticalGridLine;\n }\n _renderVerticalGridLine = renderVerticalGridLines;\n return _chart;\n };\n\n /**\n * Calculates the minimum x value to display in the chart. Includes xAxisPadding if set.\n * @method xAxisMin\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {*}\n */\n _chart.xAxisMin = function () {\n var min = d3.min(_chart.data(), function (e) {\n return _chart.keyAccessor()(e);\n });\n return dc.utils.subtract(min, _xAxisPadding);\n };\n\n /**\n * Calculates the maximum x value to display in the chart. Includes xAxisPadding if set.\n * @method xAxisMax\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {*}\n */\n _chart.xAxisMax = function () {\n var max = d3.max(_chart.data(), function (e) {\n return _chart.keyAccessor()(e);\n });\n return dc.utils.add(max, _xAxisPadding);\n };\n\n /**\n * Calculates the minimum y value to display in the chart. Includes yAxisPadding if set.\n * @method yAxisMin\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {*}\n */\n _chart.yAxisMin = function () {\n var min = d3.min(_chart.data(), function (e) {\n return _chart.valueAccessor()(e);\n });\n return dc.utils.subtract(min, _yAxisPadding);\n };\n\n /**\n * Calculates the maximum y value to display in the chart. Includes yAxisPadding if set.\n * @method yAxisMax\n * @memberof dc.coordinateGridMixin\n * @instance\n * @return {*}\n */\n _chart.yAxisMax = function () {\n var max = d3.max(_chart.data(), function (e) {\n return _chart.valueAccessor()(e);\n });\n return dc.utils.add(max, _yAxisPadding);\n };\n\n /**\n * Set or get y axis padding for the elastic y axis. The padding will be added to the top and\n * bottom of the y axis if elasticY is turned on; otherwise it is ignored.\n *\n * Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to\n * number or date axes. When padding a date axis, an integer represents number of days being padded\n * and a percentage string will be treated the same as an integer.\n * @method yAxisPadding\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Number|String} [padding=0]\n * @return {Number}\n * @return {dc.coordinateGridMixin}\n */\n _chart.yAxisPadding = function (padding) {\n if (!arguments.length) {\n return _yAxisPadding;\n }\n _yAxisPadding = padding;\n return _chart;\n };\n\n _chart.yAxisHeight = function () {\n return _chart.effectiveHeight();\n };\n\n /**\n * Set or get the rounding function used to quantize the selection when brushing is enabled.\n * @method round\n * @memberof dc.coordinateGridMixin\n * @instance\n * @example\n * // set x unit round to by month, this will make sure range selection brush will\n * // select whole months\n * chart.round(d3.time.month.round);\n * @param {Function} [round]\n * @return {Function}\n * @return {dc.coordinateGridMixin}\n */\n _chart.round = function (round) {\n if (!arguments.length) {\n return _round;\n }\n _round = round;\n return _chart;\n };\n\n _chart._rangeBandPadding = function (_) {\n if (!arguments.length) {\n return _rangeBandPadding;\n }\n _rangeBandPadding = _;\n return _chart;\n };\n\n _chart._outerRangeBandPadding = function (_) {\n if (!arguments.length) {\n return _outerRangeBandPadding;\n }\n _outerRangeBandPadding = _;\n return _chart;\n };\n\n dc.override(_chart, 'filter', function (_) {\n if (!arguments.length) {\n return _chart._filter();\n }\n\n _chart._filter(_);\n\n if (_) {\n _chart.brush().extent(_);\n } else {\n _chart.brush().clear();\n }\n\n return _chart;\n });\n\n _chart.brush = function (_) {\n if (!arguments.length) {\n return _brush;\n }\n _brush = _;\n return _chart;\n };\n\n function brushHeight () {\n return _chart._xAxisY() - _chart.margins().top;\n }\n\n _chart.renderBrush = function (g) {\n if (_brushOn) {\n _brush.on('brush', _chart._brushing);\n _brush.on('brushstart', _chart._disableMouseZoom);\n _brush.on('brushend', configureMouseZoom);\n\n var gBrush = g.append('g')\n .attr('class', 'brush')\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')')\n .call(_brush.x(_chart.x()));\n _chart.setBrushY(gBrush, false);\n _chart.setHandlePaths(gBrush);\n\n if (_chart.hasFilter()) {\n _chart.redrawBrush(g, false);\n }\n }\n };\n\n _chart.setHandlePaths = function (gBrush) {\n gBrush.selectAll('.resize').append('path').attr('d', _chart.resizeHandlePath);\n };\n\n _chart.setBrushY = function (gBrush) {\n gBrush.selectAll('rect')\n .attr('height', brushHeight());\n gBrush.selectAll('.resize path')\n .attr('d', _chart.resizeHandlePath);\n };\n\n _chart.extendBrush = function () {\n var extent = _brush.extent();\n if (_chart.round()) {\n extent[0] = extent.map(_chart.round())[0];\n extent[1] = extent.map(_chart.round())[1];\n\n _g.select('.brush')\n .call(_brush.extent(extent));\n }\n return extent;\n };\n\n _chart.brushIsEmpty = function (extent) {\n return _brush.empty() || !extent || extent[1] <= extent[0];\n };\n\n _chart._brushing = function () {\n var extent = _chart.extendBrush();\n\n _chart.redrawBrush(_g, false);\n\n if (_chart.brushIsEmpty(extent)) {\n dc.events.trigger(function () {\n _chart.filter(null);\n _chart.redrawGroup();\n }, dc.constants.EVENT_DELAY);\n } else {\n var rangedFilter = dc.filters.RangedFilter(extent[0], extent[1]);\n\n dc.events.trigger(function () {\n _chart.replaceFilter(rangedFilter);\n _chart.redrawGroup();\n }, dc.constants.EVENT_DELAY);\n }\n };\n\n _chart.redrawBrush = function (g, doTransition) {\n if (_brushOn) {\n if (_chart.filter() && _chart.brush().empty()) {\n _chart.brush().extent(_chart.filter());\n }\n\n var gBrush = dc.optionalTransition(doTransition, _chart.transitionDuration())(g.select('g.brush'));\n _chart.setBrushY(gBrush);\n gBrush.call(_chart.brush()\n .x(_chart.x())\n .extent(_chart.brush().extent()));\n }\n\n _chart.fadeDeselectedArea();\n };\n\n _chart.fadeDeselectedArea = function () {\n // do nothing, sub-chart should override this function\n };\n\n // borrowed from Crossfilter example\n _chart.resizeHandlePath = function (d) {\n var e = +(d === 'e'), x = e ? 1 : -1, y = brushHeight() / 3;\n return 'M' + (0.5 * x) + ',' + y +\n 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) +\n 'V' + (2 * y - 6) +\n 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y) +\n 'Z' +\n 'M' + (2.5 * x) + ',' + (y + 8) +\n 'V' + (2 * y - 8) +\n 'M' + (4.5 * x) + ',' + (y + 8) +\n 'V' + (2 * y - 8);\n };\n\n function getClipPathId () {\n return _chart.anchorName().replace(/[ .#=\\[\\]]/g, '-') + '-clip';\n }\n\n /**\n * Get or set the padding in pixels for the clip path. Once set padding will be applied evenly to\n * the top, left, right, and bottom when the clip path is generated. If set to zero, the clip area\n * will be exactly the chart body area minus the margins.\n * @method clipPadding\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Number} [padding=5]\n * @return {Number}\n * @return {dc.coordinateGridMixin}\n */\n _chart.clipPadding = function (padding) {\n if (!arguments.length) {\n return _clipPadding;\n }\n _clipPadding = padding;\n return _chart;\n };\n\n function generateClipPath () {\n var defs = dc.utils.appendOrSelect(_parent, 'defs');\n // cannot select elements; bug in WebKit, must select by id\n // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I\n var id = getClipPathId();\n var chartBodyClip = dc.utils.appendOrSelect(defs, '#' + id, 'clipPath').attr('id', id);\n\n var padding = _clipPadding * 2;\n\n dc.utils.appendOrSelect(chartBodyClip, 'rect')\n .attr('width', _chart.xAxisLength() + padding)\n .attr('height', _chart.yAxisHeight() + padding)\n .attr('transform', 'translate(-' + _clipPadding + ', -' + _clipPadding + ')');\n }\n\n _chart._preprocessData = function () {};\n\n _chart._doRender = function () {\n _chart.resetSvg();\n\n _chart._preprocessData();\n\n _chart._generateG();\n generateClipPath();\n\n drawChart(true);\n\n configureMouseZoom();\n\n return _chart;\n };\n\n _chart._doRedraw = function () {\n _chart._preprocessData();\n\n drawChart(false);\n generateClipPath();\n\n return _chart;\n };\n\n function drawChart (render) {\n if (_chart.isOrdinal()) {\n _brushOn = false;\n }\n\n prepareXAxis(_chart.g(), render);\n _chart._prepareYAxis(_chart.g());\n\n _chart.plotData();\n\n if (_chart.elasticX() || _resizing || render) {\n _chart.renderXAxis(_chart.g());\n }\n\n if (_chart.elasticY() || _resizing || render) {\n _chart.renderYAxis(_chart.g());\n }\n\n if (render) {\n _chart.renderBrush(_chart.g(), false);\n } else {\n _chart.redrawBrush(_chart.g(), _resizing);\n }\n _chart.fadeDeselectedArea();\n _resizing = false;\n }\n\n function configureMouseZoom () {\n if (_mouseZoomable) {\n _chart._enableMouseZoom();\n } else if (_hasBeenMouseZoomable) {\n _chart._disableMouseZoom();\n }\n }\n\n _chart._enableMouseZoom = function () {\n _hasBeenMouseZoomable = true;\n _zoom.x(_chart.x())\n .scaleExtent(_zoomScale)\n .size([_chart.width(), _chart.height()])\n .duration(_chart.transitionDuration());\n _chart.root().call(_zoom);\n };\n\n _chart._disableMouseZoom = function () {\n _chart.root().call(_nullZoom);\n };\n\n function constrainRange (range, constraint) {\n var constrainedRange = [];\n constrainedRange[0] = d3.max([range[0], constraint[0]]);\n constrainedRange[1] = d3.min([range[1], constraint[1]]);\n return constrainedRange;\n }\n\n /**\n * Zoom this chart to focus on the given range. The given range should be an array containing only\n * 2 elements (`[start, end]`) defining a range in the x domain. If the range is not given or set\n * to null, then the zoom will be reset. _For focus to work elasticX has to be turned off;\n * otherwise focus will be ignored.\n * @method focus\n * @memberof dc.coordinateGridMixin\n * @instance\n * @example\n * chart.on('renderlet', function(chart) {\n * // smooth the rendering through event throttling\n * dc.events.trigger(function(){\n * // focus some other chart to the range selected by user on this chart\n * someOtherChart.focus(chart.filter());\n * });\n * })\n * @param {Array} [range]\n */\n _chart.focus = function (range) {\n if (hasRangeSelected(range)) {\n _chart.x().domain(range);\n } else {\n _chart.x().domain(_xOriginalDomain);\n }\n\n _zoom.x(_chart.x());\n zoomHandler();\n };\n\n _chart.refocused = function () {\n return _refocused;\n };\n\n _chart.focusChart = function (c) {\n if (!arguments.length) {\n return _focusChart;\n }\n _focusChart = c;\n _chart.on('filtered', function (chart) {\n if (!chart.filter()) {\n dc.events.trigger(function () {\n _focusChart.x().domain(_focusChart.xOriginalDomain());\n });\n } else if (!rangesEqual(chart.filter(), _focusChart.filter())) {\n dc.events.trigger(function () {\n _focusChart.focus(chart.filter());\n });\n }\n });\n return _chart;\n };\n\n function rangesEqual (range1, range2) {\n if (!range1 && !range2) {\n return true;\n } else if (!range1 || !range2) {\n return false;\n } else if (range1.length === 0 && range2.length === 0) {\n return true;\n } else if (range1[0].valueOf() === range2[0].valueOf() &&\n range1[1].valueOf() === range2[1].valueOf()) {\n return true;\n }\n return false;\n }\n\n /**\n * Turn on/off the brush-based range filter. When brushing is on then user can drag the mouse\n * across a chart with a quantitative scale to perform range filtering based on the extent of the\n * brush, or click on the bars of an ordinal bar chart or slices of a pie chart to filter and\n * un-filter them. However turning on the brush filter will disable other interactive elements on\n * the chart such as highlighting, tool tips, and reference lines. Zooming will still be possible\n * if enabled, but only via scrolling (panning will be disabled.)\n * @method brushOn\n * @memberof dc.coordinateGridMixin\n * @instance\n * @param {Boolean} [brushOn=true]\n * @return {Boolean}\n * @return {dc.coordinateGridMixin}\n */\n _chart.brushOn = function (brushOn) {\n if (!arguments.length) {\n return _brushOn;\n }\n _brushOn = brushOn;\n return _chart;\n };\n\n function hasRangeSelected (range) {\n return range instanceof Array && range.length > 1;\n }\n\n return _chart;\n};\n","/**\n * Stack Mixin is an mixin that provides cross-chart support of stackability using d3.layout.stack.\n * @name stackMixin\n * @memberof dc\n * @mixin\n * @param {Object} _chart\n * @return {dc.stackMixin}\n */\ndc.stackMixin = function (_chart) {\n\n function prepareValues (layer, layerIdx) {\n var valAccessor = layer.accessor || _chart.valueAccessor();\n layer.name = String(layer.name || layerIdx);\n layer.values = layer.group.all().map(function (d, i) {\n return {\n x: _chart.keyAccessor()(d, i),\n y: layer.hidden ? null : valAccessor(d, i),\n data: d,\n layer: layer.name,\n hidden: layer.hidden\n };\n });\n\n layer.values = layer.values.filter(domainFilter());\n return layer.values;\n }\n\n var _stackLayout = d3.layout.stack()\n .values(prepareValues);\n\n var _stack = [];\n var _titles = {};\n\n var _hidableStacks = false;\n\n function domainFilter () {\n if (!_chart.x()) {\n return d3.functor(true);\n }\n var xDomain = _chart.x().domain();\n if (_chart.isOrdinal()) {\n // TODO #416\n //var domainSet = d3.set(xDomain);\n return function () {\n return true; //domainSet.has(p.x);\n };\n }\n if (_chart.elasticX()) {\n return function () { return true; };\n }\n return function (p) {\n //return true;\n return p.x >= xDomain[0] && p.x <= xDomain[xDomain.length - 1];\n };\n }\n\n /**\n * Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks\n * in the same chart will share the same key accessor and therefore the same set of keys.\n *\n * For example, in a stacked bar chart, the bars of each stack will be positioned using the same set\n * of keys on the x axis, while stacked vertically. If name is specified then it will be used to\n * generate the legend label.\n * @method stack\n * @memberof dc.stackMixin\n * @instance\n * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group}\n * @example\n * // stack group using default accessor\n * chart.stack(valueSumGroup)\n * // stack group using custom accessor\n * .stack(avgByDayGroup, function(d){return d.value.avgByDay;});\n * @param {crossfilter.group} group\n * @param {String} [name]\n * @param {Function} [accessor]\n * @return {Array<{group: crossfilter.group, name: String, accessor: Function}>}\n * @return {dc.stackMixin}\n */\n _chart.stack = function (group, name, accessor) {\n if (!arguments.length) {\n return _stack;\n }\n\n if (arguments.length <= 2) {\n accessor = name;\n }\n\n var layer = {group: group};\n if (typeof name === 'string') {\n layer.name = name;\n }\n if (typeof accessor === 'function') {\n layer.accessor = accessor;\n }\n _stack.push(layer);\n\n return _chart;\n };\n\n dc.override(_chart, 'group', function (g, n, f) {\n if (!arguments.length) {\n return _chart._group();\n }\n _stack = [];\n _titles = {};\n _chart.stack(g, n);\n if (f) {\n _chart.valueAccessor(f);\n }\n return _chart._group(g, n);\n });\n\n /**\n * Allow named stacks to be hidden or shown by clicking on legend items.\n * This does not affect the behavior of hideStack or showStack.\n * @method hidableStacks\n * @memberof dc.stackMixin\n * @instance\n * @param {Boolean} [hidableStacks=false]\n * @return {Boolean}\n * @return {dc.stackMixin}\n */\n _chart.hidableStacks = function (hidableStacks) {\n if (!arguments.length) {\n return _hidableStacks;\n }\n _hidableStacks = hidableStacks;\n return _chart;\n };\n\n function findLayerByName (n) {\n var i = _stack.map(dc.pluck('name')).indexOf(n);\n return _stack[i];\n }\n\n /**\n * Hide all stacks on the chart with the given name.\n * The chart must be re-rendered for this change to appear.\n * @method hideStack\n * @memberof dc.stackMixin\n * @instance\n * @param {String} stackName\n * @return {dc.stackMixin}\n */\n _chart.hideStack = function (stackName) {\n var layer = findLayerByName(stackName);\n if (layer) {\n layer.hidden = true;\n }\n return _chart;\n };\n\n /**\n * Show all stacks on the chart with the given name.\n * The chart must be re-rendered for this change to appear.\n * @method showStack\n * @memberof dc.stackMixin\n * @instance\n * @param {String} stackName\n * @return {dc.stackMixin}\n */\n _chart.showStack = function (stackName) {\n var layer = findLayerByName(stackName);\n if (layer) {\n layer.hidden = false;\n }\n return _chart;\n };\n\n _chart.getValueAccessorByIndex = function (index) {\n return _stack[index].accessor || _chart.valueAccessor();\n };\n\n _chart.yAxisMin = function () {\n var min = d3.min(flattenStack(), function (p) {\n return (p.y < 0) ? (p.y + p.y0) : p.y0;\n });\n\n return dc.utils.subtract(min, _chart.yAxisPadding());\n\n };\n\n _chart.yAxisMax = function () {\n var max = d3.max(flattenStack(), function (p) {\n return (p.y > 0) ? (p.y + p.y0) : p.y0;\n });\n\n return dc.utils.add(max, _chart.yAxisPadding());\n };\n\n function flattenStack () {\n var valueses = _chart.data().map(function (layer) { return layer.values; });\n return Array.prototype.concat.apply([], valueses);\n }\n\n _chart.xAxisMin = function () {\n var min = d3.min(flattenStack(), dc.pluck('x'));\n return dc.utils.subtract(min, _chart.xAxisPadding());\n };\n\n _chart.xAxisMax = function () {\n var max = d3.max(flattenStack(), dc.pluck('x'));\n return dc.utils.add(max, _chart.xAxisPadding());\n };\n\n /**\n * Set or get the title function. Chart class will use this function to render svg title (usually interpreted by\n * browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart.\n * Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to\n * use title otherwise the brush layer will block tooltip trigger.\n *\n * If the first argument is a stack name, the title function will get or set the title for that stack. If stackName\n * is not provided, the first stack is implied.\n * @method title\n * @memberof dc.stackMixin\n * @instance\n * @example\n * // set a title function on 'first stack'\n * chart.title('first stack', function(d) { return d.key + ': ' + d.value; });\n * // get a title function from 'second stack'\n * var secondTitleFunction = chart.title('second stack');\n * @param {String} [stackName]\n * @param {Function} [titleAccessor]\n * @return {String}\n * @return {dc.stackMixin}\n */\n dc.override(_chart, 'title', function (stackName, titleAccessor) {\n if (!stackName) {\n return _chart._title();\n }\n\n if (typeof stackName === 'function') {\n return _chart._title(stackName);\n }\n if (stackName === _chart._groupName && typeof titleAccessor === 'function') {\n return _chart._title(titleAccessor);\n }\n\n if (typeof titleAccessor !== 'function') {\n return _titles[stackName] || _chart._title();\n }\n\n _titles[stackName] = titleAccessor;\n\n return _chart;\n });\n\n /**\n * Gets or sets the stack layout algorithm, which computes a baseline for each stack and\n * propagates it to the next\n * @method stackLayout\n * @memberof dc.stackMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/Stack-Layout d3.layout.stack}\n * @param {Function} [stack=d3.layout.stack]\n * @return {Function}\n * @return {dc.stackMixin}\n */\n _chart.stackLayout = function (stack) {\n if (!arguments.length) {\n return _stackLayout;\n }\n _stackLayout = stack;\n if (_stackLayout.values() === d3.layout.stack().values()) {\n _stackLayout.values(prepareValues);\n }\n return _chart;\n };\n\n function visability (l) {\n return !l.hidden;\n }\n\n _chart.data(function () {\n var layers = _stack.filter(visability);\n return layers.length ? _chart.stackLayout()(layers) : [];\n });\n\n _chart._ordinalXDomain = function () {\n var flat = flattenStack().map(dc.pluck('data'));\n var ordered = _chart._computeOrderedGroups(flat);\n return ordered.map(_chart.keyAccessor());\n };\n\n _chart.colorAccessor(function (d) {\n var layer = this.layer || this.name || d.name || d.layer;\n return layer;\n });\n\n _chart.legendables = function () {\n return _stack.map(function (layer, i) {\n return {\n chart: _chart,\n name: layer.name,\n hidden: layer.hidden || false,\n color: _chart.getColor.call(layer, layer.values, i)\n };\n });\n };\n\n _chart.isLegendableHidden = function (d) {\n var layer = findLayerByName(d.name);\n return layer ? layer.hidden : false;\n };\n\n _chart.legendToggle = function (d) {\n if (_hidableStacks) {\n if (_chart.isLegendableHidden(d)) {\n _chart.showStack(d.name);\n } else {\n _chart.hideStack(d.name);\n }\n //_chart.redraw();\n _chart.renderGroup();\n }\n };\n\n return _chart;\n};\n","/**\n * Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the\n * Row and Pie Charts.\n *\n * The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest\n * will be replaced with an *others* element, with value equal to the sum of the replaced values. The\n * keys of the elements below the cap limit are recorded in order to filter by those keys when the\n * others* element is clicked.\n * @name capMixin\n * @memberof dc\n * @mixin\n * @param {Object} _chart\n * @return {dc.capMixin}\n */\ndc.capMixin = function (_chart) {\n\n var _cap = Infinity;\n\n var _othersLabel = 'Others';\n\n var _othersGrouper = function (topRows) {\n var topRowsSum = d3.sum(topRows, _chart.valueAccessor()),\n allRows = _chart.group().all(),\n allRowsSum = d3.sum(allRows, _chart.valueAccessor()),\n topKeys = topRows.map(_chart.keyAccessor()),\n allKeys = allRows.map(_chart.keyAccessor()),\n topSet = d3.set(topKeys),\n others = allKeys.filter(function (d) {return !topSet.has(d);});\n if (allRowsSum > topRowsSum) {\n return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]);\n }\n return topRows;\n };\n\n _chart.cappedKeyAccessor = function (d, i) {\n if (d.others) {\n return d.key;\n }\n return _chart.keyAccessor()(d, i);\n };\n\n _chart.cappedValueAccessor = function (d, i) {\n if (d.others) {\n return d.value;\n }\n return _chart.valueAccessor()(d, i);\n };\n\n _chart.data(function (group) {\n if (_cap === Infinity) {\n return _chart._computeOrderedGroups(group.all());\n } else {\n var topRows = group.top(_cap); // ordered by crossfilter group order (default value)\n topRows = _chart._computeOrderedGroups(topRows); // re-order using ordering (default key)\n if (_othersGrouper) {\n return _othersGrouper(topRows);\n }\n return topRows;\n }\n });\n\n /**\n * Get or set the count of elements to that will be included in the cap.\n * @method cap\n * @memberof dc.capMixin\n * @instance\n * @param {Number} [count=Infinity]\n * @return {Number}\n * @return {dc.capMixin}\n */\n _chart.cap = function (count) {\n if (!arguments.length) {\n return _cap;\n }\n _cap = count;\n return _chart;\n };\n\n /**\n * Get or set the label for *Others* slice when slices cap is specified\n * @method othersLabel\n * @memberof dc.capMixin\n * @instance\n * @param {String} [label=\"Others\"]\n * @return {String}\n * @return {dc.capMixin}\n */\n _chart.othersLabel = function (label) {\n if (!arguments.length) {\n return _othersLabel;\n }\n _othersLabel = label;\n return _chart;\n };\n\n /**\n * Get or set the grouper function that will perform the insertion of data for the *Others* slice\n * if the slices cap is specified. If set to a falsy value, no others will be added. By default the\n * grouper function computes the sum of all values below the cap.\n * @method othersGrouper\n * @memberof dc.capMixin\n * @instance\n * @example\n * // Default others grouper\n * chart.othersGrouper(function (topRows) {\n * var topRowsSum = d3.sum(topRows, _chart.valueAccessor()),\n * allRows = _chart.group().all(),\n * allRowsSum = d3.sum(allRows, _chart.valueAccessor()),\n * topKeys = topRows.map(_chart.keyAccessor()),\n * allKeys = allRows.map(_chart.keyAccessor()),\n * topSet = d3.set(topKeys),\n * others = allKeys.filter(function (d) {return !topSet.has(d);});\n * if (allRowsSum > topRowsSum) {\n * return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]);\n * }\n * return topRows;\n * });\n * // Custom others grouper\n * chart.othersGrouper(function (data) {\n * // compute the value for others, presumably the sum of all values below the cap\n * var othersSum = yourComputeOthersValueLogic(data)\n *\n * // the keys are needed to properly filter when the others element is clicked\n * var othersKeys = yourComputeOthersKeysArrayLogic(data);\n *\n * // add the others row to the dataset\n * data.push({'key': 'Others', 'value': othersSum, 'others': othersKeys });\n *\n * return data;\n * });\n * @param {Function} [grouperFunction]\n * @return {Function}\n * @return {dc.capMixin}\n */\n _chart.othersGrouper = function (grouperFunction) {\n if (!arguments.length) {\n return _othersGrouper;\n }\n _othersGrouper = grouperFunction;\n return _chart;\n };\n\n dc.override(_chart, 'onClick', function (d) {\n if (d.others) {\n _chart.filter([d.others]);\n }\n _chart._onClick(d);\n });\n\n return _chart;\n};\n","/**\n * This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles.\n * @name bubbleMixin\n * @memberof dc\n * @mixin\n * @mixes dc.colorMixin\n * @param {Object} _chart\n * @return {dc.bubbleMixin}\n */\ndc.bubbleMixin = function (_chart) {\n var _maxBubbleRelativeSize = 0.3;\n var _minRadiusWithLabel = 10;\n\n _chart.BUBBLE_NODE_CLASS = 'node';\n _chart.BUBBLE_CLASS = 'bubble';\n _chart.MIN_RADIUS = 10;\n\n _chart = dc.colorMixin(_chart);\n\n _chart.renderLabel(true);\n\n _chart.data(function (group) {\n return group.top(Infinity);\n });\n\n var _r = d3.scale.linear().domain([0, 100]);\n\n var _rValueAccessor = function (d) {\n return d.r;\n };\n\n /**\n * Get or set the bubble radius scale. By default the bubble chart uses\n * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales#linear d3.scale.linear().domain([0, 100])}\n * as its radius scale.\n * @method r\n * @memberof dc.bubbleMixin\n * @instance\n * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale}\n * @param {d3.scale} [bubbleRadiusScale=d3.scale.linear().domain([0, 100])]\n * @return {d3.scale}\n * @return {dc.bubbleMixin}\n */\n _chart.r = function (bubbleRadiusScale) {\n if (!arguments.length) {\n return _r;\n }\n _r = bubbleRadiusScale;\n return _chart;\n };\n\n /**\n * Get or set the radius value accessor function. If set, the radius value accessor function will\n * be used to retrieve a data value for each bubble. The data retrieved then will be mapped using\n * the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble\n * size.\n * @method radiusValueAccessor\n * @memberof dc.bubbleMixin\n * @instance\n * @param {Function} [radiusValueAccessor]\n * @return {Function}\n * @return {dc.bubbleMixin}\n */\n _chart.radiusValueAccessor = function (radiusValueAccessor) {\n if (!arguments.length) {\n return _rValueAccessor;\n }\n _rValueAccessor = radiusValueAccessor;\n return _chart;\n };\n\n _chart.rMin = function () {\n var min = d3.min(_chart.data(), function (e) {\n return _chart.radiusValueAccessor()(e);\n });\n return min;\n };\n\n _chart.rMax = function () {\n var max = d3.max(_chart.data(), function (e) {\n return _chart.radiusValueAccessor()(e);\n });\n return max;\n };\n\n _chart.bubbleR = function (d) {\n var value = _chart.radiusValueAccessor()(d);\n var r = _chart.r()(value);\n if (isNaN(r) || value <= 0) {\n r = 0;\n }\n return r;\n };\n\n var labelFunction = function (d) {\n return _chart.label()(d);\n };\n\n var shouldLabel = function (d) {\n return (_chart.bubbleR(d) > _minRadiusWithLabel);\n };\n\n var labelOpacity = function (d) {\n return shouldLabel(d) ? 1 : 0;\n };\n\n var labelPointerEvent = function (d) {\n return shouldLabel(d) ? 'all' : 'none';\n };\n\n _chart._doRenderLabel = function (bubbleGEnter) {\n if (_chart.renderLabel()) {\n var label = bubbleGEnter.select('text');\n\n if (label.empty()) {\n label = bubbleGEnter.append('text')\n .attr('text-anchor', 'middle')\n .attr('dy', '.3em')\n .on('click', _chart.onClick);\n }\n\n label\n .attr('opacity', 0)\n .attr('pointer-events', labelPointerEvent)\n .text(labelFunction);\n dc.transition(label, _chart.transitionDuration())\n .attr('opacity', labelOpacity);\n }\n };\n\n _chart.doUpdateLabels = function (bubbleGEnter) {\n if (_chart.renderLabel()) {\n var labels = bubbleGEnter.selectAll('text')\n .attr('pointer-events', labelPointerEvent)\n .text(labelFunction);\n dc.transition(labels, _chart.transitionDuration())\n .attr('opacity', labelOpacity);\n }\n };\n\n var titleFunction = function (d) {\n return _chart.title()(d);\n };\n\n _chart._doRenderTitles = function (g) {\n if (_chart.renderTitle()) {\n var title = g.select('title');\n\n if (title.empty()) {\n g.append('title').text(titleFunction);\n }\n }\n };\n\n _chart.doUpdateTitles = function (g) {\n if (_chart.renderTitle()) {\n g.selectAll('title').text(titleFunction);\n }\n };\n\n /**\n * Get or set the minimum radius. This will be used to initialize the radius scale's range.\n * @method minRadius\n * @memberof dc.bubbleMixin\n * @instance\n * @param {Number} [radius=10]\n * @return {Number}\n * @return {dc.bubbleMixin}\n */\n _chart.minRadius = function (radius) {\n if (!arguments.length) {\n return _chart.MIN_RADIUS;\n }\n _chart.MIN_RADIUS = radius;\n return _chart;\n };\n\n /**\n * Get or set the minimum radius for label rendering. If a bubble's radius is less than this value\n * then no label will be rendered.\n * @method minRadiusWithLabel\n * @memberof dc.bubbleMixin\n * @instance\n * @param {Number} [radius=10]\n * @return {Number}\n * @return {dc.bubbleMixin}\n */\n\n _chart.minRadiusWithLabel = function (radius) {\n if (!arguments.length) {\n return _minRadiusWithLabel;\n }\n _minRadiusWithLabel = radius;\n return _chart;\n };\n\n /**\n * Get or set the maximum relative size of a bubble to the length of x axis. This value is useful\n * when the difference in radius between bubbles is too great.\n * @method maxBubbleRelativeSize\n * @memberof dc.bubbleMixin\n * @instance\n * @param {Number} [relativeSize=0.3]\n * @return {Number}\n * @return {dc.bubbleMixin}\n */\n _chart.maxBubbleRelativeSize = function (relativeSize) {\n if (!arguments.length) {\n return _maxBubbleRelativeSize;\n }\n _maxBubbleRelativeSize = relativeSize;\n return _chart;\n };\n\n _chart.fadeDeselectedArea = function () {\n if (_chart.hasFilter()) {\n _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function (d) {\n if (_chart.isSelectedNode(d)) {\n _chart.highlightSelected(this);\n } else {\n _chart.fadeDeselected(this);\n }\n });\n } else {\n _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function () {\n _chart.resetHighlight(this);\n });\n }\n };\n\n _chart.isSelectedNode = function (d) {\n return _chart.hasFilter(d.key);\n };\n\n _chart.onClick = function (d) {\n var filter = d.key;\n dc.events.trigger(function () {\n _chart.filter(filter);\n _chart.redrawGroup();\n });\n };\n\n return _chart;\n};\n","/**\n * The pie chart implementation is usually used to visualize a small categorical distribution. The pie\n * chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each\n * slice relative to the sum of all values. Slices are ordered by {@link dc.baseMixin#ordering ordering}\n * which defaults to sorting by key.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * @class pieChart\n * @memberof dc\n * @mixes dc.capMixin\n * @mixes dc.colorMixin\n * @mixes dc.baseMixin\n * @example\n * // create a pie chart under #chart-container1 element using the default global chart group\n * var chart1 = dc.pieChart('#chart-container1');\n * // create a pie chart under #chart-container2 element using chart group A\n * var chart2 = dc.pieChart('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.pieChart}\n */\ndc.pieChart = function (parent, chartGroup) {\n var DEFAULT_MIN_ANGLE_FOR_LABEL = 0.5;\n\n var _sliceCssClass = 'pie-slice';\n var _labelCssClass = 'pie-label';\n var _sliceGroupCssClass = 'pie-slice-group';\n var _labelGroupCssClass = 'pie-label-group';\n var _emptyCssClass = 'empty-chart';\n var _emptyTitle = 'empty';\n\n var _radius,\n _givenRadius, // specified radius, if any\n _innerRadius = 0,\n _externalRadiusPadding = 0;\n\n var _g;\n var _cx;\n var _cy;\n var _minAngleForLabel = DEFAULT_MIN_ANGLE_FOR_LABEL;\n var _externalLabelRadius;\n var _drawPaths = false;\n var _chart = dc.capMixin(dc.colorMixin(dc.baseMixin({})));\n\n _chart.colorAccessor(_chart.cappedKeyAccessor);\n\n _chart.title(function (d) {\n return _chart.cappedKeyAccessor(d) + ': ' + _chart.cappedValueAccessor(d);\n });\n\n /**\n * Get or set the maximum number of slices the pie chart will generate. The top slices are determined by\n * value from high to low. Other slices exeeding the cap will be rolled up into one single *Others* slice.\n * @method slicesCap\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [cap]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.slicesCap = _chart.cap;\n\n _chart.label(_chart.cappedKeyAccessor);\n _chart.renderLabel(true);\n\n _chart.transitionDuration(350);\n\n _chart._doRender = function () {\n _chart.resetSvg();\n\n _g = _chart.svg()\n .append('g')\n .attr('transform', 'translate(' + _chart.cx() + ',' + _chart.cy() + ')');\n\n _g.append('g').attr('class', _sliceGroupCssClass);\n _g.append('g').attr('class', _labelGroupCssClass);\n\n drawChart();\n\n return _chart;\n };\n\n function drawChart () {\n // set radius on basis of chart dimension if missing\n _radius = _givenRadius ? _givenRadius : d3.min([_chart.width(), _chart.height()]) / 2;\n\n var arc = buildArcs();\n\n var pie = pieLayout();\n var pieData;\n // if we have data...\n if (d3.sum(_chart.data(), _chart.valueAccessor())) {\n pieData = pie(_chart.data());\n _g.classed(_emptyCssClass, false);\n } else {\n // otherwise we'd be getting NaNs, so override\n // note: abuse others for its ignoring the value accessor\n pieData = pie([{key: _emptyTitle, value: 1, others: [_emptyTitle]}]);\n _g.classed(_emptyCssClass, true);\n }\n\n if (_g) {\n var slices = _g.select('g.' + _sliceGroupCssClass)\n .selectAll('g.' + _sliceCssClass)\n .data(pieData);\n\n var labels = _g.select('g.' + _labelGroupCssClass)\n .selectAll('text.' + _labelCssClass)\n .data(pieData);\n\n createElements(slices, labels, arc, pieData);\n\n updateElements(pieData, arc);\n\n removeElements(slices, labels);\n\n highlightFilter();\n\n dc.transition(_g, _chart.transitionDuration())\n .attr('transform', 'translate(' + _chart.cx() + ',' + _chart.cy() + ')');\n }\n }\n\n function createElements (slices, labels, arc, pieData) {\n var slicesEnter = createSliceNodes(slices);\n\n createSlicePath(slicesEnter, arc);\n\n createTitles(slicesEnter);\n\n createLabels(labels, pieData, arc);\n }\n\n function createSliceNodes (slices) {\n var slicesEnter = slices\n .enter()\n .append('g')\n .attr('class', function (d, i) {\n return _sliceCssClass + ' _' + i;\n });\n return slicesEnter;\n }\n\n function createSlicePath (slicesEnter, arc) {\n var slicePath = slicesEnter.append('path')\n .attr('fill', fill)\n .on('click', onClick)\n .attr('d', function (d, i) {\n return safeArc(d, i, arc);\n });\n\n dc.transition(slicePath, _chart.transitionDuration(), function (s) {\n s.attrTween('d', tweenPie);\n });\n }\n\n function createTitles (slicesEnter) {\n if (_chart.renderTitle()) {\n slicesEnter.append('title').text(function (d) {\n return _chart.title()(d.data);\n });\n }\n }\n\n _chart._applyLabelText = function (labels) {\n labels\n .text(function (d) {\n var data = d.data;\n if ((sliceHasNoData(data) || sliceTooSmall(d)) && !isSelectedSlice(d)) {\n return '';\n }\n return _chart.label()(d.data);\n });\n };\n\n function positionLabels (labels, arc) {\n _chart._applyLabelText(labels);\n dc.transition(labels, _chart.transitionDuration())\n .attr('transform', function (d) {\n return labelPosition(d, arc);\n })\n .attr('text-anchor', 'middle');\n }\n\n function highlightSlice (i, whether) {\n _chart.select('g.pie-slice._' + i)\n .classed('highlight', whether);\n }\n\n function createLabels (labels, pieData, arc) {\n if (_chart.renderLabel()) {\n var labelsEnter = labels\n .enter()\n .append('text')\n .attr('class', function (d, i) {\n var classes = _sliceCssClass + ' ' + _labelCssClass + ' _' + i;\n if (_externalLabelRadius) {\n classes += ' external';\n }\n return classes;\n })\n .on('click', onClick)\n .on('mouseover', function (d, i) {\n highlightSlice(i, true);\n })\n .on('mouseout', function (d, i) {\n highlightSlice(i, false);\n });\n positionLabels(labelsEnter, arc);\n if (_externalLabelRadius && _drawPaths) {\n updateLabelPaths(pieData, arc);\n }\n }\n }\n\n function updateLabelPaths (pieData, arc) {\n var polyline = _g.selectAll('polyline.' + _sliceCssClass)\n .data(pieData);\n\n polyline\n .enter()\n .append('polyline')\n .attr('class', function (d, i) {\n return 'pie-path _' + i + ' ' + _sliceCssClass;\n })\n .on('click', onClick)\n .on('mouseover', function (d, i) {\n highlightSlice(i, true);\n })\n .on('mouseout', function (d, i) {\n highlightSlice(i, false);\n });\n\n polyline.exit().remove();\n var arc2 = d3.svg.arc()\n .outerRadius(_radius - _externalRadiusPadding + _externalLabelRadius)\n .innerRadius(_radius - _externalRadiusPadding);\n var transition = dc.transition(polyline, _chart.transitionDuration());\n // this is one rare case where d3.selection differs from d3.transition\n if (transition.attrTween) {\n transition\n .attrTween('points', function (d) {\n this._current = this._current || d;\n var interpolate = d3.interpolate(this._current, d);\n this._current = interpolate(0);\n return function (t) {\n var d2 = interpolate(t);\n return [arc.centroid(d2), arc2.centroid(d2)];\n };\n });\n } else {\n transition.attr('points', function (d) {\n return [arc.centroid(d), arc2.centroid(d)];\n });\n }\n transition.style('visibility', function (d) {\n return d.endAngle - d.startAngle < 0.0001 ? 'hidden' : 'visible';\n });\n\n }\n\n function updateElements (pieData, arc) {\n updateSlicePaths(pieData, arc);\n updateLabels(pieData, arc);\n updateTitles(pieData);\n }\n\n function updateSlicePaths (pieData, arc) {\n var slicePaths = _g.selectAll('g.' + _sliceCssClass)\n .data(pieData)\n .select('path')\n .attr('d', function (d, i) {\n return safeArc(d, i, arc);\n });\n dc.transition(slicePaths, _chart.transitionDuration(),\n function (s) {\n s.attrTween('d', tweenPie);\n }).attr('fill', fill);\n }\n\n function updateLabels (pieData, arc) {\n if (_chart.renderLabel()) {\n var labels = _g.selectAll('text.' + _labelCssClass)\n .data(pieData);\n positionLabels(labels, arc);\n if (_externalLabelRadius && _drawPaths) {\n updateLabelPaths(pieData, arc);\n }\n }\n }\n\n function updateTitles (pieData) {\n if (_chart.renderTitle()) {\n _g.selectAll('g.' + _sliceCssClass)\n .data(pieData)\n .select('title')\n .text(function (d) {\n return _chart.title()(d.data);\n });\n }\n }\n\n function removeElements (slices, labels) {\n slices.exit().remove();\n labels.exit().remove();\n }\n\n function highlightFilter () {\n if (_chart.hasFilter()) {\n _chart.selectAll('g.' + _sliceCssClass).each(function (d) {\n if (isSelectedSlice(d)) {\n _chart.highlightSelected(this);\n } else {\n _chart.fadeDeselected(this);\n }\n });\n } else {\n _chart.selectAll('g.' + _sliceCssClass).each(function () {\n _chart.resetHighlight(this);\n });\n }\n }\n\n /**\n * Get or set the external radius padding of the pie chart. This will force the radius of the\n * pie chart to become smaller or larger depending on the value.\n * @method externalRadiusPadding\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [externalRadiusPadding=0]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.externalRadiusPadding = function (externalRadiusPadding) {\n if (!arguments.length) {\n return _externalRadiusPadding;\n }\n _externalRadiusPadding = externalRadiusPadding;\n return _chart;\n };\n\n /**\n * Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the\n * pie chart will be rendered as a doughnut chart.\n * @method innerRadius\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [innerRadius=0]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.innerRadius = function (innerRadius) {\n if (!arguments.length) {\n return _innerRadius;\n }\n _innerRadius = innerRadius;\n return _chart;\n };\n\n /**\n * Get or set the outer radius. If the radius is not set, it will be half of the minimum of the\n * chart width and height.\n * @method radius\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [radius]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.radius = function (radius) {\n if (!arguments.length) {\n return _givenRadius;\n }\n _givenRadius = radius;\n return _chart;\n };\n\n /**\n * Get or set center x coordinate position. Default is center of svg.\n * @method cx\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [cx]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.cx = function (cx) {\n if (!arguments.length) {\n return (_cx || _chart.width() / 2);\n }\n _cx = cx;\n return _chart;\n };\n\n /**\n * Get or set center y coordinate position. Default is center of svg.\n * @method cy\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [cy]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.cy = function (cy) {\n if (!arguments.length) {\n return (_cy || _chart.height() / 2);\n }\n _cy = cy;\n return _chart;\n };\n\n function buildArcs () {\n return d3.svg.arc()\n .outerRadius(_radius - _externalRadiusPadding)\n .innerRadius(_innerRadius);\n }\n\n function isSelectedSlice (d) {\n return _chart.hasFilter(_chart.cappedKeyAccessor(d.data));\n }\n\n _chart._doRedraw = function () {\n drawChart();\n return _chart;\n };\n\n /**\n * Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not\n * display a slice label.\n * @method minAngleForLabel\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [minAngleForLabel=0.5]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.minAngleForLabel = function (minAngleForLabel) {\n if (!arguments.length) {\n return _minAngleForLabel;\n }\n _minAngleForLabel = minAngleForLabel;\n return _chart;\n };\n\n function pieLayout () {\n return d3.layout.pie().sort(null).value(_chart.cappedValueAccessor);\n }\n\n function sliceTooSmall (d) {\n var angle = (d.endAngle - d.startAngle);\n return isNaN(angle) || angle < _minAngleForLabel;\n }\n\n function sliceHasNoData (d) {\n return _chart.cappedValueAccessor(d) === 0;\n }\n\n function tweenPie (b) {\n b.innerRadius = _innerRadius;\n var current = this._current;\n if (isOffCanvas(current)) {\n current = {startAngle: 0, endAngle: 0};\n } else {\n // only interpolate startAngle & endAngle, not the whole data object\n current = {startAngle: current.startAngle, endAngle: current.endAngle};\n }\n var i = d3.interpolate(current, b);\n this._current = i(0);\n return function (t) {\n return safeArc(i(t), 0, buildArcs());\n };\n }\n\n function isOffCanvas (current) {\n return !current || isNaN(current.startAngle) || isNaN(current.endAngle);\n }\n\n function fill (d, i) {\n return _chart.getColor(d.data, i);\n }\n\n function onClick (d, i) {\n if (_g.attr('class') !== _emptyCssClass) {\n _chart.onClick(d.data, i);\n }\n }\n\n function safeArc (d, i, arc) {\n var path = arc(d, i);\n if (path.indexOf('NaN') >= 0) {\n path = 'M0,0';\n }\n return path;\n }\n\n /**\n * Title to use for the only slice when there is no data.\n * @method emptyTitle\n * @memberof dc.pieChart\n * @instance\n * @param {String} [title]\n * @return {String}\n * @return {dc.pieChart}\n */\n _chart.emptyTitle = function (title) {\n if (arguments.length === 0) {\n return _emptyTitle;\n }\n _emptyTitle = title;\n return _chart;\n };\n\n /**\n * Position slice labels offset from the outer edge of the chart\n *\n * The given argument sets the radial offset.\n * @method externalLabels\n * @memberof dc.pieChart\n * @instance\n * @param {Number} [externalLabelRadius]\n * @return {Number}\n * @return {dc.pieChart}\n */\n _chart.externalLabels = function (externalLabelRadius) {\n if (arguments.length === 0) {\n return _externalLabelRadius;\n } else if (externalLabelRadius) {\n _externalLabelRadius = externalLabelRadius;\n } else {\n _externalLabelRadius = undefined;\n }\n\n return _chart;\n };\n\n /**\n * Get or set whether to draw lines from pie slices to their labels.\n *\n * @method drawPaths\n * @memberof dc.pieChart\n * @instance\n * @param {Boolean} [drawPaths]\n * @return {Boolean}\n * @return {dc.pieChart}\n */\n _chart.drawPaths = function (drawPaths) {\n if (arguments.length === 0) {\n return _drawPaths;\n }\n _drawPaths = drawPaths;\n return _chart;\n };\n\n function labelPosition (d, arc) {\n var centroid;\n if (_externalLabelRadius) {\n centroid = d3.svg.arc()\n .outerRadius(_radius - _externalRadiusPadding + _externalLabelRadius)\n .innerRadius(_radius - _externalRadiusPadding + _externalLabelRadius)\n .centroid(d);\n } else {\n centroid = arc.centroid(d);\n }\n if (isNaN(centroid[0]) || isNaN(centroid[1])) {\n return 'translate(0,0)';\n } else {\n return 'translate(' + centroid + ')';\n }\n }\n\n _chart.legendables = function () {\n return _chart.data().map(function (d, i) {\n var legendable = {name: d.key, data: d.value, others: d.others, chart: _chart};\n legendable.color = _chart.getColor(d, i);\n return legendable;\n });\n };\n\n _chart.legendHighlight = function (d) {\n highlightSliceFromLegendable(d, true);\n };\n\n _chart.legendReset = function (d) {\n highlightSliceFromLegendable(d, false);\n };\n\n _chart.legendToggle = function (d) {\n _chart.onClick({key: d.name, others: d.others});\n };\n\n function highlightSliceFromLegendable (legendable, highlighted) {\n _chart.selectAll('g.pie-slice').each(function (d) {\n if (legendable.name === d.data.key) {\n d3.select(this).classed('highlight', highlighted);\n }\n });\n }\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * Concrete bar chart/histogram implementation.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats}\n * @class barChart\n * @memberof dc\n * @mixes dc.stackMixin\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a bar chart under #chart-container1 element using the default global chart group\n * var chart1 = dc.barChart('#chart-container1');\n * // create a bar chart under #chart-container2 element using chart group A\n * var chart2 = dc.barChart('#chart-container2', 'chartGroupA');\n * // create a sub-chart under a composite parent chart\n * var chart3 = dc.barChart(compositeChart);\n * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector}\n * specifying a dom block element such as a div; or a dom element or d3 selection. If the bar\n * chart is a sub-chart in a {@link dc.compositeChart Composite Chart} then pass in the parent\n * composite chart instance instead.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.barChart}\n */\ndc.barChart = function (parent, chartGroup) {\n var MIN_BAR_WIDTH = 1;\n var DEFAULT_GAP_BETWEEN_BARS = 2;\n var LABEL_PADDING = 3;\n\n var _chart = dc.stackMixin(dc.coordinateGridMixin({}));\n\n var _gap = DEFAULT_GAP_BETWEEN_BARS;\n var _centerBar = false;\n var _alwaysUseRounding = false;\n\n var _barWidth;\n\n dc.override(_chart, 'rescale', function () {\n _chart._rescale();\n _barWidth = undefined;\n return _chart;\n });\n\n dc.override(_chart, 'render', function () {\n if (_chart.round() && _centerBar && !_alwaysUseRounding) {\n dc.logger.warn('By default, brush rounding is disabled if bars are centered. ' +\n 'See dc.js bar chart API documentation for details.');\n }\n\n return _chart._render();\n });\n\n _chart.label(function (d) {\n return dc.utils.printSingleValue(d.y0 + d.y);\n }, false);\n\n _chart.plotData = function () {\n var layers = _chart.chartBodyG().selectAll('g.stack')\n .data(_chart.data());\n\n calculateBarWidth();\n\n layers\n .enter()\n .append('g')\n .attr('class', function (d, i) {\n return 'stack ' + '_' + i;\n });\n\n var last = layers.size() - 1;\n layers.each(function (d, i) {\n var layer = d3.select(this);\n\n renderBars(layer, i, d);\n\n if (_chart.renderLabel() && last === i) {\n renderLabels(layer, i, d);\n }\n });\n };\n\n function barHeight (d) {\n return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0)));\n }\n\n function renderLabels (layer, layerIndex, d) {\n var labels = layer.selectAll('text.barLabel')\n .data(d.values, dc.pluck('x'));\n\n labels.enter()\n .append('text')\n .attr('class', 'barLabel')\n .attr('text-anchor', 'middle');\n\n if (_chart.isOrdinal()) {\n labels.on('click', _chart.onClick);\n labels.attr('cursor', 'pointer');\n }\n\n dc.transition(labels, _chart.transitionDuration())\n .attr('x', function (d) {\n var x = _chart.x()(d.x);\n if (!_centerBar) {\n x += _barWidth / 2;\n }\n return dc.utils.safeNumber(x);\n })\n .attr('y', function (d) {\n var y = _chart.y()(d.y + d.y0);\n\n if (d.y < 0) {\n y -= barHeight(d);\n }\n\n return dc.utils.safeNumber(y - LABEL_PADDING);\n })\n .text(function (d) {\n return _chart.label()(d);\n });\n\n dc.transition(labels.exit(), _chart.transitionDuration())\n .attr('height', 0)\n .remove();\n }\n\n function renderBars (layer, layerIndex, d) {\n var bars = layer.selectAll('rect.bar')\n .data(d.values, dc.pluck('x'));\n\n var enter = bars.enter()\n .append('rect')\n .attr('class', 'bar')\n .attr('fill', dc.pluck('data', _chart.getColor))\n .attr('y', _chart.yAxisHeight())\n .attr('height', 0);\n\n if (_chart.renderTitle()) {\n enter.append('title').text(dc.pluck('data', _chart.title(d.name)));\n }\n\n if (_chart.isOrdinal()) {\n bars.on('click', _chart.onClick);\n }\n\n dc.transition(bars, _chart.transitionDuration())\n .attr('x', function (d) {\n var x = _chart.x()(d.x);\n if (_centerBar) {\n x -= _barWidth / 2;\n }\n if (_chart.isOrdinal() && _gap !== undefined) {\n x += _gap / 2;\n }\n return dc.utils.safeNumber(x);\n })\n .attr('y', function (d) {\n var y = _chart.y()(d.y + d.y0);\n\n if (d.y < 0) {\n y -= barHeight(d);\n }\n\n return dc.utils.safeNumber(y);\n })\n .attr('width', _barWidth)\n .attr('height', function (d) {\n return barHeight(d);\n })\n .attr('fill', dc.pluck('data', _chart.getColor))\n .select('title').text(dc.pluck('data', _chart.title(d.name)));\n\n dc.transition(bars.exit(), _chart.transitionDuration())\n .attr('x', function (d) { return _chart.x()(d.x); })\n .attr('width', _barWidth * 0.9)\n .remove();\n }\n\n function calculateBarWidth () {\n if (_barWidth === undefined) {\n var numberOfBars = _chart.xUnitCount();\n\n // please can't we always use rangeBands for bar charts?\n if (_chart.isOrdinal() && _gap === undefined) {\n _barWidth = Math.floor(_chart.x().rangeBand());\n } else if (_gap) {\n _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars);\n } else {\n _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars);\n }\n\n if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) {\n _barWidth = MIN_BAR_WIDTH;\n }\n }\n }\n\n _chart.fadeDeselectedArea = function () {\n var bars = _chart.chartBodyG().selectAll('rect.bar');\n var extent = _chart.brush().extent();\n\n if (_chart.isOrdinal()) {\n if (_chart.hasFilter()) {\n bars.classed(dc.constants.SELECTED_CLASS, function (d) {\n return _chart.hasFilter(d.x);\n });\n bars.classed(dc.constants.DESELECTED_CLASS, function (d) {\n return !_chart.hasFilter(d.x);\n });\n } else {\n bars.classed(dc.constants.SELECTED_CLASS, false);\n bars.classed(dc.constants.DESELECTED_CLASS, false);\n }\n } else {\n if (!_chart.brushIsEmpty(extent)) {\n var start = extent[0];\n var end = extent[1];\n\n bars.classed(dc.constants.DESELECTED_CLASS, function (d) {\n return d.x < start || d.x >= end;\n });\n } else {\n bars.classed(dc.constants.DESELECTED_CLASS, false);\n }\n }\n };\n\n /**\n * Whether the bar chart will render each bar centered around the data position on the x-axis.\n * @method centerBar\n * @memberof dc.barChart\n * @instance\n * @param {Boolean} [centerBar=false]\n * @return {Boolean}\n * @return {dc.barChart}\n */\n _chart.centerBar = function (centerBar) {\n if (!arguments.length) {\n return _centerBar;\n }\n _centerBar = centerBar;\n return _chart;\n };\n\n dc.override(_chart, 'onClick', function (d) {\n _chart._onClick(d.data);\n });\n\n /**\n * Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1.\n * Setting this value will also remove any previously set {@link dc.barChart#gap gap}. See the\n * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs}\n * for a visual description of how the padding is applied.\n * @method barPadding\n * @memberof dc.barChart\n * @instance\n * @param {Number} [barPadding=0]\n * @return {Number}\n * @return {dc.barChart}\n */\n _chart.barPadding = function (barPadding) {\n if (!arguments.length) {\n return _chart._rangeBandPadding();\n }\n _chart._rangeBandPadding(barPadding);\n _gap = undefined;\n return _chart;\n };\n\n _chart._useOuterPadding = function () {\n return _gap === undefined;\n };\n\n /**\n * Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts.\n * Will pad the width by `padding * barWidth` on each side of the chart.\n * @method outerPadding\n * @memberof dc.barChart\n * @instance\n * @param {Number} [padding=0.5]\n * @return {Number}\n * @return {dc.barChart}\n */\n _chart.outerPadding = _chart._outerRangeBandPadding;\n\n /**\n * Manually set fixed gap (in px) between bars instead of relying on the default auto-generated\n * gap. By default the bar chart implementation will calculate and set the gap automatically\n * based on the number of data points and the length of the x axis.\n * @method gap\n * @memberof dc.barChart\n * @instance\n * @param {Number} [gap=2]\n * @return {Number}\n * @return {dc.barChart}\n */\n _chart.gap = function (gap) {\n if (!arguments.length) {\n return _gap;\n }\n _gap = gap;\n return _chart;\n };\n\n _chart.extendBrush = function () {\n var extent = _chart.brush().extent();\n if (_chart.round() && (!_centerBar || _alwaysUseRounding)) {\n extent[0] = extent.map(_chart.round())[0];\n extent[1] = extent.map(_chart.round())[1];\n\n _chart.chartBodyG().select('.brush')\n .call(_chart.brush().extent(extent));\n }\n\n return extent;\n };\n\n /**\n * Set or get whether rounding is enabled when bars are centered. If false, using\n * rounding with centered bars will result in a warning and rounding will be ignored. This flag\n * has no effect if bars are not {@link dc.barChart#centerBar centered}.\n * When using standard d3.js rounding methods, the brush often doesn't align correctly with\n * centered bars since the bars are offset. The rounding function must add an offset to\n * compensate, such as in the following example.\n * @method alwaysUseRounding\n * @memberof dc.barChart\n * @instance\n * @example\n * chart.round(function(n) { return Math.floor(n) + 0.5; });\n * @param {Boolean} [alwaysUseRounding=false]\n * @return {Boolean}\n * @return {dc.barChart}\n */\n _chart.alwaysUseRounding = function (alwaysUseRounding) {\n if (!arguments.length) {\n return _alwaysUseRounding;\n }\n _alwaysUseRounding = alwaysUseRounding;\n return _chart;\n };\n\n function colorFilter (color, inv) {\n return function () {\n var item = d3.select(this);\n var match = item.attr('fill') === color;\n return inv ? !match : match;\n };\n }\n\n _chart.legendHighlight = function (d) {\n if (!_chart.isLegendableHidden(d)) {\n _chart.g().selectAll('rect.bar')\n .classed('highlight', colorFilter(d.color))\n .classed('fadeout', colorFilter(d.color, true));\n }\n };\n\n _chart.legendReset = function () {\n _chart.g().selectAll('rect.bar')\n .classed('highlight', false)\n .classed('fadeout', false);\n };\n\n dc.override(_chart, 'xAxisMax', function () {\n var max = this._xAxisMax();\n if ('resolution' in _chart.xUnits()) {\n var res = _chart.xUnits().resolution;\n max += res;\n }\n return max;\n });\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * Concrete line/area chart implementation.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats}\n * @class lineChart\n * @memberof dc\n * @mixes dc.stackMixin\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a line chart under #chart-container1 element using the default global chart group\n * var chart1 = dc.lineChart('#chart-container1');\n * // create a line chart under #chart-container2 element using chart group A\n * var chart2 = dc.lineChart('#chart-container2', 'chartGroupA');\n * // create a sub-chart under a composite parent chart\n * var chart3 = dc.lineChart(compositeChart);\n * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector}\n * specifying a dom block element such as a div; or a dom element or d3 selection. If the line\n * chart is a sub-chart in a {@link dc.compositeChart Composite Chart} then pass in the parent\n * composite chart instance instead.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.lineChart}\n */\ndc.lineChart = function (parent, chartGroup) {\n var DEFAULT_DOT_RADIUS = 5;\n var TOOLTIP_G_CLASS = 'dc-tooltip';\n var DOT_CIRCLE_CLASS = 'dot';\n var Y_AXIS_REF_LINE_CLASS = 'yRef';\n var X_AXIS_REF_LINE_CLASS = 'xRef';\n var DEFAULT_DOT_OPACITY = 1e-6;\n var LABEL_PADDING = 3;\n\n var _chart = dc.stackMixin(dc.coordinateGridMixin({}));\n var _renderArea = false;\n var _dotRadius = DEFAULT_DOT_RADIUS;\n var _dataPointRadius = null;\n var _dataPointFillOpacity = DEFAULT_DOT_OPACITY;\n var _dataPointStrokeOpacity = DEFAULT_DOT_OPACITY;\n var _interpolate = 'linear';\n var _tension = 0.7;\n var _defined;\n var _dashStyle;\n var _xyTipsOn = true;\n\n _chart.transitionDuration(500);\n _chart._rangeBandPadding(1);\n\n _chart.plotData = function () {\n var chartBody = _chart.chartBodyG();\n var layersList = chartBody.selectAll('g.stack-list');\n\n if (layersList.empty()) {\n layersList = chartBody.append('g').attr('class', 'stack-list');\n }\n\n var layers = layersList.selectAll('g.stack').data(_chart.data());\n\n var layersEnter = layers\n .enter()\n .append('g')\n .attr('class', function (d, i) {\n return 'stack ' + '_' + i;\n });\n\n drawLine(layersEnter, layers);\n\n drawArea(layersEnter, layers);\n\n drawDots(chartBody, layers);\n\n if (_chart.renderLabel()) {\n drawLabels(layers);\n }\n };\n\n /**\n * Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step\n * functions, splines, and cubic interpolation. This is passed to\n * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate} and\n * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate},\n * where you can find a complete list of valid arguments\n * @method interpolate\n * @memberof dc.lineChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate}\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate}\n * @param {String} [interpolate='linear']\n * @return {String}\n * @return {dc.lineChart}\n */\n _chart.interpolate = function (interpolate) {\n if (!arguments.length) {\n return _interpolate;\n }\n _interpolate = interpolate;\n return _chart;\n };\n\n /**\n * Gets or sets the tension to use for lines drawn, in the range 0 to 1.\n * This parameter further customizes the interpolation behavior. It is passed to\n * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_tension d3.svg.line.tension} and\n * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_tension d3.svg.area.tension}.\n * @method tension\n * @memberof dc.lineChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate}\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate}\n * @param {Number} [tension=0.7]\n * @return {Number}\n * @return {dc.lineChart}\n */\n _chart.tension = function (tension) {\n if (!arguments.length) {\n return _tension;\n }\n _tension = tension;\n return _chart;\n };\n\n /**\n * Gets or sets a function that will determine discontinuities in the line which should be\n * skipped: the path will be broken into separate subpaths if some points are undefined.\n * This function is passed to\n * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_defined d3.svg.line.defined}\n *\n * Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write\n * custom reduce functions to get this to work, depending on your data. See\n * https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248\n * @method defined\n * @memberof dc.lineChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_defined d3.svg.line.defined}\n * @param {Function} [defined]\n * @return {Function}\n * @return {dc.lineChart}\n */\n _chart.defined = function (defined) {\n if (!arguments.length) {\n return _defined;\n }\n _defined = defined;\n return _chart;\n };\n\n /**\n * Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty\n * array (solid line).\n * @method dashStyle\n * @memberof dc.lineChart\n * @instance\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray stroke-dasharray}\n * @example\n * // create a Dash Dot Dot Dot\n * chart.dashStyle([3,1,1,1]);\n * @param {Array} [dashStyle=[]]\n * @return {Array}\n * @return {dc.lineChart}\n */\n _chart.dashStyle = function (dashStyle) {\n if (!arguments.length) {\n return _dashStyle;\n }\n _dashStyle = dashStyle;\n return _chart;\n };\n\n /**\n * Get or set render area flag. If the flag is set to true then the chart will render the area\n * beneath each line and the line chart effectively becomes an area chart.\n * @method renderArea\n * @memberof dc.lineChart\n * @instance\n * @param {Boolean} [renderArea=false]\n * @return {Boolean}\n * @return {dc.lineChart}\n */\n _chart.renderArea = function (renderArea) {\n if (!arguments.length) {\n return _renderArea;\n }\n _renderArea = renderArea;\n return _chart;\n };\n\n function colors (d, i) {\n return _chart.getColor.call(d, d.values, i);\n }\n\n function drawLine (layersEnter, layers) {\n var line = d3.svg.line()\n .x(function (d) {\n return _chart.x()(d.x);\n })\n .y(function (d) {\n return _chart.y()(d.y + d.y0);\n })\n .interpolate(_interpolate)\n .tension(_tension);\n if (_defined) {\n line.defined(_defined);\n }\n\n var path = layersEnter.append('path')\n .attr('class', 'line')\n .attr('stroke', colors);\n if (_dashStyle) {\n path.attr('stroke-dasharray', _dashStyle);\n }\n\n dc.transition(layers.select('path.line'), _chart.transitionDuration())\n //.ease('linear')\n .attr('stroke', colors)\n .attr('d', function (d) {\n return safeD(line(d.values));\n });\n }\n\n function drawArea (layersEnter, layers) {\n if (_renderArea) {\n var area = d3.svg.area()\n .x(function (d) {\n return _chart.x()(d.x);\n })\n .y(function (d) {\n return _chart.y()(d.y + d.y0);\n })\n .y0(function (d) {\n return _chart.y()(d.y0);\n })\n .interpolate(_interpolate)\n .tension(_tension);\n if (_defined) {\n area.defined(_defined);\n }\n\n layersEnter.append('path')\n .attr('class', 'area')\n .attr('fill', colors)\n .attr('d', function (d) {\n return safeD(area(d.values));\n });\n\n dc.transition(layers.select('path.area'), _chart.transitionDuration())\n //.ease('linear')\n .attr('fill', colors)\n .attr('d', function (d) {\n return safeD(area(d.values));\n });\n }\n }\n\n function safeD (d) {\n return (!d || d.indexOf('NaN') >= 0) ? 'M0,0' : d;\n }\n\n function drawDots (chartBody, layers) {\n if (!_chart.brushOn() && _chart.xyTipsOn()) {\n var tooltipListClass = TOOLTIP_G_CLASS + '-list';\n var tooltips = chartBody.select('g.' + tooltipListClass);\n\n if (tooltips.empty()) {\n tooltips = chartBody.append('g').attr('class', tooltipListClass);\n }\n\n layers.each(function (d, layerIndex) {\n var points = d.values;\n if (_defined) {\n points = points.filter(_defined);\n }\n\n var g = tooltips.select('g.' + TOOLTIP_G_CLASS + '._' + layerIndex);\n if (g.empty()) {\n g = tooltips.append('g').attr('class', TOOLTIP_G_CLASS + ' _' + layerIndex);\n }\n\n createRefLines(g);\n\n var dots = g.selectAll('circle.' + DOT_CIRCLE_CLASS)\n .data(points, dc.pluck('x'));\n\n dots.enter()\n .append('circle')\n .attr('class', DOT_CIRCLE_CLASS)\n .attr('r', getDotRadius())\n .style('fill-opacity', _dataPointFillOpacity)\n .style('stroke-opacity', _dataPointStrokeOpacity)\n .attr('fill', _chart.getColor)\n .on('mousemove', function () {\n var dot = d3.select(this);\n showDot(dot);\n showRefLines(dot, g);\n })\n .on('mouseout', function () {\n var dot = d3.select(this);\n hideDot(dot);\n hideRefLines(g);\n });\n\n dots.call(renderTitle, d);\n\n dc.transition(dots, _chart.transitionDuration())\n .attr('cx', function (d) {\n return dc.utils.safeNumber(_chart.x()(d.x));\n })\n .attr('cy', function (d) {\n return dc.utils.safeNumber(_chart.y()(d.y + d.y0));\n })\n .attr('fill', _chart.getColor);\n\n dots.exit().remove();\n });\n }\n }\n\n _chart.label(function (d) {\n return dc.utils.printSingleValue(d.y0 + d.y);\n }, false);\n\n function drawLabels (layers) {\n layers.each(function (d, layerIndex) {\n var layer = d3.select(this);\n var labels = layer.selectAll('text.lineLabel')\n .data(d.values, dc.pluck('x'));\n\n labels.enter()\n .append('text')\n .attr('class', 'lineLabel')\n .attr('text-anchor', 'middle');\n\n dc.transition(labels, _chart.transitionDuration())\n .attr('x', function (d) {\n return dc.utils.safeNumber(_chart.x()(d.x));\n })\n .attr('y', function (d) {\n var y = _chart.y()(d.y + d.y0) - LABEL_PADDING;\n return dc.utils.safeNumber(y);\n })\n .text(function (d) {\n return _chart.label()(d);\n });\n\n dc.transition(labels.exit(), _chart.transitionDuration())\n .attr('height', 0)\n .remove();\n });\n }\n\n function createRefLines (g) {\n var yRefLine = g.select('path.' + Y_AXIS_REF_LINE_CLASS).empty() ?\n g.append('path').attr('class', Y_AXIS_REF_LINE_CLASS) : g.select('path.' + Y_AXIS_REF_LINE_CLASS);\n yRefLine.style('display', 'none').attr('stroke-dasharray', '5,5');\n\n var xRefLine = g.select('path.' + X_AXIS_REF_LINE_CLASS).empty() ?\n g.append('path').attr('class', X_AXIS_REF_LINE_CLASS) : g.select('path.' + X_AXIS_REF_LINE_CLASS);\n xRefLine.style('display', 'none').attr('stroke-dasharray', '5,5');\n }\n\n function showDot (dot) {\n dot.style('fill-opacity', 0.8);\n dot.style('stroke-opacity', 0.8);\n dot.attr('r', _dotRadius);\n return dot;\n }\n\n function showRefLines (dot, g) {\n var x = dot.attr('cx');\n var y = dot.attr('cy');\n var yAxisX = (_chart._yAxisX() - _chart.margins().left);\n var yAxisRefPathD = 'M' + yAxisX + ' ' + y + 'L' + (x) + ' ' + (y);\n var xAxisRefPathD = 'M' + x + ' ' + _chart.yAxisHeight() + 'L' + x + ' ' + y;\n g.select('path.' + Y_AXIS_REF_LINE_CLASS).style('display', '').attr('d', yAxisRefPathD);\n g.select('path.' + X_AXIS_REF_LINE_CLASS).style('display', '').attr('d', xAxisRefPathD);\n }\n\n function getDotRadius () {\n return _dataPointRadius || _dotRadius;\n }\n\n function hideDot (dot) {\n dot.style('fill-opacity', _dataPointFillOpacity)\n .style('stroke-opacity', _dataPointStrokeOpacity)\n .attr('r', getDotRadius());\n }\n\n function hideRefLines (g) {\n g.select('path.' + Y_AXIS_REF_LINE_CLASS).style('display', 'none');\n g.select('path.' + X_AXIS_REF_LINE_CLASS).style('display', 'none');\n }\n\n function renderTitle (dot, d) {\n if (_chart.renderTitle()) {\n dot.selectAll('title').remove();\n dot.append('title').text(dc.pluck('data', _chart.title(d.name)));\n }\n }\n\n /**\n * Turn on/off the mouseover behavior of an individual data point which renders a circle and x/y axis\n * dashed lines back to each respective axis. This is ignored if the chart\n * {@link dc.coordinateGridMixin#brushOn brush} is on\n * @method xyTipsOn\n * @memberof dc.lineChart\n * @instance\n * @param {Boolean} [xyTipsOn=false]\n * @return {Boolean}\n * @return {dc.lineChart}\n */\n _chart.xyTipsOn = function (xyTipsOn) {\n if (!arguments.length) {\n return _xyTipsOn;\n }\n _xyTipsOn = xyTipsOn;\n return _chart;\n };\n\n /**\n * Get or set the radius (in px) for dots displayed on the data points.\n * @method dotRadius\n * @memberof dc.lineChart\n * @instance\n * @param {Number} [dotRadius=5]\n * @return {Number}\n * @return {dc.lineChart}\n */\n _chart.dotRadius = function (dotRadius) {\n if (!arguments.length) {\n return _dotRadius;\n }\n _dotRadius = dotRadius;\n return _chart;\n };\n\n /**\n * Always show individual dots for each datapoint.\n * If `options` is falsy, it disables data point rendering.\n *\n * If no `options` are provided, the current `options` values are instead returned.\n * @method renderDataPoints\n * @memberof dc.lineChart\n * @instance\n * @example\n * chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.8})\n * @param {{fillOpacity: Number, strokeOpacity: Number, radius: Number}} [options={fillOpacity: 0.8, strokeOpacity: 0.8, radius: 2}]\n * @return {{fillOpacity: Number, strokeOpacity: Number, radius: Number}}\n * @return {dc.lineChart}\n */\n _chart.renderDataPoints = function (options) {\n if (!arguments.length) {\n return {\n fillOpacity: _dataPointFillOpacity,\n strokeOpacity: _dataPointStrokeOpacity,\n radius: _dataPointRadius\n };\n } else if (!options) {\n _dataPointFillOpacity = DEFAULT_DOT_OPACITY;\n _dataPointStrokeOpacity = DEFAULT_DOT_OPACITY;\n _dataPointRadius = null;\n } else {\n _dataPointFillOpacity = options.fillOpacity || 0.8;\n _dataPointStrokeOpacity = options.strokeOpacity || 0.8;\n _dataPointRadius = options.radius || 2;\n }\n return _chart;\n };\n\n function colorFilter (color, dashstyle, inv) {\n return function () {\n var item = d3.select(this);\n var match = (item.attr('stroke') === color &&\n item.attr('stroke-dasharray') === ((dashstyle instanceof Array) ?\n dashstyle.join(',') : null)) || item.attr('fill') === color;\n return inv ? !match : match;\n };\n }\n\n _chart.legendHighlight = function (d) {\n if (!_chart.isLegendableHidden(d)) {\n _chart.g().selectAll('path.line, path.area')\n .classed('highlight', colorFilter(d.color, d.dashstyle))\n .classed('fadeout', colorFilter(d.color, d.dashstyle, true));\n }\n };\n\n _chart.legendReset = function () {\n _chart.g().selectAll('path.line, path.area')\n .classed('highlight', false)\n .classed('fadeout', false);\n };\n\n dc.override(_chart, 'legendables', function () {\n var legendables = _chart._legendables();\n if (!_dashStyle) {\n return legendables;\n }\n return legendables.map(function (l) {\n l.dashstyle = _dashStyle;\n return l;\n });\n });\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * The data count widget is a simple widget designed to display the number of records selected by the\n * current filters out of the total number of records in the data set. Once created the data count widget\n * will automatically update the text content of the following elements under the parent element.\n *\n * Note: this widget works best for the specific case of showing the number of records out of a\n * total. If you want a more general-purpose numeric display, please use the\n * {@link dc.numberDisplay} widget instead.\n *\n * '.total-count' - total number of records\n * '.filter-count' - number of records matched by the current filters\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * @class dataCount\n * @memberof dc\n * @mixes dc.baseMixin\n * @example\n * var ndx = crossfilter(data);\n * var all = ndx.groupAll();\n *\n * dc.dataCount('.dc-data-count')\n * .dimension(ndx)\n * .group(all);\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.dataCount}\n */\ndc.dataCount = function (parent, chartGroup) {\n var _formatNumber = d3.format(',d');\n var _chart = dc.baseMixin({});\n var _html = {some: '', all: ''};\n\n /**\n * Gets or sets an optional object specifying HTML templates to use depending how many items are\n * selected. The text `%total-count` will replaced with the total number of records, and the text\n * `%filter-count` will be replaced with the number of selected records.\n * - all: HTML template to use if all items are selected\n * - some: HTML template to use if not all items are selected\n * @method html\n * @memberof dc.dataCount\n * @instance\n * @example\n * counter.html({\n * some: '%filter-count out of %total-count records selected',\n * all: 'All records selected. Click on charts to apply filters'\n * })\n * @param {{some:String, all: String}} [options]\n * @return {{some:String, all: String}}\n * @return {dc.dataCount}\n */\n _chart.html = function (options) {\n if (!arguments.length) {\n return _html;\n }\n if (options.all) {\n _html.all = options.all;\n }\n if (options.some) {\n _html.some = options.some;\n }\n return _chart;\n };\n\n /**\n * Gets or sets an optional function to format the filter count and total count.\n * @method formatNumber\n * @memberof dc.dataCount\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format}\n * @example\n * counter.formatNumber(d3.format('.2g'))\n * @param {Function} [formatter=d3.format('.2g')]\n * @return {Function}\n * @return {dc.dataCount}\n */\n _chart.formatNumber = function (formatter) {\n if (!arguments.length) {\n return _formatNumber;\n }\n _formatNumber = formatter;\n return _chart;\n };\n\n _chart._doRender = function () {\n var tot = _chart.dimension().size(),\n val = _chart.group().value();\n var all = _formatNumber(tot);\n var selected = _formatNumber(val);\n\n if ((tot === val) && (_html.all !== '')) {\n _chart.root().html(_html.all.replace('%total-count', all).replace('%filter-count', selected));\n } else if (_html.some !== '') {\n _chart.root().html(_html.some.replace('%total-count', all).replace('%filter-count', selected));\n } else {\n _chart.selectAll('.total-count').text(all);\n _chart.selectAll('.filter-count').text(selected);\n }\n return _chart;\n };\n\n _chart._doRedraw = function () {\n return _chart._doRender();\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * The data table is a simple widget designed to list crossfilter focused data set (rows being\n * filtered) in a good old tabular fashion.\n *\n * Note: Unlike other charts, the data table (and data grid chart) use the group attribute as a\n * keying function for {@link https://github.com/mbostock/d3/wiki/Arrays#-nest nesting} the data\n * together in groups. Do not pass in a crossfilter group as this will not work.\n *\n * Another interesting feature of the data table is that you can pass a crossfilter group to the `dimension`, as\n * long as you specify the {@link dc.dataTable#order order} as `d3.descending`, since the data\n * table will use `dimension.top()` to fetch the data in that case, and the method is equally\n * supported on the crossfilter group as the crossfilter dimension.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * - {@link http://dc-js.github.io/dc.js/examples/table-on-aggregated-data.html dataTable on a crossfilter group}\n * ({@link https://github.com/dc-js/dc.js/blob/develop/web/examples/table-on-aggregated-data.html source})\n * @class dataTable\n * @memberof dc\n * @mixes dc.baseMixin\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.dataTable}\n */\ndc.dataTable = function (parent, chartGroup) {\n var LABEL_CSS_CLASS = 'dc-table-label';\n var ROW_CSS_CLASS = 'dc-table-row';\n var COLUMN_CSS_CLASS = 'dc-table-column';\n var GROUP_CSS_CLASS = 'dc-table-group';\n var HEAD_CSS_CLASS = 'dc-table-head';\n\n var _chart = dc.baseMixin({});\n\n var _size = 25;\n var _columns = [];\n var _sortBy = function (d) {\n return d;\n };\n var _order = d3.ascending;\n var _beginSlice = 0;\n var _endSlice;\n var _showGroups = true;\n\n _chart._doRender = function () {\n _chart.selectAll('tbody').remove();\n\n renderRows(renderGroups());\n\n return _chart;\n };\n\n _chart._doColumnValueFormat = function (v, d) {\n return ((typeof v === 'function') ?\n v(d) : // v as function\n ((typeof v === 'string') ?\n d[v] : // v is field name string\n v.format(d) // v is Object, use fn (element 2)\n )\n );\n };\n\n _chart._doColumnHeaderFormat = function (d) {\n // if 'function', convert to string representation\n // show a string capitalized\n // if an object then display its label string as-is.\n return (typeof d === 'function') ?\n _chart._doColumnHeaderFnToString(d) :\n ((typeof d === 'string') ?\n _chart._doColumnHeaderCapitalize(d) : String(d.label));\n };\n\n _chart._doColumnHeaderCapitalize = function (s) {\n // capitalize\n return s.charAt(0).toUpperCase() + s.slice(1);\n };\n\n _chart._doColumnHeaderFnToString = function (f) {\n // columnString(f) {\n var s = String(f);\n var i1 = s.indexOf('return ');\n if (i1 >= 0) {\n var i2 = s.lastIndexOf(';');\n if (i2 >= 0) {\n s = s.substring(i1 + 7, i2);\n var i3 = s.indexOf('numberFormat');\n if (i3 >= 0) {\n s = s.replace('numberFormat', '');\n }\n }\n }\n return s;\n };\n\n function renderGroups () {\n // The 'original' example uses all 'functions'.\n // If all 'functions' are used, then don't remove/add a header, and leave\n // the html alone. This preserves the functionality of earlier releases.\n // A 2nd option is a string representing a field in the data.\n // A third option is to supply an Object such as an array of 'information', and\n // supply your own _doColumnHeaderFormat and _doColumnValueFormat functions to\n // create what you need.\n var bAllFunctions = true;\n _columns.forEach(function (f) {\n bAllFunctions = bAllFunctions & (typeof f === 'function');\n });\n\n if (!bAllFunctions) {\n // ensure one thead\n var thead = _chart.selectAll('thead').data([0]);\n thead.enter().append('thead');\n thead.exit().remove();\n\n // with one tr\n var headrow = thead.selectAll('tr').data([0]);\n headrow.enter().append('tr');\n headrow.exit().remove();\n\n // with a th for each column\n var headcols = headrow.selectAll('th')\n .data(_columns);\n headcols.enter().append('th');\n headcols.exit().remove();\n\n headcols\n .attr('class', HEAD_CSS_CLASS)\n .html(function (d) {\n return (_chart._doColumnHeaderFormat(d));\n\n });\n }\n\n var groups = _chart.root().selectAll('tbody')\n .data(nestEntries(), function (d) {\n return _chart.keyAccessor()(d);\n });\n\n var rowGroup = groups\n .enter()\n .append('tbody');\n\n if (_showGroups === true) {\n rowGroup\n .append('tr')\n .attr('class', GROUP_CSS_CLASS)\n .append('td')\n .attr('class', LABEL_CSS_CLASS)\n .attr('colspan', _columns.length)\n .html(function (d) {\n return _chart.keyAccessor()(d);\n });\n }\n\n groups.exit().remove();\n\n return rowGroup;\n }\n\n function nestEntries () {\n var entries;\n if (_order === d3.ascending) {\n entries = _chart.dimension().bottom(_size);\n } else {\n entries = _chart.dimension().top(_size);\n }\n\n return d3.nest()\n .key(_chart.group())\n .sortKeys(_order)\n .entries(entries.sort(function (a, b) {\n return _order(_sortBy(a), _sortBy(b));\n }).slice(_beginSlice, _endSlice));\n }\n\n function renderRows (groups) {\n var rows = groups.order()\n .selectAll('tr.' + ROW_CSS_CLASS)\n .data(function (d) {\n return d.values;\n });\n\n var rowEnter = rows.enter()\n .append('tr')\n .attr('class', ROW_CSS_CLASS);\n\n _columns.forEach(function (v, i) {\n rowEnter.append('td')\n .attr('class', COLUMN_CSS_CLASS + ' _' + i)\n .html(function (d) {\n return _chart._doColumnValueFormat(v, d);\n });\n });\n\n rows.exit().remove();\n\n return rows;\n }\n\n _chart._doRedraw = function () {\n return _chart._doRender();\n };\n\n /**\n * Get or set the table size which determines the number of rows displayed by the widget.\n * @method size\n * @memberof dc.dataTable\n * @instance\n * @param {Number} [size=25]\n * @return {Number}\n * @return {dc.dataTable}\n */\n _chart.size = function (size) {\n if (!arguments.length) {\n return _size;\n }\n _size = size;\n return _chart;\n };\n\n /**\n * Get or set the index of the beginning slice which determines which entries get displayed\n * by the widget. Useful when implementing pagination.\n *\n * Note: the sortBy function will determine how the rows are ordered for pagination purposes.\n\n * See the {@link http://dc-js.github.io/dc.js/examples/table-pagination.html table pagination example}\n * to see how to implement the pagination user interface using `beginSlice` and `endSlice`.\n * @method beginSlice\n * @memberof dc.dataTable\n * @instance\n * @param {Number} [beginSlice=0]\n * @return {Number}\n * @return {dc.dataTable}\n */\n _chart.beginSlice = function (beginSlice) {\n if (!arguments.length) {\n return _beginSlice;\n }\n _beginSlice = beginSlice;\n return _chart;\n };\n\n /**\n * Get or set the index of the end slice which determines which entries get displayed by the\n * widget. Useful when implementing pagination. See {@link dc.dataTable#beginSlice `beginSlice`} for more information.\n * @method endSlice\n * @memberof dc.dataTable\n * @instance\n * @param {Number|undefined} [endSlice=undefined]\n * @return {Number}\n * @return {dc.dataTable}\n */\n _chart.endSlice = function (endSlice) {\n if (!arguments.length) {\n return _endSlice;\n }\n _endSlice = endSlice;\n return _chart;\n };\n\n /**\n * Get or set column functions. The data table widget supports several methods of specifying the\n * columns to display.\n *\n * The original method uses an array of functions to generate dynamic columns. Column functions\n * are simple javascript functions with only one input argument `d` which represents a row in\n * the data set. The return value of these functions will be used to generate the content for\n * each cell. However, this method requires the HTML for the table to have a fixed set of column\n * headers.\n *\n *
chart.columns([\n     *     function(d) { return d.date; },\n     *     function(d) { return d.open; },\n     *     function(d) { return d.close; },\n     *     function(d) { return numberFormat(d.close - d.open); },\n     *     function(d) { return d.volume; }\n     * ]);\n     * 
\n *\n * In the second method, you can list the columns to read from the data without specifying it as\n * a function, except where necessary (ie, computed columns). Note the data element name is\n * capitalized when displayed in the table header. You can also mix in functions as necessary,\n * using the third `{label, format}` form, as shown below.\n *\n *
chart.columns([\n     *     \"date\",    // d[\"date\"], ie, a field accessor; capitalized automatically\n     *     \"open\",    // ...\n     *     \"close\",   // ...\n     *     {\n     *         label: \"Change\",\n     *         format: function (d) {\n     *             return numberFormat(d.close - d.open);\n     *         }\n     *     },\n     *     \"volume\"   // d[\"volume\"], ie, a field accessor; capitalized automatically\n     * ]);\n     * 
\n *\n * In the third example, we specify all fields using the `{label, format}` method:\n *
chart.columns([\n     *     {\n     *         label: \"Date\",\n     *         format: function (d) { return d.date; }\n     *     },\n     *     {\n     *         label: \"Open\",\n     *         format: function (d) { return numberFormat(d.open); }\n     *     },\n     *     {\n     *         label: \"Close\",\n     *         format: function (d) { return numberFormat(d.close); }\n     *     },\n     *     {\n     *         label: \"Change\",\n     *         format: function (d) { return numberFormat(d.close - d.open); }\n     *     },\n     *     {\n     *         label: \"Volume\",\n     *         format: function (d) { return d.volume; }\n     *     }\n     * ]);\n     * 
\n *\n * You may wish to override the dataTable functions `_doColumnHeaderCapitalize` and\n * `_doColumnHeaderFnToString`, which are used internally to translate the column information or\n * function into a displayed header. The first one is used on the \"string\" column specifier; the\n * second is used to transform a stringified function into something displayable. For the Stock\n * example, the function for Change becomes the table header **d.close - d.open**.\n *\n * Finally, you can even specify a completely different form of column definition. To do this,\n * override `_chart._doColumnHeaderFormat` and `_chart._doColumnValueFormat` Be aware that\n * fields without numberFormat specification will be displayed just as they are stored in the\n * data, unformatted.\n * @method columns\n * @memberof dc.dataTable\n * @instance\n * @param {Array} [columns=[]]\n * @return {Array}}\n * @return {dc.dataTable}\n */\n _chart.columns = function (columns) {\n if (!arguments.length) {\n return _columns;\n }\n _columns = columns;\n return _chart;\n };\n\n /**\n * Get or set sort-by function. This function works as a value accessor at row level and returns a\n * particular field to be sorted by. Default value: identity function\n * @method sortBy\n * @memberof dc.dataTable\n * @instance\n * @example\n * chart.sortBy(function(d) {\n * return d.date;\n * });\n * @param {Function} [sortBy]\n * @return {Function}\n * @return {dc.dataTable}\n */\n _chart.sortBy = function (sortBy) {\n if (!arguments.length) {\n return _sortBy;\n }\n _sortBy = sortBy;\n return _chart;\n };\n\n /**\n * Get or set sort order. If the order is `d3.ascending`, the data table will use\n * `dimension().bottom()` to fetch the data; otherwise it will use `dimension().top()`\n * @method order\n * @memberof dc.dataTable\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending}\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending}\n * @example\n * chart.order(d3.descending);\n * @param {Function} [order=d3.ascending]\n * @return {Function}\n * @return {dc.dataTable}\n */\n _chart.order = function (order) {\n if (!arguments.length) {\n return _order;\n }\n _order = order;\n return _chart;\n };\n\n /**\n * Get or set if group rows will be shown.\n *\n * The .group() getter-setter must be provided in either case.\n * @method showGroups\n * @memberof dc.dataTable\n * @instance\n * @example\n * chart\n * .group([value], [name])\n * .showGroups(true|false);\n * @param {Boolean} [showGroups=true]\n * @return {Boolean}\n * @return {dc.dataTable}\n */\n _chart.showGroups = function (showGroups) {\n if (!arguments.length) {\n return _showGroups;\n }\n _showGroups = showGroups;\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * Data grid is a simple widget designed to list the filtered records, providing\n * a simple way to define how the items are displayed.\n *\n * Note: Unlike other charts, the data grid chart (and data table) use the group attribute as a keying function\n * for {@link https://github.com/mbostock/d3/wiki/Arrays#-nest nesting} the data together in groups.\n * Do not pass in a crossfilter group as this will not work.\n *\n * Examples:\n * - {@link http://europarl.me/dc.js/web/ep/index.html List of members of the european parliament}\n * @class dataGrid\n * @memberof dc\n * @mixes dc.baseMixin\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.dataGrid}\n */\ndc.dataGrid = function (parent, chartGroup) {\n var LABEL_CSS_CLASS = 'dc-grid-label';\n var ITEM_CSS_CLASS = 'dc-grid-item';\n var GROUP_CSS_CLASS = 'dc-grid-group';\n var GRID_CSS_CLASS = 'dc-grid-top';\n\n var _chart = dc.baseMixin({});\n\n var _size = 999; // shouldn't be needed, but you might\n var _html = function (d) { return 'you need to provide an html() handling param: ' + JSON.stringify(d); };\n var _sortBy = function (d) {\n return d;\n };\n var _order = d3.ascending;\n var _beginSlice = 0, _endSlice;\n\n var _htmlGroup = function (d) {\n return '

' +\n _chart.keyAccessor()(d) + '

';\n };\n\n _chart._doRender = function () {\n _chart.selectAll('div.' + GRID_CSS_CLASS).remove();\n\n renderItems(renderGroups());\n\n return _chart;\n };\n\n function renderGroups () {\n var groups = _chart.root().selectAll('div.' + GRID_CSS_CLASS)\n .data(nestEntries(), function (d) {\n return _chart.keyAccessor()(d);\n });\n\n var itemGroup = groups\n .enter()\n .append('div')\n .attr('class', GRID_CSS_CLASS);\n\n if (_htmlGroup) {\n itemGroup\n .html(function (d) {\n return _htmlGroup(d);\n });\n }\n\n groups.exit().remove();\n return itemGroup;\n }\n\n function nestEntries () {\n var entries = _chart.dimension().top(_size);\n\n return d3.nest()\n .key(_chart.group())\n .sortKeys(_order)\n .entries(entries.sort(function (a, b) {\n return _order(_sortBy(a), _sortBy(b));\n }).slice(_beginSlice, _endSlice));\n }\n\n function renderItems (groups) {\n var items = groups.order()\n .selectAll('div.' + ITEM_CSS_CLASS)\n .data(function (d) {\n return d.values;\n });\n\n items.enter()\n .append('div')\n .attr('class', ITEM_CSS_CLASS)\n .html(function (d) {\n return _html(d);\n });\n\n items.exit().remove();\n\n return items;\n }\n\n _chart._doRedraw = function () {\n return _chart._doRender();\n };\n\n /**\n * Get or set the index of the beginning slice which determines which entries get displayed by the widget.\n * Useful when implementing pagination.\n * @method beginSlice\n * @memberof dc.dataGrid\n * @instance\n * @param {Number} [beginSlice=0]\n * @return {Number}\n * @return {dc.dataGrid}\n */\n _chart.beginSlice = function (beginSlice) {\n if (!arguments.length) {\n return _beginSlice;\n }\n _beginSlice = beginSlice;\n return _chart;\n };\n\n /**\n * Get or set the index of the end slice which determines which entries get displayed by the widget\n * Useful when implementing pagination.\n * @method endSlice\n * @memberof dc.dataGrid\n * @instance\n * @param {Number} [endSlice]\n * @return {Number}\n * @return {dc.dataGrid}\n */\n _chart.endSlice = function (endSlice) {\n if (!arguments.length) {\n return _endSlice;\n }\n _endSlice = endSlice;\n return _chart;\n };\n\n /**\n * Get or set the grid size which determines the number of items displayed by the widget.\n * @method size\n * @memberof dc.dataGrid\n * @instance\n * @param {Number} [size=999]\n * @return {Number}\n * @return {dc.dataGrid}\n */\n _chart.size = function (size) {\n if (!arguments.length) {\n return _size;\n }\n _size = size;\n return _chart;\n };\n\n /**\n * Get or set the function that formats an item. The data grid widget uses a\n * function to generate dynamic html. Use your favourite templating engine or\n * generate the string directly.\n * @method html\n * @memberof dc.dataGrid\n * @instance\n * @example\n * chart.html(function (d) { return '
'+data.exampleString+'
';});\n * @param {Function} [html]\n * @return {Function}\n * @return {dc.dataGrid}\n */\n _chart.html = function (html) {\n if (!arguments.length) {\n return _html;\n }\n _html = html;\n return _chart;\n };\n\n /**\n * Get or set the function that formats a group label.\n * @method htmlGroup\n * @memberof dc.dataGrid\n * @instance\n * @example\n * chart.htmlGroup (function (d) { return '

'.d.key . 'with ' . d.values.length .' items

'});\n * @param {Function} [htmlGroup]\n * @return {Function}\n * @return {dc.dataGrid}\n */\n _chart.htmlGroup = function (htmlGroup) {\n if (!arguments.length) {\n return _htmlGroup;\n }\n _htmlGroup = htmlGroup;\n return _chart;\n };\n\n /**\n * Get or set sort-by function. This function works as a value accessor at the item\n * level and returns a particular field to be sorted.\n * @method sortBy\n * @memberof dc.dataGrid\n * @instance\n * @example\n * chart.sortBy(function(d) {\n * return d.date;\n * });\n * @param {Function} [sortByFunction]\n * @return {Function}\n * @return {dc.dataGrid}\n */\n _chart.sortBy = function (sortByFunction) {\n if (!arguments.length) {\n return _sortBy;\n }\n _sortBy = sortByFunction;\n return _chart;\n };\n\n /**\n * Get or set sort order function.\n * @method order\n * @memberof dc.dataGrid\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending}\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending}\n * @example\n * chart.order(d3.descending);\n * @param {Function} [order=d3.ascending]\n * @return {Function}\n * @return {dc.dataGrid}\n */\n _chart.order = function (order) {\n if (!arguments.length) {\n return _order;\n }\n _order = order;\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * A concrete implementation of a general purpose bubble chart that allows data visualization using the\n * following dimensions:\n * - x axis position\n * - y axis position\n * - bubble radius\n * - color\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * - {@link http://dc-js.github.com/dc.js/vc/index.html US Venture Capital Landscape 2011}\n * @class bubbleChart\n * @memberof dc\n * @mixes dc.bubbleMixin\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a bubble chart under #chart-container1 element using the default global chart group\n * var bubbleChart1 = dc.bubbleChart('#chart-container1');\n * // create a bubble chart under #chart-container2 element using chart group A\n * var bubbleChart2 = dc.bubbleChart('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.bubbleChart}\n */\ndc.bubbleChart = function (parent, chartGroup) {\n var _chart = dc.bubbleMixin(dc.coordinateGridMixin({}));\n\n var _elasticRadius = false;\n var _sortBubbleSize = false;\n\n _chart.transitionDuration(750);\n\n var bubbleLocator = function (d) {\n return 'translate(' + (bubbleX(d)) + ',' + (bubbleY(d)) + ')';\n };\n\n /**\n * Turn on or off the elastic bubble radius feature, or return the value of the flag. If this\n * feature is turned on, then bubble radii will be automatically rescaled to fit the chart better.\n * @method elasticRadius\n * @memberof dc.bubbleChart\n * @instance\n * @param {Boolean} [elasticRadius=false]\n * @return {Boolean}\n * @return {dc.bubbleChart}\n */\n _chart.elasticRadius = function (elasticRadius) {\n if (!arguments.length) {\n return _elasticRadius;\n }\n _elasticRadius = elasticRadius;\n return _chart;\n };\n\n /**\n * Turn on or off the bubble sorting feature, or return the value of the flag. If enabled,\n * bubbles will be sorted by their radius, with smaller bubbles in front.\n * @method sortBubbleSize\n * @memberof dc.bubbleChart\n * @instance\n * @param {Boolean} [sortBubbleSize=false]\n * @return {Boolean}\n * @return {dc.bubbleChart}\n */\n _chart.sortBubbleSize = function (sortBubbleSize) {\n if (!arguments.length) {\n return _sortBubbleSize;\n }\n _sortBubbleSize = sortBubbleSize;\n return _chart;\n };\n\n _chart.plotData = function () {\n if (_elasticRadius) {\n _chart.r().domain([_chart.rMin(), _chart.rMax()]);\n }\n\n _chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]);\n\n var data = _chart.data();\n if (_sortBubbleSize) {\n // sort descending so smaller bubbles are on top\n var radiusAccessor = _chart.radiusValueAccessor();\n data.sort(function (a, b) { return d3.descending(radiusAccessor(a), radiusAccessor(b)); });\n }\n var bubbleG = _chart.chartBodyG().selectAll('g.' + _chart.BUBBLE_NODE_CLASS)\n .data(data, function (d) { return d.key; });\n if (_sortBubbleSize) {\n // Call order here to update dom order based on sort\n bubbleG.order();\n }\n\n renderNodes(bubbleG);\n\n updateNodes(bubbleG);\n\n removeNodes(bubbleG);\n\n _chart.fadeDeselectedArea();\n };\n\n function renderNodes (bubbleG) {\n var bubbleGEnter = bubbleG.enter().append('g');\n\n bubbleGEnter\n .attr('class', _chart.BUBBLE_NODE_CLASS)\n .attr('transform', bubbleLocator)\n .append('circle').attr('class', function (d, i) {\n return _chart.BUBBLE_CLASS + ' _' + i;\n })\n .on('click', _chart.onClick)\n .attr('fill', _chart.getColor)\n .attr('r', 0);\n dc.transition(bubbleG, _chart.transitionDuration())\n .selectAll('circle.' + _chart.BUBBLE_CLASS)\n .attr('r', function (d) {\n return _chart.bubbleR(d);\n })\n .attr('opacity', function (d) {\n return (_chart.bubbleR(d) > 0) ? 1 : 0;\n });\n\n _chart._doRenderLabel(bubbleGEnter);\n\n _chart._doRenderTitles(bubbleGEnter);\n }\n\n function updateNodes (bubbleG) {\n dc.transition(bubbleG, _chart.transitionDuration())\n .attr('transform', bubbleLocator)\n .selectAll('circle.' + _chart.BUBBLE_CLASS)\n .attr('fill', _chart.getColor)\n .attr('r', function (d) {\n return _chart.bubbleR(d);\n })\n .attr('opacity', function (d) {\n return (_chart.bubbleR(d) > 0) ? 1 : 0;\n });\n\n _chart.doUpdateLabels(bubbleG);\n _chart.doUpdateTitles(bubbleG);\n }\n\n function removeNodes (bubbleG) {\n bubbleG.exit().remove();\n }\n\n function bubbleX (d) {\n var x = _chart.x()(_chart.keyAccessor()(d));\n if (isNaN(x)) {\n x = 0;\n }\n return x;\n }\n\n function bubbleY (d) {\n var y = _chart.y()(_chart.valueAccessor()(d));\n if (isNaN(y)) {\n y = 0;\n }\n return y;\n }\n\n _chart.renderBrush = function () {\n // override default x axis brush from parent chart\n };\n\n _chart.redrawBrush = function () {\n // override default x axis brush from parent chart\n _chart.fadeDeselectedArea();\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * Composite charts are a special kind of chart that render multiple charts on the same Coordinate\n * Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to\n * achieve some quite flexible charting effects.\n * @class compositeChart\n * @memberof dc\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a composite chart under #chart-container1 element using the default global chart group\n * var compositeChart1 = dc.compositeChart('#chart-container1');\n * // create a composite chart under #chart-container2 element using chart group A\n * var compositeChart2 = dc.compositeChart('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.compositeChart}\n */\ndc.compositeChart = function (parent, chartGroup) {\n\n var SUB_CHART_CLASS = 'sub';\n var DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING = 12;\n\n var _chart = dc.coordinateGridMixin({});\n var _children = [];\n\n var _childOptions = {};\n\n var _shareColors = false,\n _shareTitle = true,\n _alignYAxes = false;\n\n var _rightYAxis = d3.svg.axis(),\n _rightYAxisLabel = 0,\n _rightYAxisLabelPadding = DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING,\n _rightY,\n _rightAxisGridLines = false;\n\n _chart._mandatoryAttributes([]);\n _chart.transitionDuration(500);\n\n dc.override(_chart, '_generateG', function () {\n var g = this.__generateG();\n\n for (var i = 0; i < _children.length; ++i) {\n var child = _children[i];\n\n generateChildG(child, i);\n\n if (!child.dimension()) {\n child.dimension(_chart.dimension());\n }\n if (!child.group()) {\n child.group(_chart.group());\n }\n\n child.chartGroup(_chart.chartGroup());\n child.svg(_chart.svg());\n child.xUnits(_chart.xUnits());\n child.transitionDuration(_chart.transitionDuration());\n child.brushOn(_chart.brushOn());\n child.renderTitle(_chart.renderTitle());\n child.elasticX(_chart.elasticX());\n }\n\n return g;\n });\n\n _chart._brushing = function () {\n var extent = _chart.extendBrush();\n var brushIsEmpty = _chart.brushIsEmpty(extent);\n\n for (var i = 0; i < _children.length; ++i) {\n _children[i].replaceFilter(brushIsEmpty ? null : extent);\n }\n };\n\n _chart._prepareYAxis = function () {\n var left = (leftYAxisChildren().length !== 0);\n var right = (rightYAxisChildren().length !== 0);\n var ranges = calculateYAxisRanges(left, right);\n\n if (left) { prepareLeftYAxis(ranges); }\n if (right) { prepareRightYAxis(ranges); }\n\n if (leftYAxisChildren().length > 0 && !_rightAxisGridLines) {\n _chart._renderHorizontalGridLinesForAxis(_chart.g(), _chart.y(), _chart.yAxis());\n } else if (rightYAxisChildren().length > 0) {\n _chart._renderHorizontalGridLinesForAxis(_chart.g(), _rightY, _rightYAxis);\n }\n };\n\n _chart.renderYAxis = function () {\n if (leftYAxisChildren().length !== 0) {\n _chart.renderYAxisAt('y', _chart.yAxis(), _chart.margins().left);\n _chart.renderYAxisLabel('y', _chart.yAxisLabel(), -90);\n }\n\n if (rightYAxisChildren().length !== 0) {\n _chart.renderYAxisAt('yr', _chart.rightYAxis(), _chart.width() - _chart.margins().right);\n _chart.renderYAxisLabel('yr', _chart.rightYAxisLabel(), 90, _chart.width() - _rightYAxisLabelPadding);\n }\n };\n\n function calculateYAxisRanges (left, right) {\n var lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax;\n var ranges;\n\n if (left) {\n lyAxisMin = yAxisMin();\n lyAxisMax = yAxisMax();\n }\n\n if (right) {\n ryAxisMin = rightYAxisMin();\n ryAxisMax = rightYAxisMax();\n }\n\n if (_chart.alignYAxes() && left && right) {\n ranges = alignYAxisRanges(lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax);\n }\n\n return ranges || {\n lyAxisMin: lyAxisMin,\n lyAxisMax: lyAxisMax,\n ryAxisMin: ryAxisMin,\n ryAxisMax: ryAxisMax\n };\n }\n\n function alignYAxisRanges (lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax) {\n // since the two series will share a zero, each Y is just a multiple\n // of the other. and the ratio should be the ratio of the ranges of the\n // input data, so that they come out the same height. so we just min/max\n\n // note: both ranges already include zero due to the stack mixin (#667)\n // if #667 changes, we can reconsider whether we want data height or\n // height from zero to be equal. and it will be possible for the axes\n // to be aligned but not visible.\n var extentRatio = (ryAxisMax - ryAxisMin) / (lyAxisMax - lyAxisMin);\n\n return {\n lyAxisMin: Math.min(lyAxisMin, ryAxisMin / extentRatio),\n lyAxisMax: Math.max(lyAxisMax, ryAxisMax / extentRatio),\n ryAxisMin: Math.min(ryAxisMin, lyAxisMin * extentRatio),\n ryAxisMax: Math.max(ryAxisMax, lyAxisMax * extentRatio)\n };\n }\n\n function prepareRightYAxis (ranges) {\n var needDomain = _chart.rightY() === undefined || _chart.elasticY(),\n needRange = needDomain || _chart.resizing();\n if (_chart.rightY() === undefined) {\n _chart.rightY(d3.scale.linear());\n }\n if (needDomain) {\n _chart.rightY().domain([ranges.ryAxisMin, ranges.ryAxisMax]);\n }\n if (needRange) {\n _chart.rightY().rangeRound([_chart.yAxisHeight(), 0]);\n }\n\n _chart.rightY().range([_chart.yAxisHeight(), 0]);\n _chart.rightYAxis(_chart.rightYAxis().scale(_chart.rightY()));\n\n _chart.rightYAxis().orient('right');\n }\n\n function prepareLeftYAxis (ranges) {\n var needDomain = _chart.y() === undefined || _chart.elasticY(),\n needRange = needDomain || _chart.resizing();\n if (_chart.y() === undefined) {\n _chart.y(d3.scale.linear());\n }\n if (needDomain) {\n _chart.y().domain([ranges.lyAxisMin, ranges.lyAxisMax]);\n }\n if (needRange) {\n _chart.y().rangeRound([_chart.yAxisHeight(), 0]);\n }\n\n _chart.y().range([_chart.yAxisHeight(), 0]);\n _chart.yAxis(_chart.yAxis().scale(_chart.y()));\n\n _chart.yAxis().orient('left');\n }\n\n function generateChildG (child, i) {\n child._generateG(_chart.g());\n child.g().attr('class', SUB_CHART_CLASS + ' _' + i);\n }\n\n _chart.plotData = function () {\n for (var i = 0; i < _children.length; ++i) {\n var child = _children[i];\n\n if (!child.g()) {\n generateChildG(child, i);\n }\n\n if (_shareColors) {\n child.colors(_chart.colors());\n }\n\n child.x(_chart.x());\n\n child.xAxis(_chart.xAxis());\n\n if (child.useRightYAxis()) {\n child.y(_chart.rightY());\n child.yAxis(_chart.rightYAxis());\n } else {\n child.y(_chart.y());\n child.yAxis(_chart.yAxis());\n }\n\n child.plotData();\n\n child._activateRenderlets();\n }\n };\n\n /**\n * Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the\n * default behavior. This option is only respected when subcharts with both left and right y-axes\n * are present.\n * @method useRightAxisGridLines\n * @memberof dc.compositeChart\n * @instance\n * @param {Boolean} [useRightAxisGridLines=false]\n * @return {Boolean}\n * @return {dc.compositeChart}\n */\n _chart.useRightAxisGridLines = function (useRightAxisGridLines) {\n if (!arguments) {\n return _rightAxisGridLines;\n }\n\n _rightAxisGridLines = useRightAxisGridLines;\n return _chart;\n };\n\n /**\n * Get or set chart-specific options for all child charts. This is equivalent to calling\n * {@link dc.baseMixin#options .options} on each child chart.\n * @method childOptions\n * @memberof dc.compositeChart\n * @instance\n * @param {Object} [childOptions]\n * @return {Object}\n * @return {dc.compositeChart}\n */\n _chart.childOptions = function (childOptions) {\n if (!arguments.length) {\n return _childOptions;\n }\n _childOptions = childOptions;\n _children.forEach(function (child) {\n child.options(_childOptions);\n });\n return _chart;\n };\n\n _chart.fadeDeselectedArea = function () {\n for (var i = 0; i < _children.length; ++i) {\n var child = _children[i];\n child.brush(_chart.brush());\n child.fadeDeselectedArea();\n }\n };\n\n /**\n * Set or get the right y axis label.\n * @method rightYAxisLabel\n * @memberof dc.compositeChart\n * @instance\n * @param {String} [rightYAxisLabel]\n * @param {Number} [padding]\n * @return {String}\n * @return {dc.compositeChart}\n */\n _chart.rightYAxisLabel = function (rightYAxisLabel, padding) {\n if (!arguments.length) {\n return _rightYAxisLabel;\n }\n _rightYAxisLabel = rightYAxisLabel;\n _chart.margins().right -= _rightYAxisLabelPadding;\n _rightYAxisLabelPadding = (padding === undefined) ? DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING : padding;\n _chart.margins().right += _rightYAxisLabelPadding;\n return _chart;\n };\n\n /**\n * Combine the given charts into one single composite coordinate grid chart.\n * @method compose\n * @memberof dc.compositeChart\n * @instance\n * @example\n * moveChart.compose([\n * // when creating sub-chart you need to pass in the parent chart\n * dc.lineChart(moveChart)\n * .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used\n * .valueAccessor(function (d){return d.value.avg;})\n * // most of the normal functions will continue to work in a composed chart\n * .renderArea(true)\n * .stack(monthlyMoveGroup, function (d){return d.value;})\n * .title(function (d){\n * var value = d.value.avg?d.value.avg:d.value;\n * if(isNaN(value)) value = 0;\n * return dateFormat(d.key) + '\\n' + numberFormat(value);\n * }),\n * dc.barChart(moveChart)\n * .group(volumeByMonthGroup)\n * .centerBar(true)\n * ]);\n * @param {Array} [subChartArray]\n * @return {dc.compositeChart}\n */\n _chart.compose = function (subChartArray) {\n _children = subChartArray;\n _children.forEach(function (child) {\n child.height(_chart.height());\n child.width(_chart.width());\n child.margins(_chart.margins());\n\n if (_shareTitle) {\n child.title(_chart.title());\n }\n\n child.options(_childOptions);\n });\n return _chart;\n };\n\n /**\n * Returns the child charts which are composed into the composite chart.\n * @method children\n * @memberof dc.compositeChart\n * @instance\n * @return {Array}\n */\n _chart.children = function () {\n return _children;\n };\n\n /**\n * Get or set color sharing for the chart. If set, the {@link dc.colorMixin#colors .colors()} value from this chart\n * will be shared with composed children. Additionally if the child chart implements\n * Stackable and has not set a custom .colorAccessor, then it will generate a color\n * specific to its order in the composition.\n * @method shareColors\n * @memberof dc.compositeChart\n * @instance\n * @param {Boolean} [shareColors=false]\n * @return {Boolean}\n * @return {dc.compositeChart}\n */\n _chart.shareColors = function (shareColors) {\n if (!arguments.length) {\n return _shareColors;\n }\n _shareColors = shareColors;\n return _chart;\n };\n\n /**\n * Get or set title sharing for the chart. If set, the {@link dc.baseMixin#title .title()} value from\n * this chart will be shared with composed children.\n * @method shareTitle\n * @memberof dc.compositeChart\n * @instance\n * @param {Boolean} [shareTitle=true]\n * @return {Boolean}\n * @return {dc.compositeChart}\n */\n _chart.shareTitle = function (shareTitle) {\n if (!arguments.length) {\n return _shareTitle;\n }\n _shareTitle = shareTitle;\n return _chart;\n };\n\n /**\n * Get or set the y scale for the right axis. The right y scale is typically automatically\n * generated by the chart implementation.\n * @method rightY\n * @memberof dc.compositeChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Scales d3.scale}\n * @param {d3.scale} [yScale]\n * @return {d3.scale}\n * @return {dc.compositeChart}\n */\n _chart.rightY = function (yScale) {\n if (!arguments.length) {\n return _rightY;\n }\n _rightY = yScale;\n _chart.rescale();\n return _chart;\n };\n\n /**\n * Get or set alignment between left and right y axes. A line connecting '0' on both y axis\n * will be parallel to x axis. This only has effect when {@link #dc.coordinateGridMixin+elasticY elasticY} is true.\n * @method alignYAxes\n * @memberof dc.compositeChart\n * @instance\n * @param {Boolean} [alignYAxes=false]\n * @return {Chart}\n */\n _chart.alignYAxes = function (alignYAxes) {\n if (!arguments.length) {\n return _alignYAxes;\n }\n _alignYAxes = alignYAxes;\n _chart.rescale();\n return _chart;\n };\n\n function leftYAxisChildren () {\n return _children.filter(function (child) {\n return !child.useRightYAxis();\n });\n }\n\n function rightYAxisChildren () {\n return _children.filter(function (child) {\n return child.useRightYAxis();\n });\n }\n\n function getYAxisMin (charts) {\n return charts.map(function (c) {\n return c.yAxisMin();\n });\n }\n\n delete _chart.yAxisMin;\n function yAxisMin () {\n return d3.min(getYAxisMin(leftYAxisChildren()));\n }\n\n function rightYAxisMin () {\n return d3.min(getYAxisMin(rightYAxisChildren()));\n }\n\n function getYAxisMax (charts) {\n return charts.map(function (c) {\n return c.yAxisMax();\n });\n }\n\n delete _chart.yAxisMax;\n function yAxisMax () {\n return dc.utils.add(d3.max(getYAxisMax(leftYAxisChildren())), _chart.yAxisPadding());\n }\n\n function rightYAxisMax () {\n return dc.utils.add(d3.max(getYAxisMax(rightYAxisChildren())), _chart.yAxisPadding());\n }\n\n function getAllXAxisMinFromChildCharts () {\n return _children.map(function (c) {\n return c.xAxisMin();\n });\n }\n\n dc.override(_chart, 'xAxisMin', function () {\n return dc.utils.subtract(d3.min(getAllXAxisMinFromChildCharts()), _chart.xAxisPadding());\n });\n\n function getAllXAxisMaxFromChildCharts () {\n return _children.map(function (c) {\n return c.xAxisMax();\n });\n }\n\n dc.override(_chart, 'xAxisMax', function () {\n return dc.utils.add(d3.max(getAllXAxisMaxFromChildCharts()), _chart.xAxisPadding());\n });\n\n _chart.legendables = function () {\n return _children.reduce(function (items, child) {\n if (_shareColors) {\n child.colors(_chart.colors());\n }\n items.push.apply(items, child.legendables());\n return items;\n }, []);\n };\n\n _chart.legendHighlight = function (d) {\n for (var j = 0; j < _children.length; ++j) {\n var child = _children[j];\n child.legendHighlight(d);\n }\n };\n\n _chart.legendReset = function (d) {\n for (var j = 0; j < _children.length; ++j) {\n var child = _children[j];\n child.legendReset(d);\n }\n };\n\n _chart.legendToggle = function () {\n console.log('composite should not be getting legendToggle itself');\n };\n\n /**\n * Set or get the right y axis used by the composite chart. This function is most useful when y\n * axis customization is required. The y axis in dc.js is an instance of a [d3 axis\n * object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis) therefore it supports any valid\n * d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc;\n * resetting it may cause unexpected results.\n * @method rightYAxis\n * @memberof dc.compositeChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis}\n * @example\n * // customize y axis tick format\n * chart.rightYAxis().tickFormat(function (v) {return v + '%';});\n * // customize y axis tick values\n * chart.rightYAxis().tickValues([0, 100, 200, 300]);\n * @param {d3.svg.axis} [rightYAxis]\n * @return {d3.svg.axis}\n * @return {dc.compositeChart}\n */\n _chart.rightYAxis = function (rightYAxis) {\n if (!arguments.length) {\n return _rightYAxis;\n }\n _rightYAxis = rightYAxis;\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * A series chart is a chart that shows multiple series of data overlaid on one chart, where the\n * series is specified in the data. It is a specialization of Composite Chart and inherits all\n * composite features other than recomposing the chart.\n *\n * Examples:\n * - {@link http://dc-js.github.io/dc.js/examples/series.html Series Chart}\n * @class seriesChart\n * @memberof dc\n * @mixes dc.compositeChart\n * @example\n * // create a series chart under #chart-container1 element using the default global chart group\n * var seriesChart1 = dc.seriesChart(\"#chart-container1\");\n * // create a series chart under #chart-container2 element using chart group A\n * var seriesChart2 = dc.seriesChart(\"#chart-container2\", \"chartGroupA\");\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.seriesChart}\n */\ndc.seriesChart = function (parent, chartGroup) {\n var _chart = dc.compositeChart(parent, chartGroup);\n\n function keySort (a, b) {\n return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b));\n }\n\n var _charts = {};\n var _chartFunction = dc.lineChart;\n var _seriesAccessor;\n var _seriesSort = d3.ascending;\n var _valueSort = keySort;\n\n _chart._mandatoryAttributes().push('seriesAccessor', 'chart');\n _chart.shareColors(true);\n\n _chart._preprocessData = function () {\n var keep = [];\n var childrenChanged;\n var nester = d3.nest().key(_seriesAccessor);\n if (_seriesSort) {\n nester.sortKeys(_seriesSort);\n }\n if (_valueSort) {\n nester.sortValues(_valueSort);\n }\n var nesting = nester.entries(_chart.data());\n var children =\n nesting.map(function (sub, i) {\n var subChart = _charts[sub.key] || _chartFunction.call(_chart, _chart, chartGroup, sub.key, i);\n if (!_charts[sub.key]) {\n childrenChanged = true;\n }\n _charts[sub.key] = subChart;\n keep.push(sub.key);\n return subChart\n .dimension(_chart.dimension())\n .group({all: d3.functor(sub.values)}, sub.key)\n .keyAccessor(_chart.keyAccessor())\n .valueAccessor(_chart.valueAccessor())\n .brushOn(_chart.brushOn());\n });\n // this works around the fact compositeChart doesn't really\n // have a removal interface\n Object.keys(_charts)\n .filter(function (c) {return keep.indexOf(c) === -1;})\n .forEach(function (c) {\n clearChart(c);\n childrenChanged = true;\n });\n _chart._compose(children);\n if (childrenChanged && _chart.legend()) {\n _chart.legend().render();\n }\n };\n\n function clearChart (c) {\n if (_charts[c].g()) {\n _charts[c].g().remove();\n }\n delete _charts[c];\n }\n\n function resetChildren () {\n Object.keys(_charts).map(clearChart);\n _charts = {};\n }\n\n /**\n * Get or set the chart function, which generates the child charts.\n * @method chart\n * @memberof dc.seriesChart\n * @instance\n * @example\n * // put interpolation on the line charts used for the series\n * chart.chart(function(c) { return dc.lineChart(c).interpolate('basis'); })\n * // do a scatter series chart\n * chart.chart(dc.scatterPlot)\n * @param {Function} [chartFunction=dc.lineChart]\n * @return {Function}\n * @return {dc.seriesChart}\n */\n _chart.chart = function (chartFunction) {\n if (!arguments.length) {\n return _chartFunction;\n }\n _chartFunction = chartFunction;\n resetChildren();\n return _chart;\n };\n\n /**\n * **mandatory**\n *\n * Get or set accessor function for the displayed series. Given a datum, this function\n * should return the series that datum belongs to.\n * @method seriesAccessor\n * @memberof dc.seriesChart\n * @instance\n * @example\n * // simple series accessor\n * chart.seriesAccessor(function(d) { return \"Expt: \" + d.key[0]; })\n * @param {Function} [accessor]\n * @return {Function}\n * @return {dc.seriesChart}\n */\n _chart.seriesAccessor = function (accessor) {\n if (!arguments.length) {\n return _seriesAccessor;\n }\n _seriesAccessor = accessor;\n resetChildren();\n return _chart;\n };\n\n /**\n * Get or set a function to sort the list of series by, given series values.\n * @method seriesSort\n * @memberof dc.seriesChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending}\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending}\n * @example\n * chart.seriesSort(d3.descending);\n * @param {Function} [sortFunction=d3.ascending]\n * @return {Function}\n * @return {dc.seriesChart}\n */\n _chart.seriesSort = function (sortFunction) {\n if (!arguments.length) {\n return _seriesSort;\n }\n _seriesSort = sortFunction;\n resetChildren();\n return _chart;\n };\n\n /**\n * Get or set a function to sort each series values by. By default this is the key accessor which,\n * for example, will ensure a lineChart series connects its points in increasing key/x order,\n * rather than haphazardly.\n * @method valueSort\n * @memberof dc.seriesChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending}\n * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending}\n * @example\n * // Default value sort\n * _chart.valueSort(function keySort (a, b) {\n * return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b));\n * });\n * @param {Function} [sortFunction]\n * @return {Function}\n * @return {dc.seriesChart}\n */\n _chart.valueSort = function (sortFunction) {\n if (!arguments.length) {\n return _valueSort;\n }\n _valueSort = sortFunction;\n resetChildren();\n return _chart;\n };\n\n // make compose private\n _chart._compose = _chart.compose;\n delete _chart.compose;\n\n return _chart;\n};\n","/**\n * The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map\n * from GeoJson data. This chart implementation was inspired by\n * {@link http://bl.ocks.org/4060606 the great d3 choropleth example}.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/vc/index.html US Venture Capital Landscape 2011}\n * @class geoChoroplethChart\n * @memberof dc\n * @mixes dc.colorMixin\n * @mixes dc.baseMixin\n * @example\n * // create a choropleth chart under '#us-chart' element using the default global chart group\n * var chart1 = dc.geoChoroplethChart('#us-chart');\n * // create a choropleth chart under '#us-chart2' element using chart group A\n * var chart2 = dc.compositeChart('#us-chart2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.geoChoroplethChart}\n */\ndc.geoChoroplethChart = function (parent, chartGroup) {\n var _chart = dc.colorMixin(dc.baseMixin({}));\n\n _chart.colorAccessor(function (d) {\n return d || 0;\n });\n\n var _geoPath = d3.geo.path();\n var _projectionFlag;\n\n var _geoJsons = [];\n\n _chart._doRender = function () {\n _chart.resetSvg();\n for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {\n var states = _chart.svg().append('g')\n .attr('class', 'layer' + layerIndex);\n\n var regionG = states.selectAll('g.' + geoJson(layerIndex).name)\n .data(geoJson(layerIndex).data)\n .enter()\n .append('g')\n .attr('class', geoJson(layerIndex).name);\n\n regionG\n .append('path')\n .attr('fill', 'white')\n .attr('d', _geoPath);\n\n regionG.append('title');\n\n plotData(layerIndex);\n }\n _projectionFlag = false;\n };\n\n function plotData (layerIndex) {\n var data = generateLayeredData();\n\n if (isDataLayer(layerIndex)) {\n var regionG = renderRegionG(layerIndex);\n\n renderPaths(regionG, layerIndex, data);\n\n renderTitle(regionG, layerIndex, data);\n }\n }\n\n function generateLayeredData () {\n var data = {};\n var groupAll = _chart.data();\n for (var i = 0; i < groupAll.length; ++i) {\n data[_chart.keyAccessor()(groupAll[i])] = _chart.valueAccessor()(groupAll[i]);\n }\n return data;\n }\n\n function isDataLayer (layerIndex) {\n return geoJson(layerIndex).keyAccessor;\n }\n\n function renderRegionG (layerIndex) {\n var regionG = _chart.svg()\n .selectAll(layerSelector(layerIndex))\n .classed('selected', function (d) {\n return isSelected(layerIndex, d);\n })\n .classed('deselected', function (d) {\n return isDeselected(layerIndex, d);\n })\n .attr('class', function (d) {\n var layerNameClass = geoJson(layerIndex).name;\n var regionClass = dc.utils.nameToId(geoJson(layerIndex).keyAccessor(d));\n var baseClasses = layerNameClass + ' ' + regionClass;\n if (isSelected(layerIndex, d)) {\n baseClasses += ' selected';\n }\n if (isDeselected(layerIndex, d)) {\n baseClasses += ' deselected';\n }\n return baseClasses;\n });\n return regionG;\n }\n\n function layerSelector (layerIndex) {\n return 'g.layer' + layerIndex + ' g.' + geoJson(layerIndex).name;\n }\n\n function isSelected (layerIndex, d) {\n return _chart.hasFilter() && _chart.hasFilter(getKey(layerIndex, d));\n }\n\n function isDeselected (layerIndex, d) {\n return _chart.hasFilter() && !_chart.hasFilter(getKey(layerIndex, d));\n }\n\n function getKey (layerIndex, d) {\n return geoJson(layerIndex).keyAccessor(d);\n }\n\n function geoJson (index) {\n return _geoJsons[index];\n }\n\n function renderPaths (regionG, layerIndex, data) {\n var paths = regionG\n .select('path')\n .attr('fill', function () {\n var currentFill = d3.select(this).attr('fill');\n if (currentFill) {\n return currentFill;\n }\n return 'none';\n })\n .on('click', function (d) {\n return _chart.onClick(d, layerIndex);\n });\n\n dc.transition(paths, _chart.transitionDuration()).attr('fill', function (d, i) {\n return _chart.getColor(data[geoJson(layerIndex).keyAccessor(d)], i);\n });\n }\n\n _chart.onClick = function (d, layerIndex) {\n var selectedRegion = geoJson(layerIndex).keyAccessor(d);\n dc.events.trigger(function () {\n _chart.filter(selectedRegion);\n _chart.redrawGroup();\n });\n };\n\n function renderTitle (regionG, layerIndex, data) {\n if (_chart.renderTitle()) {\n regionG.selectAll('title').text(function (d) {\n var key = getKey(layerIndex, d);\n var value = data[key];\n return _chart.title()({key: key, value: value});\n });\n }\n }\n\n _chart._doRedraw = function () {\n for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) {\n plotData(layerIndex);\n if (_projectionFlag) {\n _chart.svg().selectAll('g.' + geoJson(layerIndex).name + ' path').attr('d', _geoPath);\n }\n }\n _projectionFlag = false;\n };\n\n /**\n * **mandatory**\n *\n * Use this function to insert a new GeoJson map layer. This function can be invoked multiple times\n * if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple\n * layers with the same name the new overlay will override the existing one.\n * @method overlayGeoJson\n * @memberof dc.geoChoroplethChart\n * @instance\n * @see {@link http://geojson.org/ GeoJSON}\n * @see {@link https://github.com/mbostock/topojson/wiki TopoJSON}\n * @see {@link https://github.com/mbostock/topojson/wiki/API-Reference#feature topojson.feature}\n * @example\n * // insert a layer for rendering US states\n * chart.overlayGeoJson(statesJson.features, 'state', function(d) {\n * return d.properties.name;\n * });\n * @param {geoJson} json - a geojson feed\n * @param {String} name - name of the layer\n * @param {Function} keyAccessor - accessor function used to extract 'key' from the GeoJson data. The key extracted by\n * this function should match the keys returned by the crossfilter groups.\n * @return {dc.geoChoroplethChart}\n */\n _chart.overlayGeoJson = function (json, name, keyAccessor) {\n for (var i = 0; i < _geoJsons.length; ++i) {\n if (_geoJsons[i].name === name) {\n _geoJsons[i].data = json;\n _geoJsons[i].keyAccessor = keyAccessor;\n return _chart;\n }\n }\n _geoJsons.push({name: name, data: json, keyAccessor: keyAccessor});\n return _chart;\n };\n\n /**\n * Set custom geo projection function. See the available [d3 geo projection\n * functions](https://github.com/mbostock/d3/wiki/Geo-Projections).\n * @method projection\n * @memberof dc.geoChoroplethChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Geo-Projections d3.geo.projection}\n * @see {@link https://github.com/d3/d3-geo-projection Extended d3.geo.projection}\n * @param {d3.projection} [projection=d3.geo.albersUsa()]\n * @return {dc.geoChoroplethChart}\n */\n _chart.projection = function (projection) {\n _geoPath.projection(projection);\n _projectionFlag = true;\n return _chart;\n };\n\n /**\n * Returns all GeoJson layers currently registered with this chart. The returned array is a\n * reference to this chart's internal data structure, so any modification to this array will also\n * modify this chart's internal registration.\n * @method geoJsons\n * @memberof dc.geoChoroplethChart\n * @instance\n * @return {Array<{name:String, data: Object, accessor: Function}>}\n */\n _chart.geoJsons = function () {\n return _geoJsons;\n };\n\n /**\n * Returns the {@link https://github.com/mbostock/d3/wiki/Geo-Paths#path d3.geo.path} object used to\n * render the projection and features. Can be useful for figuring out the bounding box of the\n * feature set and thus a way to calculate scale and translation for the projection.\n * @method geoPath\n * @memberof dc.geoChoroplethChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Geo-Paths#path d3.geo.path}\n * @return {d3.geo.path}\n */\n _chart.geoPath = function () {\n return _geoPath;\n };\n\n /**\n * Remove a GeoJson layer from this chart by name\n * @method removeGeoJson\n * @memberof dc.geoChoroplethChart\n * @instance\n * @param {String} name\n * @return {dc.geoChoroplethChart}\n */\n _chart.removeGeoJson = function (name) {\n var geoJsons = [];\n\n for (var i = 0; i < _geoJsons.length; ++i) {\n var layer = _geoJsons[i];\n if (layer.name !== name) {\n geoJsons.push(layer);\n }\n }\n\n _geoJsons = geoJsons;\n\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay\n * chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the\n * typical x and y positioning while retaining the capability to visualize data using bubble radius\n * and coloring.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats}\n * @class bubbleOverlay\n * @memberof dc\n * @mixes dc.bubbleMixin\n * @mixes dc.baseMixin\n * @example\n * // create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group\n * var bubbleChart1 = dc.bubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg'));\n * // create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A\n * var bubbleChart2 = dc.compositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg'));\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.bubbleOverlay}\n */\ndc.bubbleOverlay = function (parent, chartGroup) {\n var BUBBLE_OVERLAY_CLASS = 'bubble-overlay';\n var BUBBLE_NODE_CLASS = 'node';\n var BUBBLE_CLASS = 'bubble';\n\n /**\n * **mandatory**\n *\n * Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg\n * element; therefore the bubble overlay chart will not work if this function is not invoked. If the\n * underlying image is a bitmap, then an empty svg will need to be created on top of the image.\n * @method svg\n * @memberof dc.bubbleOverlay\n * @instance\n * @example\n * // set up underlying svg element\n * chart.svg(d3.select('#chart svg'));\n * @param {SVGElement|d3.selection} [imageElement]\n * @return {dc.bubbleOverlay}\n */\n var _chart = dc.bubbleMixin(dc.baseMixin({}));\n var _g;\n var _points = [];\n\n _chart.transitionDuration(750);\n\n _chart.radiusValueAccessor(function (d) {\n return d.value;\n });\n\n /**\n * **mandatory**\n *\n * Set up a data point on the overlay. The name of a data point should match a specific 'key' among\n * data groups generated using keyAccessor. If a match is found (point name <-> data group key)\n * then a bubble will be generated at the position specified by the function. x and y\n * value specified here are relative to the underlying svg.\n * @method point\n * @memberof dc.bubbleOverlay\n * @instance\n * @param {String} name\n * @param {Number} x\n * @param {Number} y\n * @return {dc.bubbleOverlay}\n */\n _chart.point = function (name, x, y) {\n _points.push({name: name, x: x, y: y});\n return _chart;\n };\n\n _chart._doRender = function () {\n _g = initOverlayG();\n\n _chart.r().range([_chart.MIN_RADIUS, _chart.width() * _chart.maxBubbleRelativeSize()]);\n\n initializeBubbles();\n\n _chart.fadeDeselectedArea();\n\n return _chart;\n };\n\n function initOverlayG () {\n _g = _chart.select('g.' + BUBBLE_OVERLAY_CLASS);\n if (_g.empty()) {\n _g = _chart.svg().append('g').attr('class', BUBBLE_OVERLAY_CLASS);\n }\n return _g;\n }\n\n function initializeBubbles () {\n var data = mapData();\n\n _points.forEach(function (point) {\n var nodeG = getNodeG(point, data);\n\n var circle = nodeG.select('circle.' + BUBBLE_CLASS);\n\n if (circle.empty()) {\n circle = nodeG.append('circle')\n .attr('class', BUBBLE_CLASS)\n .attr('r', 0)\n .attr('fill', _chart.getColor)\n .on('click', _chart.onClick);\n }\n\n dc.transition(circle, _chart.transitionDuration())\n .attr('r', function (d) {\n return _chart.bubbleR(d);\n });\n\n _chart._doRenderLabel(nodeG);\n\n _chart._doRenderTitles(nodeG);\n });\n }\n\n function mapData () {\n var data = {};\n _chart.data().forEach(function (datum) {\n data[_chart.keyAccessor()(datum)] = datum;\n });\n return data;\n }\n\n function getNodeG (point, data) {\n var bubbleNodeClass = BUBBLE_NODE_CLASS + ' ' + dc.utils.nameToId(point.name);\n\n var nodeG = _g.select('g.' + dc.utils.nameToId(point.name));\n\n if (nodeG.empty()) {\n nodeG = _g.append('g')\n .attr('class', bubbleNodeClass)\n .attr('transform', 'translate(' + point.x + ',' + point.y + ')');\n }\n\n nodeG.datum(data[point.name]);\n\n return nodeG;\n }\n\n _chart._doRedraw = function () {\n updateBubbles();\n\n _chart.fadeDeselectedArea();\n\n return _chart;\n };\n\n function updateBubbles () {\n var data = mapData();\n\n _points.forEach(function (point) {\n var nodeG = getNodeG(point, data);\n\n var circle = nodeG.select('circle.' + BUBBLE_CLASS);\n\n dc.transition(circle, _chart.transitionDuration())\n .attr('r', function (d) {\n return _chart.bubbleR(d);\n })\n .attr('fill', _chart.getColor);\n\n _chart.doUpdateLabels(nodeG);\n\n _chart.doUpdateTitles(nodeG);\n });\n }\n\n _chart.debug = function (flag) {\n if (flag) {\n var debugG = _chart.select('g.' + dc.constants.DEBUG_GROUP_CLASS);\n\n if (debugG.empty()) {\n debugG = _chart.svg()\n .append('g')\n .attr('class', dc.constants.DEBUG_GROUP_CLASS);\n }\n\n var debugText = debugG.append('text')\n .attr('x', 10)\n .attr('y', 20);\n\n debugG\n .append('rect')\n .attr('width', _chart.width())\n .attr('height', _chart.height())\n .on('mousemove', function () {\n var position = d3.mouse(debugG.node());\n var msg = position[0] + ', ' + position[1];\n debugText.text(msg);\n });\n } else {\n _chart.selectAll('.debug').remove();\n }\n\n return _chart;\n };\n\n _chart.anchor(parent, chartGroup);\n\n return _chart;\n};\n","/**\n * Concrete row chart implementation.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * @class rowChart\n * @memberof dc\n * @mixes dc.capMixin\n * @mixes dc.marginMixin\n * @mixes dc.colorMixin\n * @mixes dc.baseMixin\n * @example\n * // create a row chart under #chart-container1 element using the default global chart group\n * var chart1 = dc.rowChart('#chart-container1');\n * // create a row chart under #chart-container2 element using chart group A\n * var chart2 = dc.rowChart('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.rowChart}\n */\ndc.rowChart = function (parent, chartGroup) {\n\n var _g;\n\n var _labelOffsetX = 10;\n var _labelOffsetY = 15;\n var _hasLabelOffsetY = false;\n var _dyOffset = '0.35em'; // this helps center labels https://github.com/mbostock/d3/wiki/SVG-Shapes#svg_text\n var _titleLabelOffsetX = 2;\n\n var _gap = 5;\n\n var _fixedBarHeight = false;\n var _rowCssClass = 'row';\n var _titleRowCssClass = 'titlerow';\n var _renderTitleLabel = false;\n\n var _chart = dc.capMixin(dc.marginMixin(dc.colorMixin(dc.baseMixin({}))));\n\n var _x;\n\n var _elasticX;\n\n var _xAxis = d3.svg.axis().orient('bottom');\n\n var _rowData;\n\n _chart.rowsCap = _chart.cap;\n\n function calculateAxisScale () {\n if (!_x || _elasticX) {\n var extent = d3.extent(_rowData, _chart.cappedValueAccessor);\n if (extent[0] > 0) {\n extent[0] = 0;\n }\n if (extent[1] < 0) {\n extent[1] = 0;\n }\n _x = d3.scale.linear().domain(extent)\n .range([0, _chart.effectiveWidth()]);\n }\n _xAxis.scale(_x);\n }\n\n function drawAxis () {\n var axisG = _g.select('g.axis');\n\n calculateAxisScale();\n\n if (axisG.empty()) {\n axisG = _g.append('g').attr('class', 'axis');\n }\n axisG.attr('transform', 'translate(0, ' + _chart.effectiveHeight() + ')');\n\n dc.transition(axisG, _chart.transitionDuration())\n .call(_xAxis);\n }\n\n _chart._doRender = function () {\n _chart.resetSvg();\n\n _g = _chart.svg()\n .append('g')\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')');\n\n drawChart();\n\n return _chart;\n };\n\n _chart.title(function (d) {\n return _chart.cappedKeyAccessor(d) + ': ' + _chart.cappedValueAccessor(d);\n });\n\n _chart.label(_chart.cappedKeyAccessor);\n\n /**\n * Gets or sets the x scale. The x scale can be any d3\n * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale}\n * @method x\n * @memberof dc.rowChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale}\n * @param {d3.scale} [scale]\n * @return {d3.scale}\n * @return {dc.rowChart}\n */\n _chart.x = function (scale) {\n if (!arguments.length) {\n return _x;\n }\n _x = scale;\n return _chart;\n };\n\n function drawGridLines () {\n _g.selectAll('g.tick')\n .select('line.grid-line')\n .remove();\n\n _g.selectAll('g.tick')\n .append('line')\n .attr('class', 'grid-line')\n .attr('x1', 0)\n .attr('y1', 0)\n .attr('x2', 0)\n .attr('y2', function () {\n return -_chart.effectiveHeight();\n });\n }\n\n function drawChart () {\n _rowData = _chart.data();\n\n drawAxis();\n drawGridLines();\n\n var rows = _g.selectAll('g.' + _rowCssClass)\n .data(_rowData);\n\n createElements(rows);\n removeElements(rows);\n updateElements(rows);\n }\n\n function createElements (rows) {\n var rowEnter = rows.enter()\n .append('g')\n .attr('class', function (d, i) {\n return _rowCssClass + ' _' + i;\n });\n\n rowEnter.append('rect').attr('width', 0);\n\n createLabels(rowEnter);\n }\n\n function removeElements (rows) {\n rows.exit().remove();\n }\n\n function rootValue () {\n var root = _x(0);\n return (root === -Infinity || root !== root) ? _x(1) : root;\n }\n\n function updateElements (rows) {\n var n = _rowData.length;\n\n var height;\n if (!_fixedBarHeight) {\n height = (_chart.effectiveHeight() - (n + 1) * _gap) / n;\n } else {\n height = _fixedBarHeight;\n }\n\n // vertically align label in center unless they override the value via property setter\n if (!_hasLabelOffsetY) {\n _labelOffsetY = height / 2;\n }\n\n var rect = rows.attr('transform', function (d, i) {\n return 'translate(0,' + ((i + 1) * _gap + i * height) + ')';\n }).select('rect')\n .attr('height', height)\n .attr('fill', _chart.getColor)\n .on('click', onClick)\n .classed('deselected', function (d) {\n return (_chart.hasFilter()) ? !isSelectedRow(d) : false;\n })\n .classed('selected', function (d) {\n return (_chart.hasFilter()) ? isSelectedRow(d) : false;\n });\n\n dc.transition(rect, _chart.transitionDuration())\n .attr('width', function (d) {\n return Math.abs(rootValue() - _x(_chart.valueAccessor()(d)));\n })\n .attr('transform', translateX);\n\n createTitles(rows);\n updateLabels(rows);\n }\n\n function createTitles (rows) {\n if (_chart.renderTitle()) {\n rows.selectAll('title').remove();\n rows.append('title').text(_chart.title());\n }\n }\n\n function createLabels (rowEnter) {\n if (_chart.renderLabel()) {\n rowEnter.append('text')\n .on('click', onClick);\n }\n if (_chart.renderTitleLabel()) {\n rowEnter.append('text')\n .attr('class', _titleRowCssClass)\n .on('click', onClick);\n }\n }\n\n function updateLabels (rows) {\n if (_chart.renderLabel()) {\n var lab = rows.select('text')\n .attr('x', _labelOffsetX)\n .attr('y', _labelOffsetY)\n .attr('dy', _dyOffset)\n .on('click', onClick)\n .attr('class', function (d, i) {\n return _rowCssClass + ' _' + i;\n })\n .text(function (d) {\n return _chart.label()(d);\n });\n dc.transition(lab, _chart.transitionDuration())\n .attr('transform', translateX);\n }\n if (_chart.renderTitleLabel()) {\n var titlelab = rows.select('.' + _titleRowCssClass)\n .attr('x', _chart.effectiveWidth() - _titleLabelOffsetX)\n .attr('y', _labelOffsetY)\n .attr('dy', _dyOffset)\n .attr('text-anchor', 'end')\n .on('click', onClick)\n .attr('class', function (d, i) {\n return _titleRowCssClass + ' _' + i ;\n })\n .text(function (d) {\n return _chart.title()(d);\n });\n dc.transition(titlelab, _chart.transitionDuration())\n .attr('transform', translateX);\n }\n }\n\n /**\n * Turn on/off Title label rendering (values) using SVG style of text-anchor 'end'\n * @method renderTitleLabel\n * @memberof dc.rowChart\n * @instance\n * @param {Boolean} [renderTitleLabel=false]\n * @return {Boolean}\n * @return {dc.rowChart}\n */\n _chart.renderTitleLabel = function (renderTitleLabel) {\n if (!arguments.length) {\n return _renderTitleLabel;\n }\n _renderTitleLabel = renderTitleLabel;\n return _chart;\n };\n\n function onClick (d) {\n _chart.onClick(d);\n }\n\n function translateX (d) {\n var x = _x(_chart.cappedValueAccessor(d)),\n x0 = rootValue(),\n s = x > x0 ? x0 : x;\n return 'translate(' + s + ',0)';\n }\n\n _chart._doRedraw = function () {\n drawChart();\n return _chart;\n };\n\n /**\n * Get the x axis for the row chart instance. Note: not settable for row charts.\n * See the {@link https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis d3 axis object}\n * documention for more information.\n * @method xAxis\n * @memberof dc.rowChart\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis d3.svg.axis}\n * @example\n * // customize x axis tick format\n * chart.xAxis().tickFormat(function (v) {return v + '%';});\n * // customize x axis tick values\n * chart.xAxis().tickValues([0, 100, 200, 300]);\n * @return {d3.svg.axis}\n */\n _chart.xAxis = function () {\n return _xAxis;\n };\n\n /**\n * Get or set the fixed bar height. Default is [false] which will auto-scale bars.\n * For example, if you want to fix the height for a specific number of bars (useful in TopN charts)\n * you could fix height as follows (where count = total number of bars in your TopN and gap is\n * your vertical gap space).\n * @method fixedBarHeight\n * @memberof dc.rowChart\n * @instance\n * @example\n * chart.fixedBarHeight( chartheight - (count + 1) * gap / count);\n * @param {Boolean|Number} [fixedBarHeight=false]\n * @return {Boolean|Number}\n * @return {dc.rowChart}\n */\n _chart.fixedBarHeight = function (fixedBarHeight) {\n if (!arguments.length) {\n return _fixedBarHeight;\n }\n _fixedBarHeight = fixedBarHeight;\n return _chart;\n };\n\n /**\n * Get or set the vertical gap space between rows on a particular row chart instance\n * @method gap\n * @memberof dc.rowChart\n * @instance\n * @param {Number} [gap=5]\n * @return {Number}\n * @return {dc.rowChart}\n */\n _chart.gap = function (gap) {\n if (!arguments.length) {\n return _gap;\n }\n _gap = gap;\n return _chart;\n };\n\n /**\n * Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescle to auto-fit the\n * data range when filtered.\n * @method elasticX\n * @memberof dc.rowChart\n * @instance\n * @param {Boolean} [elasticX]\n * @return {Boolean}\n * @return {dc.rowChart}\n */\n _chart.elasticX = function (elasticX) {\n if (!arguments.length) {\n return _elasticX;\n }\n _elasticX = elasticX;\n return _chart;\n };\n\n /**\n * Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart.\n * @method labelOffsetX\n * @memberof dc.rowChart\n * @instance\n * @param {Number} [labelOffsetX=10]\n * @return {Number}\n * @return {dc.rowChart}\n */\n _chart.labelOffsetX = function (labelOffsetX) {\n if (!arguments.length) {\n return _labelOffsetX;\n }\n _labelOffsetX = labelOffsetX;\n return _chart;\n };\n\n /**\n * Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart.\n * @method labelOffsetY\n * @memberof dc.rowChart\n * @instance\n * @param {Number} [labelOffsety=15]\n * @return {Number}\n * @return {dc.rowChart}\n */\n _chart.labelOffsetY = function (labelOffsety) {\n if (!arguments.length) {\n return _labelOffsetY;\n }\n _labelOffsetY = labelOffsety;\n _hasLabelOffsetY = true;\n return _chart;\n };\n\n /**\n * Get of set the x offset (horizontal space between right edge of row and right edge or text.\n * @method titleLabelOffsetX\n * @memberof dc.rowChart\n * @instance\n * @param {Number} [titleLabelOffsetX=2]\n * @return {Number}\n * @return {dc.rowChart}\n */\n _chart.titleLabelOffsetX = function (titleLabelOffsetX) {\n if (!arguments.length) {\n return _titleLabelOffsetX;\n }\n _titleLabelOffsetX = titleLabelOffsetX;\n return _chart;\n };\n\n function isSelectedRow (d) {\n return _chart.hasFilter(_chart.cappedKeyAccessor(d));\n }\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * Legend is a attachable widget that can be added to other dc charts to render horizontal legend\n * labels.\n *\n * Examples:\n * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index}\n * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats}\n * @class legend\n * @memberof dc\n * @example\n * chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5))\n * @return {dc.legend}\n */\ndc.legend = function () {\n var LABEL_GAP = 2;\n\n var _legend = {},\n _parent,\n _x = 0,\n _y = 0,\n _itemHeight = 12,\n _gap = 5,\n _horizontal = false,\n _legendWidth = 560,\n _itemWidth = 70,\n _autoItemWidth = false,\n _legendText = dc.pluck('name');\n\n var _g;\n\n _legend.parent = function (p) {\n if (!arguments.length) {\n return _parent;\n }\n _parent = p;\n return _legend;\n };\n\n _legend.render = function () {\n _parent.svg().select('g.dc-legend').remove();\n _g = _parent.svg().append('g')\n .attr('class', 'dc-legend')\n .attr('transform', 'translate(' + _x + ',' + _y + ')');\n var legendables = _parent.legendables();\n\n var itemEnter = _g.selectAll('g.dc-legend-item')\n .data(legendables)\n .enter()\n .append('g')\n .attr('class', 'dc-legend-item')\n .on('mouseover', function (d) {\n _parent.legendHighlight(d);\n })\n .on('mouseout', function (d) {\n _parent.legendReset(d);\n })\n .on('click', function (d) {\n d.chart.legendToggle(d);\n });\n\n _g.selectAll('g.dc-legend-item')\n .classed('fadeout', function (d) {\n return d.chart.isLegendableHidden(d);\n });\n\n if (legendables.some(dc.pluck('dashstyle'))) {\n itemEnter\n .append('line')\n .attr('x1', 0)\n .attr('y1', _itemHeight / 2)\n .attr('x2', _itemHeight)\n .attr('y2', _itemHeight / 2)\n .attr('stroke-width', 2)\n .attr('stroke-dasharray', dc.pluck('dashstyle'))\n .attr('stroke', dc.pluck('color'));\n } else {\n itemEnter\n .append('rect')\n .attr('width', _itemHeight)\n .attr('height', _itemHeight)\n .attr('fill', function (d) {return d ? d.color : 'blue';});\n }\n\n itemEnter.append('text')\n .text(_legendText)\n .attr('x', _itemHeight + LABEL_GAP)\n .attr('y', function () {\n return _itemHeight / 2 + (this.clientHeight ? this.clientHeight : 13) / 2 - 2;\n });\n\n var _cumulativeLegendTextWidth = 0;\n var row = 0;\n itemEnter.attr('transform', function (d, i) {\n if (_horizontal) {\n var translateBy = 'translate(' + _cumulativeLegendTextWidth + ',' + row * legendItemHeight() + ')';\n var itemWidth = _autoItemWidth === true ? this.getBBox().width + _gap : _itemWidth;\n\n if ((_cumulativeLegendTextWidth + itemWidth) >= _legendWidth) {\n ++row ;\n _cumulativeLegendTextWidth = 0 ;\n } else {\n _cumulativeLegendTextWidth += itemWidth;\n }\n return translateBy;\n } else {\n return 'translate(0,' + i * legendItemHeight() + ')';\n }\n });\n };\n\n function legendItemHeight () {\n return _gap + _itemHeight;\n }\n\n /**\n * Set or get x coordinate for legend widget.\n * @method x\n * @memberof dc.legend\n * @instance\n * @param {Number} [x=0]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.x = function (x) {\n if (!arguments.length) {\n return _x;\n }\n _x = x;\n return _legend;\n };\n\n /**\n * Set or get y coordinate for legend widget.\n * @method y\n * @memberof dc.legend\n * @instance\n * @param {Number} [y=0]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.y = function (y) {\n if (!arguments.length) {\n return _y;\n }\n _y = y;\n return _legend;\n };\n\n /**\n * Set or get gap between legend items.\n * @method gap\n * @memberof dc.legend\n * @instance\n * @param {Number} [gap=5]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.gap = function (gap) {\n if (!arguments.length) {\n return _gap;\n }\n _gap = gap;\n return _legend;\n };\n\n /**\n * Set or get legend item height.\n * @method itemHeight\n * @memberof dc.legend\n * @instance\n * @param {Number} [itemHeight=12]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.itemHeight = function (itemHeight) {\n if (!arguments.length) {\n return _itemHeight;\n }\n _itemHeight = itemHeight;\n return _legend;\n };\n\n /**\n * Position legend horizontally instead of vertically.\n * @method horizontal\n * @memberof dc.legend\n * @instance\n * @param {Boolean} [horizontal=false]\n * @return {Boolean}\n * @return {dc.legend}\n */\n _legend.horizontal = function (horizontal) {\n if (!arguments.length) {\n return _horizontal;\n }\n _horizontal = horizontal;\n return _legend;\n };\n\n /**\n * Maximum width for horizontal legend.\n * @method legendWidth\n * @memberof dc.legend\n * @instance\n * @param {Number} [legendWidth=500]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.legendWidth = function (legendWidth) {\n if (!arguments.length) {\n return _legendWidth;\n }\n _legendWidth = legendWidth;\n return _legend;\n };\n\n /**\n * legendItem width for horizontal legend.\n * @method itemWidth\n * @memberof dc.legend\n * @instance\n * @param {Number} [itemWidth=70]\n * @return {Number}\n * @return {dc.legend}\n */\n _legend.itemWidth = function (itemWidth) {\n if (!arguments.length) {\n return _itemWidth;\n }\n _itemWidth = itemWidth;\n return _legend;\n };\n\n /**\n * Turn automatic width for legend items on or off. If true, {@link dc.legend#itemWidth itemWidth} is ignored.\n * This setting takes into account {@link dc.legend#gap gap}.\n * @method autoItemWidth\n * @memberof dc.legend\n * @instance\n * @param {Boolean} [autoItemWidth=false]\n * @return {Boolean}\n * @return {dc.legend}\n */\n _legend.autoItemWidth = function (autoItemWidth) {\n if (!arguments.length) {\n return _autoItemWidth;\n }\n _autoItemWidth = autoItemWidth;\n return _legend;\n };\n\n /**\n * Set or get the legend text function. The legend widget uses this function to render the legend\n * text for each item. If no function is specified the legend widget will display the names\n * associated with each group.\n * @method legendText\n * @memberof dc.legend\n * @instance\n * @param {Function} [legendText]\n * @return {Function}\n * @return {dc.legend}\n * @example\n * // default legendText\n * legend.legendText(dc.pluck('name'))\n *\n * // create numbered legend items\n * chart.legend(dc.legend().legendText(function(d, i) { return i + '. ' + d.name; }))\n *\n * // create legend displaying group counts\n * chart.legend(dc.legend().legendText(function(d) { return d.name + ': ' d.data; }))\n **/\n _legend.legendText = function (legendText) {\n if (!arguments.length) {\n return _legendText;\n }\n _legendText = legendText;\n return _legend;\n };\n\n return _legend;\n};\n","/**\n * A scatter plot chart\n *\n * Examples:\n * - {@link http://dc-js.github.io/dc.js/examples/scatter.html Scatter Chart}\n * - {@link http://dc-js.github.io/dc.js/examples/multi-scatter.html Multi-Scatter Chart}\n * @class scatterPlot\n * @memberof dc\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a scatter plot under #chart-container1 element using the default global chart group\n * var chart1 = dc.scatterPlot('#chart-container1');\n * // create a scatter plot under #chart-container2 element using chart group A\n * var chart2 = dc.scatterPlot('#chart-container2', 'chartGroupA');\n * // create a sub-chart under a composite parent chart\n * var chart3 = dc.scatterPlot(compositeChart);\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.scatterPlot}\n */\ndc.scatterPlot = function (parent, chartGroup) {\n var _chart = dc.coordinateGridMixin({});\n var _symbol = d3.svg.symbol();\n\n var _existenceAccessor = function (d) { return d.value; };\n\n var originalKeyAccessor = _chart.keyAccessor();\n _chart.keyAccessor(function (d) { return originalKeyAccessor(d)[0]; });\n _chart.valueAccessor(function (d) { return originalKeyAccessor(d)[1]; });\n _chart.colorAccessor(function () { return _chart._groupName; });\n\n var _locator = function (d) {\n return 'translate(' + _chart.x()(_chart.keyAccessor()(d)) + ',' +\n _chart.y()(_chart.valueAccessor()(d)) + ')';\n };\n\n var _highlightedSize = 7;\n var _symbolSize = 5;\n var _excludedSize = 3;\n var _excludedColor = null;\n var _excludedOpacity = 1.0;\n var _emptySize = 0;\n var _filtered = [];\n\n _symbol.size(function (d, i) {\n if (!_existenceAccessor(d)) {\n return _emptySize;\n } else if (_filtered[i]) {\n return Math.pow(_symbolSize, 2);\n } else {\n return Math.pow(_excludedSize, 2);\n }\n });\n\n dc.override(_chart, '_filter', function (filter) {\n if (!arguments.length) {\n return _chart.__filter();\n }\n\n return _chart.__filter(dc.filters.RangedTwoDimensionalFilter(filter));\n });\n\n _chart.plotData = function () {\n var symbols = _chart.chartBodyG().selectAll('path.symbol')\n .data(_chart.data());\n\n symbols\n .enter()\n .append('path')\n .attr('class', 'symbol')\n .attr('opacity', 0)\n .attr('fill', _chart.getColor)\n .attr('transform', _locator);\n\n symbols.each(function (d, i) {\n _filtered[i] = !_chart.filter() || _chart.filter().isFiltered([d.key[0], d.key[1]]);\n });\n\n dc.transition(symbols, _chart.transitionDuration())\n .attr('opacity', function (d, i) {\n return !_existenceAccessor(d) ? 0 :\n _filtered[i] ? 1 : _chart.excludedOpacity();\n })\n .attr('fill', function (d, i) {\n return _chart.excludedColor() && !_filtered[i] ?\n _chart.excludedColor() :\n _chart.getColor(d);\n })\n .attr('transform', _locator)\n .attr('d', _symbol);\n\n dc.transition(symbols.exit(), _chart.transitionDuration())\n .attr('opacity', 0).remove();\n };\n\n /**\n * Get or set the existence accessor. If a point exists, it is drawn with\n * {@link dc.scatterPlot#symbolSize symbolSize} radius and\n * opacity 1; if it does not exist, it is drawn with\n * {@link dc.scatterPlot#emptySize emptySize} radius and opacity 0. By default,\n * the existence accessor checks if the reduced value is truthy.\n * @method existenceAccessor\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link dc.scatterPlot#symbolSize symbolSize}\n * @see {@link dc.scatterPlot#emptySize emptySize}\n * @example\n * // default accessor\n * chart.existenceAccessor(function (d) { return d.value; });\n * @param {Function} [accessor]\n * @return {Function}\n * @return {dc.scatterPlot}\n */\n _chart.existenceAccessor = function (accessor) {\n if (!arguments.length) {\n return _existenceAccessor;\n }\n _existenceAccessor = accessor;\n return this;\n };\n\n /**\n * Get or set the symbol type used for each point. By default the symbol is a circle.\n * Type can be a constant or an accessor.\n * @method symbol\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_type d3.svg.symbol().type()}\n * @example\n * // Circle type\n * chart.symbol('circle');\n * // Square type\n * chart.symbol('square');\n * @param {String|Function} [type='circle']\n * @return {String|Function}\n * @return {dc.scatterPlot}\n */\n _chart.symbol = function (type) {\n if (!arguments.length) {\n return _symbol.type();\n }\n _symbol.type(type);\n return _chart;\n };\n\n /**\n * Set or get radius for symbols.\n * @method symbolSize\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [symbolSize=3]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.symbolSize = function (symbolSize) {\n if (!arguments.length) {\n return _symbolSize;\n }\n _symbolSize = symbolSize;\n return _chart;\n };\n\n /**\n * Set or get radius for highlighted symbols.\n * @method highlightedSize\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [highlightedSize=5]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.highlightedSize = function (highlightedSize) {\n if (!arguments.length) {\n return _highlightedSize;\n }\n _highlightedSize = highlightedSize;\n return _chart;\n };\n\n /**\n * Set or get size for symbols excluded from this chart's filter. If null, no\n * special size is applied for symbols based on their filter status\n * @method excludedSize\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [excludedSize=null]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.excludedSize = function (excludedSize) {\n if (!arguments.length) {\n return _excludedSize;\n }\n _excludedSize = excludedSize;\n return _chart;\n };\n\n /**\n * Set or get color for symbols excluded from this chart's filter. If null, no\n * special color is applied for symbols based on their filter status\n * @method excludedColor\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [excludedColor=null]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.excludedColor = function (excludedColor) {\n if (!arguments.length) {\n return _excludedColor;\n }\n _excludedColor = excludedColor;\n return _chart;\n };\n\n /**\n * Set or get opacity for symbols excluded from this chart's filter.\n * @method excludedOpacity\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [excludedOpacity=1.0]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.excludedOpacity = function (excludedOpacity) {\n if (!arguments.length) {\n return _excludedOpacity;\n }\n _excludedOpacity = excludedOpacity;\n return _chart;\n };\n\n /**\n * Set or get radius for symbols when the group is empty.\n * @method emptySize\n * @memberof dc.scatterPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()}\n * @param {Number} [emptySize=0]\n * @return {Number}\n * @return {dc.scatterPlot}\n */\n _chart.hiddenSize = _chart.emptySize = function (emptySize) {\n if (!arguments.length) {\n return _emptySize;\n }\n _emptySize = emptySize;\n return _chart;\n };\n\n _chart.legendables = function () {\n return [{chart: _chart, name: _chart._groupName, color: _chart.getColor()}];\n };\n\n _chart.legendHighlight = function (d) {\n resizeSymbolsWhere(function (symbol) {\n return symbol.attr('fill') === d.color;\n }, _highlightedSize);\n _chart.selectAll('.chart-body path.symbol').filter(function () {\n return d3.select(this).attr('fill') !== d.color;\n }).classed('fadeout', true);\n };\n\n _chart.legendReset = function (d) {\n resizeSymbolsWhere(function (symbol) {\n return symbol.attr('fill') === d.color;\n }, _symbolSize);\n _chart.selectAll('.chart-body path.symbol').filter(function () {\n return d3.select(this).attr('fill') !== d.color;\n }).classed('fadeout', false);\n };\n\n function resizeSymbolsWhere (condition, size) {\n var symbols = _chart.selectAll('.chart-body path.symbol').filter(function () {\n return condition(d3.select(this));\n });\n var oldSize = _symbol.size();\n _symbol.size(Math.pow(size, 2));\n dc.transition(symbols, _chart.transitionDuration()).attr('d', _symbol);\n _symbol.size(oldSize);\n }\n\n _chart.setHandlePaths = function () {\n // no handle paths for poly-brushes\n };\n\n _chart.extendBrush = function () {\n var extent = _chart.brush().extent();\n if (_chart.round()) {\n extent[0] = extent[0].map(_chart.round());\n extent[1] = extent[1].map(_chart.round());\n\n _chart.g().select('.brush')\n .call(_chart.brush().extent(extent));\n }\n return extent;\n };\n\n _chart.brushIsEmpty = function (extent) {\n return _chart.brush().empty() || !extent || extent[0][0] >= extent[1][0] || extent[0][1] >= extent[1][1];\n };\n\n _chart._brushing = function () {\n var extent = _chart.extendBrush();\n\n _chart.redrawBrush(_chart.g());\n\n if (_chart.brushIsEmpty(extent)) {\n dc.events.trigger(function () {\n _chart.filter(null);\n _chart.redrawGroup();\n });\n\n } else {\n var ranged2DFilter = dc.filters.RangedTwoDimensionalFilter(extent);\n dc.events.trigger(function () {\n _chart.filter(null);\n _chart.filter(ranged2DFilter);\n _chart.redrawGroup();\n }, dc.constants.EVENT_DELAY);\n\n }\n };\n\n _chart.setBrushY = function (gBrush) {\n gBrush.call(_chart.brush().y(_chart.y()));\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * A display of a single numeric value.\n * Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and\n * a valueAccessor that returns a single value.\n * @class numberDisplay\n * @memberof dc\n * @mixes dc.baseMixin\n * @example\n * // create a number display under #chart-container1 element using the default global chart group\n * var display1 = dc.numberDisplay('#chart-container1');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.numberDisplay}\n */\ndc.numberDisplay = function (parent, chartGroup) {\n var SPAN_CLASS = 'number-display';\n var _formatNumber = d3.format('.2s');\n var _chart = dc.baseMixin({});\n var _html = {one: '', some: '', none: ''};\n var _lastValue;\n\n // dimension not required\n _chart._mandatoryAttributes(['group']);\n\n /**\n * Gets or sets an optional object specifying HTML templates to use depending on the number\n * displayed. The text `%number` will be replaced with the current value.\n * - one: HTML template to use if the number is 1\n * - zero: HTML template to use if the number is 0\n * - some: HTML template to use otherwise\n * @method html\n * @memberof dc.numberDisplay\n * @instance\n * @example\n * numberWidget.html({\n * one:'%number record',\n * some:'%number records',\n * none:'no records'})\n * @param {{one:String, some:String, none:String}} [html={one: '', some: '', none: ''}]\n * @return {{one:String, some:String, none:String}}\n * @return {dc.numberDisplay}\n */\n _chart.html = function (html) {\n if (!arguments.length) {\n return _html;\n }\n if (html.none) {\n _html.none = html.none;//if none available\n } else if (html.one) {\n _html.none = html.one;//if none not available use one\n } else if (html.some) {\n _html.none = html.some;//if none and one not available use some\n }\n if (html.one) {\n _html.one = html.one;//if one available\n } else if (html.some) {\n _html.one = html.some;//if one not available use some\n }\n if (html.some) {\n _html.some = html.some;//if some available\n } else if (html.one) {\n _html.some = html.one;//if some not available use one\n }\n return _chart;\n };\n\n /**\n * Calculate and return the underlying value of the display\n * @method value\n * @memberof dc.numberDisplay\n * @instance\n * @return {Number}\n */\n _chart.value = function () {\n return _chart.data();\n };\n\n _chart.data(function (group) {\n var valObj = group.value ? group.value() : group.top(1)[0];\n return _chart.valueAccessor()(valObj);\n });\n\n _chart.transitionDuration(250); // good default\n\n _chart._doRender = function () {\n var newValue = _chart.value(),\n span = _chart.selectAll('.' + SPAN_CLASS);\n\n if (span.empty()) {\n span = span.data([0])\n .enter()\n .append('span')\n .attr('class', SPAN_CLASS);\n }\n\n span.transition()\n .duration(_chart.transitionDuration())\n .ease('quad-out-in')\n .tween('text', function () {\n // [XA] don't try and interpolate from Infinity, else this breaks.\n var interpStart = isFinite(_lastValue) ? _lastValue : 0;\n var interp = d3.interpolateNumber(interpStart || 0, newValue);\n _lastValue = newValue;\n return function (t) {\n var html = null, num = _chart.formatNumber()(interp(t));\n if (newValue === 0 && (_html.none !== '')) {\n html = _html.none;\n } else if (newValue === 1 && (_html.one !== '')) {\n html = _html.one;\n } else if (_html.some !== '') {\n html = _html.some;\n }\n this.innerHTML = html ? html.replace('%number', num) : num;\n };\n });\n };\n\n _chart._doRedraw = function () {\n return _chart._doRender();\n };\n\n /**\n * Get or set a function to format the value for the display.\n * @method formatNumber\n * @memberof dc.numberDisplay\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format}\n * @param {Function} [formatter=d3.format('.2s')]\n * @return {Function}\n * @return {dc.numberDisplay}\n */\n _chart.formatNumber = function (formatter) {\n if (!arguments.length) {\n return _formatNumber;\n }\n _formatNumber = formatter;\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * A heat map is matrix that represents the values of two dimensions of data using colors.\n * @class heatMap\n * @memberof dc\n * @mixes dc.colorMixin\n * @mixes dc.marginMixin\n * @mixes dc.baseMixin\n * @example\n * // create a heat map under #chart-container1 element using the default global chart group\n * var heatMap1 = dc.heatMap('#chart-container1');\n * // create a heat map under #chart-container2 element using chart group A\n * var heatMap2 = dc.heatMap('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.heatMap}\n */\ndc.heatMap = function (parent, chartGroup) {\n\n var DEFAULT_BORDER_RADIUS = 6.75;\n\n var _chartBody;\n\n var _cols;\n var _rows;\n var _colOrdering = d3.ascending;\n var _rowOrdering = d3.ascending;\n var _colScale = d3.scale.ordinal();\n var _rowScale = d3.scale.ordinal();\n\n var _xBorderRadius = DEFAULT_BORDER_RADIUS;\n var _yBorderRadius = DEFAULT_BORDER_RADIUS;\n\n var _chart = dc.colorMixin(dc.marginMixin(dc.baseMixin({})));\n _chart._mandatoryAttributes(['group']);\n _chart.title(_chart.colorAccessor());\n\n var _colsLabel = function (d) {\n return d;\n };\n var _rowsLabel = function (d) {\n return d;\n };\n\n /**\n * Set or get the column label function. The chart class uses this function to render\n * column labels on the X axis. It is passed the column name.\n * @method colsLabel\n * @memberof dc.heatMap\n * @instance\n * @example\n * // the default label function just returns the name\n * chart.colsLabel(function(d) { return d; });\n * @param {Function} [labelFunction=function(d) { return d; }]\n * @return {Function}\n * @return {dc.heatMap}\n */\n _chart.colsLabel = function (labelFunction) {\n if (!arguments.length) {\n return _colsLabel;\n }\n _colsLabel = labelFunction;\n return _chart;\n };\n\n /**\n * Set or get the row label function. The chart class uses this function to render\n * row labels on the Y axis. It is passed the row name.\n * @method rowsLabel\n * @memberof dc.heatMap\n * @instance\n * @example\n * // the default label function just returns the name\n * chart.rowsLabel(function(d) { return d; });\n * @param {Function} [labelFunction=function(d) { return d; }]\n * @return {Function}\n * @return {dc.heatMap}\n */\n _chart.rowsLabel = function (labelFunction) {\n if (!arguments.length) {\n return _rowsLabel;\n }\n _rowsLabel = labelFunction;\n return _chart;\n };\n\n var _xAxisOnClick = function (d) { filterAxis(0, d); };\n var _yAxisOnClick = function (d) { filterAxis(1, d); };\n var _boxOnClick = function (d) {\n var filter = d.key;\n dc.events.trigger(function () {\n _chart.filter(filter);\n _chart.redrawGroup();\n });\n };\n\n function filterAxis (axis, value) {\n var cellsOnAxis = _chart.selectAll('.box-group').filter(function (d) {\n return d.key[axis] === value;\n });\n var unfilteredCellsOnAxis = cellsOnAxis.filter(function (d) {\n return !_chart.hasFilter(d.key);\n });\n dc.events.trigger(function () {\n if (unfilteredCellsOnAxis.empty()) {\n cellsOnAxis.each(function (d) {\n _chart.filter(d.key);\n });\n } else {\n unfilteredCellsOnAxis.each(function (d) {\n _chart.filter(d.key);\n });\n }\n _chart.redrawGroup();\n });\n }\n\n dc.override(_chart, 'filter', function (filter) {\n if (!arguments.length) {\n return _chart._filter();\n }\n\n return _chart._filter(dc.filters.TwoDimensionalFilter(filter));\n });\n\n /**\n * Gets or sets the values used to create the rows of the heatmap, as an array. By default, all\n * the values will be fetched from the data using the value accessor.\n * @method rows\n * @memberof dc.heatMap\n * @instance\n * @param {Array} [rows]\n * @return {Array}\n * @return {dc.heatMap}\n */\n\n _chart.rows = function (rows) {\n if (!arguments.length) {\n return _rows;\n }\n _rows = rows;\n return _chart;\n };\n\n /**\n #### .rowOrdering([orderFunction])\n Get or set an accessor to order the rows. Default is d3.ascending.\n */\n _chart.rowOrdering = function (_) {\n if (!arguments.length) {\n return _rowOrdering;\n }\n _rowOrdering = _;\n return _chart;\n };\n\n /**\n * Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all\n * the values will be fetched from the data using the key accessor.\n * @method cols\n * @memberof dc.heatMap\n * @instance\n * @param {Array} [cols]\n * @return {Array}\n * @return {dc.heatMap}\n */\n _chart.cols = function (cols) {\n if (!arguments.length) {\n return _cols;\n }\n _cols = cols;\n return _chart;\n };\n\n /**\n #### .colOrdering([orderFunction])\n Get or set an accessor to order the cols. Default is ascending.\n */\n _chart.colOrdering = function (_) {\n if (!arguments.length) {\n return _colOrdering;\n }\n _colOrdering = _;\n return _chart;\n };\n\n _chart._doRender = function () {\n _chart.resetSvg();\n\n _chartBody = _chart.svg()\n .append('g')\n .attr('class', 'heatmap')\n .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')');\n\n return _chart._doRedraw();\n };\n\n _chart._doRedraw = function () {\n var data = _chart.data(),\n rows = _chart.rows() || data.map(_chart.valueAccessor()),\n cols = _chart.cols() || data.map(_chart.keyAccessor());\n if (_rowOrdering) {\n rows = rows.sort(_rowOrdering);\n }\n if (_colOrdering) {\n cols = cols.sort(_colOrdering);\n }\n rows = _rowScale.domain(rows);\n cols = _colScale.domain(cols);\n\n var rowCount = rows.domain().length,\n colCount = cols.domain().length,\n boxWidth = Math.floor(_chart.effectiveWidth() / colCount),\n boxHeight = Math.floor(_chart.effectiveHeight() / rowCount);\n\n cols.rangeRoundBands([0, _chart.effectiveWidth()]);\n rows.rangeRoundBands([_chart.effectiveHeight(), 0]);\n\n var boxes = _chartBody.selectAll('g.box-group').data(_chart.data(), function (d, i) {\n return _chart.keyAccessor()(d, i) + '\\0' + _chart.valueAccessor()(d, i);\n });\n var gEnter = boxes.enter().append('g')\n .attr('class', 'box-group');\n\n gEnter.append('rect')\n .attr('class', 'heat-box')\n .attr('fill', 'white')\n .on('click', _chart.boxOnClick());\n\n if (_chart.renderTitle()) {\n gEnter.append('title');\n boxes.selectAll('title').text(_chart.title());\n }\n\n dc.transition(boxes.selectAll('rect'), _chart.transitionDuration())\n .attr('x', function (d, i) { return cols(_chart.keyAccessor()(d, i)); })\n .attr('y', function (d, i) { return rows(_chart.valueAccessor()(d, i)); })\n .attr('rx', _xBorderRadius)\n .attr('ry', _yBorderRadius)\n .attr('fill', _chart.getColor)\n .attr('width', boxWidth)\n .attr('height', boxHeight);\n\n boxes.exit().remove();\n\n var gCols = _chartBody.selectAll('g.cols');\n if (gCols.empty()) {\n gCols = _chartBody.append('g').attr('class', 'cols axis');\n }\n var gColsText = gCols.selectAll('text').data(cols.domain());\n gColsText.enter().append('text')\n .attr('x', function (d) { return cols(d) + boxWidth / 2; })\n .style('text-anchor', 'middle')\n .attr('y', _chart.effectiveHeight())\n .attr('dy', 12)\n .on('click', _chart.xAxisOnClick())\n .text(_chart.colsLabel());\n dc.transition(gColsText, _chart.transitionDuration())\n .text(_chart.colsLabel())\n .attr('x', function (d) { return cols(d) + boxWidth / 2; })\n .attr('y', _chart.effectiveHeight());\n gColsText.exit().remove();\n var gRows = _chartBody.selectAll('g.rows');\n if (gRows.empty()) {\n gRows = _chartBody.append('g').attr('class', 'rows axis');\n }\n var gRowsText = gRows.selectAll('text').data(rows.domain());\n gRowsText.enter().append('text')\n .attr('dy', 6)\n .style('text-anchor', 'end')\n .attr('x', 0)\n .attr('dx', -2)\n .on('click', _chart.yAxisOnClick())\n .text(_chart.rowsLabel());\n dc.transition(gRowsText, _chart.transitionDuration())\n .text(_chart.rowsLabel())\n .attr('y', function (d) { return rows(d) + boxHeight / 2; });\n gRowsText.exit().remove();\n\n if (_chart.hasFilter()) {\n _chart.selectAll('g.box-group').each(function (d) {\n if (_chart.isSelectedNode(d)) {\n _chart.highlightSelected(this);\n } else {\n _chart.fadeDeselected(this);\n }\n });\n } else {\n _chart.selectAll('g.box-group').each(function () {\n _chart.resetHighlight(this);\n });\n }\n return _chart;\n };\n\n /**\n * Gets or sets the handler that fires when an individual cell is clicked in the heatmap.\n * By default, filtering of the cell will be toggled.\n * @method boxOnClick\n * @memberof dc.heatMap\n * @instance\n * @example\n * // default box on click handler\n * chart.boxOnClick(function (d) {\n * var filter = d.key;\n * dc.events.trigger(function () {\n * _chart.filter(filter);\n * _chart.redrawGroup();\n * });\n * });\n * @param {Function} [handler]\n * @return {Function}\n * @return {dc.heatMap}\n */\n _chart.boxOnClick = function (handler) {\n if (!arguments.length) {\n return _boxOnClick;\n }\n _boxOnClick = handler;\n return _chart;\n };\n\n /**\n * Gets or sets the handler that fires when a column tick is clicked in the x axis.\n * By default, if any cells in the column are unselected, the whole column will be selected,\n * otherwise the whole column will be unselected.\n * @method xAxisOnClick\n * @memberof dc.heatMap\n * @instance\n * @param {Function} [handler]\n * @return {Function}\n * @return {dc.heatMap}\n */\n _chart.xAxisOnClick = function (handler) {\n if (!arguments.length) {\n return _xAxisOnClick;\n }\n _xAxisOnClick = handler;\n return _chart;\n };\n\n /**\n * Gets or sets the handler that fires when a row tick is clicked in the y axis.\n * By default, if any cells in the row are unselected, the whole row will be selected,\n * otherwise the whole row will be unselected.\n * @method yAxisOnClick\n * @memberof dc.heatMap\n * @instance\n * @param {Function} [handler]\n * @return {Function}\n * @return {dc.heatMap}\n */\n _chart.yAxisOnClick = function (handler) {\n if (!arguments.length) {\n return _yAxisOnClick;\n }\n _yAxisOnClick = handler;\n return _chart;\n };\n\n /**\n * Gets or sets the X border radius. Set to 0 to get full rectangles.\n * @method xBorderRadius\n * @memberof dc.heatMap\n * @instance\n * @param {Number} [xBorderRadius=6.75]\n * @return {Number}\n * @return {dc.heatMap}\n */\n _chart.xBorderRadius = function (xBorderRadius) {\n if (!arguments.length) {\n return _xBorderRadius;\n }\n _xBorderRadius = xBorderRadius;\n return _chart;\n };\n\n /**\n * Gets or sets the Y border radius. Set to 0 to get full rectangles.\n * @method yBorderRadius\n * @memberof dc.heatMap\n * @instance\n * @param {Number} [yBorderRadius=6.75]\n * @return {Number}\n * @return {dc.heatMap}\n */\n _chart.yBorderRadius = function (yBorderRadius) {\n if (!arguments.length) {\n return _yBorderRadius;\n }\n _yBorderRadius = yBorderRadius;\n return _chart;\n };\n\n _chart.isSelectedNode = function (d) {\n return _chart.hasFilter(d.key);\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","// https://github.com/d3/d3-plugins/blob/master/box/box.js\n(function () {\n\n // Inspired by http://informationandvisualization.de/blog/box-plot\n d3.box = function () {\n var width = 1,\n height = 1,\n duration = 0,\n domain = null,\n value = Number,\n whiskers = boxWhiskers,\n quartiles = boxQuartiles,\n tickFormat = null;\n\n // For each small multiple…\n function box (g) {\n g.each(function (d, i) {\n d = d.map(value).sort(d3.ascending);\n var g = d3.select(this),\n n = d.length,\n min = d[0],\n max = d[n - 1];\n\n // Compute quartiles. Must return exactly 3 elements.\n var quartileData = d.quartiles = quartiles(d);\n\n // Compute whiskers. Must return exactly 2 elements, or null.\n var whiskerIndices = whiskers && whiskers.call(this, d, i),\n whiskerData = whiskerIndices && whiskerIndices.map(function (i) { return d[i]; });\n\n // Compute outliers. If no whiskers are specified, all data are 'outliers'.\n // We compute the outliers as indices, so that we can join across transitions!\n var outlierIndices = whiskerIndices ?\n d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n)) : d3.range(n);\n\n // Compute the new x-scale.\n var x1 = d3.scale.linear()\n .domain(domain && domain.call(this, d, i) || [min, max])\n .range([height, 0]);\n\n // Retrieve the old x-scale, if this is an update.\n var x0 = this.__chart__ || d3.scale.linear()\n .domain([0, Infinity])\n .range(x1.range());\n\n // Stash the new scale.\n this.__chart__ = x1;\n\n // Note: the box, median, and box tick elements are fixed in number,\n // so we only have to handle enter and update. In contrast, the outliers\n // and other elements are variable, so we need to exit them! Variable\n // elements also fade in and out.\n\n // Update center line: the vertical line spanning the whiskers.\n var center = g.selectAll('line.center')\n .data(whiskerData ? [whiskerData] : []);\n\n center.enter().insert('line', 'rect')\n .attr('class', 'center')\n .attr('x1', width / 2)\n .attr('y1', function (d) { return x0(d[0]); })\n .attr('x2', width / 2)\n .attr('y2', function (d) { return x0(d[1]); })\n .style('opacity', 1e-6)\n .transition()\n .duration(duration)\n .style('opacity', 1)\n .attr('y1', function (d) { return x1(d[0]); })\n .attr('y2', function (d) { return x1(d[1]); });\n\n center.transition()\n .duration(duration)\n .style('opacity', 1)\n .attr('y1', function (d) { return x1(d[0]); })\n .attr('y2', function (d) { return x1(d[1]); });\n\n center.exit().transition()\n .duration(duration)\n .style('opacity', 1e-6)\n .attr('y1', function (d) { return x1(d[0]); })\n .attr('y2', function (d) { return x1(d[1]); })\n .remove();\n\n // Update innerquartile box.\n var box = g.selectAll('rect.box')\n .data([quartileData]);\n\n box.enter().append('rect')\n .attr('class', 'box')\n .attr('x', 0)\n .attr('y', function (d) { return x0(d[2]); })\n .attr('width', width)\n .attr('height', function (d) { return x0(d[0]) - x0(d[2]); })\n .transition()\n .duration(duration)\n .attr('y', function (d) { return x1(d[2]); })\n .attr('height', function (d) { return x1(d[0]) - x1(d[2]); });\n\n box.transition()\n .duration(duration)\n .attr('y', function (d) { return x1(d[2]); })\n .attr('height', function (d) { return x1(d[0]) - x1(d[2]); });\n\n // Update median line.\n var medianLine = g.selectAll('line.median')\n .data([quartileData[1]]);\n\n medianLine.enter().append('line')\n .attr('class', 'median')\n .attr('x1', 0)\n .attr('y1', x0)\n .attr('x2', width)\n .attr('y2', x0)\n .transition()\n .duration(duration)\n .attr('y1', x1)\n .attr('y2', x1);\n\n medianLine.transition()\n .duration(duration)\n .attr('y1', x1)\n .attr('y2', x1);\n\n // Update whiskers.\n var whisker = g.selectAll('line.whisker')\n .data(whiskerData || []);\n\n whisker.enter().insert('line', 'circle, text')\n .attr('class', 'whisker')\n .attr('x1', 0)\n .attr('y1', x0)\n .attr('x2', width)\n .attr('y2', x0)\n .style('opacity', 1e-6)\n .transition()\n .duration(duration)\n .attr('y1', x1)\n .attr('y2', x1)\n .style('opacity', 1);\n\n whisker.transition()\n .duration(duration)\n .attr('y1', x1)\n .attr('y2', x1)\n .style('opacity', 1);\n\n whisker.exit().transition()\n .duration(duration)\n .attr('y1', x1)\n .attr('y2', x1)\n .style('opacity', 1e-6)\n .remove();\n\n // Update outliers.\n var outlier = g.selectAll('circle.outlier')\n .data(outlierIndices, Number);\n\n outlier.enter().insert('circle', 'text')\n .attr('class', 'outlier')\n .attr('r', 5)\n .attr('cx', width / 2)\n .attr('cy', function (i) { return x0(d[i]); })\n .style('opacity', 1e-6)\n .transition()\n .duration(duration)\n .attr('cy', function (i) { return x1(d[i]); })\n .style('opacity', 1);\n\n outlier.transition()\n .duration(duration)\n .attr('cy', function (i) { return x1(d[i]); })\n .style('opacity', 1);\n\n outlier.exit().transition()\n .duration(duration)\n .attr('cy', function (i) { return x1(d[i]); })\n .style('opacity', 1e-6)\n .remove();\n\n // Compute the tick format.\n var format = tickFormat || x1.tickFormat(8);\n\n // Update box ticks.\n var boxTick = g.selectAll('text.box')\n .data(quartileData);\n\n boxTick.enter().append('text')\n .attr('class', 'box')\n .attr('dy', '.3em')\n .attr('dx', function (d, i) { return i & 1 ? 6 : -6; })\n .attr('x', function (d, i) { return i & 1 ? width : 0; })\n .attr('y', x0)\n .attr('text-anchor', function (d, i) { return i & 1 ? 'start' : 'end'; })\n .text(format)\n .transition()\n .duration(duration)\n .attr('y', x1);\n\n boxTick.transition()\n .duration(duration)\n .text(format)\n .attr('y', x1);\n\n // Update whisker ticks. These are handled separately from the box\n // ticks because they may or may not exist, and we want don't want\n // to join box ticks pre-transition with whisker ticks post-.\n var whiskerTick = g.selectAll('text.whisker')\n .data(whiskerData || []);\n\n whiskerTick.enter().append('text')\n .attr('class', 'whisker')\n .attr('dy', '.3em')\n .attr('dx', 6)\n .attr('x', width)\n .attr('y', x0)\n .text(format)\n .style('opacity', 1e-6)\n .transition()\n .duration(duration)\n .attr('y', x1)\n .style('opacity', 1);\n\n whiskerTick.transition()\n .duration(duration)\n .text(format)\n .attr('y', x1)\n .style('opacity', 1);\n\n whiskerTick.exit().transition()\n .duration(duration)\n .attr('y', x1)\n .style('opacity', 1e-6)\n .remove();\n });\n d3.timer.flush();\n }\n\n box.width = function (x) {\n if (!arguments.length) {\n return width;\n }\n width = x;\n return box;\n };\n\n box.height = function (x) {\n if (!arguments.length) {\n return height;\n }\n height = x;\n return box;\n };\n\n box.tickFormat = function (x) {\n if (!arguments.length) {\n return tickFormat;\n }\n tickFormat = x;\n return box;\n };\n\n box.duration = function (x) {\n if (!arguments.length) {\n return duration;\n }\n duration = x;\n return box;\n };\n\n box.domain = function (x) {\n if (!arguments.length) {\n return domain;\n }\n domain = x === null ? x : d3.functor(x);\n return box;\n };\n\n box.value = function (x) {\n if (!arguments.length) {\n return value;\n }\n value = x;\n return box;\n };\n\n box.whiskers = function (x) {\n if (!arguments.length) {\n return whiskers;\n }\n whiskers = x;\n return box;\n };\n\n box.quartiles = function (x) {\n if (!arguments.length) {\n return quartiles;\n }\n quartiles = x;\n return box;\n };\n\n return box;\n };\n\n function boxWhiskers (d) {\n return [0, d.length - 1];\n }\n\n function boxQuartiles (d) {\n return [\n d3.quantile(d, 0.25),\n d3.quantile(d, 0.5),\n d3.quantile(d, 0.75)\n ];\n }\n\n})();\n","/**\n * A box plot is a chart that depicts numerical data via their quartile ranges.\n *\n * Examples:\n * - {@link http://dc-js.github.io/dc.js/examples/box-plot-time.html Box plot time example}\n * - {@link http://dc-js.github.io/dc.js/examples/box-plot.html Box plot example}\n * @class boxPlot\n * @memberof dc\n * @mixes dc.coordinateGridMixin\n * @example\n * // create a box plot under #chart-container1 element using the default global chart group\n * var boxPlot1 = dc.boxPlot('#chart-container1');\n * // create a box plot under #chart-container2 element using chart group A\n * var boxPlot2 = dc.boxPlot('#chart-container2', 'chartGroupA');\n * @param {String|node|d3.selection} parent - Any valid\n * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.\n * Interaction with a chart will only trigger events and redraws within the chart's group.\n * @return {dc.boxPlot}\n */\ndc.boxPlot = function (parent, chartGroup) {\n var _chart = dc.coordinateGridMixin({});\n\n // Returns a function to compute the interquartile range.\n function DEFAULT_WHISKERS_IQR (k) {\n return function (d) {\n var q1 = d.quartiles[0],\n q3 = d.quartiles[2],\n iqr = (q3 - q1) * k,\n i = -1,\n j = d.length;\n do { ++i; } while (d[i] < q1 - iqr);\n do { --j; } while (d[j] > q3 + iqr);\n return [i, j];\n };\n }\n\n var _whiskerIqrFactor = 1.5;\n var _whiskersIqr = DEFAULT_WHISKERS_IQR;\n var _whiskers = _whiskersIqr(_whiskerIqrFactor);\n\n var _box = d3.box();\n var _tickFormat = null;\n\n var _boxWidth = function (innerChartWidth, xUnits) {\n if (_chart.isOrdinal()) {\n return _chart.x().rangeBand();\n } else {\n return innerChartWidth / (1 + _chart.boxPadding()) / xUnits;\n }\n };\n\n // default padding to handle min/max whisker text\n _chart.yAxisPadding(12);\n\n // default to ordinal\n _chart.x(d3.scale.ordinal());\n _chart.xUnits(dc.units.ordinal);\n\n // valueAccessor should return an array of values that can be coerced into numbers\n // or if data is overloaded for a static array of arrays, it should be `Number`.\n // Empty arrays are not included.\n _chart.data(function (group) {\n return group.all().map(function (d) {\n d.map = function (accessor) { return accessor.call(d, d); };\n return d;\n }).filter(function (d) {\n var values = _chart.valueAccessor()(d);\n return values.length !== 0;\n });\n });\n\n /**\n * Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1.\n * See the {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs}\n * for a visual description of how the padding is applied.\n * @method boxPadding\n * @memberof dc.boxPlot\n * @instance\n * @see {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3.scale.ordinal.rangeBands}\n * @param {Number} [padding=0.8]\n * @return {Number}\n * @return {dc.boxPlot}\n */\n _chart.boxPadding = _chart._rangeBandPadding;\n _chart.boxPadding(0.8);\n\n /**\n * Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts\n * or on charts with a custom {@link dc.boxPlot#boxWidth .boxWidth}. Will pad the width by\n * `padding * barWidth` on each side of the chart.\n * @method outerPadding\n * @memberof dc.boxPlot\n * @instance\n * @param {Number} [padding=0.5]\n * @return {Number}\n * @return {dc.boxPlot}\n */\n _chart.outerPadding = _chart._outerRangeBandPadding;\n _chart.outerPadding(0.5);\n\n /**\n * Get or set the numerical width of the boxplot box. The width may also be a function taking as\n * parameters the chart width excluding the right and left margins, as well as the number of x\n * units.\n * @example\n * // Using numerical parameter\n * chart.boxWidth(10);\n * // Using function\n * chart.boxWidth((innerChartWidth, xUnits) { ... });\n * @method boxWidth\n * @memberof dc.boxPlot\n * @instance\n * @param {Number|Function} [boxWidth=0.5]\n * @return {Number|Function}\n * @return {dc.boxPlot}\n */\n _chart.boxWidth = function (boxWidth) {\n if (!arguments.length) {\n return _boxWidth;\n }\n _boxWidth = d3.functor(boxWidth);\n return _chart;\n };\n\n var boxTransform = function (d, i) {\n var xOffset = _chart.x()(_chart.keyAccessor()(d, i));\n return 'translate(' + xOffset + ', 0)';\n };\n\n _chart._preprocessData = function () {\n if (_chart.elasticX()) {\n _chart.x().domain([]);\n }\n };\n\n _chart.plotData = function () {\n var _calculatedBoxWidth = _boxWidth(_chart.effectiveWidth(), _chart.xUnitCount());\n\n _box.whiskers(_whiskers)\n .width(_calculatedBoxWidth)\n .height(_chart.effectiveHeight())\n .value(_chart.valueAccessor())\n .domain(_chart.y().domain())\n .duration(_chart.transitionDuration())\n .tickFormat(_tickFormat);\n\n var boxesG = _chart.chartBodyG().selectAll('g.box').data(_chart.data(), function (d) { return d.key; });\n\n renderBoxes(boxesG);\n updateBoxes(boxesG);\n removeBoxes(boxesG);\n\n _chart.fadeDeselectedArea();\n };\n\n function renderBoxes (boxesG) {\n var boxesGEnter = boxesG.enter().append('g');\n\n boxesGEnter\n .attr('class', 'box')\n .attr('transform', boxTransform)\n .call(_box)\n .on('click', function (d) {\n _chart.filter(d.key);\n _chart.redrawGroup();\n });\n }\n\n function updateBoxes (boxesG) {\n dc.transition(boxesG, _chart.transitionDuration())\n .attr('transform', boxTransform)\n .call(_box)\n .each(function () {\n d3.select(this).select('rect.box').attr('fill', _chart.getColor);\n });\n }\n\n function removeBoxes (boxesG) {\n boxesG.exit().remove().call(_box);\n }\n\n _chart.fadeDeselectedArea = function () {\n if (_chart.hasFilter()) {\n _chart.g().selectAll('g.box').each(function (d) {\n if (_chart.isSelectedNode(d)) {\n _chart.highlightSelected(this);\n } else {\n _chart.fadeDeselected(this);\n }\n });\n } else {\n _chart.g().selectAll('g.box').each(function () {\n _chart.resetHighlight(this);\n });\n }\n };\n\n _chart.isSelectedNode = function (d) {\n return _chart.hasFilter(d.key);\n };\n\n _chart.yAxisMin = function () {\n var min = d3.min(_chart.data(), function (e) {\n return d3.min(_chart.valueAccessor()(e));\n });\n return dc.utils.subtract(min, _chart.yAxisPadding());\n };\n\n _chart.yAxisMax = function () {\n var max = d3.max(_chart.data(), function (e) {\n return d3.max(_chart.valueAccessor()(e));\n });\n return dc.utils.add(max, _chart.yAxisPadding());\n };\n\n /**\n * Set the numerical format of the boxplot median, whiskers and quartile labels. Defaults to\n * integer formatting.\n * @example\n * // format ticks to 2 decimal places\n * chart.tickFormat(d3.format('.2f'));\n * @method tickFormat\n * @memberof dc.boxPlot\n * @instance\n * @param {Function} [tickFormat]\n * @return {Number|Function}\n * @return {dc.boxPlot}\n */\n _chart.tickFormat = function (tickFormat) {\n if (!arguments.length) {\n return _tickFormat;\n }\n _tickFormat = tickFormat;\n return _chart;\n };\n\n return _chart.anchor(parent, chartGroup);\n};\n","/**\n * The select menu is a simple widget designed to filter a dimension by selecting an option from\n * an HTML `` elements. The menu can be +made into a set of radio buttons (single select) or checkboxes (multiple). + +**Kind**: global class +**Mixes**: [BaseMixin](#BaseMixin) + +* [CboxMenu](#CboxMenu) + * [new CboxMenu(parent, [chartGroup])](#new_CboxMenu_new) + * [.order([order])](#CboxMenu+order) ⇒ function \| [CboxMenu](#CboxMenu) + * [.promptText([promptText])](#CboxMenu+promptText) ⇒ String \| [CboxMenu](#CboxMenu) + * [.filterDisplayed([filterDisplayed])](#CboxMenu+filterDisplayed) ⇒ function \| [CboxMenu](#CboxMenu) + * [.multiple([multiple])](#CboxMenu+multiple) ⇒ Boolean \| [CboxMenu](#CboxMenu) + * [.promptValue([promptValue])](#CboxMenu+promptValue) ⇒ \* \| [CboxMenu](#CboxMenu) + + + +### new CboxMenu(parent, [chartGroup]) +Create a Cbox Menu. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [CompositeChart](#CompositeChart) | Any valid [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this widget should be placed in. Interaction with the widget will only trigger events and redraws within its group. | + +**Example** +```js +// create a cboxMenu under #cbox-container using the default global chart group +var cbox = new CboxMenu('#cbox-container') + .dimension(states) + .group(stateGroup); +// the option text can be set via the title() function +// by default the option text is '`key`: `value`' +cbox.title(function (d){ + return 'STATE: ' + d.key; +}) +``` + + +### cboxMenu.order([order]) ⇒ function \| [CboxMenu](#CboxMenu) +Get or set the function that controls the ordering of option tags in the +cbox menu. By default options are ordered by the group key in ascending +order. + +**Kind**: instance method of [CboxMenu](#CboxMenu) + +| Param | Type | +| --- | --- | +| [order] | function | + +**Example** +```js +// order by the group's value +chart.order(function (a,b) { + return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; +}); +``` + + +### cboxMenu.promptText([promptText]) ⇒ String \| [CboxMenu](#CboxMenu) +Get or set the text displayed in the options used to prompt selection. + +**Kind**: instance method of [CboxMenu](#CboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptText] | String | 'Select all' | + +**Example** +```js +chart.promptText('All states'); +``` + + +### cboxMenu.filterDisplayed([filterDisplayed]) ⇒ function \| [CboxMenu](#CboxMenu) +Get or set the function that filters options prior to display. By default options +with a value of < 1 are not displayed. + +**Kind**: instance method of [CboxMenu](#CboxMenu) + +| Param | Type | +| --- | --- | +| [filterDisplayed] | function | + +**Example** +```js +// display all options override the `filterDisplayed` function: +chart.filterDisplayed(function () { + return true; +}); +``` + + +### cboxMenu.multiple([multiple]) ⇒ Boolean \| [CboxMenu](#CboxMenu) +Controls the type of input element. Setting it to true converts +the HTML `input` tags from radio buttons to checkboxes. + +**Kind**: instance method of [CboxMenu](#CboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [multiple] | boolean | false | + +**Example** +```js +chart.multiple(true); +``` + + +### cboxMenu.promptValue([promptValue]) ⇒ \* \| [CboxMenu](#CboxMenu) +Controls the default value to be used for +[dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) +when only the prompt value is selected. If `null` (the default), no filtering will occur when +just the prompt is selected. + +**Kind**: instance method of [CboxMenu](#CboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptValue] | \* | | + + + +## CompositeChart +Composite charts are a special kind of chart that render multiple charts on the same Coordinate +Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to +achieve some quite flexible charting effects. + +**Kind**: global class +**Mixes**: [CoordinateGridMixin](#CoordinateGridMixin) + +* [CompositeChart](#CompositeChart) + * [new CompositeChart(parent, [chartGroup])](#new_CompositeChart_new) + * [.useRightAxisGridLines([useRightAxisGridLines])](#CompositeChart+useRightAxisGridLines) ⇒ Boolean \| [CompositeChart](#CompositeChart) + * [.childOptions([childOptions])](#CompositeChart+childOptions) ⇒ Object \| [CompositeChart](#CompositeChart) + * [.rightYAxisLabel([rightYAxisLabel], [padding])](#CompositeChart+rightYAxisLabel) ⇒ String \| [CompositeChart](#CompositeChart) + * [.compose([subChartArray])](#CompositeChart+compose) ⇒ [CompositeChart](#CompositeChart) + * [.children()](#CompositeChart+children) ⇒ [Array.<BaseMixin>](#BaseMixin) + * [.shareColors([shareColors])](#CompositeChart+shareColors) ⇒ Boolean \| [CompositeChart](#CompositeChart) + * [.shareTitle([shareTitle])](#CompositeChart+shareTitle) ⇒ Boolean \| [CompositeChart](#CompositeChart) + * [.rightY([yScale])](#CompositeChart+rightY) ⇒ d3.scale \| [CompositeChart](#CompositeChart) + * [.alignYAxes([alignYAxes])](#CompositeChart+alignYAxes) ⇒ Chart + * [.rightYAxis([rightYAxis])](#CompositeChart+rightYAxis) ⇒ d3.axisRight \| [CompositeChart](#CompositeChart) + + + +### new CompositeChart(parent, [chartGroup]) +Create a Composite Chart. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a composite chart under #chart-container1 element using the default global chart group +var compositeChart1 = new CompositeChart('#chart-container1'); +// create a composite chart under #chart-container2 element using chart group A +var compositeChart2 = new CompositeChart('#chart-container2', 'chartGroupA'); +``` + + +### compositeChart.useRightAxisGridLines([useRightAxisGridLines]) ⇒ Boolean \| [CompositeChart](#CompositeChart) +Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the +default behavior. This option is only respected when subcharts with both left and right y-axes +are present. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [useRightAxisGridLines] | Boolean | false | + + + +### compositeChart.childOptions([childOptions]) ⇒ Object \| [CompositeChart](#CompositeChart) +Get or set chart-specific options for all child charts. This is equivalent to calling +[.options](#BaseMixin+options) on each child chart. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | +| --- | --- | +| [childOptions] | Object | + + + +### compositeChart.rightYAxisLabel([rightYAxisLabel], [padding]) ⇒ String \| [CompositeChart](#CompositeChart) +Set or get the right y axis label. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | +| --- | --- | +| [rightYAxisLabel] | String | +| [padding] | Number | + + + +### compositeChart.compose([subChartArray]) ⇒ [CompositeChart](#CompositeChart) +Combine the given charts into one single composite coordinate grid chart. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | +| --- | --- | +| [subChartArray] | Array.<Chart> | + +**Example** +```js +moveChart.compose([ + // when creating sub-chart you need to pass in the parent chart + new LineChart(moveChart) + .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used + .valueAccessor(function (d){return d.value.avg;}) + // most of the normal functions will continue to work in a composed chart + .renderArea(true) + .stack(monthlyMoveGroup, function (d){return d.value;}) + .title(function (d){ + var value = d.value.avg?d.value.avg:d.value; + if(isNaN(value)) value = 0; + return dateFormat(d.key) + '\n' + numberFormat(value); + }), + new BarChart(moveChart) + .group(volumeByMonthGroup) + .centerBar(true) +]); +``` + + +### compositeChart.children() ⇒ [Array.<BaseMixin>](#BaseMixin) +Returns the child charts which are composed into the composite chart. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + + +### compositeChart.shareColors([shareColors]) ⇒ Boolean \| [CompositeChart](#CompositeChart) +Get or set color sharing for the chart. If set, the [.colors()](#ColorMixin+colors) value from this chart +will be shared with composed children. Additionally if the child chart implements +Stackable and has not set a custom .colorAccessor, then it will generate a color +specific to its order in the composition. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [shareColors] | Boolean | false | + + + +### compositeChart.shareTitle([shareTitle]) ⇒ Boolean \| [CompositeChart](#CompositeChart) +Get or set title sharing for the chart. If set, the [.title()](#BaseMixin+title) value from +this chart will be shared with composed children. + +Note: currently you must call this before `compose` or the child will still get the parent's +`title` function! + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [shareTitle] | Boolean | true | + + + +### compositeChart.rightY([yScale]) ⇒ d3.scale \| [CompositeChart](#CompositeChart) +Get or set the y scale for the right axis. The right y scale is typically automatically +generated by the chart implementation. + +**Kind**: instance method of [CompositeChart](#CompositeChart) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | +| --- | --- | +| [yScale] | d3.scale | + + + +### compositeChart.alignYAxes([alignYAxes]) ⇒ Chart +Get or set alignment between left and right y axes. A line connecting '0' on both y axis +will be parallel to x axis. This only has effect when [elasticY](#CoordinateGridMixin+elasticY) is true. + +**Kind**: instance method of [CompositeChart](#CompositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [alignYAxes] | Boolean | false | + + + +### compositeChart.rightYAxis([rightYAxis]) ⇒ d3.axisRight \| [CompositeChart](#CompositeChart) +Set or get the right y axis used by the composite chart. This function is most useful when y +axis customization is required. The y axis in dc.js is an instance of a +[d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight) therefore it supports any valid +d3 axis manipulation. + +**Caution**: The right y axis is usually generated internally by dc; resetting it may cause +unexpected results. Note also that when used as a getter, this function is not chainable: it +returns the axis, not the chart, +[so attempting to call chart functions after calling `.yAxis()` will fail](https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis). + +**Kind**: instance method of [CompositeChart](#CompositeChart) +**See**: [https://github.com/d3/d3-axis/blob/master/README.md#axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight) + +| Param | Type | +| --- | --- | +| [rightYAxis] | d3.axisRight | + +**Example** +```js +// customize y axis tick format +chart.rightYAxis().tickFormat(function (v) {return v + '%';}); +// customize y axis tick values +chart.rightYAxis().tickValues([0, 100, 200, 300]); +``` + + +## DataCount +The data count widget is a simple widget designed to display the number of records selected by the +current filters out of the total number of records in the data set. Once created the data count widget +will automatically update the text content of child elements with the following classes: + +* `.total-count` - total number of records +* `.filter-count` - number of records matched by the current filters + +Note: this widget works best for the specific case of showing the number of records out of a +total. If you want a more general-purpose numeric display, please use the +[NumberDisplay](#NumberDisplay) widget instead. + +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) + +**Kind**: global class +**Mixes**: [BaseMixin](#BaseMixin) + +* [DataCount](#DataCount) + * [new DataCount(parent, [chartGroup])](#new_DataCount_new) + * [.html([options])](#DataCount+html) ⇒ Object \| [DataCount](#DataCount) + * [.formatNumber([formatter])](#DataCount+formatNumber) ⇒ function \| [DataCount](#DataCount) + + + +### new DataCount(parent, [chartGroup]) +Create a Data Count widget. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +var ndx = crossfilter(data); +var all = ndx.groupAll(); + +new DataCount('.dc-data-count') + .crossfilter(ndx) + .groupAll(all); +``` + + +### dataCount.html([options]) ⇒ Object \| [DataCount](#DataCount) +Gets or sets an optional object specifying HTML templates to use depending how many items are +selected. The text `%total-count` will replaced with the total number of records, and the text +`%filter-count` will be replaced with the number of selected records. +- all: HTML template to use if all items are selected +- some: HTML template to use if not all items are selected + +**Kind**: instance method of [DataCount](#DataCount) + +| Param | Type | +| --- | --- | +| [options] | Object | + +**Example** +```js +counter.html({ + some: '%filter-count out of %total-count records selected', + all: 'All records selected. Click on charts to apply filters' +}) +``` + + +### dataCount.formatNumber([formatter]) ⇒ function \| [DataCount](#DataCount) +Gets or sets an optional function to format the filter count and total count. + +**Kind**: instance method of [DataCount](#DataCount) +**See**: [d3.format](https://github.com/d3/d3-format/blob/master/README.md#format) + +| Param | Type | Default | +| --- | --- | --- | +| [formatter] | function | d3.format('.2g') | + +**Example** +```js +counter.formatNumber(d3.format('.2g')) +``` + + +## DataGrid +Data grid is a simple widget designed to list the filtered records, providing +a simple way to define how the items are displayed. + +Note: Formerly the data grid chart (and data table) used the [group](#DataGrid+group) attribute as a +keying function for [nesting](https://github.com/d3/d3-collection/blob/master/README.md#nest) the data +together in sections. This was confusing so it has been renamed to `section`, although `group` still works. + +Examples: +- [List of members of the european parliament](https://dc-js.github.io/dc.js/ep/) + +**Kind**: global class +**Mixes**: [BaseMixin](#BaseMixin) + +* [DataGrid](#DataGrid) + * [new DataGrid(parent, [chartGroup])](#new_DataGrid_new) + * [.section(section)](#DataGrid+section) ⇒ function \| [DataGrid](#DataGrid) + * [.group(section)](#DataGrid+group) ⇒ function \| [DataGrid](#DataGrid) + * [.beginSlice([beginSlice])](#DataGrid+beginSlice) ⇒ Number \| [DataGrid](#DataGrid) + * [.endSlice([endSlice])](#DataGrid+endSlice) ⇒ Number \| [DataGrid](#DataGrid) + * [.size([size])](#DataGrid+size) ⇒ Number \| [DataGrid](#DataGrid) + * [.html([html])](#DataGrid+html) ⇒ function \| [DataGrid](#DataGrid) + * [.htmlSection([htmlSection])](#DataGrid+htmlSection) ⇒ function \| [DataGrid](#DataGrid) + * [.htmlGroup([htmlSection])](#DataGrid+htmlGroup) ⇒ function \| [DataGrid](#DataGrid) + * [.sortBy([sortByFunction])](#DataGrid+sortBy) ⇒ function \| [DataGrid](#DataGrid) + * [.order([order])](#DataGrid+order) ⇒ function \| [DataGrid](#DataGrid) + + + +### new DataGrid(parent, [chartGroup]) +Create a Data Grid. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + + + +### dataGrid.section(section) ⇒ function \| [DataGrid](#DataGrid) +Get or set the section function for the data grid. The section function takes a data row and +returns the key to specify to [d3.nest](https://github.com/d3/d3-collection/blob/master/README.md#nest) +to split rows into sections. + +Do not pass in a crossfilter section as this will not work. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | Description | +| --- | --- | --- | +| section | function | Function taking a row of data and returning the nest key. | + +**Example** +```js +// section rows by the value of their field +chart + .section(function(d) { return d.field; }) +``` + + +### dataGrid.group(section) ⇒ function \| [DataGrid](#DataGrid) +Backward-compatible synonym for [section](#DataGrid+section). + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | Description | +| --- | --- | --- | +| section | function | Function taking a row of data and returning the nest key. | + + + +### dataGrid.beginSlice([beginSlice]) ⇒ Number \| [DataGrid](#DataGrid) +Get or set the index of the beginning slice which determines which entries get displayed by the widget. +Useful when implementing pagination. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | Default | +| --- | --- | --- | +| [beginSlice] | Number | 0 | + + + +### dataGrid.endSlice([endSlice]) ⇒ Number \| [DataGrid](#DataGrid) +Get or set the index of the end slice which determines which entries get displayed by the widget. +Useful when implementing pagination. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | +| --- | --- | +| [endSlice] | Number | + + + +### dataGrid.size([size]) ⇒ Number \| [DataGrid](#DataGrid) +Get or set the grid size which determines the number of items displayed by the widget. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | Default | +| --- | --- | --- | +| [size] | Number | 999 | + + + +### dataGrid.html([html]) ⇒ function \| [DataGrid](#DataGrid) +Get or set the function that formats an item. The data grid widget uses a +function to generate dynamic html. Use your favourite templating engine or +generate the string directly. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | +| --- | --- | +| [html] | function | + +**Example** +```js +chart.html(function (d) { return '
'+data.exampleString+'
';}); +``` + + +### dataGrid.htmlSection([htmlSection]) ⇒ function \| [DataGrid](#DataGrid) +Get or set the function that formats a section label. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | +| --- | --- | +| [htmlSection] | function | + +**Example** +```js +chart.htmlSection (function (d) { return '

'.d.key . 'with ' . d.values.length .' items

'}); +``` + + +### dataGrid.htmlGroup([htmlSection]) ⇒ function \| [DataGrid](#DataGrid) +Backward-compatible synonym for [htmlSection](#DataGrid+htmlSection). + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | +| --- | --- | +| [htmlSection] | function | + + + +### dataGrid.sortBy([sortByFunction]) ⇒ function \| [DataGrid](#DataGrid) +Get or set sort-by function. This function works as a value accessor at the item +level and returns a particular field to be sorted. + +**Kind**: instance method of [DataGrid](#DataGrid) + +| Param | Type | +| --- | --- | +| [sortByFunction] | function | + +**Example** +```js +chart.sortBy(function(d) { + return d.date; +}); +``` + + +### dataGrid.order([order]) ⇒ function \| [DataGrid](#DataGrid) +Get or set sort the order function. + +**Kind**: instance method of [DataGrid](#DataGrid) +**See** + +- [d3.ascending](https://github.com/d3/d3-array/blob/master/README.md#ascending) +- [d3.descending](https://github.com/d3/d3-array/blob/master/README.md#descending) + + +| Param | Type | Default | +| --- | --- | --- | +| [order] | function | d3.ascending | + +**Example** +```js +chart.order(d3.descending); +``` + + +## DataTable +The data table is a simple widget designed to list crossfilter focused data set (rows being +filtered) in a good old tabular fashion. + +An interesting feature of the data table is that you can pass a crossfilter group to the +`dimension`, if you want to show aggregated data instead of raw data rows. This requires no +special code as long as you specify the [order](#DataTable+order) as `d3.descending`, +since the data table will use `dimension.top()` to fetch the data in that case, and the method is +equally supported on the crossfilter group as the crossfilter dimension. + +If you want to display aggregated data in ascending order, you will need to wrap the group +in a [fake dimension](https://github.com/dc-js/dc.js/wiki/FAQ#fake-dimensions) to support the +`.bottom()` method. See the example linked below for more details. + +Note: Formerly the data table (and data grid chart) used the [group](#DataTable+group) attribute as a +keying function for [nesting](https://github.com/d3/d3-collection/blob/master/README.md#nest) the data +together in sections. This was confusing so it has been renamed to `section`, although `group` still works. +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) +- [dataTable on a crossfilter group](http://dc-js.github.io/dc.js/examples/table-on-aggregated-data.html) +([source](https://github.com/dc-js/dc.js/blob/master/web-src/examples/table-on-aggregated-data.html)) + +**Kind**: global class +**Mixes**: [BaseMixin](#BaseMixin) + +* [DataTable](#DataTable) + * [new DataTable(parent, [chartGroup])](#new_DataTable_new) + * [.section(section)](#DataTable+section) ⇒ function \| [DataTable](#DataTable) + * [.group(section)](#DataTable+group) ⇒ function \| [DataTable](#DataTable) + * [.size([size])](#DataTable+size) ⇒ Number \| [DataTable](#DataTable) + * [.beginSlice([beginSlice])](#DataTable+beginSlice) ⇒ Number \| [DataTable](#DataTable) + * [.endSlice([endSlice])](#DataTable+endSlice) ⇒ Number \| [DataTable](#DataTable) + * [.columns([columns])](#DataTable+columns) ⇒ Array.<function()> + * [.sortBy([sortBy])](#DataTable+sortBy) ⇒ function \| [DataTable](#DataTable) + * [.order([order])](#DataTable+order) ⇒ function \| [DataTable](#DataTable) + * [.showSections([showSections])](#DataTable+showSections) ⇒ Boolean \| [DataTable](#DataTable) + * [.showGroups([showSections])](#DataTable+showGroups) ⇒ Boolean \| [DataTable](#DataTable) + + + +### new DataTable(parent, [chartGroup]) +Create a Data Table. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + + + +### dataTable.section(section) ⇒ function \| [DataTable](#DataTable) +Get or set the section function for the data table. The section function takes a data row and +returns the key to specify to [d3.nest](https://github.com/d3/d3-collection/blob/master/README.md#nest) +to split rows into sections. By default there will be only one section with no name. + +Set [showSections](#DataTable+showSections) to false to hide the section headers + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Description | +| --- | --- | --- | +| section | function | Function taking a row of data and returning the nest key. | + +**Example** +```js +// section rows by the value of their field +chart + .section(function(d) { return d.field; }) +``` + + +### dataTable.group(section) ⇒ function \| [DataTable](#DataTable) +Backward-compatible synonym for [section](#DataTable+section). + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Description | +| --- | --- | --- | +| section | function | Function taking a row of data and returning the nest key. | + + + +### dataTable.size([size]) ⇒ Number \| [DataTable](#DataTable) +Get or set the table size which determines the number of rows displayed by the widget. + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [size] | Number | 25 | + + + +### dataTable.beginSlice([beginSlice]) ⇒ Number \| [DataTable](#DataTable) +Get or set the index of the beginning slice which determines which entries get displayed +by the widget. Useful when implementing pagination. + +Note: the sortBy function will determine how the rows are ordered for pagination purposes. +See the [table pagination example](http://dc-js.github.io/dc.js/examples/table-pagination.html) +to see how to implement the pagination user interface using `beginSlice` and `endSlice`. + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [beginSlice] | Number | 0 | + + + +### dataTable.endSlice([endSlice]) ⇒ Number \| [DataTable](#DataTable) +Get or set the index of the end slice which determines which entries get displayed by the +widget. Useful when implementing pagination. See [`beginSlice`](#DataTable+beginSlice) for more information. + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | +| --- | --- | +| [endSlice] | Number \| undefined | + + + +### dataTable.columns([columns]) ⇒ Array.<function()> +Get or set column functions. The data table widget supports several methods of specifying the +columns to display. + +The original method uses an array of functions to generate dynamic columns. Column functions +are simple javascript functions with only one input argument `d` which represents a row in +the data set. The return value of these functions will be used to generate the content for +each cell. However, this method requires the HTML for the table to have a fixed set of column +headers. + +
chart.columns([
+    function(d) { return d.date; },
+    function(d) { return d.open; },
+    function(d) { return d.close; },
+    function(d) { return numberFormat(d.close - d.open); },
+    function(d) { return d.volume; }
+]);
+
+ +In the second method, you can list the columns to read from the data without specifying it as +a function, except where necessary (ie, computed columns). Note the data element name is +capitalized when displayed in the table header. You can also mix in functions as necessary, +using the third `{label, format}` form, as shown below. + +
chart.columns([
+    "date",    // d["date"], ie, a field accessor; capitalized automatically
+    "open",    // ...
+    "close",   // ...
+    {
+        label: "Change",
+        format: function (d) {
+            return numberFormat(d.close - d.open);
+        }
+    },
+    "volume"   // d["volume"], ie, a field accessor; capitalized automatically
+]);
+
+ +In the third example, we specify all fields using the `{label, format}` method: +
chart.columns([
+    {
+        label: "Date",
+        format: function (d) { return d.date; }
+    },
+    {
+        label: "Open",
+        format: function (d) { return numberFormat(d.open); }
+    },
+    {
+        label: "Close",
+        format: function (d) { return numberFormat(d.close); }
+    },
+    {
+        label: "Change",
+        format: function (d) { return numberFormat(d.close - d.open); }
+    },
+    {
+        label: "Volume",
+        format: function (d) { return d.volume; }
+    }
+]);
+
+ +You may wish to override the dataTable functions `_doColumnHeaderCapitalize` and +`_doColumnHeaderFnToString`, which are used internally to translate the column information or +function into a displayed header. The first one is used on the "string" column specifier; the +second is used to transform a stringified function into something displayable. For the Stock +example, the function for Change becomes the table header **d.close - d.open**. + +Finally, you can even specify a completely different form of column definition. To do this, +override `_chart._doColumnHeaderFormat` and `_chart._doColumnValueFormat` Be aware that +fields without numberFormat specification will be displayed just as they are stored in the +data, unformatted. + +**Kind**: instance method of [DataTable](#DataTable) +**Returns**: Array.<function()> - |DataTable} + +| Param | Type | Default | +| --- | --- | --- | +| [columns] | Array.<function()> | [] | + + + +### dataTable.sortBy([sortBy]) ⇒ function \| [DataTable](#DataTable) +Get or set sort-by function. This function works as a value accessor at row level and returns a +particular field to be sorted by. + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [sortBy] | function | identity function | + +**Example** +```js +chart.sortBy(function(d) { + return d.date; +}); +``` + + +### dataTable.order([order]) ⇒ function \| [DataTable](#DataTable) +Get or set sort order. If the order is `d3.ascending`, the data table will use +`dimension().bottom()` to fetch the data; otherwise it will use `dimension().top()` + +**Kind**: instance method of [DataTable](#DataTable) +**See** + +- [d3.ascending](https://github.com/d3/d3-array/blob/master/README.md#ascending) +- [d3.descending](https://github.com/d3/d3-array/blob/master/README.md#descending) + + +| Param | Type | Default | +| --- | --- | --- | +| [order] | function | d3.ascending | + +**Example** +```js +chart.order(d3.descending); +``` + + +### dataTable.showSections([showSections]) ⇒ Boolean \| [DataTable](#DataTable) +Get or set if section header rows will be shown. + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [showSections] | Boolean | true | + +**Example** +```js +chart + .section([value], [name]) + .showSections(true|false); +``` + + +### dataTable.showGroups([showSections]) ⇒ Boolean \| [DataTable](#DataTable) +Backward-compatible synonym for [showSections](#DataTable+showSections). + +**Kind**: instance method of [DataTable](#DataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [showSections] | Boolean | true | + + + +## GeoChoroplethChart +The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map +from GeoJson data. This chart implementation was inspired by +[the great d3 choropleth example](http://bl.ocks.org/4060606). + +Examples: +- [US Venture Capital Landscape 2011](https://dc-js.github.io/dc.js/vc/index.html) + +**Kind**: global class +**Mixes**: [ColorMixin](#ColorMixin), [BaseMixin](#BaseMixin) + +* [GeoChoroplethChart](#GeoChoroplethChart) + * [new GeoChoroplethChart(parent, [chartGroup])](#new_GeoChoroplethChart_new) + * [.overlayGeoJson(json, name, keyAccessor)](#GeoChoroplethChart+overlayGeoJson) ⇒ [GeoChoroplethChart](#GeoChoroplethChart) + * [.projection([projection])](#GeoChoroplethChart+projection) ⇒ d3.projection \| [GeoChoroplethChart](#GeoChoroplethChart) + * [.geoJsons()](#GeoChoroplethChart+geoJsons) ⇒ Array.<{name:String, data: Object, accessor: function()}> + * [.geoPath()](#GeoChoroplethChart+geoPath) ⇒ d3.geoPath + * [.removeGeoJson(name)](#GeoChoroplethChart+removeGeoJson) ⇒ [GeoChoroplethChart](#GeoChoroplethChart) + + + +### new GeoChoroplethChart(parent, [chartGroup]) +Create a Geo Choropleth Chart. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a choropleth chart under '#us-chart' element using the default global chart group +var chart1 = new GeoChoroplethChart('#us-chart'); +// create a choropleth chart under '#us-chart2' element using chart group A +var chart2 = new CompositeChart('#us-chart2', 'chartGroupA'); +``` + + +### geoChoroplethChart.overlayGeoJson(json, name, keyAccessor) ⇒ [GeoChoroplethChart](#GeoChoroplethChart) +**mandatory** + +Use this function to insert a new GeoJson map layer. This function can be invoked multiple times +if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple +layers with the same name the new overlay will override the existing one. + +**Kind**: instance method of [GeoChoroplethChart](#GeoChoroplethChart) +**See** + +- [GeoJSON](http://geojson.org/) +- [TopoJSON](https://github.com/topojson/topojson/wiki) +- [topojson.feature](https://github.com/topojson/topojson-1.x-api-reference/blob/master/API-Reference.md#wiki-feature) + + +| Param | Type | Description | +| --- | --- | --- | +| json | \_geoJson | a geojson feed | +| name | String | name of the layer | +| keyAccessor | function | accessor function used to extract 'key' from the GeoJson data. The key extracted by this function should match the keys returned by the crossfilter groups. | + +**Example** +```js +// insert a layer for rendering US states +chart.overlayGeoJson(statesJson.features, 'state', function(d) { + return d.properties.name; +}); +``` + + +### geoChoroplethChart.projection([projection]) ⇒ d3.projection \| [GeoChoroplethChart](#GeoChoroplethChart) +Gets or sets a custom geo projection function. See the available +[d3 geo projection functions](https://github.com/d3/d3-geo/blob/master/README.md#projections). + +Starting version 3.0 it has been deprecated to rely on the default projection being +[d3.geoAlbersUsa()](https://github.com/d3/d3-geo/blob/master/README.md#geoAlbersUsa). Please +set it explicitly. [Considering that `null` is also a valid value for projection](https://bl.ocks.org/mbostock/5557726), if you need +projection to be `null` please set it explicitly to `null`. + +**Kind**: instance method of [GeoChoroplethChart](#GeoChoroplethChart) +**See** + +- [d3.projection](https://github.com/d3/d3-geo/blob/master/README.md#projections) +- [d3-geo-projection](https://github.com/d3/d3-geo-projection) + + +| Param | Type | Default | +| --- | --- | --- | +| [projection] | d3.projection | d3.geoAlbersUsa() | + + + +### geoChoroplethChart.geoJsons() ⇒ Array.<{name:String, data: Object, accessor: function()}> +Returns all GeoJson layers currently registered with this chart. The returned array is a +reference to this chart's internal data structure, so any modification to this array will also +modify this chart's internal registration. + +**Kind**: instance method of [GeoChoroplethChart](#GeoChoroplethChart) + + +### geoChoroplethChart.geoPath() ⇒ d3.geoPath +Returns the [d3.geoPath](https://github.com/d3/d3-geo/blob/master/README.md#paths) object used to +render the projection and features. Can be useful for figuring out the bounding box of the +feature set and thus a way to calculate scale and translation for the projection. + +**Kind**: instance method of [GeoChoroplethChart](#GeoChoroplethChart) +**See**: [d3.geoPath](https://github.com/d3/d3-geo/blob/master/README.md#paths) + + +### geoChoroplethChart.removeGeoJson(name) ⇒ [GeoChoroplethChart](#GeoChoroplethChart) +Remove a GeoJson layer from this chart by name + +**Kind**: instance method of [GeoChoroplethChart](#GeoChoroplethChart) + +| Param | Type | +| --- | --- | +| name | String | + + + +## HeatMap +A heat map is matrix that represents the values of two dimensions of data using colors. + +**Kind**: global class +**Mixes**: [ColorMixin](#ColorMixin), [MarginMixin](#MarginMixin), [BaseMixin](#BaseMixin) + +* [HeatMap](#HeatMap) + * [new HeatMap(parent, [chartGroup])](#new_HeatMap_new) + * [.colsLabel([labelFunction])](#HeatMap+colsLabel) ⇒ function \| [HeatMap](#HeatMap) + * [.rowsLabel([labelFunction])](#HeatMap+rowsLabel) ⇒ function \| [HeatMap](#HeatMap) + * [.rows([rows])](#HeatMap+rows) ⇒ Array.<(String\|Number)> \| [HeatMap](#HeatMap) + * [.rowOrdering([rowOrdering])](#HeatMap+rowOrdering) ⇒ function \| [HeatMap](#HeatMap) + * [.cols([cols])](#HeatMap+cols) ⇒ Array.<(String\|Number)> \| [HeatMap](#HeatMap) + * [.colOrdering([colOrdering])](#HeatMap+colOrdering) ⇒ function \| [HeatMap](#HeatMap) + * [.boxOnClick([handler])](#HeatMap+boxOnClick) ⇒ function \| [HeatMap](#HeatMap) + * [.xAxisOnClick([handler])](#HeatMap+xAxisOnClick) ⇒ function \| [HeatMap](#HeatMap) + * [.yAxisOnClick([handler])](#HeatMap+yAxisOnClick) ⇒ function \| [HeatMap](#HeatMap) + * [.xBorderRadius([xBorderRadius])](#HeatMap+xBorderRadius) ⇒ Number \| [HeatMap](#HeatMap) + * [.yBorderRadius([yBorderRadius])](#HeatMap+yBorderRadius) ⇒ Number \| [HeatMap](#HeatMap) + + + +### new HeatMap(parent, [chartGroup]) +Create a Heat Map + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a heat map under #chart-container1 element using the default global chart group +var heatMap1 = new HeatMap('#chart-container1'); +// create a heat map under #chart-container2 element using chart group A +var heatMap2 = new HeatMap('#chart-container2', 'chartGroupA'); +``` + + +### heatMap.colsLabel([labelFunction]) ⇒ function \| [HeatMap](#HeatMap) +Set or get the column label function. The chart class uses this function to render +column labels on the X axis. It is passed the column name. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [labelFunction] | function | function(d) { return d; } | + +**Example** +```js +// the default label function just returns the name +chart.colsLabel(function(d) { return d; }); +``` + + +### heatMap.rowsLabel([labelFunction]) ⇒ function \| [HeatMap](#HeatMap) +Set or get the row label function. The chart class uses this function to render +row labels on the Y axis. It is passed the row name. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [labelFunction] | function | function(d) { return d; } | + +**Example** +```js +// the default label function just returns the name +chart.rowsLabel(function(d) { return d; }); +``` + + +### heatMap.rows([rows]) ⇒ Array.<(String\|Number)> \| [HeatMap](#HeatMap) +Gets or sets the values used to create the rows of the heatmap, as an array. By default, all +the values will be fetched from the data using the value accessor. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [rows] | Array.<(String\|Number)> | + + + +### heatMap.rowOrdering([rowOrdering]) ⇒ function \| [HeatMap](#HeatMap) +Get or set a comparator to order the rows. +Default is [d3.ascending](https://github.com/d3/d3-array#ascending). + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [rowOrdering] | function | + + + +### heatMap.cols([cols]) ⇒ Array.<(String\|Number)> \| [HeatMap](#HeatMap) +Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all +the values will be fetched from the data using the key accessor. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [cols] | Array.<(String\|Number)> | + + + +### heatMap.colOrdering([colOrdering]) ⇒ function \| [HeatMap](#HeatMap) +Get or set a comparator to order the columns. +Default is [d3.ascending](https://github.com/d3/d3-array#ascending). + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [colOrdering] | function | + + + +### heatMap.boxOnClick([handler]) ⇒ function \| [HeatMap](#HeatMap) +Gets or sets the handler that fires when an individual cell is clicked in the heatmap. +By default, filtering of the cell will be toggled. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + +**Example** +```js +// default box on click handler +chart.boxOnClick(function (d) { + var filter = d.key; + events.trigger(function () { + _chart.filter(filter); + _chart.redrawGroup(); + }); +}); +``` + + +### heatMap.xAxisOnClick([handler]) ⇒ function \| [HeatMap](#HeatMap) +Gets or sets the handler that fires when a column tick is clicked in the x axis. +By default, if any cells in the column are unselected, the whole column will be selected, +otherwise the whole column will be unselected. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + + + +### heatMap.yAxisOnClick([handler]) ⇒ function \| [HeatMap](#HeatMap) +Gets or sets the handler that fires when a row tick is clicked in the y axis. +By default, if any cells in the row are unselected, the whole row will be selected, +otherwise the whole row will be unselected. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + + + +### heatMap.xBorderRadius([xBorderRadius]) ⇒ Number \| [HeatMap](#HeatMap) +Gets or sets the X border radius. Set to 0 to get full rectangles. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [xBorderRadius] | Number | 6.75 | + + + +### heatMap.yBorderRadius([yBorderRadius]) ⇒ Number \| [HeatMap](#HeatMap) +Gets or sets the Y border radius. Set to 0 to get full rectangles. + +**Kind**: instance method of [HeatMap](#HeatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [yBorderRadius] | Number | 6.75 | + + + +## HtmlLegend +htmlLegend is a attachable widget that can be added to other dc charts to render horizontal/vertical legend +labels. + +**Kind**: global class + +* [HtmlLegend](#HtmlLegend) + * [.container([container])](#HtmlLegend+container) ⇒ String \| [HtmlLegend](#HtmlLegend) + * [.legendItemClass([legendItemClass])](#HtmlLegend+legendItemClass) ⇒ String \| [HtmlLegend](#HtmlLegend) + * [.highlightSelected([highlightSelected])](#HtmlLegend+highlightSelected) ⇒ String \| [HtmlLegend](#HtmlLegend) + * [.horizontal([horizontal])](#HtmlLegend+horizontal) ⇒ String \| [HtmlLegend](#HtmlLegend) + * [.legendText([legendText])](#HtmlLegend+legendText) ⇒ function \| [HtmlLegend](#HtmlLegend) + * [.maxItems([maxItems])](#HtmlLegend+maxItems) ⇒ [HtmlLegend](#HtmlLegend) + * [.keyboardAccessible([keyboardAccessible])](#HtmlLegend+keyboardAccessible) ⇒ Boolean \| [HtmlLegend](#HtmlLegend) + + + +### htmlLegend.container([container]) ⇒ String \| [HtmlLegend](#HtmlLegend) +Set the container selector for the legend widget. Required. + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [container] | String | + + + +### htmlLegend.legendItemClass([legendItemClass]) ⇒ String \| [HtmlLegend](#HtmlLegend) +This can be optionally used to override class for legenditem and just use this class style. +This is helpful for overriding the style of a particular chart rather than overriding +the style for all charts. + +Setting this will disable the highlighting of selected items also. + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [legendItemClass] | String | + + + +### htmlLegend.highlightSelected([highlightSelected]) ⇒ String \| [HtmlLegend](#HtmlLegend) +This can be optionally used to enable highlighting legends for the selections/filters for the +chart. + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [highlightSelected] | String | + + + +### htmlLegend.horizontal([horizontal]) ⇒ String \| [HtmlLegend](#HtmlLegend) +Display the legend horizontally instead of vertically + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [horizontal] | String | + + + +### htmlLegend.legendText([legendText]) ⇒ function \| [HtmlLegend](#HtmlLegend) +Set or get the legend text function. The legend widget uses this function to render the legend +text for each item. If no function is specified the legend widget will display the names +associated with each group. + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [legendText] | function | + +**Example** +```js +// default legendText +legend.legendText(pluck('name')) + +// create numbered legend items +chart.legend(new HtmlLegend().legendText(function(d, i) { return i + '. ' + d.name; })) + +// create legend displaying group counts +chart.legend(new HtmlLegend().legendText(function(d) { return d.name + ': ' d.data; })) +``` + + +### htmlLegend.maxItems([maxItems]) ⇒ [HtmlLegend](#HtmlLegend) +Maximum number of legend items to display + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | +| --- | --- | +| [maxItems] | Number | + + + +### htmlLegend.keyboardAccessible([keyboardAccessible]) ⇒ Boolean \| [HtmlLegend](#HtmlLegend) +If set, individual legend items will be focusable from keyboard and on pressing Enter or Space +will behave as if clicked on. + +If `svgDescription` on the parent chart has not been explicitly set, will also set the default +SVG description text to the class constructor name, like BarChart or HeatMap, and make the entire +SVG focusable. + +**Kind**: instance method of [HtmlLegend](#HtmlLegend) + +| Param | Type | Default | +| --- | --- | --- | +| [keyboardAccessible] | Boolean | false | + + + +## Legend +Legend is a attachable widget that can be added to other dc charts to render horizontal legend +labels. + +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) +- [Canadian City Crime Stats](https://dc-js.github.io/dc.js/crime/index.html) + +**Kind**: global class + +* [Legend](#Legend) + * [.x([x])](#Legend+x) ⇒ Number \| [Legend](#Legend) + * [.y([y])](#Legend+y) ⇒ Number \| [Legend](#Legend) + * [.gap([gap])](#Legend+gap) ⇒ Number \| [Legend](#Legend) + * [.highlightSelected([highlightSelected])](#Legend+highlightSelected) ⇒ String \| dc.legend + * [.itemHeight([itemHeight])](#Legend+itemHeight) ⇒ Number \| [Legend](#Legend) + * [.horizontal([horizontal])](#Legend+horizontal) ⇒ Boolean \| [Legend](#Legend) + * [.legendWidth([legendWidth])](#Legend+legendWidth) ⇒ Number \| [Legend](#Legend) + * [.itemWidth([itemWidth])](#Legend+itemWidth) ⇒ Number \| [Legend](#Legend) + * [.autoItemWidth([autoItemWidth])](#Legend+autoItemWidth) ⇒ Boolean \| [Legend](#Legend) + * [.legendText([legendText])](#Legend+legendText) ⇒ function \| [Legend](#Legend) + * [.maxItems([maxItems])](#Legend+maxItems) ⇒ [Legend](#Legend) + * [.keyboardAccessible([keyboardAccessible])](#Legend+keyboardAccessible) ⇒ Boolean \| [Legend](#Legend) + + + +### legend.x([x]) ⇒ Number \| [Legend](#Legend) +Set or get x coordinate for legend widget. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [x] | Number | 0 | + + + +### legend.y([y]) ⇒ Number \| [Legend](#Legend) +Set or get y coordinate for legend widget. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [y] | Number | 0 | + + + +### legend.gap([gap]) ⇒ Number \| [Legend](#Legend) +Set or get gap between legend items. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [gap] | Number | 5 | + + + +### legend.highlightSelected([highlightSelected]) ⇒ String \| dc.legend +This can be optionally used to enable highlighting legends for the selections/filters for the +chart. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | +| --- | --- | +| [highlightSelected] | String | + + + +### legend.itemHeight([itemHeight]) ⇒ Number \| [Legend](#Legend) +Set or get legend item height. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [itemHeight] | Number | 12 | + + + +### legend.horizontal([horizontal]) ⇒ Boolean \| [Legend](#Legend) +Position legend horizontally instead of vertically. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [horizontal] | Boolean | false | + + + +### legend.legendWidth([legendWidth]) ⇒ Number \| [Legend](#Legend) +Maximum width for horizontal legend. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [legendWidth] | Number | 500 | + + + +### legend.itemWidth([itemWidth]) ⇒ Number \| [Legend](#Legend) +Legend item width for horizontal legend. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [itemWidth] | Number | 70 | + + + +### legend.autoItemWidth([autoItemWidth]) ⇒ Boolean \| [Legend](#Legend) +Turn automatic width for legend items on or off. If true, [itemWidth](#Legend+itemWidth) is ignored. +This setting takes into account the [gap](#Legend+gap). + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [autoItemWidth] | Boolean | false | + + + +### legend.legendText([legendText]) ⇒ function \| [Legend](#Legend) +Set or get the legend text function. The legend widget uses this function to render the legend +text for each item. If no function is specified the legend widget will display the names +associated with each group. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | +| --- | --- | +| [legendText] | function | + +**Example** +```js +// default legendText +legend.legendText(pluck('name')) + +// create numbered legend items +chart.legend(new Legend().legendText(function(d, i) { return i + '. ' + d.name; })) + +// create legend displaying group counts +chart.legend(new Legend().legendText(function(d) { return d.name + ': ' d.data; })) +``` + + +### legend.maxItems([maxItems]) ⇒ [Legend](#Legend) +Maximum number of legend items to display + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | +| --- | --- | +| [maxItems] | Number | + + + +### legend.keyboardAccessible([keyboardAccessible]) ⇒ Boolean \| [Legend](#Legend) +If set, individual legend items will be focusable from keyboard and on pressing Enter or Space +will behave as if clicked on. + +If `svgDescription` on the parent chart has not been explicitly set, will also set the default +SVG description text to the class constructor name, like BarChart or HeatMap, and make the entire +SVG focusable. + +**Kind**: instance method of [Legend](#Legend) + +| Param | Type | Default | +| --- | --- | --- | +| [keyboardAccessible] | Boolean | false | + + + +## LineChart +Concrete line/area chart implementation. + +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) +- [Canadian City Crime Stats](https://dc-js.github.io/dc.js/crime/index.html) + +**Kind**: global class +**Mixes**: [StackMixin](#StackMixin), [CoordinateGridMixin](#CoordinateGridMixin) + +* [LineChart](#LineChart) + * [new LineChart(parent, [chartGroup])](#new_LineChart_new) + * [.curve([curve])](#LineChart+curve) ⇒ d3.curve \| [LineChart](#LineChart) + * ~~[.interpolate([interpolate])](#LineChart+interpolate) ⇒ d3.curve \| [LineChart](#LineChart)~~ + * ~~[.tension([tension])](#LineChart+tension) ⇒ Number \| [LineChart](#LineChart)~~ + * [.defined([defined])](#LineChart+defined) ⇒ function \| [LineChart](#LineChart) + * [.dashStyle([dashStyle])](#LineChart+dashStyle) ⇒ Array.<Number> \| [LineChart](#LineChart) + * [.renderArea([renderArea])](#LineChart+renderArea) ⇒ Boolean \| [LineChart](#LineChart) + * [.xyTipsOn([xyTipsOn])](#LineChart+xyTipsOn) ⇒ Boolean \| [LineChart](#LineChart) + * [.dotRadius([dotRadius])](#LineChart+dotRadius) ⇒ Number \| [LineChart](#LineChart) + * [.renderDataPoints([options])](#LineChart+renderDataPoints) ⇒ Object \| [LineChart](#LineChart) + + + +### new LineChart(parent, [chartGroup]) +Create a Line Chart. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [CompositeChart](#CompositeChart) | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. If the line chart is a sub-chart in a [Composite Chart](#CompositeChart) then pass in the parent composite chart instance instead. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a line chart under #chart-container1 element using the default global chart group +var chart1 = new LineChart('#chart-container1'); +// create a line chart under #chart-container2 element using chart group A +var chart2 = new LineChart('#chart-container2', 'chartGroupA'); +// create a sub-chart under a composite parent chart +var chart3 = new LineChart(compositeChart); +``` + + +### lineChart.curve([curve]) ⇒ d3.curve \| [LineChart](#LineChart) +Gets or sets the curve factory to use for lines and areas drawn, allowing e.g. step +functions, splines, and cubic interpolation. Typically you would use one of the interpolator functions +provided by [d3 curves](https://github.com/d3/d3-shape/blob/master/README.md#curves). + +Replaces the use of [interpolate](#LineChart+interpolate) and [tension](#LineChart+tension) +in dc.js < 3.0 + +This is passed to +[line.curve](https://github.com/d3/d3-shape/blob/master/README.md#line_curve) and +[area.curve](https://github.com/d3/d3-shape/blob/master/README.md#area_curve). + +**Kind**: instance method of [LineChart](#LineChart) +**See** + +- [line.curve](https://github.com/d3/d3-shape/blob/master/README.md#line_curve) +- [area.curve](https://github.com/d3/d3-shape/blob/master/README.md#area_curve) + + +| Param | Type | Default | +| --- | --- | --- | +| [curve] | d3.curve | d3.curveLinear | + +**Example** +```js +// default +chart + .curve(d3.curveLinear); +// Add tension to curves that support it +chart + .curve(d3.curveCardinal.tension(0.5)); +// You can use some specialized variation like +// https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline +chart + .curve(d3.curveCatmullRom.alpha(0.5)); +``` + + +### ~~lineChart.interpolate([interpolate]) ⇒ d3.curve \| [LineChart](#LineChart)~~ +***Deprecated*** + +Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step +functions, splines, and cubic interpolation. + +Possible values are: 'linear', 'linear-closed', 'step', 'step-before', 'step-after', 'basis', +'basis-open', 'basis-closed', 'bundle', 'cardinal', 'cardinal-open', 'cardinal-closed', and +'monotone'. + +This function exists for backward compatibility. Use [curve](#LineChart+curve) +which is generic and provides more options. +Value set through `.curve` takes precedence over `.interpolate` and `.tension`. + +**Kind**: instance method of [LineChart](#LineChart) +**See**: [curve](#LineChart+curve) + +| Param | Type | Default | +| --- | --- | --- | +| [interpolate] | d3.curve | d3.curveLinear | + + + +### ~~lineChart.tension([tension]) ⇒ Number \| [LineChart](#LineChart)~~ +***Deprecated*** + +Gets or sets the tension to use for lines drawn, in the range 0 to 1. + +Passed to the [d3 curve function](https://github.com/d3/d3-shape/blob/master/README.md#curves) +if it provides a `.tension` function. Example: +[curveCardinal.tension](https://github.com/d3/d3-shape/blob/master/README.md#curveCardinal_tension). + +This function exists for backward compatibility. Use [curve](#LineChart+curve) +which is generic and provides more options. +Value set through `.curve` takes precedence over `.interpolate` and `.tension`. + +**Kind**: instance method of [LineChart](#LineChart) +**See**: [curve](#LineChart+curve) + +| Param | Type | Default | +| --- | --- | --- | +| [tension] | Number | 0 | + + + +### lineChart.defined([defined]) ⇒ function \| [LineChart](#LineChart) +Gets or sets a function that will determine discontinuities in the line which should be +skipped: the path will be broken into separate subpaths if some points are undefined. +This function is passed to +[line.defined](https://github.com/d3/d3-shape/blob/master/README.md#line_defined) + +Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write +custom reduce functions to get this to work, depending on your data. See +[this GitHub comment](https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248) +for more details and an example. + +**Kind**: instance method of [LineChart](#LineChart) +**See**: [line.defined](https://github.com/d3/d3-shape/blob/master/README.md#line_defined) + +| Param | Type | +| --- | --- | +| [defined] | function | + + + +### lineChart.dashStyle([dashStyle]) ⇒ Array.<Number> \| [LineChart](#LineChart) +Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty +array (solid line). + +**Kind**: instance method of [LineChart](#LineChart) +**See**: [stroke-dasharray](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray) + +| Param | Type | Default | +| --- | --- | --- | +| [dashStyle] | Array.<Number> | [] | + +**Example** +```js +// create a Dash Dot Dot Dot +chart.dashStyle([3,1,1,1]); +``` + + +### lineChart.renderArea([renderArea]) ⇒ Boolean \| [LineChart](#LineChart) +Get or set render area flag. If the flag is set to true then the chart will render the area +beneath each line and the line chart effectively becomes an area chart. + +**Kind**: instance method of [LineChart](#LineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [renderArea] | Boolean | false | + + + +### lineChart.xyTipsOn([xyTipsOn]) ⇒ Boolean \| [LineChart](#LineChart) +Turn on/off the mouseover behavior of an individual data point which renders a circle and x/y axis +dashed lines back to each respective axis. This is ignored if the chart +[brush](#CoordinateGridMixin+brushOn) is on + +**Kind**: instance method of [LineChart](#LineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [xyTipsOn] | Boolean | false | + + + +### lineChart.dotRadius([dotRadius]) ⇒ Number \| [LineChart](#LineChart) +Get or set the radius (in px) for dots displayed on the data points. + +**Kind**: instance method of [LineChart](#LineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [dotRadius] | Number | 5 | + + + +### lineChart.renderDataPoints([options]) ⇒ Object \| [LineChart](#LineChart) +Always show individual dots for each datapoint. + +If `options` is falsy, it disables data point rendering. If no `options` are provided, the +current `options` values are instead returned. + +**Kind**: instance method of [LineChart](#LineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [options] | Object | {fillOpacity: 0.8, strokeOpacity: 0.0, radius: 2} | + +**Example** +```js +chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.0}) +``` + + +## NumberDisplay +A display of a single numeric value. + +Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and +a valueAccessor that returns a single value. + +If the group is a [groupAll](https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_groupAll) +then its `.value()` will be displayed. This is the recommended usage. + +However, if it is given an ordinary group, the `numberDisplay` will show the last bin's value, after +sorting with the [ordering](https://dc-js.github.io/dc.js/docs/html/dc.baseMixin.html#ordering__anchor) +function. `numberDisplay` defaults the `ordering` function to sorting by value, so this will display +the largest value if the values are numeric. + +**Kind**: global class +**Mixes**: [BaseMixin](#BaseMixin) + +* [NumberDisplay](#NumberDisplay) + * [new NumberDisplay(parent, [chartGroup])](#new_NumberDisplay_new) + * [.html([html])](#NumberDisplay+html) ⇒ Object \| [NumberDisplay](#NumberDisplay) + * [.value()](#NumberDisplay+value) ⇒ Number + * [.formatNumber([formatter])](#NumberDisplay+formatNumber) ⇒ function \| [NumberDisplay](#NumberDisplay) + * [.ariaLiveRegion([ariaLiveRegion])](#NumberDisplay+ariaLiveRegion) ⇒ Boolean \| [NumberDisplay](#NumberDisplay) + + + +### new NumberDisplay(parent, [chartGroup]) +Create a Number Display widget. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a number display under #chart-container1 element using the default global chart group +var display1 = new NumberDisplay('#chart-container1'); +``` + + +### numberDisplay.html([html]) ⇒ Object \| [NumberDisplay](#NumberDisplay) +Gets or sets an optional object specifying HTML templates to use depending on the number +displayed. The text `%number` will be replaced with the current value. +- one: HTML template to use if the number is 1 +- zero: HTML template to use if the number is 0 +- some: HTML template to use otherwise + +**Kind**: instance method of [NumberDisplay](#NumberDisplay) + +| Param | Type | Default | +| --- | --- | --- | +| [html] | Object | {one: '', some: '', none: ''} | + +**Example** +```js +numberWidget.html({ + one:'%number record', + some:'%number records', + none:'no records'}) +``` + + +### numberDisplay.value() ⇒ Number +Calculate and return the underlying value of the display. + +**Kind**: instance method of [NumberDisplay](#NumberDisplay) + + +### numberDisplay.formatNumber([formatter]) ⇒ function \| [NumberDisplay](#NumberDisplay) +Get or set a function to format the value for the display. + +**Kind**: instance method of [NumberDisplay](#NumberDisplay) +**See**: [d3.format](https://github.com/d3/d3-format/blob/master/README.md#format) + +| Param | Type | Default | +| --- | --- | --- | +| [formatter] | function | d3.format('.2s') | + + + +### numberDisplay.ariaLiveRegion([ariaLiveRegion]) ⇒ Boolean \| [NumberDisplay](#NumberDisplay) +If set, the Number Display widget will have its aria-live attribute set to 'polite' which will +notify screen readers when the widget changes its value. Note that setting this method will also +disable the default transition between the old and the new values. This is to avoid change +notifications spoken out before the new value finishes re-drawing. It is also advisable to check +if the widget has appropriately set accessibility description or label. + +**Kind**: instance method of [NumberDisplay](#NumberDisplay) + +| Param | Type | Default | +| --- | --- | --- | +| [ariaLiveRegion] | Boolean | false | + + + +## PieChart +The pie chart implementation is usually used to visualize a small categorical distribution. The pie +chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each +slice relative to the sum of all values. Slices are ordered by [ordering](#BaseMixin+ordering) +which defaults to sorting by key. + +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) + +**Kind**: global class +**Mixes**: [CapMixin](#CapMixin), [ColorMixin](#ColorMixin), [BaseMixin](#BaseMixin) + +* [PieChart](#PieChart) + * [new PieChart(parent, [chartGroup])](#new_PieChart_new) + * [.slicesCap([cap])](#PieChart+slicesCap) ⇒ Number \| [PieChart](#PieChart) + * [.externalRadiusPadding([externalRadiusPadding])](#PieChart+externalRadiusPadding) ⇒ Number \| [PieChart](#PieChart) + * [.innerRadius([innerRadius])](#PieChart+innerRadius) ⇒ Number \| [PieChart](#PieChart) + * [.radius([radius])](#PieChart+radius) ⇒ Number \| [PieChart](#PieChart) + * [.cx([cx])](#PieChart+cx) ⇒ Number \| [PieChart](#PieChart) + * [.cy([cy])](#PieChart+cy) ⇒ Number \| [PieChart](#PieChart) + * [.minAngleForLabel([minAngleForLabel])](#PieChart+minAngleForLabel) ⇒ Number \| [PieChart](#PieChart) + * [.emptyTitle([title])](#PieChart+emptyTitle) ⇒ String \| [PieChart](#PieChart) + * [.externalLabels([externalLabelRadius])](#PieChart+externalLabels) ⇒ Number \| [PieChart](#PieChart) + * [.drawPaths([drawPaths])](#PieChart+drawPaths) ⇒ Boolean \| [PieChart](#PieChart) + + + +### new PieChart(parent, [chartGroup]) +Create a Pie Chart + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a pie chart under #chart-container1 element using the default global chart group +var chart1 = new PieChart('#chart-container1'); +// create a pie chart under #chart-container2 element using chart group A +var chart2 = new PieChart('#chart-container2', 'chartGroupA'); +``` + + +### pieChart.slicesCap([cap]) ⇒ Number \| [PieChart](#PieChart) +Get or set the maximum number of slices the pie chart will generate. The top slices are determined by +value from high to low. Other slices exceeding the cap will be rolled up into one single *Others* slice. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [cap] | Number | + + + +### pieChart.externalRadiusPadding([externalRadiusPadding]) ⇒ Number \| [PieChart](#PieChart) +Get or set the external radius padding of the pie chart. This will force the radius of the +pie chart to become smaller or larger depending on the value. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [externalRadiusPadding] | Number | 0 | + + + +### pieChart.innerRadius([innerRadius]) ⇒ Number \| [PieChart](#PieChart) +Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the +pie chart will be rendered as a doughnut chart. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [innerRadius] | Number | 0 | + + + +### pieChart.radius([radius]) ⇒ Number \| [PieChart](#PieChart) +Get or set the outer radius. If the radius is not set, it will be half of the minimum of the +chart width and height. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [radius] | Number | + + + +### pieChart.cx([cx]) ⇒ Number \| [PieChart](#PieChart) +Get or set center x coordinate position. Default is center of svg. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [cx] | Number | + + + +### pieChart.cy([cy]) ⇒ Number \| [PieChart](#PieChart) +Get or set center y coordinate position. Default is center of svg. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [cy] | Number | + + + +### pieChart.minAngleForLabel([minAngleForLabel]) ⇒ Number \| [PieChart](#PieChart) +Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not +display a slice label. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [minAngleForLabel] | Number | 0.5 | + + + +### pieChart.emptyTitle([title]) ⇒ String \| [PieChart](#PieChart) +Title to use for the only slice when there is no data. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [title] | String | + + + +### pieChart.externalLabels([externalLabelRadius]) ⇒ Number \| [PieChart](#PieChart) +Position slice labels offset from the outer edge of the chart. + +The argument specifies the extra radius to be added for slice labels. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [externalLabelRadius] | Number | + + + +### pieChart.drawPaths([drawPaths]) ⇒ Boolean \| [PieChart](#PieChart) +Get or set whether to draw lines from pie slices to their labels. + +**Kind**: instance method of [PieChart](#PieChart) + +| Param | Type | +| --- | --- | +| [drawPaths] | Boolean | + + + +## RowChart +Concrete row chart implementation. + +Examples: +- [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) + +**Kind**: global class +**Mixes**: [CapMixin](#CapMixin), [MarginMixin](#MarginMixin), [ColorMixin](#ColorMixin), [BaseMixin](#BaseMixin) + +* [RowChart](#RowChart) + * [new RowChart(parent, [chartGroup])](#new_RowChart_new) + * [.x([scale])](#RowChart+x) ⇒ d3.scale \| [RowChart](#RowChart) + * [.renderTitleLabel([renderTitleLabel])](#RowChart+renderTitleLabel) ⇒ Boolean \| [RowChart](#RowChart) + * [.xAxis([xAxis])](#RowChart+xAxis) ⇒ d3.axis \| [RowChart](#RowChart) + * [.fixedBarHeight([fixedBarHeight])](#RowChart+fixedBarHeight) ⇒ Boolean \| Number \| [RowChart](#RowChart) + * [.gap([gap])](#RowChart+gap) ⇒ Number \| [RowChart](#RowChart) + * [.elasticX([elasticX])](#RowChart+elasticX) ⇒ Boolean \| [RowChart](#RowChart) + * [.labelOffsetX([labelOffsetX])](#RowChart+labelOffsetX) ⇒ Number \| [RowChart](#RowChart) + * [.labelOffsetY([labelOffsety])](#RowChart+labelOffsetY) ⇒ Number \| [RowChart](#RowChart) + * [.titleLabelOffsetX([titleLabelOffsetX])](#RowChart+titleLabelOffsetX) ⇒ Number \| [RowChart](#RowChart) + + + +### new RowChart(parent, [chartGroup]) +Create a Row Chart. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a row chart under #chart-container1 element using the default global chart group +var chart1 = new RowChart('#chart-container1'); +// create a row chart under #chart-container2 element using chart group A +var chart2 = new RowChart('#chart-container2', 'chartGroupA'); +``` + + +### rowChart.x([scale]) ⇒ d3.scale \| [RowChart](#RowChart) +Gets or sets the x scale. The x scale can be any d3 +[d3.scale](https://github.com/d3/d3-scale/blob/master/README.md). + +**Kind**: instance method of [RowChart](#RowChart) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | +| --- | --- | +| [scale] | d3.scale | + + + +### rowChart.renderTitleLabel([renderTitleLabel]) ⇒ Boolean \| [RowChart](#RowChart) +Turn on/off Title label rendering (values) using SVG style of text-anchor 'end'. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [renderTitleLabel] | Boolean | false | + + + +### rowChart.xAxis([xAxis]) ⇒ d3.axis \| [RowChart](#RowChart) +Get or sets the x axis for the row chart instance. +See the [d3.axis](https://github.com/d3/d3-axis/blob/master/README.md) +documention for more information. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | +| --- | --- | +| [xAxis] | d3.axis | + +**Example** +```js +// customize x axis tick format +chart.xAxis().tickFormat(function (v) {return v + '%';}); +// customize x axis tick values +chart.xAxis().tickValues([0, 100, 200, 300]); +// use a top-oriented axis. Note: position of the axis and grid lines will need to +// be set manually, see https://dc-js.github.io/dc.js/examples/row-top-axis.html +chart.xAxis(d3.axisTop()) +``` + + +### rowChart.fixedBarHeight([fixedBarHeight]) ⇒ Boolean \| Number \| [RowChart](#RowChart) +Get or set the fixed bar height. Default is [false] which will auto-scale bars. +For example, if you want to fix the height for a specific number of bars (useful in TopN charts) +you could fix height as follows (where count = total number of bars in your TopN and gap is +your vertical gap space). + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [fixedBarHeight] | Boolean \| Number | false | + +**Example** +```js +chart.fixedBarHeight( chartheight - (count + 1) * gap / count); +``` + + +### rowChart.gap([gap]) ⇒ Number \| [RowChart](#RowChart) +Get or set the vertical gap space between rows on a particular row chart instance. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [gap] | Number | 5 | + + + +### rowChart.elasticX([elasticX]) ⇒ Boolean \| [RowChart](#RowChart) +Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescale to auto-fit the +data range when filtered. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | +| --- | --- | +| [elasticX] | Boolean | + + + +### rowChart.labelOffsetX([labelOffsetX]) ⇒ Number \| [RowChart](#RowChart) +Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [labelOffsetX] | Number | 10 | + + + +### rowChart.labelOffsetY([labelOffsety]) ⇒ Number \| [RowChart](#RowChart) +Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [labelOffsety] | Number | 15 | + + + +### rowChart.titleLabelOffsetX([titleLabelOffsetX]) ⇒ Number \| [RowChart](#RowChart) +Get of set the x offset (horizontal space between right edge of row and right edge or text. + +**Kind**: instance method of [RowChart](#RowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [titleLabelOffsetX] | Number | 2 | + + + +## ScatterPlot +A scatter plot chart + +Examples: +- [Scatter Chart](http://dc-js.github.io/dc.js/examples/scatter.html) +- [Multi-Scatter Chart](http://dc-js.github.io/dc.js/examples/multi-scatter.html) + +**Kind**: global class +**Mixes**: [CoordinateGridMixin](#CoordinateGridMixin) + +* [ScatterPlot](#ScatterPlot) + * [new ScatterPlot(parent, [chartGroup])](#new_ScatterPlot_new) + * [.resetSvg()](#ScatterPlot+resetSvg) ⇒ SVGElement + * [.useCanvas([useCanvas])](#ScatterPlot+useCanvas) ⇒ Boolean \| d3.selection + * [.canvas([canvasElement])](#ScatterPlot+canvas) ⇒ CanvasElement \| d3.selection + * [.context()](#ScatterPlot+context) ⇒ CanvasContext + * [.existenceAccessor([accessor])](#ScatterPlot+existenceAccessor) ⇒ function \| [ScatterPlot](#ScatterPlot) + * [.symbol([type])](#ScatterPlot+symbol) ⇒ function \| [ScatterPlot](#ScatterPlot) + * [.customSymbol([customSymbol])](#ScatterPlot+customSymbol) ⇒ String \| function \| [ScatterPlot](#ScatterPlot) + * [.symbolSize([symbolSize])](#ScatterPlot+symbolSize) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.highlightedSize([highlightedSize])](#ScatterPlot+highlightedSize) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.excludedSize([excludedSize])](#ScatterPlot+excludedSize) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.excludedColor([excludedColor])](#ScatterPlot+excludedColor) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.excludedOpacity([excludedOpacity])](#ScatterPlot+excludedOpacity) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.emptySize([emptySize])](#ScatterPlot+emptySize) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.emptyColor([emptyColor])](#ScatterPlot+emptyColor) ⇒ String \| [ScatterPlot](#ScatterPlot) + * [.emptyOpacity([emptyOpacity])](#ScatterPlot+emptyOpacity) ⇒ Number \| [ScatterPlot](#ScatterPlot) + * [.nonemptyOpacity([nonemptyOpacity])](#ScatterPlot+nonemptyOpacity) ⇒ Number \| [ScatterPlot](#ScatterPlot) + + + +### new ScatterPlot(parent, [chartGroup]) +Create a Scatter Plot. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a scatter plot under #chart-container1 element using the default global chart group +var chart1 = new ScatterPlot('#chart-container1'); +// create a scatter plot under #chart-container2 element using chart group A +var chart2 = new ScatterPlot('#chart-container2', 'chartGroupA'); +// create a sub-chart under a composite parent chart +var chart3 = new ScatterPlot(compositeChart); +``` + + +### scatterPlot.resetSvg() ⇒ SVGElement +Method that replaces original resetSvg and appropriately inserts canvas +element along with svg element and sets their CSS properties appropriately +so they are overlapped on top of each other. +Remove the chart's SVGElements from the dom and recreate the container SVGElement. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) + + +### scatterPlot.useCanvas([useCanvas]) ⇒ Boolean \| d3.selection +Set or get whether to use canvas backend for plotting scatterPlot. Note that the +canvas backend does not currently support +[customSymbol](#ScatterPlot+customSymbol) or +[symbol](#ScatterPlot+symbol) methods and is limited to always plotting +with filled circles. Symbols are drawn with +[symbolSize](#ScatterPlot+symbolSize) radius. By default, the SVG backend +is used when `useCanvas` is set to `false`. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [useCanvas] | Boolean | false | + + + +### scatterPlot.canvas([canvasElement]) ⇒ CanvasElement \| d3.selection +Set or get canvas element. You should usually only ever use the get method as +dc.js will handle canvas element generation. Provides valid canvas only when +[useCanvas](#ScatterPlot+useCanvas) is set to `true` + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | +| --- | --- | +| [canvasElement] | CanvasElement \| d3.selection | + + + +### scatterPlot.context() ⇒ CanvasContext +Get canvas 2D context. Provides valid context only when +[useCanvas](#ScatterPlot+useCanvas) is set to `true` + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + + +### scatterPlot.existenceAccessor([accessor]) ⇒ function \| [ScatterPlot](#ScatterPlot) +Get or set the existence accessor. If a point exists, it is drawn with +[symbolSize](#ScatterPlot+symbolSize) radius and +opacity 1; if it does not exist, it is drawn with +[emptySize](#ScatterPlot+emptySize) radius and opacity 0. By default, +the existence accessor checks if the reduced value is truthy. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See** + +- [symbolSize](#ScatterPlot+symbolSize) +- [emptySize](#ScatterPlot+emptySize) + + +| Param | Type | +| --- | --- | +| [accessor] | function | + +**Example** +```js +// default accessor +chart.existenceAccessor(function (d) { return d.value; }); +``` + + +### scatterPlot.symbol([type]) ⇒ function \| [ScatterPlot](#ScatterPlot) +Get or set the symbol type used for each point. By default the symbol is a circle (d3.symbolCircle). +Type can be a constant or an accessor. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [symbol.type](https://github.com/d3/d3-shape/blob/master/README.md#symbol_type) + +| Param | Type | Default | +| --- | --- | --- | +| [type] | function | d3.symbolCircle | + +**Example** +```js +// Circle type +chart.symbol(d3.symbolCircle); +// Square type +chart.symbol(d3.symbolSquare); +``` + + +### scatterPlot.customSymbol([customSymbol]) ⇒ String \| function \| [ScatterPlot](#ScatterPlot) +Get or set the symbol generator. By default `ScatterPlot` will use +[d3.symbol()](https://github.com/d3/d3-shape/blob/master/README.md#symbol) +to generate symbols. `ScatterPlot` will set the +[symbol size accessor](https://github.com/d3/d3-shape/blob/master/README.md#symbol_size) +on the symbol generator. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See** + +- [d3.symbol](https://github.com/d3/d3-shape/blob/master/README.md#symbol) +- [Create additional D3.js symbols](https://stackoverflow.com/questions/25332120/create-additional-d3-js-symbols) + + +| Param | Type | Default | +| --- | --- | --- | +| [customSymbol] | String \| function | d3.symbol() | + + + +### scatterPlot.symbolSize([symbolSize]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get radius for symbols. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [d3.symbol.size](https://github.com/d3/d3-shape/blob/master/README.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [symbolSize] | Number | 3 | + + + +### scatterPlot.highlightedSize([highlightedSize]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get radius for highlighted symbols. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [d3.symbol.size](https://github.com/d3/d3-shape/blob/master/README.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [highlightedSize] | Number | 5 | + + + +### scatterPlot.excludedSize([excludedSize]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get size for symbols excluded from this chart's filter. If null, no +special size is applied for symbols based on their filter status. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [d3.symbol.size](https://github.com/d3/d3-shape/blob/master/README.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedSize] | Number | | + + + +### scatterPlot.excludedColor([excludedColor]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get color for symbols excluded from this chart's filter. If null, no +special color is applied for symbols based on their filter status. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedColor] | Number | | + + + +### scatterPlot.excludedOpacity([excludedOpacity]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get opacity for symbols excluded from this chart's filter. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedOpacity] | Number | 1.0 | + + + +### scatterPlot.emptySize([emptySize]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get radius for symbols when the group is empty. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) +**See**: [d3.symbol.size](https://github.com/d3/d3-shape/blob/master/README.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [emptySize] | Number | 0 | + + + +### scatterPlot.emptyColor([emptyColor]) ⇒ String \| [ScatterPlot](#ScatterPlot) +Set or get color for symbols when the group is empty. If null, just use the +[colorMixin.colors](#ColorMixin+colors) color scale zero value. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [emptyColor] | String | | + + + +### scatterPlot.emptyOpacity([emptyOpacity]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get opacity for symbols when the group is empty. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [emptyOpacity] | Number | 0 | + + + +### scatterPlot.nonemptyOpacity([nonemptyOpacity]) ⇒ Number \| [ScatterPlot](#ScatterPlot) +Set or get opacity for symbols when the group is not empty. + +**Kind**: instance method of [ScatterPlot](#ScatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [nonemptyOpacity] | Number | 1 | + + + +## SelectMenu +The select menu is a simple widget designed to filter a dimension by selecting an option from +an HTML `` menu. The menu can be optionally turned into a multiselect. - - -| Param | Type | Description | -| --- | --- | --- | -| parent | String | node | d3.selection | [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | -| [chartGroup] | String | The name of the chart group this widget should be placed in. Interaction with the widget will only trigger events and redraws within its group. | - -**Example** -```js -// create a select menu under #select-container using the default global chart group -var select = dc.selectMenu('#select-container') - .dimension(states) - .group(stateGroup); -// the option text can be set via the title() function -// by default the option text is '`key`: `value`' -select.title(function (d){ - return 'STATE: ' + d.key; -}) -``` - - -#### selectMenu.order -Get or set the function that controls the ordering of option tags in the -select menu. By default options are ordered by the group key in ascending -order. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | -| --- | --- | -| [order] | function | - -**Example** -```js -// order by the group's value -chart.order(function (a,b) { - return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; -}); -``` - - -#### selectMenu.promptText -Get or set the text displayed in the options used to prompt selection. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | Default | -| --- | --- | --- | -| [promptText] | String | 'Select all' | - -**Example** -```js -chart.promptText('All states'); -``` - - -#### selectMenu.filterDisplayed -Get or set the function that filters option tags prior to display. By default options -with a value of < 1 are not displayed. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | -| --- | --- | -| [filterDisplayed] | function | - -**Example** -```js -// display all options override the `filterDisplayed` function: -chart.filterDisplayed(function () { - return true; -}); -``` - - -#### selectMenu.multiple -Controls the type of select menu. Setting it to true converts the underlying -HTML tag into a multiple select. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | Default | -| --- | --- | --- | -| [multiple] | boolean | false | - -**Example** -```js -chart.multiple(true); -``` - - -#### selectMenu.promptValue -Controls the default value to be used for -[dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) -when only the prompt value is selected. If `null` (the default), no filtering will occur when -just the prompt is selected. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | Default | -| --- | --- | --- | -| [promptValue] | \* | | - - - -#### selectMenu.numberItems -Controls the number of items to show in the select menu, when `.multiple()` is true. This -controls the [`size` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Attributes) of -the `select` element. If `null` (the default), uses the browser's default height. - -**Kind**: instance property of [selectMenu](#dc.selectMenu) - -| Param | Type | Default | -| --- | --- | --- | -| [numberVisible] | number | | - -**Example** -```js -chart.numberVisible(10); -``` ### dc.baseMixin ⇒ [baseMixin](#dc.baseMixin) @@ -2724,6 +2680,7 @@ and available on all chart implementations in the `dc` library. * [.turnOnControls()](#dc.baseMixin+turnOnControls) ⇒ [baseMixin](#dc.baseMixin) * [.turnOffControls()](#dc.baseMixin+turnOffControls) ⇒ [baseMixin](#dc.baseMixin) * [.transitionDuration([duration])](#dc.baseMixin+transitionDuration) ⇒ Number | [baseMixin](#dc.baseMixin) + * [.transitionDelay([delay])](#dc.baseMixin+transitionDelay) ⇒ Number | [baseMixin](#dc.baseMixin) * [.render()](#dc.baseMixin+render) ⇒ [baseMixin](#dc.baseMixin) * [.redraw()](#dc.baseMixin+redraw) ⇒ [baseMixin](#dc.baseMixin) * [.commitHandler()](#dc.baseMixin+commitHandler) ⇒ [baseMixin](#dc.baseMixin) @@ -2841,14 +2798,14 @@ Set or get the minimum height attribute of a chart. This only has effect when us #### baseMixin.dimension([dimension]) ⇒ crossfilter.dimension | [baseMixin](#dc.baseMixin) **mandatory** -Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid [crossfilter -dimension](https://github.com/square/crossfilter/wiki/API-Reference#wiki-dimension). +Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid +[crossfilter dimension](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension) If a value is given, then it will be used as the new dimension. If no value is specified then the current dimension will be returned. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [crossfilter.dimension](https://github.com/square/crossfilter/wiki/API-Reference#dimension) +**See**: [crossfilter.dimension](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension) | Param | Type | | --- | --- | @@ -2865,7 +2822,7 @@ chart.dimension(dimension); #### baseMixin.data([callback]) ⇒ \* | [baseMixin](#dc.baseMixin) Set the data callback or retrieve the chart's data set. The data callback is passed the chart's group and by default will return -[group.all](https://github.com/square/crossfilter/wiki/API-Reference#group_all). +[group.all](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all). This behavior may be modified to, for instance, return only the top 5 groups. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -2887,7 +2844,7 @@ chart.data(function (group) { return group.top(5); }); **mandatory** Set or get the group attribute of a chart. In `dc` a group is a -[crossfilter group](https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce). +[crossfilter group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce). Usually the group should be created from the particular dimension associated with the same chart. If a value is given, then it will be used as the new group. @@ -2895,7 +2852,7 @@ If no value specified then the current group will be returned. If `name` is specified then it will be used to generate legend label. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [crossfilter.group](https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce) +**See**: [crossfilter.group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce) | Param | Type | | --- | --- | @@ -2913,11 +2870,11 @@ chart.group(dimension.group(crossfilter.reduceSum())); #### baseMixin.ordering([orderFunction]) ⇒ function | [baseMixin](#dc.baseMixin) Get or set an accessor to order ordinal dimensions. The chart uses -[crossfilter.quicksort.by](https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by) +[crossfilter.quicksort.by](https://github.com/crossfilter/crossfilter/wiki/API-Reference#quicksort_by) to sort elements; this accessor returns the value to order on. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [crossfilter.quicksort.by](https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by) +**See**: [crossfilter.quicksort.by](https://github.com/crossfilter/crossfilter/wiki/API-Reference#quicksort_by) | Param | Type | | --- | --- | @@ -2931,9 +2888,8 @@ _chart.ordering(dc.pluck('key')); #### baseMixin.filterAll() ⇒ [baseMixin](#dc.baseMixin) -Clear all filters associated with this chart - -The same can be achieved by calling [chart.filter(null)](#dc.baseMixin+filter). +Clear all filters associated with this chart. The same effect can be achieved by calling +[chart.filter(null)](#dc.baseMixin+filter). **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -2946,11 +2902,11 @@ This function is **not chainable** since it does not return a chart instance; ho selection result can be chained to d3 function calls. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [d3.selection](https://github.com/mbostock/d3/wiki/Selections) +**See**: [d3.select](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#d3_select) **Example** ```js -// Similar to: -d3.select('#chart-id').select(selector); +// Has the same effect as d3.select('#chart-id').select(selector) +chart.select(selector) ``` @@ -2961,17 +2917,17 @@ This function is **not chainable** since it does not return a chart instance; ho selection result can be chained to d3 function calls. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [d3.selection](https://github.com/mbostock/d3/wiki/Selections) +**See**: [d3.selectAll](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#d3_selectAll) **Example** ```js -// Similar to: -d3.select('#chart-id').selectAll(selector); +// Has the same effect as d3.select('#chart-id').selectAll(selector) +chart.selectAll(selector) ``` #### baseMixin.anchor([parent], [chartGroup]) ⇒ String | node | d3.selection | [baseMixin](#dc.baseMixin) Set the root SVGElement to either be an existing chart's root; or any valid [d3 single -selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom +selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. Optionally registers the chart within the chartGroup. This class is called internally on chart initialization, but be called again to relocate the chart. However, it will orphan any previously created SVGElements. @@ -3029,16 +2985,30 @@ Remove the chart's SVGElements from the dom and recreate the container SVGElemen #### baseMixin.filterPrinter([filterPrinterFunction]) ⇒ function | [baseMixin](#dc.baseMixin) Set or get the filter printer function. The filter printer function is used to generate human -friendly text for filter value(s) associated with the chart instance. By default dc charts use a -default filter printer `dc.printers.filter` that provides simple printing support for both -single value and ranged filters. +friendly text for filter value(s) associated with the chart instance. The text will get shown +in the `.filter element; see [turnOnControls](#dc.baseMixin+turnOnControls). + +By default dc charts use a default filter printer [filters](#dc.printers.filters) +that provides simple printing support for both single value and ranged filters. **Kind**: instance method of [baseMixin](#dc.baseMixin) | Param | Type | Default | | --- | --- | --- | -| [filterPrinterFunction] | function | dc.printers.filter | +| [filterPrinterFunction] | function | dc.printers.filters | +**Example** +```js +// for a chart with an ordinal brush, print the filters in upper case +chart.filterPrinter(function(filters) { + return filters.map(function(f) { return f.toUpperCase(); }).join(', '); +}); +// for a chart with a range brush, print the filter as start and extent +chart.filterPrinter(function(filters) { + return 'start ' + dc.utils.printSingleValue(filters[0][0]) + + ' extent ' + dc.utils.printSingleValue(filters[0][1] - filters[0][0]); +}); +``` #### baseMixin.controlsUseVisibility([controlsUseVisibility]) ⇒ Boolean | [baseMixin](#dc.baseMixin) @@ -3082,6 +3052,17 @@ Set or get the animation transition duration (in milliseconds) for this chart in | --- | --- | --- | | [duration] | Number | 750 | + + +#### baseMixin.transitionDelay([delay]) ⇒ Number | [baseMixin](#dc.baseMixin) +Set or get the animation transition delay (in milliseconds) for this chart instance. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [delay] | Number | 0 | + #### baseMixin.render() ⇒ [baseMixin](#dc.baseMixin) @@ -3100,7 +3081,7 @@ chart. Most chart interaction in dc will automatically trigger this method throu events (in particular [redrawAll](#dc.redrawAll)); therefore, you only need to manually invoke this function if data is manipulated outside of dc's control (for example if data is loaded in the background using -[crossfilter.add](https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add). +[crossfilter.add](https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add)). **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3133,8 +3114,8 @@ Renders all charts in the same group as this chart. If the chart has a #### baseMixin.hasFilterHandler([hasFilterHandler]) ⇒ function | [baseMixin](#dc.baseMixin) -Set or get the has-filter handler. The has-filter handler is a function that checks to see if -the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows +Set or get the has filter handler. The has filter handler is a function that checks to see if +the chart's current filters include a specific filter. Using a custom has filter handler allows you to change the way filters are checked for and replaced. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3145,7 +3126,7 @@ you to change the way filters are checked for and replaced. **Example** ```js -// default has-filter handler +// default has filter handler chart.hasFilterHandler(function (filters, filter) { if (filter === null || typeof(filter) === 'undefined') { return filters.length > 0; @@ -3181,7 +3162,7 @@ filter from the chart's current filters. Using a custom remove filter handler al change how filters are removed or perform additional work when removing a filter, e.g. when using a filter server other than crossfilter. -The handler should return a new or modified array as the result. +Any changes should modify the `filters` array argument and return that array. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3215,7 +3196,7 @@ the chart's filter list. Using a custom add filter handler allows you to change are added or perform additional work when adding a filter, e.g. when using a filter server other than crossfilter. -The handler should return a new or modified array as the result. +Any changes should modify the `filters` array argument and return that array. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3244,7 +3225,7 @@ chart's filter list by returning a new list. Using a custom reset filter handler change the way filters are reset, or perform additional work when resetting the filters, e.g. when using a filter server other than crossfilter. -The handler should return a new or modified array as the result. +This function should return an array. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3268,6 +3249,7 @@ chart.resetFilterHandler(function(filters) { #### baseMixin.replaceFilter([filter]) ⇒ [baseMixin](#dc.baseMixin) Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)` +but more efficient because the filter is only applied once. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3297,8 +3279,8 @@ for the [scatter plot](#dc.scatterPlot) [resetFilterHandler](#dc.baseMixin+resetFilterHandler) Note that this is always a toggle (even when it doesn't make sense for the filter type). If -you wish to replace the current filter, either call `chart.filter(null)` first, or -equivalently, call [`chart.replaceFilter(filter)`](#dc.baseMixin+replaceFilter) instead. +you wish to replace the current filter, either call `chart.filter(null)` first - or it's more +efficient to call [`chart.replaceFilter(filter)`](#dc.baseMixin+replaceFilter) instead. Each toggle is executed by checking if the value is already present using the [hasFilterHandler](#dc.baseMixin+hasFilterHandler); if it is not present, it is added @@ -3364,7 +3346,7 @@ on a specific dimension. Using a custom filter handler allows you to perform add before or after filtering. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [crossfilter.dimension.filter](https://github.com/square/crossfilter/wiki/API-Reference#dimension_filter) +**See**: [crossfilter.dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) | Param | Type | | --- | --- | @@ -3372,12 +3354,20 @@ before or after filtering. **Example** ```js -// default filter handler +// the default filter handler handles all possible cases for the charts in dc.js +// you can replace it with something more specialized for your own chart chart.filterHandler(function (dimension, filters) { - dimension.filter(null); if (filters.length === 0) { + // the empty case (no filtering) dimension.filter(null); + } else if (filters.length === 1 && !filters[0].isFiltered) { + // single value and not a function-based filter + dimension.filterExact(filters[0]); + } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { + // single range-based filter + dimension.filterRange(filters[0]); } else { + // an array of values, or an array of filter objects dimension.filterFunction(function (d) { for (var i = 0; i < filters.length; i++) { var filter = filters[i]; @@ -3561,9 +3551,9 @@ together since it is expected they share the same underlying crossfilter data se #### baseMixin.expireCache() ⇒ [baseMixin](#dc.baseMixin) Expire the internal chart cache. dc charts cache some data internally on a per chart basis to speed up rendering and avoid unnecessary calculation; however it might be useful to clear the -cache if you have changed state which will affect rendering. For example if you invoke the -[crossfilter.add](https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add) -function or reset group or dimension after rendering it is a good idea to +cache if you have changed state which will affect rendering. For example, if you invoke +[crossfilter.add](https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add) +function or reset group or dimension after rendering, it is a good idea to clear the cache to make sure charts are rendered properly. **Kind**: instance method of [baseMixin](#dc.baseMixin) @@ -3623,7 +3613,7 @@ including all renderlets' logic. * `zoomed` - This listener function will be invoked after a zoom is triggered. **Kind**: instance method of [baseMixin](#dc.baseMixin) -**See**: [d3.dispatch.on](https://github.com/mbostock/d3/wiki/Internals#dispatch_on) +**See**: [d3.dispatch.on](https://github.com/d3/d3-3.x-api-reference/blob/master/Internals.md#dispatch_on) | Param | Type | | --- | --- | @@ -3692,7 +3682,7 @@ as a mix-in for any concrete chart implementation. * [.colorDomain([domain])](#dc.colorMixin+colorDomain) ⇒ Array.<String> | [colorMixin](#dc.colorMixin) * [.calculateColorDomain()](#dc.colorMixin+calculateColorDomain) ⇒ [colorMixin](#dc.colorMixin) * [.getColor(d, [i])](#dc.colorMixin+getColor) ⇒ String - * [.colorCalculator([colorCalculator])](#dc.colorMixin+colorCalculator) ⇒ \* + * [.colorCalculator([colorCalculator])](#dc.colorMixin+colorCalculator) ⇒ function | [colorMixin](#dc.colorMixin) @@ -3701,7 +3691,7 @@ Retrieve current color scale or set a new color scale. This methods accepts any operates like a d3 scale. **Kind**: instance method of [colorMixin](#dc.colorMixin) -**See**: [d3.scale](http://github.com/mbostock/d3/wiki/Scales) +**See**: [d3.scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Scales.md) | Param | Type | Default | | --- | --- | --- | @@ -3722,7 +3712,7 @@ chart.linearColors(["#4575b4", "#ffffbf", "#a50026"]); #### colorMixin.ordinalColors(r) ⇒ [colorMixin](#dc.colorMixin) Convenience method to set the color scale to -[d3.scale.ordinal](https://github.com/mbostock/d3/wiki/Ordinal-Scales#ordinal) with +[d3.scale.ordinal](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#ordinal) with range `r`. **Kind**: instance method of [colorMixin](#dc.colorMixin) @@ -3798,8 +3788,12 @@ Get the color for the datum d and counter i. This is used internally by charts t -#### colorMixin.colorCalculator([colorCalculator]) ⇒ \* -Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. +#### colorMixin.colorCalculator([colorCalculator]) ⇒ function | [colorMixin](#dc.colorMixin) +**Deprecated.** Get/set the color calculator. This actually replaces the +[getColor](#dc.colorMixin+getColor) method! + +This is not recommended, since using a [colorAccessor](#dc.colorMixin+colorAccessor) and +color scale ([.colors](#dc.colorMixin+colors)) is more powerful and idiomatic d3. **Kind**: instance method of [colorMixin](#dc.colorMixin) @@ -3834,6 +3828,7 @@ concrete chart types, e.g. bar chart, line chart, and bubble chart. * [.xAxis([xAxis])](#dc.coordinateGridMixin+xAxis) ⇒ d3.svg.axis | [coordinateGridMixin](#dc.coordinateGridMixin) * [.elasticX([elasticX])](#dc.coordinateGridMixin+elasticX) ⇒ Boolean | [coordinateGridMixin](#dc.coordinateGridMixin) * [.xAxisPadding([padding])](#dc.coordinateGridMixin+xAxisPadding) ⇒ Number | String | [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisPaddingUnit([unit])](#dc.coordinateGridMixin+xAxisPaddingUnit) ⇒ String | [coordinateGridMixin](#dc.coordinateGridMixin) * [.xUnitCount()](#dc.coordinateGridMixin+xUnitCount) ⇒ Number * [.useRightYAxis([useRightYAxis])](#dc.coordinateGridMixin+useRightYAxis) ⇒ Boolean | [coordinateGridMixin](#dc.coordinateGridMixin) * [.isOrdinal()](#dc.coordinateGridMixin+isOrdinal) ⇒ Boolean @@ -3948,11 +3943,11 @@ Retrieve the svg group for the chart body. **mandatory** Get or set the x scale. The x scale can be any d3 -[quantitive scale](https://github.com/mbostock/d3/wiki/Quantitative-Scales) or -[ordinal scale](https://github.com/mbostock/d3/wiki/Ordinal-Scales). +[quantitive scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md) or +[ordinal scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md). **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) -**See**: [d3.scale](http://github.com/mbostock/d3/wiki/Scales) +**See**: [d3.scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Scales.md) | Param | Type | | --- | --- | @@ -3973,9 +3968,9 @@ the number of data projections on x axis such as the number of bars for a bar ch number of dots for a line chart. This function is expected to return a Javascript array of all data points on x axis, or the number of points on the axis. [d3 time range functions d3.time.days, d3.time.months, and -d3.time.years](https://github.com/mbostock/d3/wiki/Time-Intervals#aliases) are all valid xUnits -function. dc.js also provides a few units function, see the [Utilities](#dc.utils) section for -a list of built-in units functions. The default xUnits function is dc.units.integers. +d3.time.years](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Intervals.md#aliases) are all valid xUnits +function. dc.js also provides a few units function, see the [Units Namespace](#dc.units) for +a list of built-in units functions. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) **Todo** @@ -3983,9 +3978,9 @@ a list of built-in units functions. The default xUnits function is dc.units.inte - [ ] Add docs for utilities -| Param | Type | -| --- | --- | -| [xUnits] | function | +| Param | Type | Default | +| --- | --- | --- | +| [xUnits] | function | dc.units.integers | **Example** ```js @@ -4010,13 +4005,18 @@ function(start, end, xDomain) { #### coordinateGridMixin.xAxis([xAxis]) ⇒ d3.svg.axis | [coordinateGridMixin](#dc.coordinateGridMixin) Set or get the x axis used by a particular coordinate grid chart instance. This function is most -useful when x axis customization is required. The x axis in dc.js is an instance of a [d3 -axis object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis); therefore it supports any -valid d3 axis manipulation. **Caution**: The x axis is usually generated internally by dc; -resetting it may cause unexpected results. +useful when x axis customization is required. The x axis in dc.js is an instance of a +[d3 axis object](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis); +therefore it supports any valid d3 axis manipulation. + +**Caution**: The x axis is usually generated internally by dc; resetting it may cause +unexpected results. Note also that when used as a getter, this function is not chainable: +it returns the axis, not the chart, +{@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis +so attempting to call chart functions after calling `.xAxis()` will fail}. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) -**See**: [d3.svg.axis](http://github.com/mbostock/d3/wiki/SVG-Axes) +**See**: [d3.svg.axis](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) | Param | Type | Default | | --- | --- | --- | @@ -4047,9 +4047,10 @@ attempt to recalculate the x axis range whenever a redraw event is triggered. Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x axis if elasticX is turned on; otherwise it is ignored. -padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to -number or date x axes. When padding a date axis, an integer represents number of days being padded -and a percentage string will be treated the same as an integer. +Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to +number or date x axes. When padding a date axis, an integer represents number of units being padded +and a percentage string will be treated the same as an integer. The unit will be determined by the +xAxisPaddingUnit variable. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) @@ -4057,11 +4058,28 @@ and a percentage string will be treated the same as an integer. | --- | --- | --- | | [padding] | Number | String | 0 | + + +#### coordinateGridMixin.xAxisPaddingUnit([unit]) ⇒ String | [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get x axis padding unit for the elastic x axis. The padding unit will determine which unit to +use when applying xAxis padding if elasticX is turned on and if x-axis uses a time dimension; +otherwise it is ignored. + +Padding unit is a string that will be used when the padding is calculated. Available parameters are +the available d3 time intervals; see +[d3.time.interval](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Intervals.md#interval). + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [unit] | String | 'days' | + #### coordinateGridMixin.xUnitCount() ⇒ Number Returns the number of units displayed on the x axis using the unit measure configured by -.xUnits. +[xUnits](#dc.coordinateGridMixin+xUnits). **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) @@ -4102,7 +4120,7 @@ the margin to make room for the label. By default the padded is set to 12 to acc #### coordinateGridMixin.yAxisLabel([labelText], [padding]) ⇒ String | [coordinateGridMixin](#dc.coordinateGridMixin) Set or get the y axis label. If setting the label, you may optionally include additional padding -to the margin to make room for the label. By default the padded is set to 12 to accomodate the +to the margin to make room for the label. By default the padding is set to 12 to accommodate the text height. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) @@ -4118,7 +4136,7 @@ text height. Get or set the y scale. The y scale is typically automatically determined by the chart implementation. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) -**See**: [d3.scale](http://github.com/mbostock/d3/wiki/Scales) +**See**: [d3.scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Scales.md) | Param | Type | | --- | --- | @@ -4129,12 +4147,17 @@ Get or set the y scale. The y scale is typically automatically determined by the #### coordinateGridMixin.yAxis([yAxis]) ⇒ d3.svg.axis | [coordinateGridMixin](#dc.coordinateGridMixin) Set or get the y axis used by the coordinate grid chart instance. This function is most useful when y axis customization is required. The y axis in dc.js is simply an instance of a [d3 axis -object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis); therefore it supports any -valid d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc; -resetting it may cause unexpected results. +object](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis); therefore it supports any +valid d3 axis manipulation. + +**Caution**: The y axis is usually generated internally by dc; resetting it may cause +unexpected results. Note also that when used as a getter, this function is not chainable: it +returns the axis, not the chart, +{@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis +so attempting to call chart functions after calling `.yAxis()` will fail}. **Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) -**See**: [d3.svg.axis](http://github.com/mbostock/d3/wiki/SVG-Axes) +**See**: [d3.svg.axis](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) | Param | Type | Default | | --- | --- | --- | @@ -4322,7 +4345,7 @@ of keys on the x axis, while stacked vertically. If name is specified then it wi generate the legend label. **Kind**: instance method of [stackMixin](#dc.stackMixin) -**See**: [crossfilter.group](https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce) +**See**: [crossfilter.group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce) | Param | Type | | --- | --- | @@ -4402,10 +4425,10 @@ var secondTitleFunction = chart.title('second stack'); #### stackMixin.stackLayout([stack]) ⇒ function | [stackMixin](#dc.stackMixin) Gets or sets the stack layout algorithm, which computes a baseline for each stack and -propagates it to the next +propagates it to the next. **Kind**: instance method of [stackMixin](#dc.stackMixin) -**See**: [d3.layout.stack](http://github.com/mbostock/d3/wiki/Stack-Layout) +**See**: [d3.layout.stack](https://github.com/d3/d3-3.x-api-reference/blob/master/Stack-Layout.md) | Param | Type | Default | | --- | --- | --- | @@ -4437,7 +4460,23 @@ others* element is clicked. #### capMixin.cap([count]) ⇒ Number | [capMixin](#dc.capMixin) -Get or set the count of elements to that will be included in the cap. +Get or set the count of elements to that will be included in the cap. If there is an +[othersGrouper](#dc.capMixin+othersGrouper), any further elements will be combined in an +extra element with its name determined by [othersLabel](#dc.capMixin+othersLabel). + +Up through dc.js 2.0.*, capping uses +[group.top(N)](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_top), +which selects the largest items according to +[group.order()](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_order). +The chart then sorts the items according to [baseMixin.ordering()](#dc.baseMixin+ordering). +So the two values essentially have to agree, but if the former is incorrect (it's easy to +forget about `group.order()`), the latter will mask the problem. This also makes +[fake groups](https://github.com/dc-js/dc.js/wiki/FAQ#fake-groups) difficult to +implement. + +In dc.js 2.1 and forward, only +[group.all()](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all) +and `baseMixin.ordering()` are used. **Kind**: instance method of [capMixin](#dc.capMixin) @@ -4448,7 +4487,7 @@ Get or set the count of elements to that will be included in the cap. #### capMixin.othersLabel([label]) ⇒ String | [capMixin](#dc.capMixin) -Get or set the label for *Others* slice when slices cap is specified +Get or set the label for *Others* slice when slices cap is specified. **Kind**: instance method of [capMixin](#dc.capMixin) @@ -4471,6 +4510,8 @@ grouper function computes the sum of all values below the cap. **Example** ```js +// Do not show others +chart.othersGrouper(null); // Default others grouper chart.othersGrouper(function (topRows) { var topRowsSum = d3.sum(topRows, _chart.valueAccessor()), @@ -4481,7 +4522,11 @@ chart.othersGrouper(function (topRows) { topSet = d3.set(topKeys), others = allKeys.filter(function (d) {return !topSet.has(d);}); if (allRowsSum > topRowsSum) { - return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]); + return topRows.concat([{ + 'others': others, + 'key': _chart.othersLabel(), + 'value': allRowsSum - topRowsSum + }]); } return topRows; }); @@ -4523,11 +4568,11 @@ This Mixin provides reusable functionalities for any chart that needs to visuali #### bubbleMixin.r([bubbleRadiusScale]) ⇒ d3.scale | [bubbleMixin](#dc.bubbleMixin) Get or set the bubble radius scale. By default the bubble chart uses -[d3.scale.linear().domain([0, 100])](https://github.com/mbostock/d3/wiki/Quantitative-Scales#linear) +[d3.scale.linear().domain([0, 100])](https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md#linear) as its radius scale. **Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) -**See**: [d3.scale](http://github.com/mbostock/d3/wiki/Scales) +**See**: [d3.scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Scales.md) | Param | Type | Default | | --- | --- | --- | @@ -4582,6 +4627,14 @@ when the difference in radius between bubbles is too great. | --- | --- | --- | | [relativeSize] | Number | 0.3 | + + +### dc.disableTransitions : Boolean +If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen +immediately. + +**Kind**: static property of [dc](#dc) +**Default**: false ### dc.dateFormat : function @@ -4736,14 +4789,14 @@ chart.xUnits(dc.units.integers) // already the default #### units.ordinal(start, end, domain) ⇒ Array.<String> This argument can be passed to the [.xUnits](#dc.coordinateGridMixin+xUnits) function of the to specify ordinal units for the x axis. Usually this parameter is used in combination with passing -[d3.scale.ordinal](https://github.com/mbostock/d3/wiki/Ordinal-Scales) to +[d3.scale.ordinal](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md) to [.x](#dc.coordinateGridMixin+x). It just returns the domain passed to it, which for ordinal charts is an array of all values. **Kind**: static method of [units](#dc.units) **See** -- [d3.scale.ordinal](https://github.com/mbostock/d3/wiki/Ordinal-Scales) +- [d3.scale.ordinal](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md) - [coordinateGridMixin.xUnits](#dc.coordinateGridMixin+xUnits) - [coordinateGridMixin.x](#dc.coordinateGridMixin+x) @@ -4771,18 +4824,18 @@ chart.xUnits(dc.units.ordinal) #### printers.filters(filters) ⇒ String -Converts a list of filters into a readable string +Converts a list of filters into a readable string. **Kind**: static method of [printers](#dc.printers) | Param | Type | | --- | --- | -| filters | Array.<(dc.filters\|any)> | +| filters | [Array.<filters>](#dc.filters) | #### printers.filter(filter) ⇒ String -Converts a filter into a readable string +Converts a filter into a readable string. **Kind**: static method of [printers](#dc.printers) @@ -4797,8 +4850,8 @@ Converts a filter into a readable string * [.utils](#dc.utils) : object * [.printSingleValue(filter)](#dc.utils.printSingleValue) ⇒ String - * [.add(l, r)](#dc.utils.add) ⇒ String | Date | Number - * [.subtract(l, r)](#dc.utils.subtract) ⇒ String | Date | Number + * [.add(l, r, [t])](#dc.utils.add) ⇒ String | Date | Number + * [.subtract(l, r, [t])](#dc.utils.subtract) ⇒ String | Date | Number * [.isNumber(n)](#dc.utils.isNumber) ⇒ Boolean * [.isFloat(n)](#dc.utils.isFloat) ⇒ Boolean * [.isInteger(n)](#dc.utils.isInteger) ⇒ Boolean @@ -4812,7 +4865,7 @@ Converts a filter into a readable string #### utils.printSingleValue(filter) ⇒ String -Print a single value filter +Print a single value filter. **Kind**: static method of [utils](#dc.utils) @@ -4822,7 +4875,7 @@ Print a single value filter -#### utils.add(l, r) ⇒ String | Date | Number +#### utils.add(l, r, [t]) ⇒ String | Date | Number Arbitrary add one value to another. **Kind**: static method of [utils](#dc.utils) @@ -4832,14 +4885,15 @@ Arbitrary add one value to another. They also generate strange results if l is a string. -| Param | Type | -| --- | --- | -| l | String | Date | Number | -| r | Number | +| Param | Type | Description | +| --- | --- | --- | +| l | String | Date | Number | the value to modify | +| r | Number | the amount by which to modify the value | +| [t] | String | if `l` is a `Date`, the [interval](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Intervals.md#interval) in the `d3.time` namespace | -#### utils.subtract(l, r) ⇒ String | Date | Number +#### utils.subtract(l, r, [t]) ⇒ String | Date | Number Arbitrary subtract one value from another. **Kind**: static method of [utils](#dc.utils) @@ -4849,10 +4903,11 @@ Arbitrary subtract one value from another. They also generate strange results if l is a string. -| Param | Type | -| --- | --- | -| l | String | Date | Number | -| r | Number | +| Param | Type | Description | +| --- | --- | --- | +| l | String | Date | Number | the value to modify | +| r | Number | the amount by which to modify the value | +| [t] | String | if `l` is a `Date`, the [interval](https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Intervals.md#interval) in the `d3.time` namespace | @@ -4931,7 +4986,7 @@ Convert a name to an ID. #### utils.appendOrSelect(parent, selector, tag) ⇒ d3.selection -Append or select an item on a parent element +Append or select an item on a parent element. **Kind**: static method of [utils](#dc.utils) @@ -5140,20 +5195,30 @@ from scratch. | --- | --- | | [group] | String | - + -### dc.disableTransitions() ⇒ Boolean -If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen -immediately +### dc.transition(selection, [duration], [delay], [name]) ⇒ d3.transition | d3.selection +Start a transition on a selection if transitions are globally enabled +([disableTransitions](#dc.disableTransitions) is false) and the duration is greater than zero; otherwise return +the selection. Since most operations are the same on a d3 selection and a d3 transition, this +allows a common code path for both cases. **Kind**: static method of [dc](#dc) -**Default**: false + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| selection | d3.selection | | the selection to be transitioned | +| [duration] | Number | function | 250 | the duration of the transition in milliseconds, a function returning the duration, or 0 for no transition | +| [delay] | Number | function | | the delay of the transition in milliseconds, or a function returning the delay, or 0 for no delay | +| [name] | String | | the name of the transition (if concurrent transitions on the same elements are needed) | + ### dc.pluck(n, [f]) ⇒ function Returns a function that given a string property name, can be used to pluck the property off an object. A function -can be passed as the second argument to also alter the data being returned. This can be a useful shorthand method to create -accessor functions. +can be passed as the second argument to also alter the data being returned. + +This can be a useful shorthand method to create accessor functions. **Kind**: static method of [dc](#dc) diff --git a/docs/old-api-docs/api-2.1.0.md b/docs/old-api-docs/api-2.1.0.md new file mode 100644 index 0000000000..e0e3ecc5a1 --- /dev/null +++ b/docs/old-api-docs/api-2.1.0.md @@ -0,0 +1,5468 @@ + + +## dc : object +The entire dc.js library is scoped under the **dc** name space. It does not introduce +anything else into the global name space. + +Most `dc` functions are designed to allow function chaining, meaning they return the current chart +instance whenever it is appropriate. The getter forms of functions do not participate in function +chaining because they return values that are not the chart, although some, +such as [.svg](#dc.baseMixin+svg) and [.xAxis](#dc.coordinateGridMixin+xAxis), +return values that are themselves chainable d3 objects. + +**Kind**: global namespace +**Version**: 2.1.10 +**Example** +```js +// Example chaining +chart.width(300) + .height(300) + .filter('sunday'); +``` + +* [dc](#dc) : object + * [.pieChart](#dc.pieChart) + * [new pieChart(parent, [chartGroup])](#new_dc.pieChart_new) + * [.slicesCap([cap])](#dc.pieChart+slicesCap) ⇒ Number \| [pieChart](#dc.pieChart) + * [.externalRadiusPadding([externalRadiusPadding])](#dc.pieChart+externalRadiusPadding) ⇒ Number \| [pieChart](#dc.pieChart) + * [.innerRadius([innerRadius])](#dc.pieChart+innerRadius) ⇒ Number \| [pieChart](#dc.pieChart) + * [.radius([radius])](#dc.pieChart+radius) ⇒ Number \| [pieChart](#dc.pieChart) + * [.cx([cx])](#dc.pieChart+cx) ⇒ Number \| [pieChart](#dc.pieChart) + * [.cy([cy])](#dc.pieChart+cy) ⇒ Number \| [pieChart](#dc.pieChart) + * [.minAngleForLabel([minAngleForLabel])](#dc.pieChart+minAngleForLabel) ⇒ Number \| [pieChart](#dc.pieChart) + * [.emptyTitle([title])](#dc.pieChart+emptyTitle) ⇒ String \| [pieChart](#dc.pieChart) + * [.externalLabels([externalLabelRadius])](#dc.pieChart+externalLabels) ⇒ Number \| [pieChart](#dc.pieChart) + * [.drawPaths([drawPaths])](#dc.pieChart+drawPaths) ⇒ Boolean \| [pieChart](#dc.pieChart) + * [.barChart](#dc.barChart) + * [new barChart(parent, [chartGroup])](#new_dc.barChart_new) + * [.centerBar([centerBar])](#dc.barChart+centerBar) ⇒ Boolean \| [barChart](#dc.barChart) + * [.barPadding([barPadding])](#dc.barChart+barPadding) ⇒ Number \| [barChart](#dc.barChart) + * [.outerPadding([padding])](#dc.barChart+outerPadding) ⇒ Number \| [barChart](#dc.barChart) + * [.gap([gap])](#dc.barChart+gap) ⇒ Number \| [barChart](#dc.barChart) + * [.alwaysUseRounding([alwaysUseRounding])](#dc.barChart+alwaysUseRounding) ⇒ Boolean \| [barChart](#dc.barChart) + * [.lineChart](#dc.lineChart) + * [new lineChart(parent, [chartGroup])](#new_dc.lineChart_new) + * [.interpolate([interpolate])](#dc.lineChart+interpolate) ⇒ String \| [lineChart](#dc.lineChart) + * [.tension([tension])](#dc.lineChart+tension) ⇒ Number \| [lineChart](#dc.lineChart) + * [.defined([defined])](#dc.lineChart+defined) ⇒ function \| [lineChart](#dc.lineChart) + * [.dashStyle([dashStyle])](#dc.lineChart+dashStyle) ⇒ Array.<Number> \| [lineChart](#dc.lineChart) + * [.renderArea([renderArea])](#dc.lineChart+renderArea) ⇒ Boolean \| [lineChart](#dc.lineChart) + * [.xyTipsOn([xyTipsOn])](#dc.lineChart+xyTipsOn) ⇒ Boolean \| [lineChart](#dc.lineChart) + * [.dotRadius([dotRadius])](#dc.lineChart+dotRadius) ⇒ Number \| [lineChart](#dc.lineChart) + * [.renderDataPoints([options])](#dc.lineChart+renderDataPoints) ⇒ Object \| [lineChart](#dc.lineChart) + * [.dataCount](#dc.dataCount) + * [new dataCount(parent, [chartGroup])](#new_dc.dataCount_new) + * [.html([options])](#dc.dataCount+html) ⇒ Object \| [dataCount](#dc.dataCount) + * [.formatNumber([formatter])](#dc.dataCount+formatNumber) ⇒ function \| [dataCount](#dc.dataCount) + * [.dataTable](#dc.dataTable) + * [new dataTable(parent, [chartGroup])](#new_dc.dataTable_new) + * [.group(groupFunction)](#dc.dataTable+group) ⇒ function \| [dataTable](#dc.dataTable) + * [.size([size])](#dc.dataTable+size) ⇒ Number \| [dataTable](#dc.dataTable) + * [.beginSlice([beginSlice])](#dc.dataTable+beginSlice) ⇒ Number \| [dataTable](#dc.dataTable) + * [.endSlice([endSlice])](#dc.dataTable+endSlice) ⇒ Number \| [dataTable](#dc.dataTable) + * [.columns([columns])](#dc.dataTable+columns) ⇒ Array.<function()> + * [.sortBy([sortBy])](#dc.dataTable+sortBy) ⇒ function \| [dataTable](#dc.dataTable) + * [.order([order])](#dc.dataTable+order) ⇒ function \| [dataTable](#dc.dataTable) + * [.showGroups([showGroups])](#dc.dataTable+showGroups) ⇒ Boolean \| [dataTable](#dc.dataTable) + * [.dataGrid](#dc.dataGrid) + * [new dataGrid(parent, [chartGroup])](#new_dc.dataGrid_new) + * [.group(groupFunction)](#dc.dataGrid+group) ⇒ function \| [dataTable](#dc.dataTable) + * [.beginSlice([beginSlice])](#dc.dataGrid+beginSlice) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.endSlice([endSlice])](#dc.dataGrid+endSlice) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.size([size])](#dc.dataGrid+size) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.html([html])](#dc.dataGrid+html) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.htmlGroup([htmlGroup])](#dc.dataGrid+htmlGroup) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.sortBy([sortByFunction])](#dc.dataGrid+sortBy) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.order([order])](#dc.dataGrid+order) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.bubbleChart](#dc.bubbleChart) + * [new bubbleChart(parent, [chartGroup])](#new_dc.bubbleChart_new) + * [.elasticRadius([elasticRadius])](#dc.bubbleChart+elasticRadius) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) + * [.sortBubbleSize([sortBubbleSize])](#dc.bubbleChart+sortBubbleSize) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) + * [.compositeChart](#dc.compositeChart) + * [new compositeChart(parent, [chartGroup])](#new_dc.compositeChart_new) + * [.useRightAxisGridLines([useRightAxisGridLines])](#dc.compositeChart+useRightAxisGridLines) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.childOptions([childOptions])](#dc.compositeChart+childOptions) ⇒ Object \| [compositeChart](#dc.compositeChart) + * [.rightYAxisLabel([rightYAxisLabel], [padding])](#dc.compositeChart+rightYAxisLabel) ⇒ String \| [compositeChart](#dc.compositeChart) + * [.compose([subChartArray])](#dc.compositeChart+compose) ⇒ [compositeChart](#dc.compositeChart) + * [.children()](#dc.compositeChart+children) ⇒ [Array.<baseMixin>](#dc.baseMixin) + * [.shareColors([shareColors])](#dc.compositeChart+shareColors) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.shareTitle([shareTitle])](#dc.compositeChart+shareTitle) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.rightY([yScale])](#dc.compositeChart+rightY) ⇒ d3.scale \| [compositeChart](#dc.compositeChart) + * [.alignYAxes([alignYAxes])](#dc.compositeChart+alignYAxes) ⇒ Chart + * [.rightYAxis([rightYAxis])](#dc.compositeChart+rightYAxis) ⇒ d3.svg.axis \| [compositeChart](#dc.compositeChart) + * [.seriesChart](#dc.seriesChart) + * [new seriesChart(parent, [chartGroup])](#new_dc.seriesChart_new) + * [.chart([chartFunction])](#dc.seriesChart+chart) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.seriesAccessor([accessor])](#dc.seriesChart+seriesAccessor) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.seriesSort([sortFunction])](#dc.seriesChart+seriesSort) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.valueSort([sortFunction])](#dc.seriesChart+valueSort) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.geoChoroplethChart](#dc.geoChoroplethChart) + * [new geoChoroplethChart(parent, [chartGroup])](#new_dc.geoChoroplethChart_new) + * [.overlayGeoJson(json, name, keyAccessor)](#dc.geoChoroplethChart+overlayGeoJson) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + * [.projection([projection])](#dc.geoChoroplethChart+projection) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + * [.geoJsons()](#dc.geoChoroplethChart+geoJsons) ⇒ Array.<{name:String, data: Object, accessor: function()}> + * [.geoPath()](#dc.geoChoroplethChart+geoPath) ⇒ d3.geo.path + * [.removeGeoJson(name)](#dc.geoChoroplethChart+removeGeoJson) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + * [.bubbleOverlay](#dc.bubbleOverlay) + * [new bubbleOverlay(parent, [chartGroup])](#new_dc.bubbleOverlay_new) + * [.svg([imageElement])](#dc.bubbleOverlay+svg) ⇒ [bubbleOverlay](#dc.bubbleOverlay) + * [.point(name, x, y)](#dc.bubbleOverlay+point) ⇒ [bubbleOverlay](#dc.bubbleOverlay) + * [.rowChart](#dc.rowChart) + * [new rowChart(parent, [chartGroup])](#new_dc.rowChart_new) + * [.x([scale])](#dc.rowChart+x) ⇒ d3.scale \| [rowChart](#dc.rowChart) + * [.renderTitleLabel([renderTitleLabel])](#dc.rowChart+renderTitleLabel) ⇒ Boolean \| [rowChart](#dc.rowChart) + * [.xAxis()](#dc.rowChart+xAxis) ⇒ d3.svg.axis + * [.fixedBarHeight([fixedBarHeight])](#dc.rowChart+fixedBarHeight) ⇒ Boolean \| Number \| [rowChart](#dc.rowChart) + * [.gap([gap])](#dc.rowChart+gap) ⇒ Number \| [rowChart](#dc.rowChart) + * [.elasticX([elasticX])](#dc.rowChart+elasticX) ⇒ Boolean \| [rowChart](#dc.rowChart) + * [.labelOffsetX([labelOffsetX])](#dc.rowChart+labelOffsetX) ⇒ Number \| [rowChart](#dc.rowChart) + * [.labelOffsetY([labelOffsety])](#dc.rowChart+labelOffsetY) ⇒ Number \| [rowChart](#dc.rowChart) + * [.titleLabelOffsetX([titleLabelOffsetX])](#dc.rowChart+titleLabelOffsetX) ⇒ Number \| [rowChart](#dc.rowChart) + * [.legend](#dc.legend) + * [new legend()](#new_dc.legend_new) + * [.x([x])](#dc.legend+x) ⇒ Number \| [legend](#dc.legend) + * [.y([y])](#dc.legend+y) ⇒ Number \| [legend](#dc.legend) + * [.gap([gap])](#dc.legend+gap) ⇒ Number \| [legend](#dc.legend) + * [.itemHeight([itemHeight])](#dc.legend+itemHeight) ⇒ Number \| [legend](#dc.legend) + * [.horizontal([horizontal])](#dc.legend+horizontal) ⇒ Boolean \| [legend](#dc.legend) + * [.legendWidth([legendWidth])](#dc.legend+legendWidth) ⇒ Number \| [legend](#dc.legend) + * [.itemWidth([itemWidth])](#dc.legend+itemWidth) ⇒ Number \| [legend](#dc.legend) + * [.autoItemWidth([autoItemWidth])](#dc.legend+autoItemWidth) ⇒ Boolean \| [legend](#dc.legend) + * [.legendText([legendText])](#dc.legend+legendText) ⇒ function \| [legend](#dc.legend) + * [.maxItems([maxItems])](#dc.legend+maxItems) ⇒ [legend](#dc.legend) + * [.scatterPlot](#dc.scatterPlot) + * [new scatterPlot(parent, [chartGroup])](#new_dc.scatterPlot_new) + * [.emptyColor](#dc.scatterPlot+emptyColor) ⇒ String \| [scatterPlot](#dc.scatterPlot) + * [.emptyOpacity](#dc.scatterPlot+emptyOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.nonemptyOpacity](#dc.scatterPlot+nonemptyOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.existenceAccessor([accessor])](#dc.scatterPlot+existenceAccessor) ⇒ function \| [scatterPlot](#dc.scatterPlot) + * [.symbol([type])](#dc.scatterPlot+symbol) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) + * [.customSymbol([customSymbol])](#dc.scatterPlot+customSymbol) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) + * [.symbolSize([symbolSize])](#dc.scatterPlot+symbolSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.highlightedSize([highlightedSize])](#dc.scatterPlot+highlightedSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedSize([excludedSize])](#dc.scatterPlot+excludedSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedColor([excludedColor])](#dc.scatterPlot+excludedColor) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedOpacity([excludedOpacity])](#dc.scatterPlot+excludedOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.emptySize([emptySize])](#dc.scatterPlot+emptySize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.numberDisplay](#dc.numberDisplay) + * [new numberDisplay(parent, [chartGroup])](#new_dc.numberDisplay_new) + * [.html([html])](#dc.numberDisplay+html) ⇒ Object \| [numberDisplay](#dc.numberDisplay) + * [.value()](#dc.numberDisplay+value) ⇒ Number + * [.formatNumber([formatter])](#dc.numberDisplay+formatNumber) ⇒ function \| [numberDisplay](#dc.numberDisplay) + * [.heatMap](#dc.heatMap) + * [new heatMap(parent, [chartGroup])](#new_dc.heatMap_new) + * [.colsLabel([labelFunction])](#dc.heatMap+colsLabel) ⇒ function \| [heatMap](#dc.heatMap) + * [.rowsLabel([labelFunction])](#dc.heatMap+rowsLabel) ⇒ function \| [heatMap](#dc.heatMap) + * [.rows([rows])](#dc.heatMap+rows) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) + * [.cols([cols])](#dc.heatMap+cols) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) + * [.boxOnClick([handler])](#dc.heatMap+boxOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.xAxisOnClick([handler])](#dc.heatMap+xAxisOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.yAxisOnClick([handler])](#dc.heatMap+yAxisOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.xBorderRadius([xBorderRadius])](#dc.heatMap+xBorderRadius) ⇒ Number \| [heatMap](#dc.heatMap) + * [.yBorderRadius([yBorderRadius])](#dc.heatMap+yBorderRadius) ⇒ Number \| [heatMap](#dc.heatMap) + * [.boxPlot](#dc.boxPlot) + * [new boxPlot(parent, [chartGroup])](#new_dc.boxPlot_new) + * [.boxPadding([padding])](#dc.boxPlot+boxPadding) ⇒ Number \| [boxPlot](#dc.boxPlot) + * [.outerPadding([padding])](#dc.boxPlot+outerPadding) ⇒ Number \| [boxPlot](#dc.boxPlot) + * [.boxWidth([boxWidth])](#dc.boxPlot+boxWidth) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) + * [.tickFormat([tickFormat])](#dc.boxPlot+tickFormat) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) + * [.selectMenu](#dc.selectMenu) + * [new selectMenu(parent, [chartGroup])](#new_dc.selectMenu_new) + * [.order](#dc.selectMenu+order) + * [.promptText](#dc.selectMenu+promptText) + * [.filterDisplayed](#dc.selectMenu+filterDisplayed) + * [.multiple](#dc.selectMenu+multiple) + * [.promptValue](#dc.selectMenu+promptValue) + * [.numberItems](#dc.selectMenu+numberItems) + * [.baseMixin](#dc.baseMixin) ⇒ [baseMixin](#dc.baseMixin) + * [.height([height])](#dc.baseMixin+height) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.width([width])](#dc.baseMixin+width) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.minWidth([minWidth])](#dc.baseMixin+minWidth) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.minHeight([minHeight])](#dc.baseMixin+minHeight) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.useViewBoxResizing([useViewBoxResizing])](#dc.baseMixin+useViewBoxResizing) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.dimension([dimension])](#dc.baseMixin+dimension) ⇒ crossfilter.dimension \| [baseMixin](#dc.baseMixin) + * [.data([callback])](#dc.baseMixin+data) ⇒ \* \| [baseMixin](#dc.baseMixin) + * [.group([group], [name])](#dc.baseMixin+group) ⇒ crossfilter.group \| [baseMixin](#dc.baseMixin) + * [.ordering([orderFunction])](#dc.baseMixin+ordering) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.filterAll()](#dc.baseMixin+filterAll) ⇒ [baseMixin](#dc.baseMixin) + * [.select()](#dc.baseMixin+select) ⇒ d3.selection + * [.selectAll()](#dc.baseMixin+selectAll) ⇒ d3.selection + * [.anchor([parent], [chartGroup])](#dc.baseMixin+anchor) ⇒ String \| node \| d3.selection \| [baseMixin](#dc.baseMixin) + * [.anchorName()](#dc.baseMixin+anchorName) ⇒ String + * [.root([rootElement])](#dc.baseMixin+root) ⇒ HTMLElement \| [baseMixin](#dc.baseMixin) + * [.svg([svgElement])](#dc.baseMixin+svg) ⇒ SVGElement \| d3.selection \| [baseMixin](#dc.baseMixin) + * [.resetSvg()](#dc.baseMixin+resetSvg) ⇒ SVGElement + * [.filterPrinter([filterPrinterFunction])](#dc.baseMixin+filterPrinter) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.controlsUseVisibility([controlsUseVisibility])](#dc.baseMixin+controlsUseVisibility) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.turnOnControls()](#dc.baseMixin+turnOnControls) ⇒ [baseMixin](#dc.baseMixin) + * [.turnOffControls()](#dc.baseMixin+turnOffControls) ⇒ [baseMixin](#dc.baseMixin) + * [.transitionDuration([duration])](#dc.baseMixin+transitionDuration) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.transitionDelay([delay])](#dc.baseMixin+transitionDelay) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.render()](#dc.baseMixin+render) ⇒ [baseMixin](#dc.baseMixin) + * [.redraw()](#dc.baseMixin+redraw) ⇒ [baseMixin](#dc.baseMixin) + * [.commitHandler()](#dc.baseMixin+commitHandler) ⇒ [baseMixin](#dc.baseMixin) + * [.redrawGroup()](#dc.baseMixin+redrawGroup) ⇒ [baseMixin](#dc.baseMixin) + * [.renderGroup()](#dc.baseMixin+renderGroup) ⇒ [baseMixin](#dc.baseMixin) + * [.hasFilterHandler([hasFilterHandler])](#dc.baseMixin+hasFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.hasFilter([filter])](#dc.baseMixin+hasFilter) ⇒ Boolean + * [.removeFilterHandler([removeFilterHandler])](#dc.baseMixin+removeFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.addFilterHandler([addFilterHandler])](#dc.baseMixin+addFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.resetFilterHandler([resetFilterHandler])](#dc.baseMixin+resetFilterHandler) ⇒ [baseMixin](#dc.baseMixin) + * [.replaceFilter([filter])](#dc.baseMixin+replaceFilter) ⇒ [baseMixin](#dc.baseMixin) + * [.filter([filter])](#dc.baseMixin+filter) ⇒ [baseMixin](#dc.baseMixin) + * [.filters()](#dc.baseMixin+filters) ⇒ Array.<\*> + * [.onClick(datum)](#dc.baseMixin+onClick) + * [.filterHandler([filterHandler])](#dc.baseMixin+filterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.keyAccessor([keyAccessor])](#dc.baseMixin+keyAccessor) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.valueAccessor([valueAccessor])](#dc.baseMixin+valueAccessor) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.label([labelFunction], [enableLabels])](#dc.baseMixin+label) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.renderLabel([renderLabel])](#dc.baseMixin+renderLabel) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.title([titleFunction])](#dc.baseMixin+title) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.renderTitle([renderTitle])](#dc.baseMixin+renderTitle) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * ~~[.renderlet(renderletFunction)](#dc.baseMixin+renderlet) ⇒ [baseMixin](#dc.baseMixin)~~ + * [.chartGroup([chartGroup])](#dc.baseMixin+chartGroup) ⇒ String \| [baseMixin](#dc.baseMixin) + * [.expireCache()](#dc.baseMixin+expireCache) ⇒ [baseMixin](#dc.baseMixin) + * [.legend([legend])](#dc.baseMixin+legend) ⇒ [legend](#dc.legend) \| [baseMixin](#dc.baseMixin) + * [.chartID()](#dc.baseMixin+chartID) ⇒ String + * [.options(opts)](#dc.baseMixin+options) ⇒ [baseMixin](#dc.baseMixin) + * [.on(event, listener)](#dc.baseMixin+on) ⇒ [baseMixin](#dc.baseMixin) + * [.marginMixin](#dc.marginMixin) ⇒ [marginMixin](#dc.marginMixin) + * [.margins([margins])](#dc.marginMixin+margins) ⇒ Object \| [marginMixin](#dc.marginMixin) + * [.colorMixin](#dc.colorMixin) ⇒ [colorMixin](#dc.colorMixin) + * [.colors([colorScale])](#dc.colorMixin+colors) ⇒ d3.scale \| [colorMixin](#dc.colorMixin) + * [.ordinalColors(r)](#dc.colorMixin+ordinalColors) ⇒ [colorMixin](#dc.colorMixin) + * [.linearColors(r)](#dc.colorMixin+linearColors) ⇒ [colorMixin](#dc.colorMixin) + * [.colorAccessor([colorAccessor])](#dc.colorMixin+colorAccessor) ⇒ function \| [colorMixin](#dc.colorMixin) + * [.colorDomain([domain])](#dc.colorMixin+colorDomain) ⇒ Array.<String> \| [colorMixin](#dc.colorMixin) + * [.calculateColorDomain()](#dc.colorMixin+calculateColorDomain) ⇒ [colorMixin](#dc.colorMixin) + * [.getColor(d, [i])](#dc.colorMixin+getColor) ⇒ String + * [.colorCalculator([colorCalculator])](#dc.colorMixin+colorCalculator) ⇒ function \| [colorMixin](#dc.colorMixin) + * [.coordinateGridMixin](#dc.coordinateGridMixin) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.rescale()](#dc.coordinateGridMixin+rescale) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.rangeChart([rangeChart])](#dc.coordinateGridMixin+rangeChart) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.zoomScale([extent])](#dc.coordinateGridMixin+zoomScale) ⇒ Array.<(Number\|Date)> \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.zoomOutRestrict([zoomOutRestrict])](#dc.coordinateGridMixin+zoomOutRestrict) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.g([gElement])](#dc.coordinateGridMixin+g) ⇒ SVGElement \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.mouseZoomable([mouseZoomable])](#dc.coordinateGridMixin+mouseZoomable) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.chartBodyG([chartBodyG])](#dc.coordinateGridMixin+chartBodyG) ⇒ SVGElement + * [.x([xScale])](#dc.coordinateGridMixin+x) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xUnits([xUnits])](#dc.coordinateGridMixin+xUnits) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxis([xAxis])](#dc.coordinateGridMixin+xAxis) ⇒ d3.svg.axis \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.elasticX([elasticX])](#dc.coordinateGridMixin+elasticX) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisPadding([padding])](#dc.coordinateGridMixin+xAxisPadding) ⇒ Number \| String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisPaddingUnit([unit])](#dc.coordinateGridMixin+xAxisPaddingUnit) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xUnitCount()](#dc.coordinateGridMixin+xUnitCount) ⇒ Number + * [.useRightYAxis([useRightYAxis])](#dc.coordinateGridMixin+useRightYAxis) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.isOrdinal()](#dc.coordinateGridMixin+isOrdinal) ⇒ Boolean + * [.xAxisLabel([labelText], [padding])](#dc.coordinateGridMixin+xAxisLabel) ⇒ String + * [.yAxisLabel([labelText], [padding])](#dc.coordinateGridMixin+yAxisLabel) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.y([yScale])](#dc.coordinateGridMixin+y) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.yAxis([yAxis])](#dc.coordinateGridMixin+yAxis) ⇒ d3.svg.axis \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.elasticY([elasticY])](#dc.coordinateGridMixin+elasticY) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.renderHorizontalGridLines([renderHorizontalGridLines])](#dc.coordinateGridMixin+renderHorizontalGridLines) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.renderVerticalGridLines([renderVerticalGridLines])](#dc.coordinateGridMixin+renderVerticalGridLines) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisMin()](#dc.coordinateGridMixin+xAxisMin) ⇒ \* + * [.xAxisMax()](#dc.coordinateGridMixin+xAxisMax) ⇒ \* + * [.yAxisMin()](#dc.coordinateGridMixin+yAxisMin) ⇒ \* + * [.yAxisMax()](#dc.coordinateGridMixin+yAxisMax) ⇒ \* + * [.yAxisPadding([padding])](#dc.coordinateGridMixin+yAxisPadding) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.round([round])](#dc.coordinateGridMixin+round) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.clipPadding([padding])](#dc.coordinateGridMixin+clipPadding) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.focus([range])](#dc.coordinateGridMixin+focus) + * [.brushOn([brushOn])](#dc.coordinateGridMixin+brushOn) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.stackMixin](#dc.stackMixin) ⇒ [stackMixin](#dc.stackMixin) + * [.stack(group, [name], [accessor])](#dc.stackMixin+stack) ⇒ Array.<{group: crossfilter.group, name: String, accessor: function()}> \| [stackMixin](#dc.stackMixin) + * [.hidableStacks([hidableStacks])](#dc.stackMixin+hidableStacks) ⇒ Boolean \| [stackMixin](#dc.stackMixin) + * [.hideStack(stackName)](#dc.stackMixin+hideStack) ⇒ [stackMixin](#dc.stackMixin) + * [.showStack(stackName)](#dc.stackMixin+showStack) ⇒ [stackMixin](#dc.stackMixin) + * [.title([stackName], [titleAccessor])](#dc.stackMixin+title) ⇒ String \| [stackMixin](#dc.stackMixin) + * [.stackLayout([stack])](#dc.stackMixin+stackLayout) ⇒ function \| [stackMixin](#dc.stackMixin) + * [.evadeDomainFilter([evadeDomainFilter])](#dc.stackMixin+evadeDomainFilter) ⇒ Boolean \| [stackMixin](#dc.stackMixin) + * [.capMixin](#dc.capMixin) ⇒ [capMixin](#dc.capMixin) + * [.cap([count])](#dc.capMixin+cap) ⇒ Number \| [capMixin](#dc.capMixin) + * [.takeFront([takeFront])](#dc.capMixin+takeFront) ⇒ Boolean \| [capMixin](#dc.capMixin) + * [.othersLabel([label])](#dc.capMixin+othersLabel) ⇒ String \| [capMixin](#dc.capMixin) + * [.othersGrouper([grouperFunction])](#dc.capMixin+othersGrouper) ⇒ function \| [capMixin](#dc.capMixin) + * [.bubbleMixin](#dc.bubbleMixin) ⇒ [bubbleMixin](#dc.bubbleMixin) + * [.r([bubbleRadiusScale])](#dc.bubbleMixin+r) ⇒ d3.scale \| [bubbleMixin](#dc.bubbleMixin) + * [.radiusValueAccessor([radiusValueAccessor])](#dc.bubbleMixin+radiusValueAccessor) ⇒ function \| [bubbleMixin](#dc.bubbleMixin) + * [.minRadius([radius])](#dc.bubbleMixin+minRadius) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + * [.minRadiusWithLabel([radius])](#dc.bubbleMixin+minRadiusWithLabel) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + * [.maxBubbleRelativeSize([relativeSize])](#dc.bubbleMixin+maxBubbleRelativeSize) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + * [.disableTransitions](#dc.disableTransitions) : Boolean + * [.dateFormat](#dc.dateFormat) : function + * [.chartRegistry](#dc.chartRegistry) : object + * [.has(chart)](#dc.chartRegistry.has) ⇒ Boolean + * [.register(chart, [group])](#dc.chartRegistry.register) + * [.deregister(chart, [group])](#dc.chartRegistry.deregister) + * [.clear(group)](#dc.chartRegistry.clear) + * [.list([group])](#dc.chartRegistry.list) ⇒ Array.<Object> + * [.units](#dc.units) : object + * [.fp](#dc.units.fp) : object + * [.precision(precision)](#dc.units.fp.precision) ⇒ function + * [.integers(start, end)](#dc.units.integers) ⇒ Number + * [.ordinal(start, end, domain)](#dc.units.ordinal) ⇒ Array.<String> + * [.printers](#dc.printers) : object + * [.filters(filters)](#dc.printers.filters) ⇒ String + * [.filter(filter)](#dc.printers.filter) ⇒ String + * [.utils](#dc.utils) : object + * [.printSingleValue(filter)](#dc.utils.printSingleValue) ⇒ String + * [.add(l, r, [t])](#dc.utils.add) ⇒ String \| Date \| Number + * [.subtract(l, r, [t])](#dc.utils.subtract) ⇒ String \| Date \| Number + * [.isNumber(n)](#dc.utils.isNumber) ⇒ Boolean + * [.isFloat(n)](#dc.utils.isFloat) ⇒ Boolean + * [.isInteger(n)](#dc.utils.isInteger) ⇒ Boolean + * [.isNegligible(n)](#dc.utils.isNegligible) ⇒ Boolean + * [.clamp(val, min, max)](#dc.utils.clamp) ⇒ any + * [.uniqueId()](#dc.utils.uniqueId) ⇒ Number + * [.nameToId(name)](#dc.utils.nameToId) ⇒ String + * [.appendOrSelect(parent, selector, tag)](#dc.utils.appendOrSelect) ⇒ d3.selection + * [.safeNumber(n)](#dc.utils.safeNumber) ⇒ Number + * [.filters](#dc.filters) : object + * [.RangedFilter](#dc.filters.RangedFilter) + * [new RangedFilter(low, high)](#new_dc.filters.RangedFilter_new) + * [.TwoDimensionalFilter](#dc.filters.TwoDimensionalFilter) + * [new TwoDimensionalFilter(filter)](#new_dc.filters.TwoDimensionalFilter_new) + * [.RangedTwoDimensionalFilter](#dc.filters.RangedTwoDimensionalFilter) + * [new RangedTwoDimensionalFilter(filter)](#new_dc.filters.RangedTwoDimensionalFilter_new) + * [.registerChart(chart, [group])](#dc.registerChart) + * [.deregisterChart(chart, [group])](#dc.deregisterChart) + * [.hasChart(chart)](#dc.hasChart) ⇒ Boolean + * [.deregisterAllCharts(group)](#dc.deregisterAllCharts) + * [.filterAll([group])](#dc.filterAll) + * [.refocusAll([group])](#dc.refocusAll) + * [.renderAll([group])](#dc.renderAll) + * [.redrawAll([group])](#dc.redrawAll) + * [.transition(selection, [duration], [delay], [name])](#dc.transition) ⇒ d3.transition \| d3.selection + * [.pluck(n, [f])](#dc.pluck) ⇒ function + + + +### dc.pieChart +**Kind**: static class of [dc](#dc) +**Mixes**: [capMixin](#dc.capMixin), [colorMixin](#dc.colorMixin), [baseMixin](#dc.baseMixin) + +* [.pieChart](#dc.pieChart) + * [new pieChart(parent, [chartGroup])](#new_dc.pieChart_new) + * [.slicesCap([cap])](#dc.pieChart+slicesCap) ⇒ Number \| [pieChart](#dc.pieChart) + * [.externalRadiusPadding([externalRadiusPadding])](#dc.pieChart+externalRadiusPadding) ⇒ Number \| [pieChart](#dc.pieChart) + * [.innerRadius([innerRadius])](#dc.pieChart+innerRadius) ⇒ Number \| [pieChart](#dc.pieChart) + * [.radius([radius])](#dc.pieChart+radius) ⇒ Number \| [pieChart](#dc.pieChart) + * [.cx([cx])](#dc.pieChart+cx) ⇒ Number \| [pieChart](#dc.pieChart) + * [.cy([cy])](#dc.pieChart+cy) ⇒ Number \| [pieChart](#dc.pieChart) + * [.minAngleForLabel([minAngleForLabel])](#dc.pieChart+minAngleForLabel) ⇒ Number \| [pieChart](#dc.pieChart) + * [.emptyTitle([title])](#dc.pieChart+emptyTitle) ⇒ String \| [pieChart](#dc.pieChart) + * [.externalLabels([externalLabelRadius])](#dc.pieChart+externalLabels) ⇒ Number \| [pieChart](#dc.pieChart) + * [.drawPaths([drawPaths])](#dc.pieChart+drawPaths) ⇒ Boolean \| [pieChart](#dc.pieChart) + + + +#### new pieChart(parent, [chartGroup]) +The pie chart implementation is usually used to visualize a small categorical distribution. The pie +chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each +slice relative to the sum of all values. Slices are ordered by [ordering](#dc.baseMixin+ordering) +which defaults to sorting by key. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a pie chart under #chart-container1 element using the default global chart group +var chart1 = dc.pieChart('#chart-container1'); +// create a pie chart under #chart-container2 element using chart group A +var chart2 = dc.pieChart('#chart-container2', 'chartGroupA'); +``` + + +#### pieChart.slicesCap([cap]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set the maximum number of slices the pie chart will generate. The top slices are determined by +value from high to low. Other slices exceeding the cap will be rolled up into one single *Others* slice. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [cap] | Number | + + + +#### pieChart.externalRadiusPadding([externalRadiusPadding]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set the external radius padding of the pie chart. This will force the radius of the +pie chart to become smaller or larger depending on the value. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [externalRadiusPadding] | Number | 0 | + + + +#### pieChart.innerRadius([innerRadius]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the +pie chart will be rendered as a doughnut chart. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [innerRadius] | Number | 0 | + + + +#### pieChart.radius([radius]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set the outer radius. If the radius is not set, it will be half of the minimum of the +chart width and height. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [radius] | Number | + + + +#### pieChart.cx([cx]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set center x coordinate position. Default is center of svg. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [cx] | Number | + + + +#### pieChart.cy([cy]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set center y coordinate position. Default is center of svg. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [cy] | Number | + + + +#### pieChart.minAngleForLabel([minAngleForLabel]) ⇒ Number \| [pieChart](#dc.pieChart) +Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not +display a slice label. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | Default | +| --- | --- | --- | +| [minAngleForLabel] | Number | 0.5 | + + + +#### pieChart.emptyTitle([title]) ⇒ String \| [pieChart](#dc.pieChart) +Title to use for the only slice when there is no data. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [title] | String | + + + +#### pieChart.externalLabels([externalLabelRadius]) ⇒ Number \| [pieChart](#dc.pieChart) +Position slice labels offset from the outer edge of the chart. + +The argument specifies the extra radius to be added for slice labels. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [externalLabelRadius] | Number | + + + +#### pieChart.drawPaths([drawPaths]) ⇒ Boolean \| [pieChart](#dc.pieChart) +Get or set whether to draw lines from pie slices to their labels. + +**Kind**: instance method of [pieChart](#dc.pieChart) + +| Param | Type | +| --- | --- | +| [drawPaths] | Boolean | + + + +### dc.barChart +**Kind**: static class of [dc](#dc) +**Mixes**: [stackMixin](#dc.stackMixin), [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.barChart](#dc.barChart) + * [new barChart(parent, [chartGroup])](#new_dc.barChart_new) + * [.centerBar([centerBar])](#dc.barChart+centerBar) ⇒ Boolean \| [barChart](#dc.barChart) + * [.barPadding([barPadding])](#dc.barChart+barPadding) ⇒ Number \| [barChart](#dc.barChart) + * [.outerPadding([padding])](#dc.barChart+outerPadding) ⇒ Number \| [barChart](#dc.barChart) + * [.gap([gap])](#dc.barChart+gap) ⇒ Number \| [barChart](#dc.barChart) + * [.alwaysUseRounding([alwaysUseRounding])](#dc.barChart+alwaysUseRounding) ⇒ Boolean \| [barChart](#dc.barChart) + + + +#### new barChart(parent, [chartGroup]) +Concrete bar chart/histogram implementation. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) +- [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. If the bar chart is a sub-chart in a [Composite Chart](#dc.compositeChart) then pass in the parent composite chart instance instead. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a bar chart under #chart-container1 element using the default global chart group +var chart1 = dc.barChart('#chart-container1'); +// create a bar chart under #chart-container2 element using chart group A +var chart2 = dc.barChart('#chart-container2', 'chartGroupA'); +// create a sub-chart under a composite parent chart +var chart3 = dc.barChart(compositeChart); +``` + + +#### barChart.centerBar([centerBar]) ⇒ Boolean \| [barChart](#dc.barChart) +Whether the bar chart will render each bar centered around the data position on the x-axis. + +**Kind**: instance method of [barChart](#dc.barChart) + +| Param | Type | Default | +| --- | --- | --- | +| [centerBar] | Boolean | false | + + + +#### barChart.barPadding([barPadding]) ⇒ Number \| [barChart](#dc.barChart) +Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1. +Setting this value will also remove any previously set [gap](#dc.barChart+gap). See the +[d3 docs](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#ordinal_rangeBands) +for a visual description of how the padding is applied. + +**Kind**: instance method of [barChart](#dc.barChart) + +| Param | Type | Default | +| --- | --- | --- | +| [barPadding] | Number | 0 | + + + +#### barChart.outerPadding([padding]) ⇒ Number \| [barChart](#dc.barChart) +Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts. +Will pad the width by `padding * barWidth` on each side of the chart. + +**Kind**: instance method of [barChart](#dc.barChart) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number | 0.5 | + + + +#### barChart.gap([gap]) ⇒ Number \| [barChart](#dc.barChart) +Manually set fixed gap (in px) between bars instead of relying on the default auto-generated +gap. By default the bar chart implementation will calculate and set the gap automatically +based on the number of data points and the length of the x axis. + +**Kind**: instance method of [barChart](#dc.barChart) + +| Param | Type | Default | +| --- | --- | --- | +| [gap] | Number | 2 | + + + +#### barChart.alwaysUseRounding([alwaysUseRounding]) ⇒ Boolean \| [barChart](#dc.barChart) +Set or get whether rounding is enabled when bars are centered. If false, using +rounding with centered bars will result in a warning and rounding will be ignored. This flag +has no effect if bars are not [centered](#dc.barChart+centerBar). +When using standard d3.js rounding methods, the brush often doesn't align correctly with +centered bars since the bars are offset. The rounding function must add an offset to +compensate, such as in the following example. + +**Kind**: instance method of [barChart](#dc.barChart) + +| Param | Type | Default | +| --- | --- | --- | +| [alwaysUseRounding] | Boolean | false | + +**Example** +```js +chart.round(function(n) { return Math.floor(n) + 0.5; }); +``` + + +### dc.lineChart +**Kind**: static class of [dc](#dc) +**Mixes**: [stackMixin](#dc.stackMixin), [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.lineChart](#dc.lineChart) + * [new lineChart(parent, [chartGroup])](#new_dc.lineChart_new) + * [.interpolate([interpolate])](#dc.lineChart+interpolate) ⇒ String \| [lineChart](#dc.lineChart) + * [.tension([tension])](#dc.lineChart+tension) ⇒ Number \| [lineChart](#dc.lineChart) + * [.defined([defined])](#dc.lineChart+defined) ⇒ function \| [lineChart](#dc.lineChart) + * [.dashStyle([dashStyle])](#dc.lineChart+dashStyle) ⇒ Array.<Number> \| [lineChart](#dc.lineChart) + * [.renderArea([renderArea])](#dc.lineChart+renderArea) ⇒ Boolean \| [lineChart](#dc.lineChart) + * [.xyTipsOn([xyTipsOn])](#dc.lineChart+xyTipsOn) ⇒ Boolean \| [lineChart](#dc.lineChart) + * [.dotRadius([dotRadius])](#dc.lineChart+dotRadius) ⇒ Number \| [lineChart](#dc.lineChart) + * [.renderDataPoints([options])](#dc.lineChart+renderDataPoints) ⇒ Object \| [lineChart](#dc.lineChart) + + + +#### new lineChart(parent, [chartGroup]) +Concrete line/area chart implementation. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) +- [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. If the line chart is a sub-chart in a [Composite Chart](#dc.compositeChart) then pass in the parent composite chart instance instead. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a line chart under #chart-container1 element using the default global chart group +var chart1 = dc.lineChart('#chart-container1'); +// create a line chart under #chart-container2 element using chart group A +var chart2 = dc.lineChart('#chart-container2', 'chartGroupA'); +// create a sub-chart under a composite parent chart +var chart3 = dc.lineChart(compositeChart); +``` + + +#### lineChart.interpolate([interpolate]) ⇒ String \| [lineChart](#dc.lineChart) +Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step +functions, splines, and cubic interpolation. This is passed to +[d3.svg.line.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_interpolate) and +[d3.svg.area.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#area_interpolate), +where you can find a complete list of valid arguments. + +**Kind**: instance method of [lineChart](#dc.lineChart) +**See** + +- [d3.svg.line.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_interpolate) +- [d3.svg.area.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#area_interpolate) + + +| Param | Type | Default | +| --- | --- | --- | +| [interpolate] | String | 'linear' | + + + +#### lineChart.tension([tension]) ⇒ Number \| [lineChart](#dc.lineChart) +Gets or sets the tension to use for lines drawn, in the range 0 to 1. +This parameter further customizes the interpolation behavior. It is passed to +[d3.svg.line.tension](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_tension) and +[d3.svg.area.tension](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#area_tension). + +**Kind**: instance method of [lineChart](#dc.lineChart) +**See** + +- [d3.svg.line.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_interpolate) +- [d3.svg.area.interpolate](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#area_interpolate) + + +| Param | Type | Default | +| --- | --- | --- | +| [tension] | Number | 0.7 | + + + +#### lineChart.defined([defined]) ⇒ function \| [lineChart](#dc.lineChart) +Gets or sets a function that will determine discontinuities in the line which should be +skipped: the path will be broken into separate subpaths if some points are undefined. +This function is passed to +[d3.svg.line.defined](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_defined) + +Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write +custom reduce functions to get this to work, depending on your data. See +[this GitHub comment](https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248) +for more details and an example. + +**Kind**: instance method of [lineChart](#dc.lineChart) +**See**: [d3.svg.line.defined](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#line_defined) + +| Param | Type | +| --- | --- | +| [defined] | function | + + + +#### lineChart.dashStyle([dashStyle]) ⇒ Array.<Number> \| [lineChart](#dc.lineChart) +Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty +array (solid line). + +**Kind**: instance method of [lineChart](#dc.lineChart) +**See**: [stroke-dasharray](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray) + +| Param | Type | Default | +| --- | --- | --- | +| [dashStyle] | Array.<Number> | [] | + +**Example** +```js +// create a Dash Dot Dot Dot +chart.dashStyle([3,1,1,1]); +``` + + +#### lineChart.renderArea([renderArea]) ⇒ Boolean \| [lineChart](#dc.lineChart) +Get or set render area flag. If the flag is set to true then the chart will render the area +beneath each line and the line chart effectively becomes an area chart. + +**Kind**: instance method of [lineChart](#dc.lineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [renderArea] | Boolean | false | + + + +#### lineChart.xyTipsOn([xyTipsOn]) ⇒ Boolean \| [lineChart](#dc.lineChart) +Turn on/off the mouseover behavior of an individual data point which renders a circle and x/y axis +dashed lines back to each respective axis. This is ignored if the chart +[brush](#dc.coordinateGridMixin+brushOn) is on + +**Kind**: instance method of [lineChart](#dc.lineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [xyTipsOn] | Boolean | false | + + + +#### lineChart.dotRadius([dotRadius]) ⇒ Number \| [lineChart](#dc.lineChart) +Get or set the radius (in px) for dots displayed on the data points. + +**Kind**: instance method of [lineChart](#dc.lineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [dotRadius] | Number | 5 | + + + +#### lineChart.renderDataPoints([options]) ⇒ Object \| [lineChart](#dc.lineChart) +Always show individual dots for each datapoint. + +If `options` is falsy, it disables data point rendering. If no `options` are provided, the +current `options` values are instead returned. + +**Kind**: instance method of [lineChart](#dc.lineChart) + +| Param | Type | Default | +| --- | --- | --- | +| [options] | Object | {fillOpacity: 0.8, strokeOpacity: 0.8, radius: 2} | + +**Example** +```js +chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.8}) +``` + + +### dc.dataCount +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.dataCount](#dc.dataCount) + * [new dataCount(parent, [chartGroup])](#new_dc.dataCount_new) + * [.html([options])](#dc.dataCount+html) ⇒ Object \| [dataCount](#dc.dataCount) + * [.formatNumber([formatter])](#dc.dataCount+formatNumber) ⇒ function \| [dataCount](#dc.dataCount) + + + +#### new dataCount(parent, [chartGroup]) +The data count widget is a simple widget designed to display the number of records selected by the +current filters out of the total number of records in the data set. Once created the data count widget +will automatically update the text content of child elements with the following classes: + +* `.total-count` - total number of records +* `.filter-count` - number of records matched by the current filters + +Note: this widget works best for the specific case of showing the number of records out of a +total. If you want a more general-purpose numeric display, please use the +[numberDisplay](#dc.numberDisplay) widget instead. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +var ndx = crossfilter(data); +var all = ndx.groupAll(); + +dc.dataCount('.dc-data-count') + .dimension(ndx) + .group(all); +``` + + +#### dataCount.html([options]) ⇒ Object \| [dataCount](#dc.dataCount) +Gets or sets an optional object specifying HTML templates to use depending how many items are +selected. The text `%total-count` will replaced with the total number of records, and the text +`%filter-count` will be replaced with the number of selected records. +- all: HTML template to use if all items are selected +- some: HTML template to use if not all items are selected + +**Kind**: instance method of [dataCount](#dc.dataCount) + +| Param | Type | +| --- | --- | +| [options] | Object | + +**Example** +```js +counter.html({ + some: '%filter-count out of %total-count records selected', + all: 'All records selected. Click on charts to apply filters' +}) +``` + + +#### dataCount.formatNumber([formatter]) ⇒ function \| [dataCount](#dc.dataCount) +Gets or sets an optional function to format the filter count and total count. + +**Kind**: instance method of [dataCount](#dc.dataCount) +**See**: [d3.format](https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md) + +| Param | Type | Default | +| --- | --- | --- | +| [formatter] | function | d3.format('.2g') | + +**Example** +```js +counter.formatNumber(d3.format('.2g')) +``` + + +### dc.dataTable +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.dataTable](#dc.dataTable) + * [new dataTable(parent, [chartGroup])](#new_dc.dataTable_new) + * [.group(groupFunction)](#dc.dataTable+group) ⇒ function \| [dataTable](#dc.dataTable) + * [.size([size])](#dc.dataTable+size) ⇒ Number \| [dataTable](#dc.dataTable) + * [.beginSlice([beginSlice])](#dc.dataTable+beginSlice) ⇒ Number \| [dataTable](#dc.dataTable) + * [.endSlice([endSlice])](#dc.dataTable+endSlice) ⇒ Number \| [dataTable](#dc.dataTable) + * [.columns([columns])](#dc.dataTable+columns) ⇒ Array.<function()> + * [.sortBy([sortBy])](#dc.dataTable+sortBy) ⇒ function \| [dataTable](#dc.dataTable) + * [.order([order])](#dc.dataTable+order) ⇒ function \| [dataTable](#dc.dataTable) + * [.showGroups([showGroups])](#dc.dataTable+showGroups) ⇒ Boolean \| [dataTable](#dc.dataTable) + + + +#### new dataTable(parent, [chartGroup]) +The data table is a simple widget designed to list crossfilter focused data set (rows being +filtered) in a good old tabular fashion. + +Note: Unlike other charts, the data table (and data grid chart) use the [group](#dc.dataTable+group) attribute as a +keying function for [nesting](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#nest) the data +together in groups. Do not pass in a crossfilter group as this will not work. + +Another interesting feature of the data table is that you can pass a crossfilter group to the `dimension`, as +long as you specify the [order](#dc.dataTable+order) as `d3.descending`, since the data +table will use `dimension.top()` to fetch the data in that case, and the method is equally +supported on the crossfilter group as the crossfilter dimension. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) +- [dataTable on a crossfilter group](http://dc-js.github.io/dc.js/examples/table-on-aggregated-data.html) +([source](https://github.com/dc-js/dc.js/blob/develop/web/examples/table-on-aggregated-data.html)) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + + + +#### dataTable.group(groupFunction) ⇒ function \| [dataTable](#dc.dataTable) +Get or set the group function for the data table. The group function takes a data row and +returns the key to specify to [d3.nest](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_nest) +to split rows into groups. + +Do not pass in a crossfilter group as this will not work. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | Description | +| --- | --- | --- | +| groupFunction | function | Function taking a row of data and returning the nest key. | + +**Example** +```js +// group rows by the value of their field +chart + .group(function(d) { return d.field; }) +``` + + +#### dataTable.size([size]) ⇒ Number \| [dataTable](#dc.dataTable) +Get or set the table size which determines the number of rows displayed by the widget. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [size] | Number | 25 | + + + +#### dataTable.beginSlice([beginSlice]) ⇒ Number \| [dataTable](#dc.dataTable) +Get or set the index of the beginning slice which determines which entries get displayed +by the widget. Useful when implementing pagination. + +Note: the sortBy function will determine how the rows are ordered for pagination purposes. +See the [table pagination example](http://dc-js.github.io/dc.js/examples/table-pagination.html) +to see how to implement the pagination user interface using `beginSlice` and `endSlice`. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [beginSlice] | Number | 0 | + + + +#### dataTable.endSlice([endSlice]) ⇒ Number \| [dataTable](#dc.dataTable) +Get or set the index of the end slice which determines which entries get displayed by the +widget. Useful when implementing pagination. See [`beginSlice`](#dc.dataTable+beginSlice) for more information. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | +| --- | --- | +| [endSlice] | Number \| undefined | + + + +#### dataTable.columns([columns]) ⇒ Array.<function()> +Get or set column functions. The data table widget supports several methods of specifying the +columns to display. + +The original method uses an array of functions to generate dynamic columns. Column functions +are simple javascript functions with only one input argument `d` which represents a row in +the data set. The return value of these functions will be used to generate the content for +each cell. However, this method requires the HTML for the table to have a fixed set of column +headers. + +
chart.columns([
+    function(d) { return d.date; },
+    function(d) { return d.open; },
+    function(d) { return d.close; },
+    function(d) { return numberFormat(d.close - d.open); },
+    function(d) { return d.volume; }
+]);
+
+ +In the second method, you can list the columns to read from the data without specifying it as +a function, except where necessary (ie, computed columns). Note the data element name is +capitalized when displayed in the table header. You can also mix in functions as necessary, +using the third `{label, format}` form, as shown below. + +
chart.columns([
+    "date",    // d["date"], ie, a field accessor; capitalized automatically
+    "open",    // ...
+    "close",   // ...
+    {
+        label: "Change",
+        format: function (d) {
+            return numberFormat(d.close - d.open);
+        }
+    },
+    "volume"   // d["volume"], ie, a field accessor; capitalized automatically
+]);
+
+ +In the third example, we specify all fields using the `{label, format}` method: +
chart.columns([
+    {
+        label: "Date",
+        format: function (d) { return d.date; }
+    },
+    {
+        label: "Open",
+        format: function (d) { return numberFormat(d.open); }
+    },
+    {
+        label: "Close",
+        format: function (d) { return numberFormat(d.close); }
+    },
+    {
+        label: "Change",
+        format: function (d) { return numberFormat(d.close - d.open); }
+    },
+    {
+        label: "Volume",
+        format: function (d) { return d.volume; }
+    }
+]);
+
+ +You may wish to override the dataTable functions `_doColumnHeaderCapitalize` and +`_doColumnHeaderFnToString`, which are used internally to translate the column information or +function into a displayed header. The first one is used on the "string" column specifier; the +second is used to transform a stringified function into something displayable. For the Stock +example, the function for Change becomes the table header **d.close - d.open**. + +Finally, you can even specify a completely different form of column definition. To do this, +override `_chart._doColumnHeaderFormat` and `_chart._doColumnValueFormat` Be aware that +fields without numberFormat specification will be displayed just as they are stored in the +data, unformatted. + +**Kind**: instance method of [dataTable](#dc.dataTable) +**Returns**: Array.<function()> - |dc.dataTable} + +| Param | Type | Default | +| --- | --- | --- | +| [columns] | Array.<function()> | [] | + + + +#### dataTable.sortBy([sortBy]) ⇒ function \| [dataTable](#dc.dataTable) +Get or set sort-by function. This function works as a value accessor at row level and returns a +particular field to be sorted by. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [sortBy] | function | identity function | + +**Example** +```js +chart.sortBy(function(d) { + return d.date; +}); +``` + + +#### dataTable.order([order]) ⇒ function \| [dataTable](#dc.dataTable) +Get or set sort order. If the order is `d3.ascending`, the data table will use +`dimension().bottom()` to fetch the data; otherwise it will use `dimension().top()` + +**Kind**: instance method of [dataTable](#dc.dataTable) +**See** + +- [d3.ascending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_ascending) +- [d3.descending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_descending) + + +| Param | Type | Default | +| --- | --- | --- | +| [order] | function | d3.ascending | + +**Example** +```js +chart.order(d3.descending); +``` + + +#### dataTable.showGroups([showGroups]) ⇒ Boolean \| [dataTable](#dc.dataTable) +Get or set if group rows will be shown. The dataTable [group](#dc.dataTable+group) +function must be specified even if groups are not shown. + +**Kind**: instance method of [dataTable](#dc.dataTable) + +| Param | Type | Default | +| --- | --- | --- | +| [showGroups] | Boolean | true | + +**Example** +```js +chart + .group([value], [name]) + .showGroups(true|false); +``` + + +### dc.dataGrid +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.dataGrid](#dc.dataGrid) + * [new dataGrid(parent, [chartGroup])](#new_dc.dataGrid_new) + * [.group(groupFunction)](#dc.dataGrid+group) ⇒ function \| [dataTable](#dc.dataTable) + * [.beginSlice([beginSlice])](#dc.dataGrid+beginSlice) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.endSlice([endSlice])](#dc.dataGrid+endSlice) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.size([size])](#dc.dataGrid+size) ⇒ Number \| [dataGrid](#dc.dataGrid) + * [.html([html])](#dc.dataGrid+html) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.htmlGroup([htmlGroup])](#dc.dataGrid+htmlGroup) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.sortBy([sortByFunction])](#dc.dataGrid+sortBy) ⇒ function \| [dataGrid](#dc.dataGrid) + * [.order([order])](#dc.dataGrid+order) ⇒ function \| [dataGrid](#dc.dataGrid) + + + +#### new dataGrid(parent, [chartGroup]) +Data grid is a simple widget designed to list the filtered records, providing +a simple way to define how the items are displayed. + +Note: Unlike other charts, the data grid chart (and data table) use the [group](#dc.dataGrid+group) attribute as a keying function +for [nesting](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#nest) the data together in groups. +Do not pass in a crossfilter group as this will not work. + +Examples: +- [List of members of the european parliament](http://europarl.me/dc.js/web/ep/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + + + +#### dataGrid.group(groupFunction) ⇒ function \| [dataTable](#dc.dataTable) +Get or set the group function for the data grid. The group function takes a data row and +returns the key to specify to [d3.nest](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_nest) +to split rows into groups. + +Do not pass in a crossfilter group as this will not work. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | Description | +| --- | --- | --- | +| groupFunction | function | Function taking a row of data and returning the nest key. | + +**Example** +```js +// group rows by the value of their field +chart + .group(function(d) { return d.field; }) +``` + + +#### dataGrid.beginSlice([beginSlice]) ⇒ Number \| [dataGrid](#dc.dataGrid) +Get or set the index of the beginning slice which determines which entries get displayed by the widget. +Useful when implementing pagination. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | Default | +| --- | --- | --- | +| [beginSlice] | Number | 0 | + + + +#### dataGrid.endSlice([endSlice]) ⇒ Number \| [dataGrid](#dc.dataGrid) +Get or set the index of the end slice which determines which entries get displayed by the widget. +Useful when implementing pagination. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | +| --- | --- | +| [endSlice] | Number | + + + +#### dataGrid.size([size]) ⇒ Number \| [dataGrid](#dc.dataGrid) +Get or set the grid size which determines the number of items displayed by the widget. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | Default | +| --- | --- | --- | +| [size] | Number | 999 | + + + +#### dataGrid.html([html]) ⇒ function \| [dataGrid](#dc.dataGrid) +Get or set the function that formats an item. The data grid widget uses a +function to generate dynamic html. Use your favourite templating engine or +generate the string directly. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | +| --- | --- | +| [html] | function | + +**Example** +```js +chart.html(function (d) { return '
'+data.exampleString+'
';}); +``` + + +#### dataGrid.htmlGroup([htmlGroup]) ⇒ function \| [dataGrid](#dc.dataGrid) +Get or set the function that formats a group label. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | +| --- | --- | +| [htmlGroup] | function | + +**Example** +```js +chart.htmlGroup (function (d) { return '

'.d.key . 'with ' . d.values.length .' items

'}); +``` + + +#### dataGrid.sortBy([sortByFunction]) ⇒ function \| [dataGrid](#dc.dataGrid) +Get or set sort-by function. This function works as a value accessor at the item +level and returns a particular field to be sorted. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) + +| Param | Type | +| --- | --- | +| [sortByFunction] | function | + +**Example** +```js +chart.sortBy(function(d) { + return d.date; +}); +``` + + +#### dataGrid.order([order]) ⇒ function \| [dataGrid](#dc.dataGrid) +Get or set sort the order function. + +**Kind**: instance method of [dataGrid](#dc.dataGrid) +**See** + +- [d3.ascending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_ascending) +- [d3.descending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_descending) + + +| Param | Type | Default | +| --- | --- | --- | +| [order] | function | d3.ascending | + +**Example** +```js +chart.order(d3.descending); +``` + + +### dc.bubbleChart +**Kind**: static class of [dc](#dc) +**Mixes**: [bubbleMixin](#dc.bubbleMixin), [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.bubbleChart](#dc.bubbleChart) + * [new bubbleChart(parent, [chartGroup])](#new_dc.bubbleChart_new) + * [.elasticRadius([elasticRadius])](#dc.bubbleChart+elasticRadius) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) + * [.sortBubbleSize([sortBubbleSize])](#dc.bubbleChart+sortBubbleSize) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) + + + +#### new bubbleChart(parent, [chartGroup]) +A concrete implementation of a general purpose bubble chart that allows data visualization using the +following dimensions: +- x axis position +- y axis position +- bubble radius +- color + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) +- [US Venture Capital Landscape 2011](http://dc-js.github.com/dc.js/vc/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a bubble chart under #chart-container1 element using the default global chart group +var bubbleChart1 = dc.bubbleChart('#chart-container1'); +// create a bubble chart under #chart-container2 element using chart group A +var bubbleChart2 = dc.bubbleChart('#chart-container2', 'chartGroupA'); +``` + + +#### bubbleChart.elasticRadius([elasticRadius]) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) +Turn on or off the elastic bubble radius feature, or return the value of the flag. If this +feature is turned on, then bubble radii will be automatically rescaled to fit the chart better. + +**Kind**: instance method of [bubbleChart](#dc.bubbleChart) + +| Param | Type | Default | +| --- | --- | --- | +| [elasticRadius] | Boolean | false | + + + +#### bubbleChart.sortBubbleSize([sortBubbleSize]) ⇒ Boolean \| [bubbleChart](#dc.bubbleChart) +Turn on or off the bubble sorting feature, or return the value of the flag. If enabled, +bubbles will be sorted by their radius, with smaller bubbles in front. + +**Kind**: instance method of [bubbleChart](#dc.bubbleChart) + +| Param | Type | Default | +| --- | --- | --- | +| [sortBubbleSize] | Boolean | false | + + + +### dc.compositeChart +**Kind**: static class of [dc](#dc) +**Mixes**: [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.compositeChart](#dc.compositeChart) + * [new compositeChart(parent, [chartGroup])](#new_dc.compositeChart_new) + * [.useRightAxisGridLines([useRightAxisGridLines])](#dc.compositeChart+useRightAxisGridLines) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.childOptions([childOptions])](#dc.compositeChart+childOptions) ⇒ Object \| [compositeChart](#dc.compositeChart) + * [.rightYAxisLabel([rightYAxisLabel], [padding])](#dc.compositeChart+rightYAxisLabel) ⇒ String \| [compositeChart](#dc.compositeChart) + * [.compose([subChartArray])](#dc.compositeChart+compose) ⇒ [compositeChart](#dc.compositeChart) + * [.children()](#dc.compositeChart+children) ⇒ [Array.<baseMixin>](#dc.baseMixin) + * [.shareColors([shareColors])](#dc.compositeChart+shareColors) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.shareTitle([shareTitle])](#dc.compositeChart+shareTitle) ⇒ Boolean \| [compositeChart](#dc.compositeChart) + * [.rightY([yScale])](#dc.compositeChart+rightY) ⇒ d3.scale \| [compositeChart](#dc.compositeChart) + * [.alignYAxes([alignYAxes])](#dc.compositeChart+alignYAxes) ⇒ Chart + * [.rightYAxis([rightYAxis])](#dc.compositeChart+rightYAxis) ⇒ d3.svg.axis \| [compositeChart](#dc.compositeChart) + + + +#### new compositeChart(parent, [chartGroup]) +Composite charts are a special kind of chart that render multiple charts on the same Coordinate +Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to +achieve some quite flexible charting effects. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a composite chart under #chart-container1 element using the default global chart group +var compositeChart1 = dc.compositeChart('#chart-container1'); +// create a composite chart under #chart-container2 element using chart group A +var compositeChart2 = dc.compositeChart('#chart-container2', 'chartGroupA'); +``` + + +#### compositeChart.useRightAxisGridLines([useRightAxisGridLines]) ⇒ Boolean \| [compositeChart](#dc.compositeChart) +Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the +default behavior. This option is only respected when subcharts with both left and right y-axes +are present. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [useRightAxisGridLines] | Boolean | false | + + + +#### compositeChart.childOptions([childOptions]) ⇒ Object \| [compositeChart](#dc.compositeChart) +Get or set chart-specific options for all child charts. This is equivalent to calling +[.options](#dc.baseMixin+options) on each child chart. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | +| --- | --- | +| [childOptions] | Object | + + + +#### compositeChart.rightYAxisLabel([rightYAxisLabel], [padding]) ⇒ String \| [compositeChart](#dc.compositeChart) +Set or get the right y axis label. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | +| --- | --- | +| [rightYAxisLabel] | String | +| [padding] | Number | + + + +#### compositeChart.compose([subChartArray]) ⇒ [compositeChart](#dc.compositeChart) +Combine the given charts into one single composite coordinate grid chart. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | +| --- | --- | +| [subChartArray] | Array.<Chart> | + +**Example** +```js +moveChart.compose([ + // when creating sub-chart you need to pass in the parent chart + dc.lineChart(moveChart) + .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used + .valueAccessor(function (d){return d.value.avg;}) + // most of the normal functions will continue to work in a composed chart + .renderArea(true) + .stack(monthlyMoveGroup, function (d){return d.value;}) + .title(function (d){ + var value = d.value.avg?d.value.avg:d.value; + if(isNaN(value)) value = 0; + return dateFormat(d.key) + '\n' + numberFormat(value); + }), + dc.barChart(moveChart) + .group(volumeByMonthGroup) + .centerBar(true) +]); +``` + + +#### compositeChart.children() ⇒ [Array.<baseMixin>](#dc.baseMixin) +Returns the child charts which are composed into the composite chart. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + + +#### compositeChart.shareColors([shareColors]) ⇒ Boolean \| [compositeChart](#dc.compositeChart) +Get or set color sharing for the chart. If set, the [.colors()](#dc.colorMixin+colors) value from this chart +will be shared with composed children. Additionally if the child chart implements +Stackable and has not set a custom .colorAccessor, then it will generate a color +specific to its order in the composition. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [shareColors] | Boolean | false | + + + +#### compositeChart.shareTitle([shareTitle]) ⇒ Boolean \| [compositeChart](#dc.compositeChart) +Get or set title sharing for the chart. If set, the [.title()](#dc.baseMixin+title) value from +this chart will be shared with composed children. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [shareTitle] | Boolean | true | + + + +#### compositeChart.rightY([yScale]) ⇒ d3.scale \| [compositeChart](#dc.compositeChart) +Get or set the y scale for the right axis. The right y scale is typically automatically +generated by the chart implementation. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) +**See**: [d3.scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Scales.md) + +| Param | Type | +| --- | --- | +| [yScale] | d3.scale | + + + +#### compositeChart.alignYAxes([alignYAxes]) ⇒ Chart +Get or set alignment between left and right y axes. A line connecting '0' on both y axis +will be parallel to x axis. This only has effect when [elasticY](#dc.coordinateGridMixin+elasticY) is true. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) + +| Param | Type | Default | +| --- | --- | --- | +| [alignYAxes] | Boolean | false | + + + +#### compositeChart.rightYAxis([rightYAxis]) ⇒ d3.svg.axis \| [compositeChart](#dc.compositeChart) +Set or get the right y axis used by the composite chart. This function is most useful when y +axis customization is required. The y axis in dc.js is an instance of a [d3 axis +object](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) therefore it supports any valid +d3 axis manipulation. + +**Caution**: The y axis is usually generated internally by dc; resetting it may cause +unexpected results. + +**Kind**: instance method of [compositeChart](#dc.compositeChart) +**See**: [d3.svg.axis](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) + +| Param | Type | +| --- | --- | +| [rightYAxis] | d3.svg.axis | + +**Example** +```js +// customize y axis tick format +chart.rightYAxis().tickFormat(function (v) {return v + '%';}); +// customize y axis tick values +chart.rightYAxis().tickValues([0, 100, 200, 300]); +``` + + +### dc.seriesChart +**Kind**: static class of [dc](#dc) +**Mixes**: [compositeChart](#dc.compositeChart) + +* [.seriesChart](#dc.seriesChart) + * [new seriesChart(parent, [chartGroup])](#new_dc.seriesChart_new) + * [.chart([chartFunction])](#dc.seriesChart+chart) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.seriesAccessor([accessor])](#dc.seriesChart+seriesAccessor) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.seriesSort([sortFunction])](#dc.seriesChart+seriesSort) ⇒ function \| [seriesChart](#dc.seriesChart) + * [.valueSort([sortFunction])](#dc.seriesChart+valueSort) ⇒ function \| [seriesChart](#dc.seriesChart) + + + +#### new seriesChart(parent, [chartGroup]) +A series chart is a chart that shows multiple series of data overlaid on one chart, where the +series is specified in the data. It is a specialization of Composite Chart and inherits all +composite features other than recomposing the chart. + +Examples: +- [Series Chart](http://dc-js.github.io/dc.js/examples/series.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a series chart under #chart-container1 element using the default global chart group +var seriesChart1 = dc.seriesChart("#chart-container1"); +// create a series chart under #chart-container2 element using chart group A +var seriesChart2 = dc.seriesChart("#chart-container2", "chartGroupA"); +``` + + +#### seriesChart.chart([chartFunction]) ⇒ function \| [seriesChart](#dc.seriesChart) +Get or set the chart function, which generates the child charts. + +**Kind**: instance method of [seriesChart](#dc.seriesChart) + +| Param | Type | Default | +| --- | --- | --- | +| [chartFunction] | function | dc.lineChart | + +**Example** +```js +// put interpolation on the line charts used for the series +chart.chart(function(c) { return dc.lineChart(c).interpolate('basis'); }) +// do a scatter series chart +chart.chart(dc.scatterPlot) +``` + + +#### seriesChart.seriesAccessor([accessor]) ⇒ function \| [seriesChart](#dc.seriesChart) +**mandatory** + +Get or set accessor function for the displayed series. Given a datum, this function +should return the series that datum belongs to. + +**Kind**: instance method of [seriesChart](#dc.seriesChart) + +| Param | Type | +| --- | --- | +| [accessor] | function | + +**Example** +```js +// simple series accessor +chart.seriesAccessor(function(d) { return "Expt: " + d.key[0]; }) +``` + + +#### seriesChart.seriesSort([sortFunction]) ⇒ function \| [seriesChart](#dc.seriesChart) +Get or set a function to sort the list of series by, given series values. + +**Kind**: instance method of [seriesChart](#dc.seriesChart) +**See** + +- [d3.ascending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_ascending) +- [d3.descending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_descending) + + +| Param | Type | Default | +| --- | --- | --- | +| [sortFunction] | function | d3.ascending | + +**Example** +```js +chart.seriesSort(d3.descending); +``` + + +#### seriesChart.valueSort([sortFunction]) ⇒ function \| [seriesChart](#dc.seriesChart) +Get or set a function to sort each series values by. By default this is the key accessor which, +for example, will ensure a lineChart series connects its points in increasing key/x order, +rather than haphazardly. + +**Kind**: instance method of [seriesChart](#dc.seriesChart) +**See** + +- [d3.ascending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_ascending) +- [d3.descending](https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md#d3_descending) + + +| Param | Type | +| --- | --- | +| [sortFunction] | function | + +**Example** +```js +// Default value sort +_chart.valueSort(function keySort (a, b) { + return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b)); +}); +``` + + +### dc.geoChoroplethChart +**Kind**: static class of [dc](#dc) +**Mixes**: [colorMixin](#dc.colorMixin), [baseMixin](#dc.baseMixin) + +* [.geoChoroplethChart](#dc.geoChoroplethChart) + * [new geoChoroplethChart(parent, [chartGroup])](#new_dc.geoChoroplethChart_new) + * [.overlayGeoJson(json, name, keyAccessor)](#dc.geoChoroplethChart+overlayGeoJson) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + * [.projection([projection])](#dc.geoChoroplethChart+projection) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + * [.geoJsons()](#dc.geoChoroplethChart+geoJsons) ⇒ Array.<{name:String, data: Object, accessor: function()}> + * [.geoPath()](#dc.geoChoroplethChart+geoPath) ⇒ d3.geo.path + * [.removeGeoJson(name)](#dc.geoChoroplethChart+removeGeoJson) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) + + + +#### new geoChoroplethChart(parent, [chartGroup]) +The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map +from GeoJson data. This chart implementation was inspired by +[the great d3 choropleth example](http://bl.ocks.org/4060606). + +Examples: +- [US Venture Capital Landscape 2011](http://dc-js.github.com/dc.js/vc/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a choropleth chart under '#us-chart' element using the default global chart group +var chart1 = dc.geoChoroplethChart('#us-chart'); +// create a choropleth chart under '#us-chart2' element using chart group A +var chart2 = dc.compositeChart('#us-chart2', 'chartGroupA'); +``` + + +#### geoChoroplethChart.overlayGeoJson(json, name, keyAccessor) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) +**mandatory** + +Use this function to insert a new GeoJson map layer. This function can be invoked multiple times +if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple +layers with the same name the new overlay will override the existing one. + +**Kind**: instance method of [geoChoroplethChart](#dc.geoChoroplethChart) +**See** + +- [GeoJSON](http://geojson.org/) +- [TopoJSON](https://github.com/topojson/topojson/wiki) +- [topojson.feature](https://github.com/topojson/topojson-1.x-api-reference/blob/master/API-Reference.md#wiki-feature) + + +| Param | Type | Description | +| --- | --- | --- | +| json | geoJson | a geojson feed | +| name | String | name of the layer | +| keyAccessor | function | accessor function used to extract 'key' from the GeoJson data. The key extracted by this function should match the keys returned by the crossfilter groups. | + +**Example** +```js +// insert a layer for rendering US states +chart.overlayGeoJson(statesJson.features, 'state', function(d) { + return d.properties.name; +}); +``` + + +#### geoChoroplethChart.projection([projection]) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) +Set custom geo projection function. See the available +[d3 geo projection functions](https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Projections.md). + +**Kind**: instance method of [geoChoroplethChart](#dc.geoChoroplethChart) +**See** + +- [d3.geo.projection](https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Projections.md) +- [Extended d3.geo.projection](https://github.com/d3/d3-geo-projection) + + +| Param | Type | Default | +| --- | --- | --- | +| [projection] | d3.projection | d3.geo.albersUsa() | + + + +#### geoChoroplethChart.geoJsons() ⇒ Array.<{name:String, data: Object, accessor: function()}> +Returns all GeoJson layers currently registered with this chart. The returned array is a +reference to this chart's internal data structure, so any modification to this array will also +modify this chart's internal registration. + +**Kind**: instance method of [geoChoroplethChart](#dc.geoChoroplethChart) + + +#### geoChoroplethChart.geoPath() ⇒ d3.geo.path +Returns the [d3.geo.path](https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Paths.md#path) object used to +render the projection and features. Can be useful for figuring out the bounding box of the +feature set and thus a way to calculate scale and translation for the projection. + +**Kind**: instance method of [geoChoroplethChart](#dc.geoChoroplethChart) +**See**: [d3.geo.path](https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Paths.md#path) + + +#### geoChoroplethChart.removeGeoJson(name) ⇒ [geoChoroplethChart](#dc.geoChoroplethChart) +Remove a GeoJson layer from this chart by name + +**Kind**: instance method of [geoChoroplethChart](#dc.geoChoroplethChart) + +| Param | Type | +| --- | --- | +| name | String | + + + +### dc.bubbleOverlay +**Kind**: static class of [dc](#dc) +**Mixes**: [bubbleMixin](#dc.bubbleMixin), [baseMixin](#dc.baseMixin) + +* [.bubbleOverlay](#dc.bubbleOverlay) + * [new bubbleOverlay(parent, [chartGroup])](#new_dc.bubbleOverlay_new) + * [.svg([imageElement])](#dc.bubbleOverlay+svg) ⇒ [bubbleOverlay](#dc.bubbleOverlay) + * [.point(name, x, y)](#dc.bubbleOverlay+point) ⇒ [bubbleOverlay](#dc.bubbleOverlay) + + + +#### new bubbleOverlay(parent, [chartGroup]) +The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay +chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the +typical x and y positioning while retaining the capability to visualize data using bubble radius +and coloring. + +Examples: +- [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group +var bubbleChart1 = dc.bubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg')); +// create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A +var bubbleChart2 = dc.compositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg')); +``` + + +#### bubbleOverlay.svg([imageElement]) ⇒ [bubbleOverlay](#dc.bubbleOverlay) +**mandatory** + +Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg +element; therefore the bubble overlay chart will not work if this function is not invoked. If the +underlying image is a bitmap, then an empty svg will need to be created on top of the image. + +**Kind**: instance method of [bubbleOverlay](#dc.bubbleOverlay) + +| Param | Type | +| --- | --- | +| [imageElement] | SVGElement \| d3.selection | + +**Example** +```js +// set up underlying svg element +chart.svg(d3.select('#chart svg')); +``` + + +#### bubbleOverlay.point(name, x, y) ⇒ [bubbleOverlay](#dc.bubbleOverlay) +**mandatory** + +Set up a data point on the overlay. The name of a data point should match a specific 'key' among +data groups generated using keyAccessor. If a match is found (point name <-> data group key) +then a bubble will be generated at the position specified by the function. x and y +value specified here are relative to the underlying svg. + +**Kind**: instance method of [bubbleOverlay](#dc.bubbleOverlay) + +| Param | Type | +| --- | --- | +| name | String | +| x | Number | +| y | Number | + + + +### dc.rowChart +**Kind**: static class of [dc](#dc) +**Mixes**: [capMixin](#dc.capMixin), [marginMixin](#dc.marginMixin), [colorMixin](#dc.colorMixin), [baseMixin](#dc.baseMixin) + +* [.rowChart](#dc.rowChart) + * [new rowChart(parent, [chartGroup])](#new_dc.rowChart_new) + * [.x([scale])](#dc.rowChart+x) ⇒ d3.scale \| [rowChart](#dc.rowChart) + * [.renderTitleLabel([renderTitleLabel])](#dc.rowChart+renderTitleLabel) ⇒ Boolean \| [rowChart](#dc.rowChart) + * [.xAxis()](#dc.rowChart+xAxis) ⇒ d3.svg.axis + * [.fixedBarHeight([fixedBarHeight])](#dc.rowChart+fixedBarHeight) ⇒ Boolean \| Number \| [rowChart](#dc.rowChart) + * [.gap([gap])](#dc.rowChart+gap) ⇒ Number \| [rowChart](#dc.rowChart) + * [.elasticX([elasticX])](#dc.rowChart+elasticX) ⇒ Boolean \| [rowChart](#dc.rowChart) + * [.labelOffsetX([labelOffsetX])](#dc.rowChart+labelOffsetX) ⇒ Number \| [rowChart](#dc.rowChart) + * [.labelOffsetY([labelOffsety])](#dc.rowChart+labelOffsetY) ⇒ Number \| [rowChart](#dc.rowChart) + * [.titleLabelOffsetX([titleLabelOffsetX])](#dc.rowChart+titleLabelOffsetX) ⇒ Number \| [rowChart](#dc.rowChart) + + + +#### new rowChart(parent, [chartGroup]) +Concrete row chart implementation. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a row chart under #chart-container1 element using the default global chart group +var chart1 = dc.rowChart('#chart-container1'); +// create a row chart under #chart-container2 element using chart group A +var chart2 = dc.rowChart('#chart-container2', 'chartGroupA'); +``` + + +#### rowChart.x([scale]) ⇒ d3.scale \| [rowChart](#dc.rowChart) +Gets or sets the x scale. The x scale can be any d3 +[quantitive scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md). + +**Kind**: instance method of [rowChart](#dc.rowChart) +**See**: [quantitive scale](https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md) + +| Param | Type | +| --- | --- | +| [scale] | d3.scale | + + + +#### rowChart.renderTitleLabel([renderTitleLabel]) ⇒ Boolean \| [rowChart](#dc.rowChart) +Turn on/off Title label rendering (values) using SVG style of text-anchor 'end'. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [renderTitleLabel] | Boolean | false | + + + +#### rowChart.xAxis() ⇒ d3.svg.axis +Get the x axis for the row chart instance. Note: not settable for row charts. +See the [d3 axis object](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) +documention for more information. + +**Kind**: instance method of [rowChart](#dc.rowChart) +**See**: [d3.svg.axis](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#axis) +**Example** +```js +// customize x axis tick format +chart.xAxis().tickFormat(function (v) {return v + '%';}); +// customize x axis tick values +chart.xAxis().tickValues([0, 100, 200, 300]); +``` + + +#### rowChart.fixedBarHeight([fixedBarHeight]) ⇒ Boolean \| Number \| [rowChart](#dc.rowChart) +Get or set the fixed bar height. Default is [false] which will auto-scale bars. +For example, if you want to fix the height for a specific number of bars (useful in TopN charts) +you could fix height as follows (where count = total number of bars in your TopN and gap is +your vertical gap space). + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [fixedBarHeight] | Boolean \| Number | false | + +**Example** +```js +chart.fixedBarHeight( chartheight - (count + 1) * gap / count); +``` + + +#### rowChart.gap([gap]) ⇒ Number \| [rowChart](#dc.rowChart) +Get or set the vertical gap space between rows on a particular row chart instance. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [gap] | Number | 5 | + + + +#### rowChart.elasticX([elasticX]) ⇒ Boolean \| [rowChart](#dc.rowChart) +Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescle to auto-fit the +data range when filtered. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | +| --- | --- | +| [elasticX] | Boolean | + + + +#### rowChart.labelOffsetX([labelOffsetX]) ⇒ Number \| [rowChart](#dc.rowChart) +Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [labelOffsetX] | Number | 10 | + + + +#### rowChart.labelOffsetY([labelOffsety]) ⇒ Number \| [rowChart](#dc.rowChart) +Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [labelOffsety] | Number | 15 | + + + +#### rowChart.titleLabelOffsetX([titleLabelOffsetX]) ⇒ Number \| [rowChart](#dc.rowChart) +Get of set the x offset (horizontal space between right edge of row and right edge or text. + +**Kind**: instance method of [rowChart](#dc.rowChart) + +| Param | Type | Default | +| --- | --- | --- | +| [titleLabelOffsetX] | Number | 2 | + + + +### dc.legend +**Kind**: static class of [dc](#dc) + +* [.legend](#dc.legend) + * [new legend()](#new_dc.legend_new) + * [.x([x])](#dc.legend+x) ⇒ Number \| [legend](#dc.legend) + * [.y([y])](#dc.legend+y) ⇒ Number \| [legend](#dc.legend) + * [.gap([gap])](#dc.legend+gap) ⇒ Number \| [legend](#dc.legend) + * [.itemHeight([itemHeight])](#dc.legend+itemHeight) ⇒ Number \| [legend](#dc.legend) + * [.horizontal([horizontal])](#dc.legend+horizontal) ⇒ Boolean \| [legend](#dc.legend) + * [.legendWidth([legendWidth])](#dc.legend+legendWidth) ⇒ Number \| [legend](#dc.legend) + * [.itemWidth([itemWidth])](#dc.legend+itemWidth) ⇒ Number \| [legend](#dc.legend) + * [.autoItemWidth([autoItemWidth])](#dc.legend+autoItemWidth) ⇒ Boolean \| [legend](#dc.legend) + * [.legendText([legendText])](#dc.legend+legendText) ⇒ function \| [legend](#dc.legend) + * [.maxItems([maxItems])](#dc.legend+maxItems) ⇒ [legend](#dc.legend) + + + +#### new legend() +Legend is a attachable widget that can be added to other dc charts to render horizontal legend +labels. + +Examples: +- [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) +- [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) + +**Example** +```js +chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) +``` + + +#### legend.x([x]) ⇒ Number \| [legend](#dc.legend) +Set or get x coordinate for legend widget. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [x] | Number | 0 | + + + +#### legend.y([y]) ⇒ Number \| [legend](#dc.legend) +Set or get y coordinate for legend widget. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [y] | Number | 0 | + + + +#### legend.gap([gap]) ⇒ Number \| [legend](#dc.legend) +Set or get gap between legend items. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [gap] | Number | 5 | + + + +#### legend.itemHeight([itemHeight]) ⇒ Number \| [legend](#dc.legend) +Set or get legend item height. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [itemHeight] | Number | 12 | + + + +#### legend.horizontal([horizontal]) ⇒ Boolean \| [legend](#dc.legend) +Position legend horizontally instead of vertically. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [horizontal] | Boolean | false | + + + +#### legend.legendWidth([legendWidth]) ⇒ Number \| [legend](#dc.legend) +Maximum width for horizontal legend. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [legendWidth] | Number | 500 | + + + +#### legend.itemWidth([itemWidth]) ⇒ Number \| [legend](#dc.legend) +Legend item width for horizontal legend. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [itemWidth] | Number | 70 | + + + +#### legend.autoItemWidth([autoItemWidth]) ⇒ Boolean \| [legend](#dc.legend) +Turn automatic width for legend items on or off. If true, [itemWidth](#dc.legend+itemWidth) is ignored. +This setting takes into account the [gap](#dc.legend+gap). + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | Default | +| --- | --- | --- | +| [autoItemWidth] | Boolean | false | + + + +#### legend.legendText([legendText]) ⇒ function \| [legend](#dc.legend) +Set or get the legend text function. The legend widget uses this function to render the legend +text for each item. If no function is specified the legend widget will display the names +associated with each group. + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | +| --- | --- | +| [legendText] | function | + +**Example** +```js +// default legendText +legend.legendText(dc.pluck('name')) + +// create numbered legend items +chart.legend(dc.legend().legendText(function(d, i) { return i + '. ' + d.name; })) + +// create legend displaying group counts +chart.legend(dc.legend().legendText(function(d) { return d.name + ': ' d.data; })) +``` + + +#### legend.maxItems([maxItems]) ⇒ [legend](#dc.legend) +Maximum number of legend items to display + +**Kind**: instance method of [legend](#dc.legend) + +| Param | Type | +| --- | --- | +| [maxItems] | Number | + + + +### dc.scatterPlot +**Kind**: static class of [dc](#dc) +**Mixes**: [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.scatterPlot](#dc.scatterPlot) + * [new scatterPlot(parent, [chartGroup])](#new_dc.scatterPlot_new) + * [.emptyColor](#dc.scatterPlot+emptyColor) ⇒ String \| [scatterPlot](#dc.scatterPlot) + * [.emptyOpacity](#dc.scatterPlot+emptyOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.nonemptyOpacity](#dc.scatterPlot+nonemptyOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.existenceAccessor([accessor])](#dc.scatterPlot+existenceAccessor) ⇒ function \| [scatterPlot](#dc.scatterPlot) + * [.symbol([type])](#dc.scatterPlot+symbol) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) + * [.customSymbol([customSymbol])](#dc.scatterPlot+customSymbol) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) + * [.symbolSize([symbolSize])](#dc.scatterPlot+symbolSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.highlightedSize([highlightedSize])](#dc.scatterPlot+highlightedSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedSize([excludedSize])](#dc.scatterPlot+excludedSize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedColor([excludedColor])](#dc.scatterPlot+excludedColor) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.excludedOpacity([excludedOpacity])](#dc.scatterPlot+excludedOpacity) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + * [.emptySize([emptySize])](#dc.scatterPlot+emptySize) ⇒ Number \| [scatterPlot](#dc.scatterPlot) + + + +#### new scatterPlot(parent, [chartGroup]) +A scatter plot chart + +Examples: +- [Scatter Chart](http://dc-js.github.io/dc.js/examples/scatter.html) +- [Multi-Scatter Chart](http://dc-js.github.io/dc.js/examples/multi-scatter.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a scatter plot under #chart-container1 element using the default global chart group +var chart1 = dc.scatterPlot('#chart-container1'); +// create a scatter plot under #chart-container2 element using chart group A +var chart2 = dc.scatterPlot('#chart-container2', 'chartGroupA'); +// create a sub-chart under a composite parent chart +var chart3 = dc.scatterPlot(compositeChart); +``` + + +#### scatterPlot.emptyColor ⇒ String \| [scatterPlot](#dc.scatterPlot) +Set or get color for symbols when the group is empty. If null, just use the +[colorMixin.colors](#dc.colorMixin+colors) color scale zero value. + +**Kind**: instance property of [scatterPlot](#dc.scatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [emptyColor] | String | | + + + +#### scatterPlot.emptyOpacity ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get opacity for symbols when the group is empty. + +**Kind**: instance property of [scatterPlot](#dc.scatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [emptyOpacity] | Number | 0 | + + + +#### scatterPlot.nonemptyOpacity ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get opacity for symbols when the group is not empty. + +**Kind**: instance property of [scatterPlot](#dc.scatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [nonemptyOpacity] | Number | 1 | + + + +#### scatterPlot.existenceAccessor([accessor]) ⇒ function \| [scatterPlot](#dc.scatterPlot) +Get or set the existence accessor. If a point exists, it is drawn with +[symbolSize](#dc.scatterPlot+symbolSize) radius and +opacity 1; if it does not exist, it is drawn with +[emptySize](#dc.scatterPlot+emptySize) radius and opacity 0. By default, +the existence accessor checks if the reduced value is truthy. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See** + +- [symbolSize](#dc.scatterPlot+symbolSize) +- [emptySize](#dc.scatterPlot+emptySize) + + +| Param | Type | +| --- | --- | +| [accessor] | function | + +**Example** +```js +// default accessor +chart.existenceAccessor(function (d) { return d.value; }); +``` + + +#### scatterPlot.symbol([type]) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) +Get or set the symbol type used for each point. By default the symbol is a circle. +Type can be a constant or an accessor. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See**: [d3.svg.symbol.type](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_type) + +| Param | Type | Default | +| --- | --- | --- | +| [type] | String \| function | 'circle' | + +**Example** +```js +// Circle type +chart.symbol('circle'); +// Square type +chart.symbol('square'); +``` + + +#### scatterPlot.customSymbol([customSymbol]) ⇒ String \| function \| [scatterPlot](#dc.scatterPlot) +Get or set the symbol generator. By default `dc.scatterPlot` will use +[d3.svg.symbol()](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol) +to generate symbols. `dc.scatterPlot` will set the +[size accessor](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_size) +on the symbol generator. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See** + +- [d3.svg.symbol](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol) +- [Create additional D3.js symbols](https://stackoverflow.com/questions/25332120/create-additional-d3-js-symbols) + + +| Param | Type | Default | +| --- | --- | --- | +| [customSymbol] | String \| function | d3.svg.symbol() | + + + +#### scatterPlot.symbolSize([symbolSize]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get radius for symbols. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See**: [d3.svg.symbol.size](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [symbolSize] | Number | 3 | + + + +#### scatterPlot.highlightedSize([highlightedSize]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get radius for highlighted symbols. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See**: [d3.svg.symbol.size](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [highlightedSize] | Number | 5 | + + + +#### scatterPlot.excludedSize([excludedSize]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get size for symbols excluded from this chart's filter. If null, no +special size is applied for symbols based on their filter status. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See**: [d3.svg.symbol.size](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedSize] | Number | | + + + +#### scatterPlot.excludedColor([excludedColor]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get color for symbols excluded from this chart's filter. If null, no +special color is applied for symbols based on their filter status. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedColor] | Number | | + + + +#### scatterPlot.excludedOpacity([excludedOpacity]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get opacity for symbols excluded from this chart's filter. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [excludedOpacity] | Number | 1.0 | + + + +#### scatterPlot.emptySize([emptySize]) ⇒ Number \| [scatterPlot](#dc.scatterPlot) +Set or get radius for symbols when the group is empty. + +**Kind**: instance method of [scatterPlot](#dc.scatterPlot) +**See**: [d3.svg.symbol.size](https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#symbol_size) + +| Param | Type | Default | +| --- | --- | --- | +| [emptySize] | Number | 0 | + + + +### dc.numberDisplay +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.numberDisplay](#dc.numberDisplay) + * [new numberDisplay(parent, [chartGroup])](#new_dc.numberDisplay_new) + * [.html([html])](#dc.numberDisplay+html) ⇒ Object \| [numberDisplay](#dc.numberDisplay) + * [.value()](#dc.numberDisplay+value) ⇒ Number + * [.formatNumber([formatter])](#dc.numberDisplay+formatNumber) ⇒ function \| [numberDisplay](#dc.numberDisplay) + + + +#### new numberDisplay(parent, [chartGroup]) +A display of a single numeric value. +Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and +a valueAccessor that returns a single value. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a number display under #chart-container1 element using the default global chart group +var display1 = dc.numberDisplay('#chart-container1'); +``` + + +#### numberDisplay.html([html]) ⇒ Object \| [numberDisplay](#dc.numberDisplay) +Gets or sets an optional object specifying HTML templates to use depending on the number +displayed. The text `%number` will be replaced with the current value. +- one: HTML template to use if the number is 1 +- zero: HTML template to use if the number is 0 +- some: HTML template to use otherwise + +**Kind**: instance method of [numberDisplay](#dc.numberDisplay) + +| Param | Type | Default | +| --- | --- | --- | +| [html] | Object | {one: '', some: '', none: ''} | + +**Example** +```js +numberWidget.html({ + one:'%number record', + some:'%number records', + none:'no records'}) +``` + + +#### numberDisplay.value() ⇒ Number +Calculate and return the underlying value of the display. + +**Kind**: instance method of [numberDisplay](#dc.numberDisplay) + + +#### numberDisplay.formatNumber([formatter]) ⇒ function \| [numberDisplay](#dc.numberDisplay) +Get or set a function to format the value for the display. + +**Kind**: instance method of [numberDisplay](#dc.numberDisplay) +**See**: [d3.format](https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md) + +| Param | Type | Default | +| --- | --- | --- | +| [formatter] | function | d3.format('.2s') | + + + +### dc.heatMap +**Kind**: static class of [dc](#dc) +**Mixes**: [colorMixin](#dc.colorMixin), [marginMixin](#dc.marginMixin), [baseMixin](#dc.baseMixin) + +* [.heatMap](#dc.heatMap) + * [new heatMap(parent, [chartGroup])](#new_dc.heatMap_new) + * [.colsLabel([labelFunction])](#dc.heatMap+colsLabel) ⇒ function \| [heatMap](#dc.heatMap) + * [.rowsLabel([labelFunction])](#dc.heatMap+rowsLabel) ⇒ function \| [heatMap](#dc.heatMap) + * [.rows([rows])](#dc.heatMap+rows) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) + * [.cols([cols])](#dc.heatMap+cols) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) + * [.boxOnClick([handler])](#dc.heatMap+boxOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.xAxisOnClick([handler])](#dc.heatMap+xAxisOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.yAxisOnClick([handler])](#dc.heatMap+yAxisOnClick) ⇒ function \| [heatMap](#dc.heatMap) + * [.xBorderRadius([xBorderRadius])](#dc.heatMap+xBorderRadius) ⇒ Number \| [heatMap](#dc.heatMap) + * [.yBorderRadius([yBorderRadius])](#dc.heatMap+yBorderRadius) ⇒ Number \| [heatMap](#dc.heatMap) + + + +#### new heatMap(parent, [chartGroup]) +A heat map is matrix that represents the values of two dimensions of data using colors. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a heat map under #chart-container1 element using the default global chart group +var heatMap1 = dc.heatMap('#chart-container1'); +// create a heat map under #chart-container2 element using chart group A +var heatMap2 = dc.heatMap('#chart-container2', 'chartGroupA'); +``` + + +#### heatMap.colsLabel([labelFunction]) ⇒ function \| [heatMap](#dc.heatMap) +Set or get the column label function. The chart class uses this function to render +column labels on the X axis. It is passed the column name. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [labelFunction] | function | function(d) { return d; } | + +**Example** +```js +// the default label function just returns the name +chart.colsLabel(function(d) { return d; }); +``` + + +#### heatMap.rowsLabel([labelFunction]) ⇒ function \| [heatMap](#dc.heatMap) +Set or get the row label function. The chart class uses this function to render +row labels on the Y axis. It is passed the row name. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [labelFunction] | function | function(d) { return d; } | + +**Example** +```js +// the default label function just returns the name +chart.rowsLabel(function(d) { return d; }); +``` + + +#### heatMap.rows([rows]) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) +Gets or sets the values used to create the rows of the heatmap, as an array. By default, all +the values will be fetched from the data using the value accessor. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | +| --- | --- | +| [rows] | Array.<(String\|Number)> | + + + +#### heatMap.cols([cols]) ⇒ Array.<(String\|Number)> \| [heatMap](#dc.heatMap) +Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all +the values will be fetched from the data using the key accessor. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | +| --- | --- | +| [cols] | Array.<(String\|Number)> | + + + +#### heatMap.boxOnClick([handler]) ⇒ function \| [heatMap](#dc.heatMap) +Gets or sets the handler that fires when an individual cell is clicked in the heatmap. +By default, filtering of the cell will be toggled. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + +**Example** +```js +// default box on click handler +chart.boxOnClick(function (d) { + var filter = d.key; + dc.events.trigger(function () { + _chart.filter(filter); + _chart.redrawGroup(); + }); +}); +``` + + +#### heatMap.xAxisOnClick([handler]) ⇒ function \| [heatMap](#dc.heatMap) +Gets or sets the handler that fires when a column tick is clicked in the x axis. +By default, if any cells in the column are unselected, the whole column will be selected, +otherwise the whole column will be unselected. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + + + +#### heatMap.yAxisOnClick([handler]) ⇒ function \| [heatMap](#dc.heatMap) +Gets or sets the handler that fires when a row tick is clicked in the y axis. +By default, if any cells in the row are unselected, the whole row will be selected, +otherwise the whole row will be unselected. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | +| --- | --- | +| [handler] | function | + + + +#### heatMap.xBorderRadius([xBorderRadius]) ⇒ Number \| [heatMap](#dc.heatMap) +Gets or sets the X border radius. Set to 0 to get full rectangles. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [xBorderRadius] | Number | 6.75 | + + + +#### heatMap.yBorderRadius([yBorderRadius]) ⇒ Number \| [heatMap](#dc.heatMap) +Gets or sets the Y border radius. Set to 0 to get full rectangles. + +**Kind**: instance method of [heatMap](#dc.heatMap) + +| Param | Type | Default | +| --- | --- | --- | +| [yBorderRadius] | Number | 6.75 | + + + +### dc.boxPlot +**Kind**: static class of [dc](#dc) +**Mixes**: [coordinateGridMixin](#dc.coordinateGridMixin) + +* [.boxPlot](#dc.boxPlot) + * [new boxPlot(parent, [chartGroup])](#new_dc.boxPlot_new) + * [.boxPadding([padding])](#dc.boxPlot+boxPadding) ⇒ Number \| [boxPlot](#dc.boxPlot) + * [.outerPadding([padding])](#dc.boxPlot+outerPadding) ⇒ Number \| [boxPlot](#dc.boxPlot) + * [.boxWidth([boxWidth])](#dc.boxPlot+boxWidth) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) + * [.tickFormat([tickFormat])](#dc.boxPlot+tickFormat) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) + + + +#### new boxPlot(parent, [chartGroup]) +A box plot is a chart that depicts numerical data via their quartile ranges. + +Examples: +- [Box plot time example](http://dc-js.github.io/dc.js/examples/box-plot-time.html) +- [Box plot example](http://dc-js.github.io/dc.js/examples/box-plot.html) + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection | Any valid [d3 single selector](https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +// create a box plot under #chart-container1 element using the default global chart group +var boxPlot1 = dc.boxPlot('#chart-container1'); +// create a box plot under #chart-container2 element using chart group A +var boxPlot2 = dc.boxPlot('#chart-container2', 'chartGroupA'); +``` + + +#### boxPlot.boxPadding([padding]) ⇒ Number \| [boxPlot](#dc.boxPlot) +Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1. +See the [d3 docs](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#ordinal_rangeBands) +for a visual description of how the padding is applied. + +**Kind**: instance method of [boxPlot](#dc.boxPlot) +**See**: [d3.scale.ordinal.rangeBands](https://github.com/d3/d3-3.x-api-reference/blob/master/Ordinal-Scales.md#ordinal_rangeBands) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number | 0.8 | + + + +#### boxPlot.outerPadding([padding]) ⇒ Number \| [boxPlot](#dc.boxPlot) +Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts +or on charts with a custom [.boxWidth](#dc.boxPlot+boxWidth). Will pad the width by +`padding * barWidth` on each side of the chart. + +**Kind**: instance method of [boxPlot](#dc.boxPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number | 0.5 | + + + +#### boxPlot.boxWidth([boxWidth]) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) +Get or set the numerical width of the boxplot box. The width may also be a function taking as +parameters the chart width excluding the right and left margins, as well as the number of x +units. + +**Kind**: instance method of [boxPlot](#dc.boxPlot) + +| Param | Type | Default | +| --- | --- | --- | +| [boxWidth] | Number \| function | 0.5 | + +**Example** +```js +// Using numerical parameter +chart.boxWidth(10); +// Using function +chart.boxWidth((innerChartWidth, xUnits) { ... }); +``` + + +#### boxPlot.tickFormat([tickFormat]) ⇒ Number \| function \| [boxPlot](#dc.boxPlot) +Set the numerical format of the boxplot median, whiskers and quartile labels. Defaults to +integer formatting. + +**Kind**: instance method of [boxPlot](#dc.boxPlot) + +| Param | Type | +| --- | --- | +| [tickFormat] | function | + +**Example** +```js +// format ticks to 2 decimal places +chart.tickFormat(d3.format('.2f')); +``` + + +### dc.selectMenu +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.selectMenu](#dc.selectMenu) + * [new selectMenu(parent, [chartGroup])](#new_dc.selectMenu_new) + * [.order](#dc.selectMenu+order) + * [.promptText](#dc.selectMenu+promptText) + * [.filterDisplayed](#dc.selectMenu+filterDisplayed) + * [.multiple](#dc.selectMenu+multiple) + * [.promptValue](#dc.selectMenu+promptValue) + * [.numberItems](#dc.selectMenu+numberItems) + + + +#### new selectMenu(parent, [chartGroup]) +The select menu is a simple widget designed to filter a dimension by selecting an option from +an HTML `` menu. The menu can be optionally turned into a multiselect. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this widget should be placed in. Interaction with the widget will only trigger events and redraws within its group. | + +**Example** +```js +// create a select menu under #select-container using the default global chart group +var select = dc.selectMenu('#select-container') + .dimension(states) + .group(stateGroup); +// the option text can be set via the title() function +// by default the option text is '`key`: `value`' +select.title(function (d){ + return 'STATE: ' + d.key; +}) +``` + + +#### selectMenu.order([order]) ⇒ function \| [selectMenu](#dc.selectMenu) +Get or set the function that controls the ordering of option tags in the +select menu. By default options are ordered by the group key in ascending +order. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | +| --- | --- | +| [order] | function | + +**Example** +```js +// order by the group's value +chart.order(function (a,b) { + return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; +}); +``` + + +#### selectMenu.promptText([promptText]) ⇒ String \| [selectMenu](#dc.selectMenu) +Get or set the text displayed in the options used to prompt selection. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptText] | String | 'Select all' | + +**Example** +```js +chart.promptText('All states'); +``` + + +#### selectMenu.filterDisplayed([filterDisplayed]) ⇒ function \| [selectMenu](#dc.selectMenu) +Get or set the function that filters option tags prior to display. By default options +with a value of < 1 are not displayed. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | +| --- | --- | +| [filterDisplayed] | function | + +**Example** +```js +// display all options override the `filterDisplayed` function: +chart.filterDisplayed(function () { + return true; +}); +``` + + +#### selectMenu.multiple([multiple]) ⇒ boolean \| [selectMenu](#dc.selectMenu) +Controls the type of select menu. Setting it to true converts the underlying +HTML tag into a multiple select. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [multiple] | boolean | false | + +**Example** +```js +chart.multiple(true); +``` + + +#### selectMenu.promptValue([promptValue]) ⇒ \* \| [selectMenu](#dc.selectMenu) +Controls the default value to be used for +[dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) +when only the prompt value is selected. If `null` (the default), no filtering will occur when +just the prompt is selected. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptValue] | \* | | + + + +#### selectMenu.numberItems([numberVisible]) ⇒ number \| [selectMenu](#dc.selectMenu) +Controls the number of items to show in the select menu, when `.multiple()` is true. This +controls the [`size` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Attributes) of +the `select` element. If `null` (the default), uses the browser's default height. + +**Kind**: instance method of [selectMenu](#dc.selectMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [numberVisible] | number | | + +**Example** +```js +chart.numberVisible(10); +``` + + +### dc.textFilterWidget +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.textFilterWidget](#dc.textFilterWidget) + * [new textFilterWidget(parent, [chartGroup])](#new_dc.textFilterWidget_new) + * [.normalize](#dc.textFilterWidget+normalize) ⇒ [textFilterWidget](#dc.textFilterWidget) \| function + * [.placeHolder](#dc.textFilterWidget+placeHolder) ⇒ [textFilterWidget](#dc.textFilterWidget) \| string + * [.filterFunctionFactory](#dc.textFilterWidget+filterFunctionFactory) ⇒ [textFilterWidget](#dc.textFilterWidget) \| function + + + +#### new textFilterWidget(parent, [chartGroup]) +Text Filter Widget + +The text filter widget is a simple widget designed to display an input field allowing to filter +data that matches the text typed. +As opposed to the other charts, this doesn't display any result and doesn't update its display, +it's just to input an filter other charts. + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/d3/d3-selection/blob/master/README.md#select) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this chart instance should be placed in. Interaction with a chart will only trigger events and redraws within the chart's group. | + +**Example** +```js +var data = [{"firstName":"John","lastName":"Coltrane"}{"firstName":"Miles",lastName:"Davis"}] +var ndx = crossfilter(data); +var dimension = ndx.dimension(function(d) { + return d.lastName.toLowerCase() + ' ' + d.firstName.toLowerCase(); +}); + +dc.textFilterWidget('#search') + .dimension(dimension); + // you don't need the group() function +``` + + +#### textFilterWidget.normalize ⇒ [textFilterWidget](#dc.textFilterWidget) \| function +This function will be called on values before calling the filter function. + +**Kind**: instance property of [textFilterWidget](#dc.textFilterWidget) + +| Param | Type | +| --- | --- | +| [normalize] | function | + +**Example** +```js +// This is the default +chart.normalize(function (s) { + return s.toLowerCase(); +}); +``` + + +#### textFilterWidget.placeHolder ⇒ [textFilterWidget](#dc.textFilterWidget) \| string +Placeholder text in the search box. + +**Kind**: instance property of [textFilterWidget](#dc.textFilterWidget) + +| Param | Type | Default | +| --- | --- | --- | +| [placeHolder] | function | 'search' | + +**Example** +```js +// This is the default +chart.placeHolder('type to filter'); +``` + + +#### textFilterWidget.filterFunctionFactory ⇒ [textFilterWidget](#dc.textFilterWidget) \| function +This function will be called with the search text, it needs to return a function that will be used to +filter the data. The default function checks presence of the search text. + +**Kind**: instance property of [textFilterWidget](#dc.textFilterWidget) + +| Param | Type | +| --- | --- | +| [filterFunctionFactory] | function | + +**Example** +```js +// This is the default +function (query) { + query = _normalize(query); + return function (d) { + return _normalize(d).indexOf(query) !== -1; + }; +}; +``` + + +### dc.cboxMenu +**Kind**: static class of [dc](#dc) +**Mixes**: [baseMixin](#dc.baseMixin) + +* [.cboxMenu](#dc.cboxMenu) + * [new cboxMenu(parent, [chartGroup])](#new_dc.cboxMenu_new) + * [.order([order])](#dc.cboxMenu+order) ⇒ function \| [cboxMenu](#dc.cboxMenu) + * [.promptText([promptText])](#dc.cboxMenu+promptText) ⇒ String \| [cboxMenu](#dc.cboxMenu) + * [.filterDisplayed([filterDisplayed])](#dc.cboxMenu+filterDisplayed) ⇒ function \| [cboxMenu](#dc.cboxMenu) + * [.multiple([multiple])](#dc.cboxMenu+multiple) ⇒ Boolean \| [cboxMenu](#dc.cboxMenu) + * [.promptValue([promptValue])](#dc.cboxMenu+promptValue) ⇒ \* \| [cboxMenu](#dc.cboxMenu) + + + +#### new cboxMenu(parent, [chartGroup]) +The cboxMenu is a simple widget designed to filter a dimension by +selecting option(s) from a set of HTML `` elements. The menu can be +made into a set of radio buttons (single select) or checkboxes (multiple). + + +| Param | Type | Description | +| --- | --- | --- | +| parent | String \| node \| d3.selection \| [compositeChart](#dc.compositeChart) | Any valid [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom block element such as a div; or a dom element or d3 selection. | +| [chartGroup] | String | The name of the chart group this widget should be placed in. Interaction with the widget will only trigger events and redraws within its group. | + +**Example** +```js +// create a cboxMenu under #cbox-container using the default global chart group +var cbox = dc.cboxMenu('#cbox-container') + .dimension(states) + .group(stateGroup); +// the option text can be set via the title() function +// by default the option text is '`key`: `value`' +cbox.title(function (d){ + return 'STATE: ' + d.key; +}) +``` + + +#### cboxMenu.order([order]) ⇒ function \| [cboxMenu](#dc.cboxMenu) +Get or set the function that controls the ordering of option tags in the +cbox menu. By default options are ordered by the group key in ascending +order. + +**Kind**: instance method of [cboxMenu](#dc.cboxMenu) + +| Param | Type | +| --- | --- | +| [order] | function | + +**Example** +```js +// order by the group's value +chart.order(function (a,b) { + return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; +}); +``` + + +#### cboxMenu.promptText([promptText]) ⇒ String \| [cboxMenu](#dc.cboxMenu) +Get or set the text displayed in the options used to prompt selection. + +**Kind**: instance method of [cboxMenu](#dc.cboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptText] | String | 'Select all' | + +**Example** +```js +chart.promptText('All states'); +``` + + +#### cboxMenu.filterDisplayed([filterDisplayed]) ⇒ function \| [cboxMenu](#dc.cboxMenu) +Get or set the function that filters options prior to display. By default options +with a value of < 1 are not displayed. + +**Kind**: instance method of [cboxMenu](#dc.cboxMenu) + +| Param | Type | +| --- | --- | +| [filterDisplayed] | function | + +**Example** +```js +// display all options override the `filterDisplayed` function: +chart.filterDisplayed(function () { + return true; +}); +``` + + +#### cboxMenu.multiple([multiple]) ⇒ Boolean \| [cboxMenu](#dc.cboxMenu) +Controls the type of input element. Setting it to true converts +the HTML `input` tags from radio buttons to checkboxes. + +**Kind**: instance method of [cboxMenu](#dc.cboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [multiple] | boolean | false | + +**Example** +```js +chart.multiple(true); +``` + + +#### cboxMenu.promptValue([promptValue]) ⇒ \* \| [cboxMenu](#dc.cboxMenu) +Controls the default value to be used for +[dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) +when only the prompt value is selected. If `null` (the default), no filtering will occur when +just the prompt is selected. + +**Kind**: instance method of [cboxMenu](#dc.cboxMenu) + +| Param | Type | Default | +| --- | --- | --- | +| [promptValue] | \* | | + + + +### dc.baseMixin ⇒ [baseMixin](#dc.baseMixin) +`dc.baseMixin` is an abstract functional object representing a basic `dc` chart object +for all chart and widget implementations. Methods from the [dc.baseMixin](#dc.baseMixin) are inherited +and available on all chart implementations in the `dc` library. + +**Kind**: static mixin of [dc](#dc) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.baseMixin](#dc.baseMixin) ⇒ [baseMixin](#dc.baseMixin) + * [.height([height])](#dc.baseMixin+height) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.width([width])](#dc.baseMixin+width) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.minWidth([minWidth])](#dc.baseMixin+minWidth) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.minHeight([minHeight])](#dc.baseMixin+minHeight) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.useViewBoxResizing([useViewBoxResizing])](#dc.baseMixin+useViewBoxResizing) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.dimension([dimension])](#dc.baseMixin+dimension) ⇒ crossfilter.dimension \| [baseMixin](#dc.baseMixin) + * [.data([callback])](#dc.baseMixin+data) ⇒ \* \| [baseMixin](#dc.baseMixin) + * [.group([group], [name])](#dc.baseMixin+group) ⇒ crossfilter.group \| [baseMixin](#dc.baseMixin) + * [.ordering([orderFunction])](#dc.baseMixin+ordering) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.filterAll()](#dc.baseMixin+filterAll) ⇒ [baseMixin](#dc.baseMixin) + * [.select(sel)](#dc.baseMixin+select) ⇒ d3.selection + * [.selectAll(sel)](#dc.baseMixin+selectAll) ⇒ d3.selection + * [.anchor([parent], [chartGroup])](#dc.baseMixin+anchor) ⇒ String \| node \| d3.selection \| [baseMixin](#dc.baseMixin) + * [.anchorName()](#dc.baseMixin+anchorName) ⇒ String + * [.root([rootElement])](#dc.baseMixin+root) ⇒ HTMLElement \| [baseMixin](#dc.baseMixin) + * [.svg([svgElement])](#dc.baseMixin+svg) ⇒ SVGElement \| d3.selection \| [baseMixin](#dc.baseMixin) + * [.resetSvg()](#dc.baseMixin+resetSvg) ⇒ SVGElement + * [.filterPrinter([filterPrinterFunction])](#dc.baseMixin+filterPrinter) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.controlsUseVisibility([controlsUseVisibility])](#dc.baseMixin+controlsUseVisibility) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.turnOnControls()](#dc.baseMixin+turnOnControls) ⇒ [baseMixin](#dc.baseMixin) + * [.turnOffControls()](#dc.baseMixin+turnOffControls) ⇒ [baseMixin](#dc.baseMixin) + * [.transitionDuration([duration])](#dc.baseMixin+transitionDuration) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.transitionDelay([delay])](#dc.baseMixin+transitionDelay) ⇒ Number \| [baseMixin](#dc.baseMixin) + * [.render()](#dc.baseMixin+render) ⇒ [baseMixin](#dc.baseMixin) + * [.redraw()](#dc.baseMixin+redraw) ⇒ [baseMixin](#dc.baseMixin) + * [.commitHandler(commitHandler)](#dc.baseMixin+commitHandler) ⇒ [baseMixin](#dc.baseMixin) + * [.redrawGroup()](#dc.baseMixin+redrawGroup) ⇒ [baseMixin](#dc.baseMixin) + * [.renderGroup()](#dc.baseMixin+renderGroup) ⇒ [baseMixin](#dc.baseMixin) + * [.hasFilterHandler([hasFilterHandler])](#dc.baseMixin+hasFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.hasFilter([filter])](#dc.baseMixin+hasFilter) ⇒ Boolean + * [.removeFilterHandler([removeFilterHandler])](#dc.baseMixin+removeFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.addFilterHandler([addFilterHandler])](#dc.baseMixin+addFilterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.resetFilterHandler([resetFilterHandler])](#dc.baseMixin+resetFilterHandler) ⇒ [baseMixin](#dc.baseMixin) + * [.replaceFilter([filter])](#dc.baseMixin+replaceFilter) ⇒ [baseMixin](#dc.baseMixin) + * [.filter([filter])](#dc.baseMixin+filter) ⇒ [baseMixin](#dc.baseMixin) + * [.filters()](#dc.baseMixin+filters) ⇒ Array.<\*> + * [.onClick(datum)](#dc.baseMixin+onClick) ⇒ undefined + * [.filterHandler([filterHandler])](#dc.baseMixin+filterHandler) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.keyAccessor([keyAccessor])](#dc.baseMixin+keyAccessor) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.valueAccessor([valueAccessor])](#dc.baseMixin+valueAccessor) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.label([labelFunction], [enableLabels])](#dc.baseMixin+label) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.renderLabel([renderLabel])](#dc.baseMixin+renderLabel) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * [.title([titleFunction])](#dc.baseMixin+title) ⇒ function \| [baseMixin](#dc.baseMixin) + * [.renderTitle([renderTitle])](#dc.baseMixin+renderTitle) ⇒ Boolean \| [baseMixin](#dc.baseMixin) + * ~~[.renderlet(renderletFunction)](#dc.baseMixin+renderlet) ⇒ [baseMixin](#dc.baseMixin)~~ + * [.chartGroup([chartGroup])](#dc.baseMixin+chartGroup) ⇒ String \| [baseMixin](#dc.baseMixin) + * [.expireCache()](#dc.baseMixin+expireCache) ⇒ [baseMixin](#dc.baseMixin) + * [.legend([legend])](#dc.baseMixin+legend) ⇒ [legend](#dc.legend) \| [baseMixin](#dc.baseMixin) + * [.chartID()](#dc.baseMixin+chartID) ⇒ String + * [.options(opts)](#dc.baseMixin+options) ⇒ [baseMixin](#dc.baseMixin) + * [.on(event, listener)](#dc.baseMixin+on) ⇒ [baseMixin](#dc.baseMixin) + + + +#### baseMixin.height([height]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the height attribute of a chart. The height is applied to the SVGElement generated by +the chart when rendered (or re-rendered). If a value is given, then it will be used to calculate +the new height and the chart returned for method chaining. The value can either be a numeric, a +function, or falsy. If no value is specified then the value of the current height attribute will +be returned. + +By default, without an explicit height being given, the chart will select the width of its +anchor element. If that isn't possible it defaults to 200 (provided by the +[minHeight](#dc.baseMixin+minHeight) property). Setting the value falsy will return +the chart to the default behavior. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [minHeight](#dc.baseMixin+minHeight) + +| Param | Type | +| --- | --- | +| [height] | Number \| function | + +**Example** +```js +// Default height +chart.height(function (element) { + var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; + return (height && height > chart.minHeight()) ? height : chart.minHeight(); +}); + +chart.height(250); // Set the chart's height to 250px; +chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function +chart.height(null); // reset the height to the default auto calculation +``` + + +#### baseMixin.width([width]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the width attribute of a chart. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See** + +- [height](#dc.baseMixin+height) +- [minWidth](#dc.baseMixin+minWidth) + + +| Param | Type | +| --- | --- | +| [width] | Number \| function | + +**Example** +```js +// Default width +chart.width(function (element) { + var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; + return (width && width > chart.minWidth()) ? width : chart.minWidth(); +}); +``` + + +#### baseMixin.minWidth([minWidth]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the minimum width attribute of a chart. This only has effect when used with the default +[width](#dc.baseMixin+width) function. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [width](#dc.baseMixin+width) + +| Param | Type | Default | +| --- | --- | --- | +| [minWidth] | Number | 200 | + + + +#### baseMixin.minHeight([minHeight]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the minimum height attribute of a chart. This only has effect when used with the default +[height](#dc.baseMixin+height) function. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [height](#dc.baseMixin+height) + +| Param | Type | Default | +| --- | --- | --- | +| [minHeight] | Number | 200 | + + + +#### baseMixin.useViewBoxResizing([useViewBoxResizing]) ⇒ Boolean \| [baseMixin](#dc.baseMixin) +Turn on/off using the SVG +[`viewBox` attribute](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox). +When enabled, `viewBox` will be set on the svg root element instead of `width` and `height`. +Requires that the chart aspect ratio be defined using chart.width(w) and chart.height(h). + +This will maintain the aspect ratio while enabling the chart to resize responsively to the +space given to the chart using CSS. For example, the chart can use `width: 100%; height: +100%` or absolute positioning to resize to its parent div. + +Since the text will be sized as if the chart is drawn according to the width and height, and +will be resized if the chart is any other size, you need to set the chart width and height so +that the text looks good. In practice, 600x400 seems to work pretty well for most charts. + +You can see examples of this resizing strategy in the [Chart Resizing +Examples](http://dc-js.github.io/dc.js/resizing/); just add `?resize=viewbox` to any of the +one-chart examples to enable `useViewBoxResizing`. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [useViewBoxResizing] | Boolean | false | + + + +#### baseMixin.dimension([dimension]) ⇒ crossfilter.dimension \| [baseMixin](#dc.baseMixin) +**mandatory** + +Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid +[crossfilter dimension](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension) + +If a value is given, then it will be used as the new dimension. If no value is specified then +the current dimension will be returned. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [crossfilter.dimension](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension) + +| Param | Type | +| --- | --- | +| [dimension] | crossfilter.dimension | + +**Example** +```js +var index = crossfilter([]); +var dimension = index.dimension(dc.pluck('key')); +chart.dimension(dimension); +``` + + +#### baseMixin.data([callback]) ⇒ \* \| [baseMixin](#dc.baseMixin) +Set the data callback or retrieve the chart's data set. The data callback is passed the chart's +group and by default will return +[group.all](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all). +This behavior may be modified to, for instance, return only the top 5 groups. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [callback] | function | + +**Example** +```js +// Default data function +chart.data(function (group) { return group.all(); }); + +chart.data(function (group) { return group.top(5); }); +``` + + +#### baseMixin.group([group], [name]) ⇒ crossfilter.group \| [baseMixin](#dc.baseMixin) +**mandatory** + +Set or get the group attribute of a chart. In `dc` a group is a +[crossfilter group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce). +Usually the group should be created from the particular dimension associated with the same chart. If a value is +given, then it will be used as the new group. + +If no value specified then the current group will be returned. +If `name` is specified then it will be used to generate legend label. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [crossfilter.group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce) + +| Param | Type | +| --- | --- | +| [group] | crossfilter.group | +| [name] | String | + +**Example** +```js +var index = crossfilter([]); +var dimension = index.dimension(dc.pluck('key')); +chart.dimension(dimension); +chart.group(dimension.group().reduceSum()); +``` + + +#### baseMixin.ordering([orderFunction]) ⇒ function \| [baseMixin](#dc.baseMixin) +Get or set an accessor to order ordinal dimensions. The chart uses +[Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) +to sort elements; this accessor returns the value to order on. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [orderFunction] | function | + +**Example** +```js +// Default ordering accessor +_chart.ordering(dc.pluck('key')); +``` + + +#### baseMixin.filterAll() ⇒ [baseMixin](#dc.baseMixin) +Clear all filters associated with this chart. The same effect can be achieved by calling +[chart.filter(null)](#dc.baseMixin+filter). + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.select(sel) ⇒ d3.selection +Execute d3 single selection in the chart's scope using the given selector and return the d3 +selection. + +This function is **not chainable** since it does not return a chart instance; however the d3 +selection result can be chained to d3 function calls. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [d3.select](https://github.com/d3/d3-selection/blob/master/README.md#select) + +| Param | Type | Description | +| --- | --- | --- | +| sel | String | CSS selector string | + +**Example** +```js +// Has the same effect as d3.select('#chart-id').select(selector) +chart.select(selector) +``` + + +#### baseMixin.selectAll(sel) ⇒ d3.selection +Execute in scope d3 selectAll using the given selector and return d3 selection result. + +This function is **not chainable** since it does not return a chart instance; however the d3 +selection result can be chained to d3 function calls. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [d3.selectAll](https://github.com/d3/d3-selection/blob/master/README.md#selectAll) + +| Param | Type | Description | +| --- | --- | --- | +| sel | String | CSS selector string | + +**Example** +```js +// Has the same effect as d3.select('#chart-id').selectAll(selector) +chart.selectAll(selector) +``` + + +#### baseMixin.anchor([parent], [chartGroup]) ⇒ String \| node \| d3.selection \| [baseMixin](#dc.baseMixin) +Set the root SVGElement to either be an existing chart's root; or any valid [d3 single +selector](https://github.com/d3/d3-selection/blob/master/README.md#selecting-elements) specifying a dom +block element such as a div; or a dom element or d3 selection. Optionally registers the chart +within the chartGroup. This class is called internally on chart initialization, but be called +again to relocate the chart. However, it will orphan any previously created SVGElements. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [parent] | anchorChart \| anchorSelector \| anchorNode | +| [chartGroup] | String | + + + +#### baseMixin.anchorName() ⇒ String +Returns the DOM id for the chart's anchored location. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.root([rootElement]) ⇒ HTMLElement \| [baseMixin](#dc.baseMixin) +Returns the root element where a chart resides. Usually it will be the parent div element where +the SVGElement was created. You can also pass in a new root element however this is usually handled by +dc internally. Resetting the root element on a chart outside of dc internals may have +unexpected consequences. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) + +| Param | Type | +| --- | --- | +| [rootElement] | HTMLElement | + + + +#### baseMixin.svg([svgElement]) ⇒ SVGElement \| d3.selection \| [baseMixin](#dc.baseMixin) +Returns the top SVGElement for this specific chart. You can also pass in a new SVGElement, +however this is usually handled by dc internally. Resetting the SVGElement on a chart outside +of dc internals may have unexpected consequences. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) + +| Param | Type | +| --- | --- | +| [svgElement] | SVGElement \| d3.selection | + + + +#### baseMixin.resetSvg() ⇒ SVGElement +Remove the chart's SVGElements from the dom and recreate the container SVGElement. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) + + +#### baseMixin.filterPrinter([filterPrinterFunction]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the filter printer function. The filter printer function is used to generate human +friendly text for filter value(s) associated with the chart instance. The text will get shown +in the `.filter element; see [turnOnControls](#dc.baseMixin+turnOnControls). + +By default dc charts use a default filter printer [filters](#dc.printers.filters) +that provides simple printing support for both single value and ranged filters. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [filterPrinterFunction] | function | dc.printers.filters | + +**Example** +```js +// for a chart with an ordinal brush, print the filters in upper case +chart.filterPrinter(function(filters) { + return filters.map(function(f) { return f.toUpperCase(); }).join(', '); +}); +// for a chart with a range brush, print the filter as start and extent +chart.filterPrinter(function(filters) { + return 'start ' + dc.utils.printSingleValue(filters[0][0]) + + ' extent ' + dc.utils.printSingleValue(filters[0][1] - filters[0][0]); +}); +``` + + +#### baseMixin.controlsUseVisibility([controlsUseVisibility]) ⇒ Boolean \| [baseMixin](#dc.baseMixin) +If set, use the `visibility` attribute instead of the `display` attribute for showing/hiding +chart reset and filter controls, for less disruption to the layout. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [controlsUseVisibility] | Boolean | false | + + + +#### baseMixin.turnOnControls() ⇒ [baseMixin](#dc.baseMixin) +Turn on optional control elements within the root element. dc currently supports the +following html control elements. +* root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type +of control element is usually used to store a reset link to allow user to reset filter on a +certain chart. This element will be turned off automatically if the filter is cleared. +* root.selectAll('.filter') elements are turned on if the chart has an active filter. The text +content of this element is then replaced with the current filter value using the filter printer +function. This type of element will be turned off automatically if the filter is cleared. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.turnOffControls() ⇒ [baseMixin](#dc.baseMixin) +Turn off optional control elements within the root element. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [turnOnControls](#dc.baseMixin+turnOnControls) + + +#### baseMixin.transitionDuration([duration]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the animation transition duration (in milliseconds) for this chart instance. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [duration] | Number | 750 | + + + +#### baseMixin.transitionDelay([delay]) ⇒ Number \| [baseMixin](#dc.baseMixin) +Set or get the animation transition delay (in milliseconds) for this chart instance. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [delay] | Number | 0 | + + + +#### baseMixin.render() ⇒ [baseMixin](#dc.baseMixin) +Invoking this method will force the chart to re-render everything from scratch. Generally it +should only be used to render the chart for the first time on the page or if you want to make +sure everything is redrawn from scratch instead of relying on the default incremental redrawing +behaviour. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.redraw() ⇒ [baseMixin](#dc.baseMixin) +Calling redraw will cause the chart to re-render data changes incrementally. If there is no +change in the underlying data dimension then calling this method will have no effect on the +chart. Most chart interaction in dc will automatically trigger this method through internal +events (in particular [redrawAll](#dc.redrawAll)); therefore, you only need to +manually invoke this function if data is manipulated outside of dc's control (for example if +data is loaded in the background using +[crossfilter.add](https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add)). + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.commitHandler(commitHandler) ⇒ [baseMixin](#dc.baseMixin) +Gets/sets the commit handler. If the chart has a commit handler, the handler will be called when +the chart's filters have changed, in order to send the filter data asynchronously to a server. + +Unlike other functions in dc.js, the commit handler is asynchronous. It takes two arguments: +a flag indicating whether this is a render (true) or a redraw (false), and a callback to be +triggered once the commit is done. The callback has the standard node.js continuation signature +with error first and result second. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| commitHandler | function | + + + +#### baseMixin.redrawGroup() ⇒ [baseMixin](#dc.baseMixin) +Redraws all charts in the same group as this chart, typically in reaction to a filter +change. If the chart has a [commitHandler](dc.baseMixin.commitFilter), it will +be executed and waited for. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.renderGroup() ⇒ [baseMixin](#dc.baseMixin) +Renders all charts in the same group as this chart. If the chart has a +[commitHandler](dc.baseMixin.commitFilter), it will be executed and waited for + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.hasFilterHandler([hasFilterHandler]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the has-filter handler. The has-filter handler is a function that checks to see if +the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows +you to change the way filters are checked for and replaced. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [hasFilterHandler] | function | + +**Example** +```js +// default has-filter handler +chart.hasFilterHandler(function (filters, filter) { + if (filter === null || typeof(filter) === 'undefined') { + return filters.length > 0; + } + return filters.some(function (f) { + return filter <= f && filter >= f; + }); +}); + +// custom filter handler (no-op) +chart.hasFilterHandler(function(filters, filter) { + return false; +}); +``` + + +#### baseMixin.hasFilter([filter]) ⇒ Boolean +Check whether any active filter or a specific filter is associated with particular chart instance. +This function is **not chainable**. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [hasFilterHandler](#dc.baseMixin+hasFilterHandler) + +| Param | Type | +| --- | --- | +| [filter] | \* | + + + +#### baseMixin.removeFilterHandler([removeFilterHandler]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the remove filter handler. The remove filter handler is a function that removes a +filter from the chart's current filters. Using a custom remove filter handler allows you to +change how filters are removed or perform additional work when removing a filter, e.g. when +using a filter server other than crossfilter. + +The handler should return a new or modified array as the result. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [removeFilterHandler] | function | + +**Example** +```js +// default remove filter handler +chart.removeFilterHandler(function (filters, filter) { + for (var i = 0; i < filters.length; i++) { + if (filters[i] <= filter && filters[i] >= filter) { + filters.splice(i, 1); + break; + } + } + return filters; +}); + +// custom filter handler (no-op) +chart.removeFilterHandler(function(filters, filter) { + return filters; +}); +``` + + +#### baseMixin.addFilterHandler([addFilterHandler]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the add filter handler. The add filter handler is a function that adds a filter to +the chart's filter list. Using a custom add filter handler allows you to change the way filters +are added or perform additional work when adding a filter, e.g. when using a filter server other +than crossfilter. + +The handler should return a new or modified array as the result. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [addFilterHandler] | function | + +**Example** +```js +// default add filter handler +chart.addFilterHandler(function (filters, filter) { + filters.push(filter); + return filters; +}); + +// custom filter handler (no-op) +chart.addFilterHandler(function(filters, filter) { + return filters; +}); +``` + + +#### baseMixin.resetFilterHandler([resetFilterHandler]) ⇒ [baseMixin](#dc.baseMixin) +Set or get the reset filter handler. The reset filter handler is a function that resets the +chart's filter list by returning a new list. Using a custom reset filter handler allows you to +change the way filters are reset, or perform additional work when resetting the filters, +e.g. when using a filter server other than crossfilter. + +The handler should return a new or modified array as the result. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [resetFilterHandler] | function | + +**Example** +```js +// default remove filter handler +function (filters) { + return []; +} + +// custom filter handler (no-op) +chart.resetFilterHandler(function(filters) { + return filters; +}); +``` + + +#### baseMixin.replaceFilter([filter]) ⇒ [baseMixin](#dc.baseMixin) +Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)` +but more efficient because the filter is only applied once. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [filter] | \* | + + + +#### baseMixin.filter([filter]) ⇒ [baseMixin](#dc.baseMixin) +Filter the chart by the given parameter, or return the current filter if no input parameter +is given. + +The filter parameter can take one of these forms: +* A single value: the value will be toggled (added if it is not present in the current +filters, removed if it is present) +* An array containing a single array of values (`[[value,value,value]]`): each value is +toggled +* When appropriate for the chart, a [dc filter object](#dc.filters) such as + * [`dc.filters.RangedFilter`](#dc.filters.RangedFilter) for the +[coordinateGridMixin](#dc.coordinateGridMixin) charts + * [`dc.filters.TwoDimensionalFilter`](#dc.filters.TwoDimensionalFilter) for the +[heat map](#dc.heatMap) + * [`dc.filters.RangedTwoDimensionalFilter`](#dc.filters.RangedTwoDimensionalFilter) +for the [scatter plot](#dc.scatterPlot) +* `null`: the filter will be reset using the +[resetFilterHandler](#dc.baseMixin+resetFilterHandler) + +Note that this is always a toggle (even when it doesn't make sense for the filter type). If +you wish to replace the current filter, either call `chart.filter(null)` first - or it's more +efficient to call [`chart.replaceFilter(filter)`](#dc.baseMixin+replaceFilter) instead. + +Each toggle is executed by checking if the value is already present using the +[hasFilterHandler](#dc.baseMixin+hasFilterHandler); if it is not present, it is added +using the [addFilterHandler](#dc.baseMixin+addFilterHandler); if it is already present, +it is removed using the [removeFilterHandler](#dc.baseMixin+removeFilterHandler). + +Once the filters array has been updated, the filters are applied to the +crossfilter dimension, using the [filterHandler](#dc.baseMixin+filterHandler). + +Once you have set the filters, call [`chart.redrawGroup()`](#dc.baseMixin+redrawGroup) +(or [`dc.redrawAll()`](#dc.redrawAll)) to redraw the chart's group. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See** + +- [addFilterHandler](#dc.baseMixin+addFilterHandler) +- [removeFilterHandler](#dc.baseMixin+removeFilterHandler) +- [resetFilterHandler](#dc.baseMixin+resetFilterHandler) +- [filterHandler](#dc.baseMixin+filterHandler) + + +| Param | Type | +| --- | --- | +| [filter] | \* | + +**Example** +```js +// filter by a single string +chart.filter('Sunday'); +// filter by a single age +chart.filter(18); +// filter by a set of states +chart.filter([['MA', 'TX', 'ND', 'WA']]); +// filter by range -- note the use of dc.filters.RangedFilter, which is different +// from the syntax for filtering a crossfilter dimension directly, dimension.filter([15,20]) +chart.filter(dc.filters.RangedFilter(15,20)); +``` + + +#### baseMixin.filters() ⇒ Array.<\*> +Returns all current filters. This method does not perform defensive cloning of the internal +filter array before returning, therefore any modification of the returned array will effect the +chart's internal filter storage. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.onClick(datum) ⇒ undefined +This function is passed to d3 as the onClick handler for each chart. The default behavior is to +filter on the clicked datum (passed to the callback) and redraw the chart group. + +This function can be replaced in order to change the click behavior (but first look at + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| datum | \* | + +**Example** +```js +var oldHandler = chart.onClick; +chart.onClick = function(datum) { + // use datum. +``` + + +#### baseMixin.filterHandler([filterHandler]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the filter handler. The filter handler is a function that performs the filter action +on a specific dimension. Using a custom filter handler allows you to perform additional logic +before or after filtering. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [crossfilter.dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) + +| Param | Type | +| --- | --- | +| [filterHandler] | function | + +**Example** +```js +// the default filter handler handles all possible cases for the charts in dc.js +// you can replace it with something more specialized for your own chart +chart.filterHandler(function (dimension, filters) { + if (filters.length === 0) { + // the empty case (no filtering) + dimension.filter(null); + } else if (filters.length === 1 && !filters[0].isFiltered) { + // single value and not a function-based filter + dimension.filterExact(filters[0]); + } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { + // single range-based filter + dimension.filterRange(filters[0]); + } else { + // an array of values, or an array of filter objects + dimension.filterFunction(function (d) { + for (var i = 0; i < filters.length; i++) { + var filter = filters[i]; + if (filter.isFiltered && filter.isFiltered(d)) { + return true; + } else if (filter <= d && filter >= d) { + return true; + } + } + return false; + }); + } + return filters; +}); + +// custom filter handler +chart.filterHandler(function(dimension, filter){ + var newFilter = filter + 10; + dimension.filter(newFilter); + return newFilter; // set the actual filter value to the new value +}); +``` + + +#### baseMixin.keyAccessor([keyAccessor]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the key accessor function. The key accessor function is used to retrieve the key +value from the crossfilter group. Key values are used differently in different charts, for +example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [keyAccessor] | function | + +**Example** +```js +// default key accessor +chart.keyAccessor(function(d) { return d.key; }); +// custom key accessor for a multi-value crossfilter reduction +chart.keyAccessor(function(p) { return p.value.absGain; }); +``` + + +#### baseMixin.valueAccessor([valueAccessor]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the value accessor function. The value accessor function is used to retrieve the +value from the crossfilter group. Group values are used differently in different charts, for +example values correspond to slice sizes in a pie chart and y axis positions in a grid +coordinate chart. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [valueAccessor] | function | + +**Example** +```js +// default value accessor +chart.valueAccessor(function(d) { return d.value; }); +// custom value accessor for a multi-value crossfilter reduction +chart.valueAccessor(function(p) { return p.value.percentageGain; }); +``` + + +#### baseMixin.label([labelFunction], [enableLabels]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the label function. The chart class will use this function to render labels for each +child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every +chart supports the label function, for example line chart does not use this function +at all. By default, enables labels; pass false for the second parameter if this is not desired. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [labelFunction] | function | | +| [enableLabels] | Boolean | true | + +**Example** +```js +// default label function just return the key +chart.label(function(d) { return d.key; }); +// label function has access to the standard d3 data binding and can get quite complicated +chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; }); +``` + + +#### baseMixin.renderLabel([renderLabel]) ⇒ Boolean \| [baseMixin](#dc.baseMixin) +Turn on/off label rendering + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [renderLabel] | Boolean | false | + + + +#### baseMixin.title([titleFunction]) ⇒ function \| [baseMixin](#dc.baseMixin) +Set or get the title function. The chart class will use this function to render the SVGElement title +(usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice +in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function; +however in grid coordinate charts you need to turn off the brush in order to see titles, because +otherwise the brush layer will block tooltip triggering. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [titleFunction] | function | + +**Example** +```js +// default title function shows "key: value" +chart.title(function(d) { return d.key + ': ' + d.value; }); +// title function has access to the standard d3 data binding and can get quite complicated +chart.title(function(p) { + return p.key.getFullYear() + + '\n' + + 'Index Gain: ' + numberFormat(p.value.absGain) + '\n' + + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\n' + + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'; +}); +``` + + +#### baseMixin.renderTitle([renderTitle]) ⇒ Boolean \| [baseMixin](#dc.baseMixin) +Turn on/off title rendering, or return the state of the render title flag if no arguments are +given. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [renderTitle] | Boolean | true | + + + +#### ~~baseMixin.renderlet(renderletFunction) ⇒ [baseMixin](#dc.baseMixin)~~ +***Deprecated*** + +A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added +to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked +right after the chart finishes its transitions, giving you a way to modify the SVGElements. +Renderlet functions take the chart instance as the only input parameter and you can +use the dc API or use raw d3 to achieve pretty much any effect. + +Use [on](#dc.baseMixin+on) with a 'renderlet' prefix. +Generates a random key for the renderlet, which makes it hard to remove. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| renderletFunction | function | + +**Example** +```js +// do this instead of .renderlet(function(chart) { ... }) +chart.on("renderlet", function(chart){ + // mix of dc API and d3 manipulation + chart.select('g.y').style('display', 'none'); + // its a closure so you can also access other chart variable available in the closure scope + moveChart.filter(chart.filter()); +}); +``` + + +#### baseMixin.chartGroup([chartGroup]) ⇒ String \| [baseMixin](#dc.baseMixin) +Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn +together since it is expected they share the same underlying crossfilter data set. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [chartGroup] | String | + + + +#### baseMixin.expireCache() ⇒ [baseMixin](#dc.baseMixin) +Expire the internal chart cache. dc charts cache some data internally on a per chart basis to +speed up rendering and avoid unnecessary calculation; however it might be useful to clear the +cache if you have changed state which will affect rendering. For example, if you invoke +[crossfilter.add](https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add) +function or reset group or dimension after rendering, it is a good idea to +clear the cache to make sure charts are rendered properly. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.legend([legend]) ⇒ [legend](#dc.legend) \| [baseMixin](#dc.baseMixin) +Attach a dc.legend widget to this chart. The legend widget will automatically draw legend labels +based on the color setting and names associated with each group. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| [legend] | [legend](#dc.legend) | + +**Example** +```js +chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) +``` + + +#### baseMixin.chartID() ⇒ String +Returns the internal numeric ID of the chart. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + + +#### baseMixin.options(opts) ⇒ [baseMixin](#dc.baseMixin) +Set chart options using a configuration object. Each key in the object will cause the method of +the same name to be called with the value to set that attribute for the chart. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| opts | Object | + +**Example** +```js +chart.options({dimension: myDimension, group: myGroup}); +``` + + +#### baseMixin.on(event, listener) ⇒ [baseMixin](#dc.baseMixin) +All dc chart instance supports the following listeners. +Supports the following events: +* `renderlet` - This listener function will be invoked after transitions after redraw and render. Replaces the +deprecated [renderlet](#dc.baseMixin+renderlet) method. +* `pretransition` - Like `.on('renderlet', ...)` but the event is fired before transitions start. +* `preRender` - This listener function will be invoked before chart rendering. +* `postRender` - This listener function will be invoked after chart finish rendering including +all renderlets' logic. +* `preRedraw` - This listener function will be invoked before chart redrawing. +* `postRedraw` - This listener function will be invoked after chart finish redrawing +including all renderlets' logic. +* `filtered` - This listener function will be invoked after a filter is applied, added or removed. +* `zoomed` - This listener function will be invoked after a zoom is triggered. + +**Kind**: instance method of [baseMixin](#dc.baseMixin) +**See**: [d3.dispatch.on](https://github.com/d3/d3-dispatch/blob/master/README.md#dispatch_on) + +| Param | Type | +| --- | --- | +| event | String | +| listener | function | + +**Example** +```js +.on('renderlet', function(chart, filter){...}) +.on('pretransition', function(chart, filter){...}) +.on('preRender', function(chart){...}) +.on('postRender', function(chart){...}) +.on('preRedraw', function(chart){...}) +.on('postRedraw', function(chart){...}) +.on('filtered', function(chart, filter){...}) +.on('zoomed', function(chart, filter){...}) +``` + + +### dc.marginMixin ⇒ [marginMixin](#dc.marginMixin) +Margin is a mixin that provides margin utility functions for both the Row Chart and Coordinate Grid +Charts. + +**Kind**: static mixin of [dc](#dc) + +| Param | Type | +| --- | --- | +| _chart | Object | + + + +#### marginMixin.margins([margins]) ⇒ Object \| [marginMixin](#dc.marginMixin) +Get or set the margins for a particular coordinate grid chart instance. The margins is stored as +an associative Javascript array. + +**Kind**: instance method of [marginMixin](#dc.marginMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [margins] | Object | {top: 10, right: 50, bottom: 30, left: 30} | + +**Example** +```js +var leftMargin = chart.margins().left; // 30 by default +chart.margins().left = 50; +leftMargin = chart.margins().left; // now 50 +``` + + +### dc.colorMixin ⇒ [colorMixin](#dc.colorMixin) +The Color Mixin is an abstract chart functional class providing universal coloring support +as a mix-in for any concrete chart implementation. + +**Kind**: static mixin of [dc](#dc) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.colorMixin](#dc.colorMixin) ⇒ [colorMixin](#dc.colorMixin) + * [.colors([colorScale])](#dc.colorMixin+colors) ⇒ d3.scale \| [colorMixin](#dc.colorMixin) + * [.ordinalColors(r)](#dc.colorMixin+ordinalColors) ⇒ [colorMixin](#dc.colorMixin) + * [.linearColors(r)](#dc.colorMixin+linearColors) ⇒ [colorMixin](#dc.colorMixin) + * [.colorAccessor([colorAccessor])](#dc.colorMixin+colorAccessor) ⇒ function \| [colorMixin](#dc.colorMixin) + * [.colorDomain([domain])](#dc.colorMixin+colorDomain) ⇒ Array.<String> \| [colorMixin](#dc.colorMixin) + * [.calculateColorDomain()](#dc.colorMixin+calculateColorDomain) ⇒ [colorMixin](#dc.colorMixin) + * [.getColor(d, [i])](#dc.colorMixin+getColor) ⇒ String + * [.colorCalculator([colorCalculator])](#dc.colorMixin+colorCalculator) ⇒ function \| [colorMixin](#dc.colorMixin) + + + +#### colorMixin.colors([colorScale]) ⇒ d3.scale \| [colorMixin](#dc.colorMixin) +Retrieve current color scale or set a new color scale. This methods accepts any function that +operates like a d3 scale. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | Default | +| --- | --- | --- | +| [colorScale] | d3.scale | d3.scaleOrdinal(d3.schemeCategory20c) | + +**Example** +```js +// alternate categorical scale +chart.colors(d3.scale.category20b()); +// ordinal scale +chart.colors(d3.scaleOrdinal().range(['red','green','blue'])); +// convenience method, the same as above +chart.ordinalColors(['red','green','blue']); +// set a linear scale +chart.linearColors(["#4575b4", "#ffffbf", "#a50026"]); +``` + + +#### colorMixin.ordinalColors(r) ⇒ [colorMixin](#dc.colorMixin) +Convenience method to set the color scale to +[d3.scaleOrdinal](https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales) with +range `r`. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| r | Array.<String> | + + + +#### colorMixin.linearColors(r) ⇒ [colorMixin](#dc.colorMixin) +Convenience method to set the color scale to an Hcl interpolated linear scale with range `r`. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| r | Array.<Number> | + + + +#### colorMixin.colorAccessor([colorAccessor]) ⇒ function \| [colorMixin](#dc.colorMixin) +Set or the get color accessor function. This function will be used to map a data point in a +crossfilter group to a color value on the color scale. The default function uses the key +accessor. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| [colorAccessor] | function | + +**Example** +```js +// default index based color accessor +.colorAccessor(function (d, i){return i;}) +// color accessor for a multi-value crossfilter reduction +.colorAccessor(function (d){return d.value.absGain;}) +``` + + +#### colorMixin.colorDomain([domain]) ⇒ Array.<String> \| [colorMixin](#dc.colorMixin) +Set or get the current domain for the color mapping function. The domain must be supplied as an +array. + +Note: previously this method accepted a callback function. Instead you may use a custom scale +set by [.colors](#dc.colorMixin+colors). + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| [domain] | Array.<String> | + + + +#### colorMixin.calculateColorDomain() ⇒ [colorMixin](#dc.colorMixin) +Set the domain by determining the min and max values as retrieved by +[.colorAccessor](#dc.colorMixin+colorAccessor) over the chart's dataset. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + + +#### colorMixin.getColor(d, [i]) ⇒ String +Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| d | \* | +| [i] | Number | + + + +#### colorMixin.colorCalculator([colorCalculator]) ⇒ function \| [colorMixin](#dc.colorMixin) +Overrides the color selection algorithm, replacing it with a simple function. + +Normally colors will be determined by calling the `colorAccessor` to get a value, and then passing that +value through the `colorScale`. + +But sometimes it is difficult to get a color scale to produce the desired effect. The `colorCalculator` +takes the datum and index and returns a color directly. + +**Kind**: instance method of [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| [colorCalculator] | \* | + + + +### dc.coordinateGridMixin ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) +Coordinate Grid is an abstract base chart designed to support a number of coordinate grid based +concrete chart types, e.g. bar chart, line chart, and bubble chart. + +**Kind**: static mixin of [dc](#dc) +**Mixes**: [colorMixin](#dc.colorMixin), [marginMixin](#dc.marginMixin), [baseMixin](#dc.baseMixin) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.coordinateGridMixin](#dc.coordinateGridMixin) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.rescale()](#dc.coordinateGridMixin+rescale) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.rangeChart([rangeChart])](#dc.coordinateGridMixin+rangeChart) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) + * [.zoomScale([extent])](#dc.coordinateGridMixin+zoomScale) ⇒ Array.<(Number\|Date)> \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.zoomOutRestrict([zoomOutRestrict])](#dc.coordinateGridMixin+zoomOutRestrict) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.g([gElement])](#dc.coordinateGridMixin+g) ⇒ SVGElement \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.mouseZoomable([mouseZoomable])](#dc.coordinateGridMixin+mouseZoomable) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.chartBodyG([chartBodyG])](#dc.coordinateGridMixin+chartBodyG) ⇒ SVGElement + * [.x([xScale])](#dc.coordinateGridMixin+x) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xUnits([xUnits])](#dc.coordinateGridMixin+xUnits) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxis([xAxis])](#dc.coordinateGridMixin+xAxis) ⇒ d3.axis \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.elasticX([elasticX])](#dc.coordinateGridMixin+elasticX) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisPadding([padding])](#dc.coordinateGridMixin+xAxisPadding) ⇒ Number \| String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisPaddingUnit([unit])](#dc.coordinateGridMixin+xAxisPaddingUnit) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xUnitCount()](#dc.coordinateGridMixin+xUnitCount) ⇒ Number + * [.useRightYAxis([useRightYAxis])](#dc.coordinateGridMixin+useRightYAxis) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.isOrdinal()](#dc.coordinateGridMixin+isOrdinal) ⇒ Boolean + * [.xAxisLabel([labelText], [padding])](#dc.coordinateGridMixin+xAxisLabel) ⇒ String + * [.yAxisLabel([labelText], [padding])](#dc.coordinateGridMixin+yAxisLabel) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.y([yScale])](#dc.coordinateGridMixin+y) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.yAxis([yAxis])](#dc.coordinateGridMixin+yAxis) ⇒ d3.axisLeft \| d3.axisRight \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.elasticY([elasticY])](#dc.coordinateGridMixin+elasticY) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.renderHorizontalGridLines([renderHorizontalGridLines])](#dc.coordinateGridMixin+renderHorizontalGridLines) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.renderVerticalGridLines([renderVerticalGridLines])](#dc.coordinateGridMixin+renderVerticalGridLines) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.xAxisMin()](#dc.coordinateGridMixin+xAxisMin) ⇒ \* + * [.xAxisMax()](#dc.coordinateGridMixin+xAxisMax) ⇒ \* + * [.yAxisMin()](#dc.coordinateGridMixin+yAxisMin) ⇒ \* + * [.yAxisMax()](#dc.coordinateGridMixin+yAxisMax) ⇒ \* + * [.yAxisPadding([padding])](#dc.coordinateGridMixin+yAxisPadding) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.round([round])](#dc.coordinateGridMixin+round) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.brush([_])](#dc.coordinateGridMixin+brush) ⇒ d3.brush \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.clipPadding([padding])](#dc.coordinateGridMixin+clipPadding) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.focus([range], [noRaiseEvents])](#dc.coordinateGridMixin+focus) ⇒ undefined + * [.brushOn([brushOn])](#dc.coordinateGridMixin+brushOn) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + * [.parentBrushOn([brushOn])](#dc.coordinateGridMixin+parentBrushOn) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) + + + +#### coordinateGridMixin.rescale() ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) +When changing the domain of the x or y scale, it is necessary to tell the chart to recalculate +and redraw the axes. (`.rescale()` is called automatically when the x or y scale is replaced +with [.x()](dc.coordinateGridMixin+x) or [.y()](#dc.coordinateGridMixin+y), and has +no effect on elastic scales.) + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.rangeChart([rangeChart]) ⇒ [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the range selection chart associated with this instance. Setting the range selection +chart using this function will automatically update its selection brush when the current chart +zooms in. In return the given range chart will also automatically attach this chart as its focus +chart hence zoom in when range brush updates. + +Usually the range and focus charts will share a dimension. The range chart will set the zoom +boundaries for the focus chart, so its dimension values must be compatible with the domain of +the focus chart. + +See the [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) example for this effect in action. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | +| --- | --- | +| [rangeChart] | [coordinateGridMixin](#dc.coordinateGridMixin) | + + + +#### coordinateGridMixin.zoomScale([extent]) ⇒ Array.<(Number\|Date)> \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the scale extent for mouse zooms. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [extent] | Array.<(Number\|Date)> | [1, Infinity] | + + + +#### coordinateGridMixin.zoomOutRestrict([zoomOutRestrict]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the zoom restriction for the chart. If true limits the zoom to origional domain of the chart. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [zoomOutRestrict] | Boolean | true | + + + +#### coordinateGridMixin.g([gElement]) ⇒ SVGElement \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the root g element. This method is usually used to retrieve the g element in order to +overlay custom svg drawing programatically. **Caution**: The root g element is usually generated +by dc.js internals, and resetting it might produce unpredictable result. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | +| --- | --- | +| [gElement] | SVGElement | + + + +#### coordinateGridMixin.mouseZoomable([mouseZoomable]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get mouse zoom capability flag (default: false). When turned on the chart will be +zoomable using the mouse wheel. If the range selector chart is attached zooming will also update +the range selection brush on the associated range selector chart. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [mouseZoomable] | Boolean | false | + + + +#### coordinateGridMixin.chartBodyG([chartBodyG]) ⇒ SVGElement +Retrieve the svg group for the chart body. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | +| --- | --- | +| [chartBodyG] | SVGElement | + + + +#### coordinateGridMixin.x([xScale]) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) +**mandatory** + +Get or set the x scale. The x scale can be any d3 +[d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) or +[ordinal scale](https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales) + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | +| --- | --- | +| [xScale] | d3.scale | + +**Example** +```js +// set x to a linear scale +chart.x(d3.scaleLinear().domain([-2500, 2500])) +// set x to a time scale to generate histogram +chart.x(d3.scaleTime().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) +``` + + +#### coordinateGridMixin.xUnits([xUnits]) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get the xUnits function. The coordinate grid chart uses the xUnits function to calculate +the number of data projections on the x axis such as the number of bars for a bar chart or the +number of dots for a line chart. + +This function is expected to return a Javascript array of all data points on the x axis, or +the number of points on the axis. d3 time range functions [d3.timeDays, d3.timeMonths, and +d3.timeYears](https://github.com/d3/d3-time/blob/master/README.md#intervals) are all valid +xUnits functions. + +dc.js also provides a few units function, see the [Units Namespace](#dc.units) for +a list of built-in units functions. + +Note that as of dc.js 3.0, `dc.units.ordinal` is not a real function, because it is not +possible to define this function compliant with the d3 range functions. It was already a +magic value which caused charts to behave differently, and now it is completely so. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [xUnits] | function | dc.units.integers | + +**Example** +```js +// set x units to count days +chart.xUnits(d3.timeDays); +// set x units to count months +chart.xUnits(d3.timeMonths); + +// A custom xUnits function can be used as long as it follows the following interface: +// units in integer +function(start, end) { + // simply calculates how many integers in the domain + return Math.abs(end - start); +} + +// fixed units +function(start, end) { + // be aware using fixed units will disable the focus/zoom ability on the chart + return 1000; +} +``` + + +#### coordinateGridMixin.xAxis([xAxis]) ⇒ d3.axis \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get the x axis used by a particular coordinate grid chart instance. This function is most +useful when x axis customization is required. The x axis in dc.js is an instance of a +[d3 bottom axis object](https://github.com/d3/d3-axis/blob/master/README.md#axisBottom); +therefore it supports any valid d3 axisBottom manipulation. + +**Caution**: The x axis is usually generated internally by dc; resetting it may cause +unexpected results. Note also that when used as a getter, this function is not chainable: +it returns the axis, not the chart, +{@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis +so attempting to call chart functions after calling `.xAxis()` will fail}. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) +**See**: [d3.axisBottom](https://github.com/d3/d3-axis/blob/master/README.md#axisBottom) + +| Param | Type | Default | +| --- | --- | --- | +| [xAxis] | d3.axis | d3.axisBottom() | + +**Example** +```js +// customize x axis tick format +chart.xAxis().tickFormat(function(v) {return v + '%';}); +// customize x axis tick values +chart.xAxis().tickValues([0, 100, 200, 300]); +``` + + +#### coordinateGridMixin.elasticX([elasticX]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Turn on/off elastic x axis behavior. If x axis elasticity is turned on, then the grid chart will +attempt to recalculate the x axis range whenever a redraw event is triggered. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [elasticX] | Boolean | false | + + + +#### coordinateGridMixin.xAxisPadding([padding]) ⇒ Number \| String \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x +axis if elasticX is turned on; otherwise it is ignored. + +Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to +number or date x axes. When padding a date axis, an integer represents number of units being padded +and a percentage string will be treated the same as an integer. The unit will be determined by the +xAxisPaddingUnit variable. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number \| String | 0 | + + + +#### coordinateGridMixin.xAxisPaddingUnit([unit]) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get x axis padding unit for the elastic x axis. The padding unit will determine which unit to +use when applying xAxis padding if elasticX is turned on and if x-axis uses a time dimension; +otherwise it is ignored. + +The padding unit should be a +[d3 time interval](https://github.com/d3/d3-time/blob/master/README.md#_interval). +For backward compatibility with dc.js 2.0, it can also be the name of a d3 time interval +('day', 'hour', etc). Available arguments are the +[d3 time intervals](https://github.com/d3/d3-time/blob/master/README.md#intervals d3.timeInterval). + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [unit] | String | d3.timeDay | + + + +#### coordinateGridMixin.xUnitCount() ⇒ Number +Returns the number of units displayed on the x axis. If the x axis is ordinal (`xUnits` is +`dc.units.ordinal`), this is the number of items in the domain of the x scale. Otherwise, the +x unit count is calculated using the [xUnits](#dc.coordinateGridMixin+xUnits) function. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.useRightYAxis([useRightYAxis]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Gets or sets whether the chart should be drawn with a right axis instead of a left axis. When +used with a chart in a composite chart, allows both left and right Y axes to be shown on a +chart. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [useRightYAxis] | Boolean | false | + + + +#### coordinateGridMixin.isOrdinal() ⇒ Boolean +Returns true if the chart is using ordinal xUnits ([ordinal](#dc.units.ordinal), or false +otherwise. Most charts behave differently with ordinal data and use the result of this method to +trigger the appropriate logic. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.xAxisLabel([labelText], [padding]) ⇒ String +Set or get the x axis label. If setting the label, you may optionally include additional padding to +the margin to make room for the label. By default the padded is set to 12 to accomodate the text height. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [labelText] | String | | +| [padding] | Number | 12 | + + + +#### coordinateGridMixin.yAxisLabel([labelText], [padding]) ⇒ String \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get the y axis label. If setting the label, you may optionally include additional padding +to the margin to make room for the label. By default the padding is set to 12 to accommodate the +text height. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [labelText] | String | | +| [padding] | Number | 12 | + + + +#### coordinateGridMixin.y([yScale]) ⇒ d3.scale \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the y scale. The y scale is typically automatically determined by the chart implementation. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | +| --- | --- | +| [yScale] | d3.scale | + + + +#### coordinateGridMixin.yAxis([yAxis]) ⇒ d3.axisLeft \| d3.axisRight \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get the y axis used by the coordinate grid chart instance. This function is most useful +when y axis customization is required. Depending on `useRightYAxis` the y axis in dc.js is an instance of +either [d3.axisLeft](https://github.com/d3/d3-axis/blob/master/README.md#axisLeft) or +[d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight); therefore it supports any +valid d3 axis manipulation. + +**Caution**: The y axis is usually generated internally by dc; resetting it may cause +unexpected results. Note also that when used as a getter, this function is not chainable: it +returns the axis, not the chart, +{@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis +so attempting to call chart functions after calling `.yAxis()` will fail}. +In addition, depending on whether you are going to use the axis on left or right +you need to appropriately pass [d3.axisLeft](https://github.com/d3/d3-axis/blob/master/README.md#axisLeft) +or [d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight) + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) +**See**: [d3.axis](https://github.com/d3/d3-axis/blob/master/README.md) + +| Param | Type | +| --- | --- | +| [yAxis] | d3.axisLeft \| d3.axisRight | + +**Example** +```js +// customize y axis tick format +chart.yAxis().tickFormat(function(v) {return v + '%';}); +// customize y axis tick values +chart.yAxis().tickValues([0, 100, 200, 300]); +``` + + +#### coordinateGridMixin.elasticY([elasticY]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Turn on/off elastic y axis behavior. If y axis elasticity is turned on, then the grid chart will +attempt to recalculate the y axis range whenever a redraw event is triggered. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [elasticY] | Boolean | false | + + + +#### coordinateGridMixin.renderHorizontalGridLines([renderHorizontalGridLines]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Turn on/off horizontal grid lines. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [renderHorizontalGridLines] | Boolean | false | + + + +#### coordinateGridMixin.renderVerticalGridLines([renderVerticalGridLines]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Turn on/off vertical grid lines. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [renderVerticalGridLines] | Boolean | false | + + + +#### coordinateGridMixin.xAxisMin() ⇒ \* +Calculates the minimum x value to display in the chart. Includes xAxisPadding if set. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.xAxisMax() ⇒ \* +Calculates the maximum x value to display in the chart. Includes xAxisPadding if set. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.yAxisMin() ⇒ \* +Calculates the minimum y value to display in the chart. Includes yAxisPadding if set. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.yAxisMax() ⇒ \* +Calculates the maximum y value to display in the chart. Includes yAxisPadding if set. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + + +#### coordinateGridMixin.yAxisPadding([padding]) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get y axis padding for the elastic y axis. The padding will be added to the top and +bottom of the y axis if elasticY is turned on; otherwise it is ignored. + +Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to +number or date axes. When padding a date axis, an integer represents number of days being padded +and a percentage string will be treated the same as an integer. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number \| String | 0 | + + + +#### coordinateGridMixin.round([round]) ⇒ function \| [coordinateGridMixin](#dc.coordinateGridMixin) +Set or get the rounding function used to quantize the selection when brushing is enabled. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | +| --- | --- | +| [round] | function | + +**Example** +```js +// set x unit round to by month, this will make sure range selection brush will +// select whole months +chart.round(d3.timeMonth.round); +``` + + +#### coordinateGridMixin.brush([_]) ⇒ d3.brush \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the brush. Brush must be an instance of d3 brushes +https://github.com/d3/d3-brush/blob/master/README.md +You will use this only if you are writing a new chart type that supports brushing. + +**Caution**: dc creates and manages brushes internally. Go through and understand the source code +if you want to pass a new brush object. Even if you are only using the getter, +the brush object may not behave the way you expect. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | +| --- | --- | +| [_] | d3.brush | + + + +#### coordinateGridMixin.clipPadding([padding]) ⇒ Number \| [coordinateGridMixin](#dc.coordinateGridMixin) +Get or set the padding in pixels for the clip path. Once set padding will be applied evenly to +the top, left, right, and bottom when the clip path is generated. If set to zero, the clip area +will be exactly the chart body area minus the margins. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [padding] | Number | 5 | + + + +#### coordinateGridMixin.focus([range], [noRaiseEvents]) ⇒ undefined +Zoom this chart to focus on the given range. The given range should be an array containing only +2 elements (`[start, end]`) defining a range in the x domain. If the range is not given or set +to null, then the zoom will be reset. _For focus to work elasticX has to be turned off; +otherwise focus will be ignored. + +To avoid ping-pong volley of events between a pair of range and focus charts please set +`noRaiseEvents` to `true`. In that case it will update this chart but will not fire `zoom` event +and not try to update back the associated range chart. +If you are calling it manually - typically you will leave it to `false` (the default). + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [range] | Array.<Number> | | +| [noRaiseEvents] | Boolean | false | + +**Example** +```js +chart.on('renderlet', function(chart) { + // smooth the rendering through event throttling + dc.events.trigger(function(){ + // focus some other chart to the range selected by user on this chart + someOtherChart.focus(chart.filter()); + }); +}) +``` + + +#### coordinateGridMixin.brushOn([brushOn]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +Turn on/off the brush-based range filter. When brushing is on then user can drag the mouse +across a chart with a quantitative scale to perform range filtering based on the extent of the +brush, or click on the bars of an ordinal bar chart or slices of a pie chart to filter and +un-filter them. However turning on the brush filter will disable other interactive elements on +the chart such as highlighting, tool tips, and reference lines. Zooming will still be possible +if enabled, but only via scrolling (panning will be disabled.) + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [brushOn] | Boolean | true | + + + +#### coordinateGridMixin.parentBrushOn([brushOn]) ⇒ Boolean \| [coordinateGridMixin](#dc.coordinateGridMixin) +This will be internally used by composite chart onto children. Please go not invoke directly. + +**Kind**: instance method of [coordinateGridMixin](#dc.coordinateGridMixin) +**Access**: protected + +| Param | Type | Default | +| --- | --- | --- | +| [brushOn] | Boolean | false | + + + +### dc.stackMixin ⇒ [stackMixin](#dc.stackMixin) +Stack Mixin is an mixin that provides cross-chart support of stackability using d3.stackD3v3. + +**Kind**: static mixin of [dc](#dc) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.stackMixin](#dc.stackMixin) ⇒ [stackMixin](#dc.stackMixin) + * [.stack(group, [name], [accessor])](#dc.stackMixin+stack) ⇒ Array.<{group: crossfilter.group, name: String, accessor: function()}> \| [stackMixin](#dc.stackMixin) + * [.hidableStacks([hidableStacks])](#dc.stackMixin+hidableStacks) ⇒ Boolean \| [stackMixin](#dc.stackMixin) + * [.hideStack(stackName)](#dc.stackMixin+hideStack) ⇒ [stackMixin](#dc.stackMixin) + * [.showStack(stackName)](#dc.stackMixin+showStack) ⇒ [stackMixin](#dc.stackMixin) + * [.title([stackName], [titleAccessor])](#dc.stackMixin+title) ⇒ String \| [stackMixin](#dc.stackMixin) + * [.stackLayout([stack])](#dc.stackMixin+stackLayout) ⇒ function \| [stackMixin](#dc.stackMixin) + * [.evadeDomainFilter([evadeDomainFilter])](#dc.stackMixin+evadeDomainFilter) ⇒ Boolean \| [stackMixin](#dc.stackMixin) + + + +#### stackMixin.stack(group, [name], [accessor]) ⇒ Array.<{group: crossfilter.group, name: String, accessor: function()}> \| [stackMixin](#dc.stackMixin) +Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks +in the same chart will share the same key accessor and therefore the same set of keys. + +For example, in a stacked bar chart, the bars of each stack will be positioned using the same set +of keys on the x axis, while stacked vertically. If name is specified then it will be used to +generate the legend label. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) +**See**: [crossfilter.group](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce) + +| Param | Type | +| --- | --- | +| group | crossfilter.group | +| [name] | String | +| [accessor] | function | + +**Example** +```js +// stack group using default accessor +chart.stack(valueSumGroup) +// stack group using custom accessor +.stack(avgByDayGroup, function(d){return d.value.avgByDay;}); +``` + + +#### stackMixin.hidableStacks([hidableStacks]) ⇒ Boolean \| [stackMixin](#dc.stackMixin) +Allow named stacks to be hidden or shown by clicking on legend items. +This does not affect the behavior of hideStack or showStack. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [hidableStacks] | Boolean | false | + + + +#### stackMixin.hideStack(stackName) ⇒ [stackMixin](#dc.stackMixin) +Hide all stacks on the chart with the given name. +The chart must be re-rendered for this change to appear. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) + +| Param | Type | +| --- | --- | +| stackName | String | + + + +#### stackMixin.showStack(stackName) ⇒ [stackMixin](#dc.stackMixin) +Show all stacks on the chart with the given name. +The chart must be re-rendered for this change to appear. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) + +| Param | Type | +| --- | --- | +| stackName | String | + + + +#### stackMixin.title([stackName], [titleAccessor]) ⇒ String \| [stackMixin](#dc.stackMixin) +Set or get the title function. Chart class will use this function to render svg title (usually interpreted by +browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart. +Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to +use title otherwise the brush layer will block tooltip trigger. + +If the first argument is a stack name, the title function will get or set the title for that stack. If stackName +is not provided, the first stack is implied. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) + +| Param | Type | +| --- | --- | +| [stackName] | String | +| [titleAccessor] | function | + +**Example** +```js +// set a title function on 'first stack' +chart.title('first stack', function(d) { return d.key + ': ' + d.value; }); +// get a title function from 'second stack' +var secondTitleFunction = chart.title('second stack'); +``` + + +#### stackMixin.stackLayout([stack]) ⇒ function \| [stackMixin](#dc.stackMixin) +Gets or sets the stack layout algorithm, which computes a baseline for each stack and +propagates it to the next. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) +**See**: [d3.stackD3v3](https://github.com/d3/d3-3.x-api-reference/blob/master/Stack-Layout.md) + +| Param | Type | Default | +| --- | --- | --- | +| [stack] | function | d3.stackD3v3 | + + + +#### stackMixin.evadeDomainFilter([evadeDomainFilter]) ⇒ Boolean \| [stackMixin](#dc.stackMixin) +Since dc.js 2.0, there has been [an issue](https://github.com/dc-js/dc.js/issues/949) +where points are filtered to the current domain. While this is a useful optimization, it is +incorrectly implemented: the next point outside the domain is required in order to draw lines +that are clipped to the bounds, as well as bars that are partly clipped. + +A fix will be included in dc.js 2.1.x, but a workaround is needed for dc.js 2.0 and until +that fix is published, so set this flag to skip any filtering of points. + +Once the bug is fixed, this flag will have no effect, and it will be deprecated. + +**Kind**: instance method of [stackMixin](#dc.stackMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [evadeDomainFilter] | Boolean | false | + + + +### dc.capMixin ⇒ [capMixin](#dc.capMixin) +Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the +Row and Pie Charts. + +The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest +will be replaced with an *others* element, with value equal to the sum of the replaced values. The +keys of the elements below the cap limit are recorded in order to filter by those keys when the +others* element is clicked. + +**Kind**: static mixin of [dc](#dc) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.capMixin](#dc.capMixin) ⇒ [capMixin](#dc.capMixin) + * [.cap([count])](#dc.capMixin+cap) ⇒ Number \| [capMixin](#dc.capMixin) + * [.takeFront([takeFront])](#dc.capMixin+takeFront) ⇒ Boolean \| [capMixin](#dc.capMixin) + * [.othersLabel([label])](#dc.capMixin+othersLabel) ⇒ String \| [capMixin](#dc.capMixin) + * [.othersGrouper([grouperFunction])](#dc.capMixin+othersGrouper) ⇒ function \| [capMixin](#dc.capMixin) + + + +#### capMixin.cap([count]) ⇒ Number \| [capMixin](#dc.capMixin) +Get or set the count of elements to that will be included in the cap. If there is an +[othersGrouper](#dc.capMixin+othersGrouper), any further elements will be combined in an +extra element with its name determined by [othersLabel](#dc.capMixin+othersLabel). + +As of dc.js 2.1 and onward, the capped charts use +[group.all()](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all) +and [baseMixin.ordering()](#dc.baseMixin+ordering) to determine the order of +elements. Then `cap` and [takeFront](#dc.capMixin+takeFront) determine how many elements +to keep, from which end of the resulting array. + +**Migration note:** Up through dc.js 2.0.*, capping used +[group.top(N)](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_top), +which selects the largest items according to +[group.order()](https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_order). +The chart then sorted the items according to [baseMixin.ordering()](#dc.baseMixin+ordering). +So the two values essentially had to agree, but if the `group.order()` was incorrect (it's +easy to forget about), the wrong rows or slices would be displayed, in the correct order. + +If your chart previously relied on `group.order()`, use `chart.ordering()` instead. As of +2.1.5, the ordering defaults to sorting from greatest to least like `group.top(N)` did. + +If you want to cap by one ordering but sort by another, you can still do this by +specifying your own [`.data()`](#dc.baseMixin+data) callback. For details, see the example +[Cap and Sort Differently](https://dc-js.github.io/dc.js/examples/cap-and-sort-differently.html). + +**Kind**: instance method of [capMixin](#dc.capMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [count] | Number | Infinity | + + + +#### capMixin.takeFront([takeFront]) ⇒ Boolean \| [capMixin](#dc.capMixin) +Get or set the direction of capping. If set, the chart takes the first +[cap](#dc.capMixin+cap) elements from the sorted array of elements; otherwise +it takes the last `cap` elements. + +**Kind**: instance method of [capMixin](#dc.capMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [takeFront] | Boolean | true | + + + +#### capMixin.othersLabel([label]) ⇒ String \| [capMixin](#dc.capMixin) +Get or set the label for *Others* slice when slices cap is specified. + +**Kind**: instance method of [capMixin](#dc.capMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [label] | String | "Others" | + + + +#### capMixin.othersGrouper([grouperFunction]) ⇒ function \| [capMixin](#dc.capMixin) +Get or set the grouper function that will perform the insertion of data for the *Others* slice +if the slices cap is specified. If set to a falsy value, no others will be added. + +The grouper function takes an array of included ("top") items, and an array of the rest of +the items. By default the grouper function computes the sum of the rest. + +**Kind**: instance method of [capMixin](#dc.capMixin) + +| Param | Type | +| --- | --- | +| [grouperFunction] | function | + +**Example** +```js +// Do not show others +chart.othersGrouper(null); +// Default others grouper +chart.othersGrouper(function (topItems, restItems) { + var restItemsSum = d3.sum(restItems, _chart.valueAccessor()), + restKeys = restItems.map(_chart.keyAccessor()); + if (restItemsSum > 0) { + return topItems.concat([{ + others: restKeys, + key: _chart.othersLabel(), + value: restItemsSum + }]); + } + return topItems; +}); +``` + + +### dc.bubbleMixin ⇒ [bubbleMixin](#dc.bubbleMixin) +This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles. + +**Kind**: static mixin of [dc](#dc) +**Mixes**: [colorMixin](#dc.colorMixin) + +| Param | Type | +| --- | --- | +| _chart | Object | + + +* [.bubbleMixin](#dc.bubbleMixin) ⇒ [bubbleMixin](#dc.bubbleMixin) + * [.r([bubbleRadiusScale])](#dc.bubbleMixin+r) ⇒ d3.scale \| [bubbleMixin](#dc.bubbleMixin) + * [.radiusValueAccessor([radiusValueAccessor])](#dc.bubbleMixin+radiusValueAccessor) ⇒ function \| [bubbleMixin](#dc.bubbleMixin) + * [.minRadius([radius])](#dc.bubbleMixin+minRadius) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + * [.minRadiusWithLabel([radius])](#dc.bubbleMixin+minRadiusWithLabel) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + * [.maxBubbleRelativeSize([relativeSize])](#dc.bubbleMixin+maxBubbleRelativeSize) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) + + + +#### bubbleMixin.r([bubbleRadiusScale]) ⇒ d3.scale \| [bubbleMixin](#dc.bubbleMixin) +Get or set the bubble radius scale. By default the bubble chart uses +[d3.scaleLinear().domain([0, 100])](https://github.com/d3/d3-scale/blob/master/README.md#scaleLinear) +as its radius scale. + +**Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) +**See**: [d3.scale](https://github.com/d3/d3-scale/blob/master/README.md) + +| Param | Type | Default | +| --- | --- | --- | +| [bubbleRadiusScale] | d3.scale | d3.scaleLinear().domain([0, 100]) | + + + +#### bubbleMixin.radiusValueAccessor([radiusValueAccessor]) ⇒ function \| [bubbleMixin](#dc.bubbleMixin) +Get or set the radius value accessor function. If set, the radius value accessor function will +be used to retrieve a data value for each bubble. The data retrieved then will be mapped using +the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble +size. + +**Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) + +| Param | Type | +| --- | --- | +| [radiusValueAccessor] | function | + + + +#### bubbleMixin.minRadius([radius]) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) +Get or set the minimum radius. This will be used to initialize the radius scale's range. + +**Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [radius] | Number | 10 | + + + +#### bubbleMixin.minRadiusWithLabel([radius]) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) +Get or set the minimum radius for label rendering. If a bubble's radius is less than this value +then no label will be rendered. + +**Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [radius] | Number | 10 | + + + +#### bubbleMixin.maxBubbleRelativeSize([relativeSize]) ⇒ Number \| [bubbleMixin](#dc.bubbleMixin) +Get or set the maximum relative size of a bubble to the length of x axis. This value is useful +when the difference in radius between bubbles is too great. + +**Kind**: instance method of [bubbleMixin](#dc.bubbleMixin) + +| Param | Type | Default | +| --- | --- | --- | +| [relativeSize] | Number | 0.3 | + + + +### dc.disableTransitions : Boolean +If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen +immediately. + +**Kind**: static property of [dc](#dc) +**Default**: false + + +### dc.dateFormat : function +The default date format for dc.js + +**Kind**: static property of [dc](#dc) +**Default**: d3.timeFormat('%m/%d/%Y') + + +### dc.chartRegistry : object +The dc.chartRegistry object maintains sets of all instantiated dc.js charts under named groups +and the default group. + +A chart group often corresponds to a crossfilter instance. It specifies +the set of charts which should be updated when a filter changes on one of the charts or when the +global functions [filterAll](#dc.filterAll), [refocusAll](#dc.refocusAll), +[renderAll](#dc.renderAll), [redrawAll](#dc.redrawAll), or chart functions +[baseMixin.renderGroup](#dc.baseMixin+renderGroup), +[baseMixin.redrawGroup](#dc.baseMixin+redrawGroup) are called. + +**Kind**: static namespace of [dc](#dc) + +* [.chartRegistry](#dc.chartRegistry) : object + * [.has(chart)](#dc.chartRegistry.has) ⇒ Boolean + * [.register(chart, [group])](#dc.chartRegistry.register) ⇒ undefined + * [.deregister(chart, [group])](#dc.chartRegistry.deregister) ⇒ undefined + * [.clear(group)](#dc.chartRegistry.clear) ⇒ undefined + * [.list([group])](#dc.chartRegistry.list) ⇒ Array.<Object> + + + +#### chartRegistry.has(chart) ⇒ Boolean +Determine if a given chart instance resides in any group in the registry. + +**Kind**: static method of [chartRegistry](#dc.chartRegistry) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | + + + +#### chartRegistry.register(chart, [group]) ⇒ undefined +Add given chart instance to the given group, creating the group if necessary. +If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. + +**Kind**: static method of [chartRegistry](#dc.chartRegistry) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | +| [group] | String | Group name | + + + +#### chartRegistry.deregister(chart, [group]) ⇒ undefined +Remove given chart instance from the given group, creating the group if necessary. +If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. + +**Kind**: static method of [chartRegistry](#dc.chartRegistry) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | +| [group] | String | Group name | + + + +#### chartRegistry.clear(group) ⇒ undefined +Clear given group if one is provided, otherwise clears all groups. + +**Kind**: static method of [chartRegistry](#dc.chartRegistry) + +| Param | Type | Description | +| --- | --- | --- | +| group | String | Group name | + + + +#### chartRegistry.list([group]) ⇒ Array.<Object> +Get an array of each chart instance in the given group. +If no group is provided, the charts in the default group are returned. + +**Kind**: static method of [chartRegistry](#dc.chartRegistry) + +| Param | Type | Description | +| --- | --- | --- | +| [group] | String | Group name | + + + +### dc.units : object +**Kind**: static namespace of [dc](#dc) + +* [.units](#dc.units) : object + * [.fp](#dc.units.fp) : object + * [.precision(precision)](#dc.units.fp.precision) ⇒ function + * [.integers(start, end)](#dc.units.integers) ⇒ Number + * [.ordinal()](#dc.units.ordinal) ⇒ uncallable + + + +#### units.fp : object +**Kind**: static namespace of [units](#dc.units) + + +##### fp.precision(precision) ⇒ function +This function generates an argument for the [Coordinate Grid Chart](#dc.coordinateGridMixin) +[.xUnits](#dc.coordinateGridMixin+xUnits) function specifying that the x values are floating-point +numbers with the given precision. +The returned function determines how many values at the given precision will fit into the range +supplied in its start and end parameters. + +**Kind**: static method of [fp](#dc.units.fp) +**Returns**: function - start-end unit function +**See**: [coordinateGridMixin.xUnits](#dc.coordinateGridMixin+xUnits) + +| Param | Type | +| --- | --- | +| precision | Number | + +**Example** +```js +// specify values (and ticks) every 0.1 units +chart.xUnits(dc.units.fp.precision(0.1) +// there are 500 units between 0.5 and 1 if the precision is 0.001 +var thousandths = dc.units.fp.precision(0.001); +thousandths(0.5, 1.0) // returns 500 +``` + + +#### units.integers(start, end) ⇒ Number +The default value for [.xUnits](#dc.coordinateGridMixin+xUnits) for the +[Coordinate Grid Chart](#dc.coordinateGridMixin) and should +be used when the x values are a sequence of integers. +It is a function that counts the number of integers in the range supplied in its start and end parameters. + +**Kind**: static method of [units](#dc.units) +**See**: [coordinateGridMixin.xUnits](#dc.coordinateGridMixin+xUnits) + +| Param | Type | +| --- | --- | +| start | Number | +| end | Number | + +**Example** +```js +chart.xUnits(dc.units.integers) // already the default +``` + + +#### units.ordinal() ⇒ uncallable +This argument can be passed to the [.xUnits](#dc.coordinateGridMixin+xUnits) function of a +coordinate grid chart to specify ordinal units for the x axis. Usually this parameter is used in +combination with passing +[d3.scaleOrdinal](https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales) +to [.x](#dc.coordinateGridMixin+x). + +As of dc.js 3.0, this is purely a placeholder or magic value which causes the chart to go into ordinal mode; the +function is not called. + +**Kind**: static method of [units](#dc.units) +**See** + +- [d3.scaleOrdinal](https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales) +- [coordinateGridMixin.xUnits](#dc.coordinateGridMixin+xUnits) +- [coordinateGridMixin.x](#dc.coordinateGridMixin+x) + +**Example** +```js +chart.xUnits(dc.units.ordinal) + .x(d3.scaleOrdinal()) +``` + + +### dc.printers : object +**Kind**: static namespace of [dc](#dc) + +* [.printers](#dc.printers) : object + * [.filters(filters)](#dc.printers.filters) ⇒ String + * [.filter(filter)](#dc.printers.filter) ⇒ String + + + +#### printers.filters(filters) ⇒ String +Converts a list of filters into a readable string. + +**Kind**: static method of [printers](#dc.printers) + +| Param | Type | +| --- | --- | +| filters | [Array.<filters>](#dc.filters) | + + + +#### printers.filter(filter) ⇒ String +Converts a filter into a readable string. + +**Kind**: static method of [printers](#dc.printers) + +| Param | Type | +| --- | --- | +| filter | [filters](#dc.filters) \| any \| Array.<any> | + + + +### dc.utils : object +**Kind**: static namespace of [dc](#dc) + +* [.utils](#dc.utils) : object + * [.printSingleValue(filter)](#dc.utils.printSingleValue) ⇒ String + * [.add(l, r, [t])](#dc.utils.add) ⇒ Date \| Number + * [.subtract(l, r, [t])](#dc.utils.subtract) ⇒ Date \| Number + * [.isNumber(n)](#dc.utils.isNumber) ⇒ Boolean + * [.isFloat(n)](#dc.utils.isFloat) ⇒ Boolean + * [.isInteger(n)](#dc.utils.isInteger) ⇒ Boolean + * [.isNegligible(n)](#dc.utils.isNegligible) ⇒ Boolean + * [.clamp(val, min, max)](#dc.utils.clamp) ⇒ any + * [.constant(x)](#dc.utils.constant) ⇒ function + * [.uniqueId()](#dc.utils.uniqueId) ⇒ Number + * [.nameToId(name)](#dc.utils.nameToId) ⇒ String + * [.appendOrSelect(parent, selector, tag)](#dc.utils.appendOrSelect) ⇒ d3.selection + * [.safeNumber(n)](#dc.utils.safeNumber) ⇒ Number + * [.arraysEqual(a1, a2)](#dc.utils.arraysEqual) ⇒ Boolean + + + +#### utils.printSingleValue(filter) ⇒ String +Print a single value filter. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| filter | any | + + + +#### utils.add(l, r, [t]) ⇒ Date \| Number +Arbitrary add one value to another. + +If the value l is of type Date, adds r units to it. t becomes the unit. +For example dc.utils.add(dt, 3, 'week') will add 3 (r = 3) weeks (t= 'week') to dt. + +If l is of type numeric, t is ignored. In this case if r is of type string, +it is assumed to be percentage (whether or not it includes %). For example +dc.utils.add(30, 10) will give 40 and dc.utils.add(30, '10') will give 33. + +They also generate strange results if l is a string. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| l | Date \| Number | | the value to modify | +| r | String \| Number | | the amount by which to modify the value | +| [t] | function \| String | d3.timeDay | if `l` is a `Date`, then this should be a [d3 time interval](https://github.com/d3/d3-time/blob/master/README.md#_interval). For backward compatibility with dc.js 2.0, it can also be the name of an interval, i.e. 'millis', 'second', 'minute', 'hour', 'day', 'week', 'month', or 'year' | + + + +#### utils.subtract(l, r, [t]) ⇒ Date \| Number +Arbitrary subtract one value from another. + +If the value l is of type Date, subtracts r units from it. t becomes the unit. +For example dc.utils.subtract(dt, 3, 'week') will subtract 3 (r = 3) weeks (t= 'week') from dt. + +If l is of type numeric, t is ignored. In this case if r is of type string, +it is assumed to be percentage (whether or not it includes %). For example +dc.utils.subtract(30, 10) will give 20 and dc.utils.subtract(30, '10') will give 27. + +They also generate strange results if l is a string. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| l | Date \| Number | | the value to modify | +| r | String \| Number | | the amount by which to modify the value | +| [t] | function \| String | d3.timeDay | if `l` is a `Date`, then this should be a [d3 time interval](https://github.com/d3/d3-time/blob/master/README.md#_interval). For backward compatibility with dc.js 2.0, it can also be the name of an interval, i.e. 'millis', 'second', 'minute', 'hour', 'day', 'week', 'month', or 'year' | + + + +#### utils.isNumber(n) ⇒ Boolean +Is the value a number? + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| n | any | + + + +#### utils.isFloat(n) ⇒ Boolean +Is the value a float? + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| n | any | + + + +#### utils.isInteger(n) ⇒ Boolean +Is the value an integer? + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| n | any | + + + +#### utils.isNegligible(n) ⇒ Boolean +Is the value very close to zero? + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| n | any | + + + +#### utils.clamp(val, min, max) ⇒ any +Ensure the value is no greater or less than the min/max values. If it is return the boundary value. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| val | any | +| min | any | +| max | any | + + + +#### utils.constant(x) ⇒ function +Given `x`, return a function that always returns `x`. + +[`d3.functor` was removed in d3 version 4](https://github.com/d3/d3/blob/master/CHANGES.md#internals). +This function helps to implement the replacement, +`typeof x === "function" ? x : dc.utils.constant(x)` + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| x | any | + + + +#### utils.uniqueId() ⇒ Number +Using a simple static counter, provide a unique integer id. + +**Kind**: static method of [utils](#dc.utils) + + +#### utils.nameToId(name) ⇒ String +Convert a name to an ID. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| name | String | + + + +#### utils.appendOrSelect(parent, selector, tag) ⇒ d3.selection +Append or select an item on a parent element. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| parent | d3.selection | +| selector | String | +| tag | String | + + + +#### utils.safeNumber(n) ⇒ Number +Return the number if the value is a number; else 0. + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| n | Number \| any | + + + +#### utils.arraysEqual(a1, a2) ⇒ Boolean +Return true if both arrays are equal, if both array are null these are considered equal + +**Kind**: static method of [utils](#dc.utils) + +| Param | Type | +| --- | --- | +| a1 | Array \| null | +| a2 | Array \| null | + + + +### dc.filters : object +The dc.js filters are functions which are passed into crossfilter to chose which records will be +accumulated to produce values for the charts. In the crossfilter model, any filters applied on one +dimension will affect all the other dimensions but not that one. dc always applies a filter +function to the dimension; the function combines multiple filters and if any of them accept a +record, it is filtered in. + +These filter constructors are used as appropriate by the various charts to implement brushing. We +mention below which chart uses which filter. In some cases, many instances of a filter will be added. + +Each of the dc.js filters is an object with the following properties: +* `isFiltered` - a function that returns true if a value is within the filter +* `filterType` - a string identifying the filter, here the name of the constructor + +Currently these filter objects are also arrays, but this is not a requirement. Custom filters +can be used as long as they have the properties above. + +**Kind**: static namespace of [dc](#dc) + +* [.filters](#dc.filters) : object + * [.RangedFilter](#dc.filters.RangedFilter) + * [new RangedFilter(low, high)](#new_dc.filters.RangedFilter_new) + * [.TwoDimensionalFilter](#dc.filters.TwoDimensionalFilter) + * [new TwoDimensionalFilter(filter)](#new_dc.filters.TwoDimensionalFilter_new) + * [.RangedTwoDimensionalFilter](#dc.filters.RangedTwoDimensionalFilter) + * [new RangedTwoDimensionalFilter(filter)](#new_dc.filters.RangedTwoDimensionalFilter_new) + * [.HierarchyFilter](#dc.filters.HierarchyFilter) + * [new HierarchyFilter(path)](#new_dc.filters.HierarchyFilter_new) + + + +#### filters.RangedFilter +**Kind**: static class of [filters](#dc.filters) + + +##### new RangedFilter(low, high) +RangedFilter is a filter which accepts keys between `low` and `high`. It is used to implement X +axis brushing for the [coordinate grid charts](#dc.coordinateGridMixin). + +Its `filterType` is 'RangedFilter' + + +| Param | Type | +| --- | --- | +| low | Number | +| high | Number | + + + +#### filters.TwoDimensionalFilter +**Kind**: static class of [filters](#dc.filters) + + +##### new TwoDimensionalFilter(filter) +TwoDimensionalFilter is a filter which accepts a single two-dimensional value. It is used by the +[heat map chart](#dc.heatMap) to include particular cells as they are clicked. (Rows and columns are +filtered by filtering all the cells in the row or column.) + +Its `filterType` is 'TwoDimensionalFilter' + + +| Param | Type | +| --- | --- | +| filter | Array.<Number> | + + + +#### filters.RangedTwoDimensionalFilter +**Kind**: static class of [filters](#dc.filters) + + +##### new RangedTwoDimensionalFilter(filter) +The RangedTwoDimensionalFilter allows filtering all values which fit within a rectangular +region. It is used by the [scatter plot](#dc.scatterPlot) to implement rectangular brushing. + +It takes two two-dimensional points in the form `[[x1,y1],[x2,y2]]`, and normalizes them so that +`x1 <= x2` and `y1 <= y2`. It then returns a filter which accepts any points which are in the +rectangular range including the lower values but excluding the higher values. + +If an array of two values are given to the RangedTwoDimensionalFilter, it interprets the values as +two x coordinates `x1` and `x2` and returns a filter which accepts any points for which `x1 <= x < +x2`. + +Its `filterType` is 'RangedTwoDimensionalFilter' + + +| Param | Type | +| --- | --- | +| filter | Array.<Array.<Number>> | + + + +#### filters.HierarchyFilter +**Kind**: static class of [filters](#dc.filters) + + +##### new HierarchyFilter(path) +HierarchyFilter is a filter which accepts a key path as an array. It matches any node at, or +child of, the given path. It is used by the [sunburst chart](#dc.sunburstChart) to include particular cells and all +their children as they are clicked. + + +| Param | Type | +| --- | --- | +| path | String | + + + +### dc.registerChart(chart, [group]) ⇒ undefined +Add given chart instance to the given group, creating the group if necessary. +If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. + +**Kind**: static method of [dc](#dc) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | +| [group] | String | Group name | + + + +### dc.deregisterChart(chart, [group]) ⇒ undefined +Remove given chart instance from the given group, creating the group if necessary. +If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. + +**Kind**: static method of [dc](#dc) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | +| [group] | String | Group name | + + + +### dc.hasChart(chart) ⇒ Boolean +Determine if a given chart instance resides in any group in the registry. + +**Kind**: static method of [dc](#dc) + +| Param | Type | Description | +| --- | --- | --- | +| chart | Object | dc.js chart instance | + + + +### dc.deregisterAllCharts(group) ⇒ undefined +Clear given group if one is provided, otherwise clears all groups. + +**Kind**: static method of [dc](#dc) + +| Param | Type | Description | +| --- | --- | --- | +| group | String | Group name | + + + +### dc.filterAll([group]) ⇒ undefined +Clear all filters on all charts within the given chart group. If the chart group is not given then +only charts that belong to the default chart group will be reset. + +**Kind**: static method of [dc](#dc) + +| Param | Type | +| --- | --- | +| [group] | String | + + + +### dc.refocusAll([group]) ⇒ undefined +Reset zoom level / focus on all charts that belong to the given chart group. If the chart group is +not given then only charts that belong to the default chart group will be reset. + +**Kind**: static method of [dc](#dc) + +| Param | Type | +| --- | --- | +| [group] | String | + + + +### dc.renderAll([group]) ⇒ undefined +Re-render all charts belong to the given chart group. If the chart group is not given then only +charts that belong to the default chart group will be re-rendered. + +**Kind**: static method of [dc](#dc) + +| Param | Type | +| --- | --- | +| [group] | String | + + + +### dc.redrawAll([group]) ⇒ undefined +Redraw all charts belong to the given chart group. If the chart group is not given then only charts +that belong to the default chart group will be re-drawn. Redraw is different from re-render since +when redrawing dc tries to update the graphic incrementally, using transitions, instead of starting +from scratch. + +**Kind**: static method of [dc](#dc) + +| Param | Type | +| --- | --- | +| [group] | String | + + + +### dc.transition(selection, [duration], [delay], [name]) ⇒ d3.transition \| d3.selection +Start a transition on a selection if transitions are globally enabled +([disableTransitions](#dc.disableTransitions) is false) and the duration is greater than zero; otherwise return +the selection. Since most operations are the same on a d3 selection and a d3 transition, this +allows a common code path for both cases. + +**Kind**: static method of [dc](#dc) + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| selection | d3.selection | | the selection to be transitioned | +| [duration] | Number \| function | 250 | the duration of the transition in milliseconds, a function returning the duration, or 0 for no transition | +| [delay] | Number \| function | | the delay of the transition in milliseconds, or a function returning the delay, or 0 for no delay | +| [name] | String | | the name of the transition (if concurrent transitions on the same elements are needed) | + + + +### dc.pluck(n, [f]) ⇒ function +Returns a function that given a string property name, can be used to pluck the property off an object. A function +can be passed as the second argument to also alter the data being returned. + +This can be a useful shorthand method to create accessor functions. + +**Kind**: static method of [dc](#dc) + +| Param | Type | +| --- | --- | +| n | String | +| [f] | function | + +**Example** +```js +var xPluck = dc.pluck('x'); +var objA = {x: 1}; +xPluck(objA) // 1 +``` +**Example** +```js +var xPosition = dc.pluck('x', function (x, i) { + // `this` is the original datum, + // `x` is the x property of the datum, + // `i` is the position in the array + return this.radius + x; +}); +dc.selectAll('.circle').data(...).x(xPosition); +``` diff --git a/docs/welcome.base.md b/docs/welcome.base.md new file mode 100644 index 0000000000..710acbfa60 --- /dev/null +++ b/docs/welcome.base.md @@ -0,0 +1,21 @@ +# dc.js + +Welcome to the dc.js documentation. + +This library may be used as ES6 modules or as a JS file (UMD) in your webpage. + +When used as UMD in your webpage, the entire library is scoped under dc namespace. + +When used as modules you will see the classes and functions as per your import +statements. + +A class diagram is shown below - mixins are blue and chart classes are green. (Relations between mixins are somewhat subjective.) + + + diff --git a/grunt/format-file-list.js b/grunt/format-file-list.js index 3ffd592d2f..ab8b5d353c 100644 --- a/grunt/format-file-list.js +++ b/grunt/format-file-list.js @@ -1,30 +1,33 @@ module.exports = function (grunt) { + const PER_ROW = 4; return function (list, opts) { - var files = list.sort().map(function (entry) { - var f = entry.replace(/.*\//, ''); + const files = list.sort().map(entry => { + const f = entry.replace(/.*\//, ''); return [f.replace('.html', '').replace(/-/g, ' '), f]; - }).filter(function (e) { return e[0] !== 'index'; }); - var rows = []; - for (var i = 0; i < files.length; i += 5) { - var cols = []; - for (var j = 0; j < 5; ++j) { + }).filter(e => e[0] !== 'index'); + const rows = []; + for (let i = 0; i < files.length; i += PER_ROW) { + const cols = []; + for (let j = 0; j < PER_ROW; ++j) { if (i + j >= files.length) { break; } - var file = files[i + j]; - cols.push(' ' + file[0] + ''); + const file = files[i + j]; + cols.push(` ${file[0]}`); } - rows.push(' \n' + cols.join('\n') + '\n'); + rows.push(` \n${cols.join('\n')}\n `); } - var body = '\n' + rows.join('\n') + '\n
'; + const alsoSee = opts.also ? `

Also see ${opts.also.map(cat => `${cat}`).join(' – ')}.

`: ''; + const body = `\n${rows.join('\n')}\n
`; return [ - '' + opts.title + '', + `${opts.title}`, '', '
', - '

' + opts.heading + '

', - '

' + opts.description + '

', - '

Contributions ' + 'welcome.', - 'Source ', + `

${opts.heading}

`, + `

${opts.description}

`, + alsoSee, + '

Contributions welcome.', + `Source `, 'here.

', body, '
' diff --git a/index.js b/index.js deleted file mode 100644 index d56a35c978..0000000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// Import DC and dependencies - -d3 = require("d3"); -crossfilter = require("crossfilter"); -module.exports = require("./dc"); diff --git a/jsdoc.conf.json b/jsdoc.conf.json index b2060b56fb..feb3debfa0 100644 --- a/jsdoc.conf.json +++ b/jsdoc.conf.json @@ -12,17 +12,21 @@ "outputSourcePath": true, "systemName": "dc.js", "footer": "", - "copyright": "dc.js Copyright © 2012-2016 Copyright 2012-2016 Nick Zhu & the dc.js Developers", + "copyright": "dc.js Copyright © 2012-2018 Nick Zhu & the dc.js Developers", "navType": "vertical", "theme": "cosmo", "linenums": true, "collapseSymbols": false, "inverseNav": true, "protocol": "html://", - "methodHeadingReturns": false + "methodHeadingReturns": false, + "default": { + "staticFiles": { + "include": ["./web/img/class-hierarchy.svg"] + } + } }, "markdown": { - "parser": "gfm", - "hardwrap": true + "parser": "gfm" } } diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000000..29c942516f --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,69 @@ +// Karma configuration +// Generated on Thu Jul 05 2018 16:43:26 GMT+0530 (IST) + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine'], + plugins: [ + require('@chiragrupani/karma-chromium-edge-launcher'), + require('karma-chrome-launcher'), + require('karma-coverage'), + require('karma-firefox-launcher'), + require('karma-jasmine'), + require('karma-safari-launcher'), + require('karma-summary-reporter'), + ], + files: [ + // CSS files + 'dist/style/dc.css', + // Helpers + 'spec/helpers/*.js', + // JS code dependencies + 'spec/3rd-party/*.js', + // Code to be tested + 'dist/dc.js', + // Jasmine spec files + 'spec/*spec.js' + ], + exclude: [], + preprocessors: {}, + // possible values: 'dots', 'progress' + reporters: ['progress', 'summary'], + summaryReporter: { + // 'failed', 'skipped' or 'all' + show: 'failed', + // Limit the spec label to this length + specLength: 100, + // Show an 'all' column as a summary + overviewColumn: true + }, + customLaunchers: { + // See https://github.com/karma-runner/karma/issues/2603 + // This is used by grunt:ci task, so, do not remove + ChromeNoSandboxHeadless: { + base: 'Chrome', + flags: [ + '--no-sandbox', + // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md + '--headless', + '--disable-gpu', + // Without a remote debugging port, Google Chrome exits immediately. + ' --remote-debugging-port=9222' + ] + }, + FirefoxHeadless: { + base: 'Firefox', + flags: ['-headless'] + } + }, + port: 9876, + colors: true, + logLevel: 'INFO', + autoWatch: false, + browsers: ['FirefoxHeadless'], + browserConsoleLogOptions: {level: 'error'}, + singleRun: true, + concurrency: Infinity + }) +}; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json deleted file mode 100644 index 5dc5e421f7..0000000000 --- a/npm-shrinkwrap.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "dc", - "version": "2.0.0-beta.29", - "dependencies": { - "crossfilter2": { - "version": "~1.3" - }, - "d3": { - "version": "^3" - }, - "grunt-gh-pages": { - "version": "1.1.0", - "from": "grunt-gh-pages@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/grunt-gh-pages/-/grunt-gh-pages-1.1.0.tgz", - "dependencies": { - "async": { - "version": "0.2.9" - }, - "graceful-fs": { - "version": "3.0.8" - }, - "q": { - "version": "0.9.3" - }, - "q-io": { - "version": "2.*", - "GW-note-5-23-16": "this is the important override" - }, - "url-safe": { - "version": "1.0.1" - }, - "wrench": { - "version": "1.5.1" - } - } - } - } -} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..f4e4365435 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9921 @@ +{ + "name": "dc", + "version": "4.2.7", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", + "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.4", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@chiragrupani/karma-chromium-edge-launcher": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@chiragrupani/karma-chromium-edge-launcher/-/karma-chromium-edge-launcher-2.1.0.tgz", + "integrity": "sha512-POHDni57WeEzA/liw8Ksdzj9FLDoX0KPtvBG+jhXEBcPPARKdRCiP5ntBQLWIHZbp61g5G2g1sD5ZuGuLYyhPA==", + "dev": true + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@ranfdev/deepobj": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ranfdev/deepobj/-/deepobj-1.0.2.tgz", + "integrity": "sha512-FM3y6kfJaj5MCoAjdv24EDCTDbuFz+4+pgAunbjYfugwIE4O/xx8mPNji1n/ouG8pHCntSnBr1xwTOensF23Gg==", + "dev": true + }, + "@rollup/plugin-json": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz", + "integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.8" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/node": { + "version": "14.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz", + "integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ajv": { + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "archiver": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", + "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^2.6.3", + "buffer-crc32": "^0.2.1", + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "tar-stream": "^2.1.0", + "zip-stream": "^2.1.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "dev": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-1.0.0.tgz", + "integrity": "sha512-ZqrZp9Hi5Uq7vfSGmNP2bUT/9DzZC2Y/GXjHB8rUJN1a+KLmbV05+vxHipNsg8+CSVgjcVVzLV8VZms6w8ZeRw==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collect-all": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.3.tgz", + "integrity": "sha512-0y0rBgoX8IzIjBAUnO73SEtSb4Mhk3IoceWJq5zZSxb9mWORhWH8xLYo4EDSOE1jRBk1LhmfjqWFFt10h/+MEA==", + "dev": true, + "requires": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dev": true, + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + } + } + }, + "command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commenting": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commenting/-/commenting-1.1.0.tgz", + "integrity": "sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==", + "dev": true + }, + "common-sequence": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.0.tgz", + "integrity": "sha512-f0QqPLpRTgMQn/pQIynf+SdE73Lw5Q1jn4hjirHLgH/NJ71TiHjXusV16BmOyuK5rRQ1W2f++II+TFZbQOh4hA==", + "dev": true + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compress-commons": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", + "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^3.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^2.3.6" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "requires": { + "walk-back": "^2.0.1" + }, + "dependencies": { + "walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true + } + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "connect-livereload": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz", + "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz", + "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==", + "dev": true, + "requires": { + "crc": "^3.4.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "crossfilter2": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/crossfilter2/-/crossfilter2-1.5.4.tgz", + "integrity": "sha512-oOGqOM0RocwQFOXJnEaUKqYV6Mc1TNCRv3LrNUa0QlofQTutGAXyQaLW1aGKLls2sfnbwBEtsa6tPD3jY+ycqQ==", + "dev": true, + "requires": { + "@ranfdev/deepobj": "1.0.2" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d3": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/d3/-/d3-6.6.2.tgz", + "integrity": "sha512-wvC9cZe05bUCo00VFKXLQJWmWhGv0U43Qv0gn+tkl144S7bV22E80Gnp06BEuJVuwVfa6+S8UOfl8H9Ru/cmgA==", + "requires": { + "d3-array": "2", + "d3-axis": "2", + "d3-brush": "2", + "d3-chord": "2", + "d3-color": "2", + "d3-contour": "2", + "d3-delaunay": "5", + "d3-dispatch": "2", + "d3-drag": "2", + "d3-dsv": "2", + "d3-ease": "2", + "d3-fetch": "2", + "d3-force": "2", + "d3-format": "2", + "d3-geo": "2", + "d3-hierarchy": "2", + "d3-interpolate": "2", + "d3-path": "2", + "d3-polygon": "2", + "d3-quadtree": "2", + "d3-random": "2", + "d3-scale": "3", + "d3-scale-chromatic": "2", + "d3-selection": "2", + "d3-shape": "2", + "d3-time": "2", + "d3-time-format": "3", + "d3-timer": "2", + "d3-transition": "2", + "d3-zoom": "2" + } + }, + "d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "requires": { + "internmap": "^1.0.0" + } + }, + "d3-axis": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.1.0.tgz", + "integrity": "sha512-z/G2TQMyuf0X3qP+Mh+2PimoJD41VOCjViJzT0BHeL/+JQAofkiWZbWxlwFGb1N8EN+Cl/CW+MUKbVzr1689Cw==" + }, + "d3-brush": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-2.1.0.tgz", + "integrity": "sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==", + "requires": { + "d3-dispatch": "1 - 2", + "d3-drag": "2", + "d3-interpolate": "1 - 2", + "d3-selection": "2", + "d3-transition": "2" + } + }, + "d3-chord": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-2.0.0.tgz", + "integrity": "sha512-D5PZb7EDsRNdGU4SsjQyKhja8Zgu+SHZfUSO5Ls8Wsn+jsAKUUGkcshLxMg9HDFxG3KqavGWaWkJ8EpU8ojuig==", + "requires": { + "d3-path": "1 - 2" + } + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "d3-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==" + }, + "d3-contour": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-2.0.0.tgz", + "integrity": "sha512-9unAtvIaNk06UwqBmvsdHX7CZ+NPDZnn8TtNH1myW93pWJkhsV25JcgnYAu0Ck5Veb1DHiCv++Ic5uvJ+h50JA==", + "requires": { + "d3-array": "2" + } + }, + "d3-delaunay": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.3.0.tgz", + "integrity": "sha512-amALSrOllWVLaHTnDLHwMIiz0d1bBu9gZXd1FiLfXf8sHcX9jrcj81TVZOqD4UX7MgBZZ07c8GxzEgBpJqc74w==", + "requires": { + "delaunator": "4" + } + }, + "d3-dispatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", + "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==" + }, + "d3-drag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz", + "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==", + "requires": { + "d3-dispatch": "1 - 2", + "d3-selection": "2" + } + }, + "d3-dsv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-2.0.0.tgz", + "integrity": "sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==", + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + } + }, + "d3-ease": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz", + "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==" + }, + "d3-fetch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-2.0.0.tgz", + "integrity": "sha512-TkYv/hjXgCryBeNKiclrwqZH7Nb+GaOwo3Neg24ZVWA3MKB+Rd+BY84Nh6tmNEMcjUik1CSUWjXYndmeO6F7sw==", + "requires": { + "d3-dsv": "1 - 2" + } + }, + "d3-force": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz", + "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==", + "requires": { + "d3-dispatch": "1 - 2", + "d3-quadtree": "1 - 2", + "d3-timer": "1 - 2" + } + }, + "d3-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==" + }, + "d3-geo": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.1.tgz", + "integrity": "sha512-M6yzGbFRfxzNrVhxDJXzJqSLQ90q1cCyb3EWFZ1LF4eWOBYxFypw7I/NFVBNXKNqxv1bqLathhYvdJ6DC+th3A==", + "requires": { + "d3-array": ">=2.5" + } + }, + "d3-hierarchy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz", + "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw==" + }, + "d3-interpolate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", + "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", + "requires": { + "d3-color": "1 - 2" + } + }, + "d3-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz", + "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==" + }, + "d3-polygon": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", + "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==" + }, + "d3-quadtree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz", + "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==" + }, + "d3-random": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz", + "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw==" + }, + "d3-scale": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.4.tgz", + "integrity": "sha512-PG6gtpbPCFqKbvdBEswQcJcTzHC8VEd/XzezF5e68KlkT4/ggELw/nR1tv863jY6ufKTvDlzCMZvhe06codbbA==", + "requires": { + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "1 - 2", + "d3-time-format": "2 - 3" + } + }, + "d3-scale-chromatic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz", + "integrity": "sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA==", + "requires": { + "d3-color": "1 - 2", + "d3-interpolate": "1 - 2" + } + }, + "d3-selection": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz", + "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==" + }, + "d3-shape": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz", + "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==", + "requires": { + "d3-path": "1 - 2" + } + }, + "d3-time": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.0.0.tgz", + "integrity": "sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==" + }, + "d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "requires": { + "d3-time": "1 - 2" + } + }, + "d3-timer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==" + }, + "d3-transition": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz", + "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==", + "requires": { + "d3-color": "1 - 2", + "d3-dispatch": "1 - 2", + "d3-ease": "1 - 2", + "d3-interpolate": "1 - 2", + "d3-timer": "1 - 2" + } + }, + "d3-zoom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz", + "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==", + "requires": { + "d3-dispatch": "1 - 2", + "d3-drag": "2", + "d3-interpolate": "1 - 2", + "d3-selection": "2", + "d3-transition": "2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "dev": true + }, + "date-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-1.1.0.tgz", + "integrity": "sha1-GIdtC9pMGf5w3Tv0sDTygbEqQLY=", + "dev": true, + "requires": { + "time-zone": "^0.1.0" + } + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delaunator": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", + "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "dmd": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-4.0.6.tgz", + "integrity": "sha512-7ZYAnFQ6jGm4SICArwqNPylJ83PaOdPTAkds3Z/s1ueFqSc5ilJ2F0b7uP+35W1PUbemH++gn5/VlC3KwEgiHQ==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "cache-point": "^1.0.0", + "common-sequence": "^2.0.0", + "file-set": "^3.0.0", + "handlebars": "^4.5.3", + "marked": "^0.7.0", + "object-get": "^2.1.0", + "reduce-flatten": "^3.0.0", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^4.0.0" + }, + "dependencies": { + "marked": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true + }, + "reduce-flatten": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz", + "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==", + "dev": true + } + } + }, + "docco": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/docco/-/docco-0.6.3.tgz", + "integrity": "sha1-xHtYI9eVY9b8Or1J895ImG5VIu4=", + "dev": true, + "requires": { + "commander": ">= 0.5.2", + "fs-extra": ">= 0.6.0", + "highlight.js": ">= 8.0.x", + "marked": ">= 0.2.7", + "underscore": ">= 1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.0.1.tgz", + "integrity": "sha512-1Aj1Qy3YLbdslkI75QEOfdp9TkQ3o8LRISAzxOibjBs/xWwr1WxZFOQphFkZuepHFGo+kB8e5FVJSS0faAJ4Rw==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.2.0.tgz", + "integrity": "sha512-0haAxVr1PR0SqYwCH7mxMpHZUwjih9oPPedqpR/KufsnxPyZ9dyVw1R5093qnJF3WXSbjBkdzRWLw/knJV/fAg==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", + "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "~7.4.2" + }, + "dependencies": { + "ws": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", + "dev": true + } + } + }, + "engine.io-client": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.1.tgz", + "integrity": "sha512-oVu9kBkGbcggulyVF0kz6BV3ganqUeqXvD79WOFKa+11oK692w1NyFkuEj4xrkFRpZhn92QOqTk4RQq5LiBXbQ==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~7.4.2", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "ws": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", + "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", + "dev": true + } + } + }, + "engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "dev": true, + "requires": { + "string-template": "~0.2.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz", + "integrity": "sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ==", + "dev": true, + "requires": { + "eslint-utils": "^1.4.2", + "regexpp": "^3.0.0" + }, + "dependencies": { + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz", + "integrity": "sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ==", + "dev": true, + "requires": { + "eslint-plugin-es": "^2.0.0", + "eslint-utils": "^1.4.2", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz", + "integrity": "sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-saver": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz", + "integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg==", + "dev": true + }, + "file-set": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-3.0.0.tgz", + "integrity": "sha512-B/SdeSIeRv7VlOgIjtH3dkxMI+tEy5m+OeCXfAUsirBoVoY+bGtsmvmmTFPm/G23TBY4RiTtjpcgePCfwXRjqA==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "glob": "^7.1.5" + } + }, + "file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "grunt": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.3.0.tgz", + "integrity": "sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA==", + "dev": true, + "requires": { + "dateformat": "~3.0.3", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~0.3.0", + "glob": "~7.1.6", + "grunt-cli": "~1.3.2", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.0", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "mkdirp": "~1.0.4", + "nopt": "~3.0.6", + "rimraf": "~3.0.2" + }, + "dependencies": { + "grunt-cli": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", + "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", + "dev": true, + "requires": { + "grunt-known-options": "~1.1.0", + "interpret": "~1.1.0", + "liftoff": "~2.5.0", + "nopt": "~4.0.1", + "v8flags": "~3.1.1" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + } + } + }, + "grunt-cli": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.2.tgz", + "integrity": "sha512-wsu6BZh7KCnfeaSkDrKIAvOlqGKxNRTZjc8xfZlvxCByQIqUfZ31kh5uHpPnhQ4NdVgvaWaVxa1LUbVU80nACw==", + "dev": true, + "requires": { + "grunt-known-options": "~1.1.1", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } + } + }, + "grunt-contrib-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-2.0.0.tgz", + "integrity": "sha512-JVjM9UDP84WbT2S7swkyuwPuxFtT+zry/RUBuP3IT8LZPEQjtzzMwiM+qimswNKQ9plh5WhcFWaaqz2ruB9/DA==", + "dev": true, + "requires": { + "async": "^2.6.1", + "connect": "^3.6.6", + "connect-livereload": "^0.6.0", + "morgan": "^1.9.0", + "node-http2": "^4.0.1", + "opn": "^5.3.0", + "portscanner": "^2.2.0", + "serve-index": "^1.9.1", + "serve-static": "^1.13.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "grunt-contrib-copy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "grunt-contrib-cssmin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-3.0.0.tgz", + "integrity": "sha512-eXpooYmVGKMs/xV7DzTLgJFPVOfMuawPD3x0JwhlH0mumq2NtH3xsxaHxp1Y3NKxp0j0tRhFS6kSBRsz6TuTGg==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "clean-css": "~4.2.1", + "maxmin": "^2.1.0" + } + }, + "grunt-contrib-jasmine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-jasmine/-/grunt-contrib-jasmine-2.1.0.tgz", + "integrity": "sha512-nkOIG3Rvv9iedz/CC5hRKHUMJ1aSGOac87h5Xm4fuBUh9RQpbhiQ7xw1lWyhxrLUN3M0ksBKNWBB6KM+rgmI2A==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "grunt-eslint": "^22.0.0", + "lodash": "^4.17.15", + "pacote": "^9.5.4", + "puppeteer": "^1.19.0", + "rimraf": "^2.6.3", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + } + } + }, + "grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "dev": true, + "requires": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "grunt-docco2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/grunt-docco2/-/grunt-docco2-0.2.1.tgz", + "integrity": "sha1-ZghyYavBkcjofI77/LeIEr/krMs=", + "dev": true, + "requires": { + "docco": "~0.6.3" + } + }, + "grunt-eslint": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-22.0.0.tgz", + "integrity": "sha512-I7vIU4x/mb20fmA6TAmLx6Wzn7mfs8ZXeuk7LbP2ujKVFV7KZmJ3qXUyqe2wnD+v/74Rs5uYOZrLL8EoBmlG9Q==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "eslint": "^6.0.1" + } + }, + "grunt-fileindex": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/grunt-fileindex/-/grunt-fileindex-0.1.0.tgz", + "integrity": "sha1-x67aVBPpmnYzbDnAtwSqZAKmikU=", + "dev": true + }, + "grunt-gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/grunt-gh-pages/-/grunt-gh-pages-4.0.0.tgz", + "integrity": "sha512-vuU13G0/my6VM6hLYZwnGzNI8jNJiyJprT3vkMp2S3fjBs+etWTo2ldF9mkiH5MuZYkuS2yJ6B3Fy/Tj7fzRzg==", + "dev": true, + "requires": { + "async": "^3.2.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.2.3", + "url-safe": "^2.0.0" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "grunt-jsdoc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", + "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1", + "jsdoc": "^3.6.3" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "grunt-jsdoc-to-markdown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/grunt-jsdoc-to-markdown/-/grunt-jsdoc-to-markdown-5.0.0.tgz", + "integrity": "sha512-3mCIeYZF7h1mug5N7+mqn+D0Cqc4PQ6b8fHqzME0pLXgFoQZMAZP67ELwrwy7CEKXCo5fWzezyiBYs3Tt0QM4A==", + "dev": true, + "requires": { + "jsdoc-to-markdown": "^5.0.2" + } + }, + "grunt-karma": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/grunt-karma/-/grunt-karma-3.0.2.tgz", + "integrity": "sha512-imNhQO1bR1O7X6/3F5vO0o7mKy4xdkpSd40QVfxGO70cBAFcOqjv2Zu5QzsfEsSrppuu3N0vIQPbfBRjeGdpWg==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "grunt-known-options": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", + "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "dev": true + }, + "grunt-legacy-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", + "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", + "dev": true, + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.19" + } + }, + "grunt-legacy-log-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", + "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", + "dev": true, + "requires": { + "chalk": "~4.1.0", + "lodash": "~4.17.19" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "grunt-legacy-util": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.0.tgz", + "integrity": "sha512-ZEmYFB44bblwPE2oz3q3ygfF6hseQja9tx8I3UZIwbUik32FMWewA+d1qSFicMFB+8dNXDkh35HcDCWlpRsGlA==", + "dev": true, + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.20", + "underscore.string": "~3.3.5", + "which": "~1.3.0" + } + }, + "grunt-sass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", + "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", + "dev": true + }, + "grunt-shell": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-2.1.0.tgz", + "integrity": "sha1-Q595FZ7RHmSmUaacyKPQK+v17MI=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "npm-run-path": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gzip-size": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", + "dev": true, + "requires": { + "duplexer": "^0.1.1" + } + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "highlight.js": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.1.2.tgz", + "integrity": "sha512-Q39v/Mn5mfBlMff9r+zzA+gWxRsCRKwEMvYTiisLr/XUiFI/4puWt0Ojdko3R3JCNWGdOWaA5g/Yxqa23kC5AA==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", + "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "ink-docstrap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ink-docstrap/-/ink-docstrap-1.3.2.tgz", + "integrity": "sha512-STx5orGQU1gfrkoI/fMU7lX6CSP7LBGO10gXNgOZhwKhUqbtNjCkYSewJtNnLmWP1tAGN6oyEpG1HFPw5vpa5Q==", + "dev": true, + "requires": { + "moment": "^2.14.1", + "sanitize-html": "^1.13.0" + } + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dev": true, + "requires": { + "lodash.isfinite": "^3.3.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jasmine-core": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", + "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "dev": true + }, + "jest-worker": { + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", + "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdoc": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz", + "integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.10.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + } + } + }, + "jsdoc-api": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-5.0.4.tgz", + "integrity": "sha512-1KMwLnfo0FyhF06TQKzqIm8BiY1yoMIGICxRdJHUjzskaHMzHMmpLlmNFgzoa4pAC8t1CDPK5jWuQTvv1pBsEQ==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "cache-point": "^1.0.0", + "collect-all": "^1.0.3", + "file-set": "^2.0.1", + "fs-then-native": "^2.0.0", + "jsdoc": "^3.6.3", + "object-to-spawn-args": "^1.1.1", + "temp-path": "^1.0.0", + "walk-back": "^3.0.1" + }, + "dependencies": { + "file-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-2.0.1.tgz", + "integrity": "sha512-XgOUUpgR6FbbfYcniLw0qm1Am7PnNYIAkd+eXxRt42LiYhjaso0WiuQ+VmrNdtwotyM+cLCfZ56AZrySP3QnKA==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "glob": "^7.1.3" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "walk-back": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-3.0.1.tgz", + "integrity": "sha512-umiNB2qLO731Sxbp6cfZ9pwURJzTnftxE4Gc7hq8n/ehkuXC//s9F65IEIJA2ZytQZ1ZOsm/Fju4IWx0bivkUQ==", + "dev": true + } + } + }, + "jsdoc-parse": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-4.0.1.tgz", + "integrity": "sha512-qIObw8yqYZjrP2qxWROB5eLQFLTUX2jRGLhW9hjo2CC2fQVlskidCIzjCoctwsDvauBp2a/lR31jkSleczSo8Q==", + "dev": true, + "requires": { + "array-back": "^4.0.0", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^2.0.0", + "test-value": "^3.0.0" + } + }, + "jsdoc-to-markdown": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-5.0.3.tgz", + "integrity": "sha512-tQv5tBV0fTYidRQtE60lJKxE98mmuLcYuITFDKQiDPE9hGccpeEGUNFcVkInq1vigyuPnZmt79bQ8wv2GKjY0Q==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^4.0.5", + "jsdoc-api": "^5.0.4", + "jsdoc-parse": "^4.0.1", + "walk-back": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "karma": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.3.tgz", + "integrity": "sha512-tHdyFADhVVPBorIKCX8A37iLHxc6RBRphkSoQ+MLKdAtFn1k97tD8WUGi1KlEtDZKL3hui0qhsY9HXUfSNDYPQ==", + "dev": true, + "requires": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.4.2", + "colors": "^1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.6", + "lodash": "^4.17.19", + "log4js": "^6.2.1", + "mime": "^2.4.5", + "minimatch": "^3.0.4", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^2.3.0", + "source-map": "^0.6.1", + "tmp": "0.2.1", + "ua-parser-js": "0.7.22", + "yargs": "^15.3.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, + "karma-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.3.tgz", + "integrity": "sha512-atDvLQqvPcLxhED0cmXYdsPMCQuh6Asa9FMZW1bhNqlVEhJoB9qyZ2BY1gu7D/rr5GLGb5QzYO4siQskxaWP/g==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.1", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", + "minimatch": "^3.0.4" + } + }, + "karma-firefox-launcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.3.0.tgz", + "integrity": "sha512-Fi7xPhwrRgr+94BnHX0F5dCl1miIW4RHnzjIGxF8GaIEp7rNqX7LSi7ok63VXs3PS/5MQaQMhGxw+bvD+pibBQ==", + "dev": true, + "requires": { + "is-wsl": "^2.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "karma-jasmine": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", + "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", + "dev": true + }, + "karma-safari-launcher": { + "version": "git+https://github.com/RLovelett/karma-safari-launcher.git#a1407eeaf0822a5e00e2a2b57c112c82f052a8ff", + "from": "git+https://github.com/RLovelett/karma-safari-launcher.git#safari-webdriver", + "dev": true, + "requires": { + "wd": ">=1.11.2" + } + }, + "karma-summary-reporter": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/karma-summary-reporter/-/karma-summary-reporter-1.10.1.tgz", + "integrity": "sha512-6q82sSxscAJcL9+jTOmJY6wg0C+fUEVsgTUfJ552M2FjJTvWaulS0ch8eCiUUN4hF+M+t14ASM0wjOgI0lCQLA==", + "dev": true, + "requires": { + "chalk": "^1.1.3 || 2.x" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "dev": true, + "requires": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, + "dependencies": { + "findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "livereload-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", + "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", + "dev": true + }, + "load-grunt-tasks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-4.0.0.tgz", + "integrity": "sha512-w5JYPHpZgMxu9XFR9N9MEzyX8E0mLhQkwQ1qVP4mb3gmuomw8Ww8J49NHMbXqyQliq2LUCqdU7/wW96IVuPCKw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "multimatch": "^2.0.0", + "pkg-up": "^2.0.0", + "resolve-pkg": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "log4js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "dev": true, + "requires": { + "date-format": "^3.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.1", + "rfdc": "^1.1.4", + "streamroller": "^2.2.4" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "make-fetch-happen": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "marked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.1.tgz", + "integrity": "sha512-5+/fKgMv2hARmMW7DOpykr2iLhl0NgjyELk5yn92iE7z8Se1IS9n3UsFm86hFXIkvMBmVxki8+ckcpjBeyo/hw==", + "dev": true + }, + "maxmin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^3.0.0", + "pretty-bytes": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", + "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", + "dev": true + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "dev": true + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-fetch-npm": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + } + } + }, + "node-http2": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/node-http2/-/node-http2-4.0.1.tgz", + "integrity": "sha1-Fk/1O13SLITwrxQrh3xerraAmVk=", + "dev": true, + "requires": { + "assert": "1.4.1", + "events": "1.1.1", + "https-browserify": "0.0.1", + "setimmediate": "^1.0.5", + "stream-browserify": "2.0.1", + "timers-browserify": "2.0.2", + "url": "^0.11.0", + "websocket-stream": "^5.0.1" + } + }, + "node-sass": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", + "dev": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "npm-registry-fetch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.7.tgz", + "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-to-spawn-args": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-1.1.1.tgz", + "integrity": "sha1-d9qIJ/Bz0BHJ4bFz+JV4FHAkZ4U=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-name-regex": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/package-name-regex/-/package-name-regex-1.0.9.tgz", + "integrity": "sha512-+U2oQCfEz2IlGqws8gmfKzdMDbSd6+RZp6UIFdKo+GAw3+o+kfnsgXkWtJ1JMoKhpP2kEvuYyTy1lXOEQEe0ZA==", + "dev": true + }, + "pacote": { + "version": "9.5.12", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.12.tgz", + "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^3.0.0", + "npm-registry-fetch": "^4.0.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.10", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-ms": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", + "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=", + "dev": true + }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", + "dev": true + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plur": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-1.0.0.tgz", + "integrity": "sha1-24XGgU9eXlo7Se/CjWBP7GKXUVY=", + "dev": true + }, + "portscanner": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", + "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "dev": true, + "requires": { + "async": "^2.6.0", + "is-number-like": "^1.0.3" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-bytes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "pretty-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-2.1.0.tgz", + "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=", + "dev": true, + "requires": { + "is-finite": "^1.0.1", + "parse-ms": "^1.0.0", + "plur": "^1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "puppeteer": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz", + "integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^2.2.1", + "mime": "^2.0.3", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", + "dev": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, + "dependencies": { + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "requires": { + "test-value": "^1.0.1" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "requires": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + } + } + } + }, + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true + }, + "reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true + }, + "reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "requires": { + "test-value": "^2.0.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "requires": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + } + } + } + }, + "reductio": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/reductio/-/reductio-0.6.3.tgz", + "integrity": "sha1-KSsvZpZKCKvg0GH+BNPq6XTkHYM=", + "dev": true, + "requires": { + "crossfilter2": "^1.4.0-alpha.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz", + "integrity": "sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc=", + "dev": true + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-pkg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-1.0.0.tgz", + "integrity": "sha1-4ZoV54rKLhJEYdySsuOUPvk0lNk=", + "dev": true, + "requires": { + "resolve-from": "^2.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + } + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "1.32.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz", + "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-license": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-license/-/rollup-plugin-license-2.3.0.tgz", + "integrity": "sha512-oi8pL59fVTwXCkLUsZ8dVGVJjO7Hcc5UT0chJvKd0MktPgeYHSadkaicAYUemdYHHpjb0D3DyvedZAEPt+2r8w==", + "dev": true, + "requires": { + "commenting": "1.1.0", + "glob": "7.1.6", + "lodash": "4.17.21", + "magic-string": "0.25.7", + "mkdirp": "1.0.4", + "moment": "2.29.1", + "package-name-regex": "1.0.9", + "spdx-expression-validate": "2.0.0", + "spdx-satisfies": "5.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "dev": true + } + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, + "rxjs": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-html": { + "version": "1.27.4", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.4.tgz", + "integrity": "sha512-VvY1hxVvMXzSos/LzqeBl9/KYu3mkEOtl5NMwz6jER318dSHDCig0AOjZOtnoCwAC3HMs9LhfWkPCmQGttb4ng==", + "dev": true, + "requires": { + "htmlparser2": "^4.1.0", + "lodash": "^4.17.15", + "parse-srcset": "^1.0.2", + "postcss": "^7.0.27" + } + }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", + "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", + "dev": true, + "requires": { + "debug": "~4.1.0", + "engine.io": "~3.5.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.4.0", + "socket.io-parser": "~3.4.0" + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", + "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.5.0", + "has-binary2": "~1.0.2", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "socket.io-parser": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", + "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", + "dev": true, + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + } + } + }, + "socket.io-parser": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", + "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "dev": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + } + } + }, + "sort-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-2.0.0.tgz", + "integrity": "sha1-OKnG2if9fRR7QuYFVPKBGHtN9HI=", + "dev": true, + "requires": { + "array-back": "^1.0.4", + "object-get": "^2.1.0", + "typical": "^2.6.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "spdx-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz", + "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==", + "dev": true, + "requires": { + "array-find-index": "^1.0.2", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-expression-validate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz", + "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "spdx-ranges": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz", + "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==", + "dev": true + }, + "spdx-satisfies": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-5.0.0.tgz", + "integrity": "sha512-/hGhwh20BeGmkA+P/lm06RvXD94JduwNxtx/oX3B5ClPt1/u/m5MCaDNo1tV3Y9laLkQr/NRde63b9lLMhlNfw==", + "dev": true, + "requires": { + "spdx-compare": "^1.0.0", + "spdx-expression-parse": "^3.0.0", + "spdx-ranges": "^2.0.0" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "requires": { + "array-back": "^1.0.2" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, + "streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", + "dev": true, + "requires": { + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, + "terser": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.4.tgz", + "integrity": "sha512-dxuB8KQo8Gt6OVOeLg/rxfcxdNZI/V1G6ze1czFUzPeCFWZRtvZMgSzlZZ5OYBZ4HoG607F6pFPNLekJyV+yVw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "time-grunt": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/time-grunt/-/time-grunt-1.4.0.tgz", + "integrity": "sha1-BiIT5mDJB+hvRAVWwB6mWXtxJCA=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "date-time": "^1.1.0", + "figures": "^1.0.0", + "hooker": "^0.2.3", + "number-is-nan": "^1.0.0", + "pretty-ms": "^2.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "time-zone": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-0.1.0.tgz", + "integrity": "sha1-Sncotqwo2w4Aj1FAQ/1VW9VXO0Y=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.2.tgz", + "integrity": "sha1-q0iDz1l9zVCvIRNJoA+8pWrIa4Y=", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "dev": true, + "requires": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + } + }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", + "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.2.tgz", + "integrity": "sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow==", + "dev": true, + "optional": true + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==", + "dev": true + }, + "underscore.string": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", + "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "dev": true, + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.3.0.tgz", + "integrity": "sha512-Q9Q9RlMM08eWfdPPmDDrXd8Ny3R1sY/DaRDR2zTPPneJ6GYiLx3++fPiZobv49ovkYAnHl/P72Ie3HWXIRVVYA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-safe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/url-safe/-/url-safe-2.0.0.tgz", + "integrity": "sha1-3NRt5GZqdUbuQ+qQasF12qYm3p4=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vargs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", + "integrity": "sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "walk-back": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz", + "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==", + "dev": true + }, + "wd": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/wd/-/wd-1.14.0.tgz", + "integrity": "sha512-X7ZfGHHYlQ5zYpRlgP16LUsvYti+Al/6fz3T/ClVyivVCpCZQpESTDdz6zbK910O5OIvujO23Ym2DBBo3XsQlA==", + "dev": true, + "requires": { + "archiver": "^3.0.0", + "async": "^2.0.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.1", + "q": "^1.5.1", + "request": "2.88.0", + "vargs": "^0.1.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "websocket-stream": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.2.tgz", + "integrity": "sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==", + "dev": true, + "requires": { + "duplexify": "^3.5.1", + "inherits": "^2.0.1", + "readable-stream": "^2.3.3", + "safe-buffer": "^5.1.2", + "ws": "^3.2.0", + "xtend": "^4.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "zip-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + } + } +} diff --git a/package.json b/package.json index 4334386a16..6ab3819b00 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "dc", - "version": "2.1.0-dev", + "version": "4.2.7", "license": "Apache-2.0", - "copyright": "2016", + "copyright": "2020", "description": "A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js ", "keywords": [ "visualization", @@ -25,56 +25,56 @@ "url": "https://github.com/dc-js/dc.js.git" }, "dependencies": { - "crossfilter2": "~1.3", - "d3": "^3" + "d3": "^6.6.2" }, "devDependencies": { - "grunt": "~0.4", - "grunt-browserify": "~5.0", - "grunt-cli": "~1.2", - "grunt-contrib-concat": "~1.0", - "grunt-contrib-connect": "~1.0", + "@chiragrupani/karma-chromium-edge-launcher": "^2.1.0", + "@rollup/plugin-json": "^4.1.0", + "compare-versions": "^3.6.0", + "crossfilter2": "^1.5.4", + "d3-collection": "^1.0.7", + "eslint": "^6.8.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.3.1", + "file-saver": "^1.3.8", + "grunt": "^1.3.0", + "grunt-cli": "^1.4.2", + "grunt-contrib-connect": "~2.0", "grunt-contrib-copy": "~1.0", - "grunt-contrib-cssmin": "~1.0", - "grunt-contrib-jasmine": "~1.0", - "grunt-contrib-jshint": "~0.11.0", - "grunt-contrib-uglify": "~1.0", - "grunt-contrib-watch": "~1.0", - "grunt-docco2": "~0.2", + "grunt-contrib-cssmin": "3.x", + "grunt-contrib-jasmine": "~2.1", + "grunt-contrib-watch": "^1.1.0", + "grunt-docco2": "^0.2.1", "grunt-fileindex": "~0.1", - "grunt-gh-pages": "~1.1", - "grunt-jscs": "~2.8", - "grunt-jsdoc": "~2.0", - "grunt-jsdoc-to-markdown": "~1.2", - "grunt-lib-phantomjs": "~1.1", - "grunt-markdown": "~0.7", - "grunt-saucelabs": "~8.6", - "grunt-shell": "~1.3", - "grunt-template-jasmine-istanbul": "~0.4", - "ink-docstrap": "~1.1", - "jsdifflib": "~1.1", - "load-grunt-tasks": "~3.5", - "marked": "~0.3", - "time-grunt": "~1.3", - "uglify-js": "~2.6", - "file-saver": "^1.3.0" + "grunt-gh-pages": "^4.0.0", + "grunt-jsdoc": "^2.4.1", + "grunt-jsdoc-to-markdown": "^5.0.0", + "grunt-karma": "^3.0.2", + "grunt-sass": "^3.1.0", + "grunt-shell": "~2.1", + "ink-docstrap": "^1.3.2", + "jasmine-core": "^2.99.1", + "karma": "^5.2.3", + "karma-chrome-launcher": "^2.2.0", + "karma-coverage": "^2.0.3", + "karma-firefox-launcher": "^1.3.0", + "karma-jasmine": "^1.1.2", + "karma-safari-launcher": "git+https://github.com/RLovelett/karma-safari-launcher.git#safari-webdriver", + "karma-summary-reporter": "^1.10.1", + "load-grunt-tasks": "~4", + "node-sass": "^4.14.1", + "reductio": "0.6.x", + "regression": "^2.0.1", + "rollup": "^1.32.1", + "rollup-plugin-license": "^2.3.0", + "rollup-plugin-terser": "^7.0.2", + "time-grunt": "~1.4" }, "scripts": { "test": "grunt test" }, - "npmName": "dc", - "npmFileMap": [ - { - "basePath": "/", - "files": [ - "dc.css", - "dc.min.css", - "dc.min.js", - "dc.min.js.map", - "dc.js", - "dc.js.map" - ] - } - ], - "browser": "dc.js" + "browser": "dist/dc.js", + "main": "dist/dc.js", + "module": "src/index.js" } diff --git a/regression/rendered-stock-fixture.html b/regression/rendered-stock-fixture.html index 3254680b76..38a4a91b28 100644 --- a/regression/rendered-stock-fixture.html +++ b/regression/rendered-stock-fixture.html @@ -880,7 +880,6 @@

Nasdaq 100 Index 1985/11/01-2012/06/29

- @@ -901,4 +900,4 @@

Nasdaq 100 Index 1985/11/01-2012/06/29

- \ No newline at end of file + diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000000..ebe31227f6 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,64 @@ +import {terser} from 'rollup-plugin-terser'; +import json from '@rollup/plugin-json'; +import license from 'rollup-plugin-license'; + +const jsonPlugin = json({include: 'package.json', preferConst: true}); +const licensePlugin = license({ + sourcemap: true, + banner: { + content: { + file: 'LICENSE_BANNER' + } + } +}); + +const d3Modules = { + 'd3': 'd3', + 'd3-array': 'd3', + 'd3-axis': 'd3', + 'd3-brush': 'd3', + 'd3-collection': 'd3', + 'd3-dispatch': 'd3', + 'd3-ease': 'd3', + 'd3-format': 'd3', + 'd3-geo': 'd3', + 'd3-hierarchy': 'd3', + 'd3-interpolate': 'd3', + 'd3-scale-chromatic': 'd3', + 'd3-scale': 'd3', + 'd3-selection': 'd3', + 'd3-shape': 'd3', + 'd3-time': 'd3', + 'd3-time-format': 'd3', + 'd3-timer': 'd3', + 'd3-zoom': 'd3' +}; + +const umdConf = { + file: 'dist/dc.js', + format: 'umd', + name: 'dc', + sourcemap: true, + globals: d3Modules, + paths: d3Modules +}; + +const umdMinConf = Object.assign({}, umdConf, { + file: 'dist/dc.min.js', + plugins: [terser()] +}); + +export default [ + { + input: 'src/index-with-version.js', + external: Object.keys(d3Modules), + plugins: [ + jsonPlugin, + licensePlugin + ], + output: [ + umdConf, + umdMinConf + ] + } +]; diff --git a/scripts/generate-redirects.sh b/scripts/generate-redirects.sh new file mode 100755 index 0000000000..b96cbcd75b --- /dev/null +++ b/scripts/generate-redirects.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +OLDIES="dc.barChart.html +dc.baseMixin.html +dc.boxPlot.html +dc.bubbleChart.html +dc.bubbleMixin.html +dc.bubbleOverlay.html +dc.capMixin.html +dc.cboxMenu.html +dc.chartRegistry.html +dc.colorMixin.html +dc.compositeChart.html +dc.config.html +dc.coordinateGridMixin.html +dc.dataCount.html +dc.dataGrid.html +dc.dataTable.html +dc.filters.HierarchyFilter.html +dc.filters.html +dc.filters.RangedFilter.html +dc.filters.RangedTwoDimensionalFilter.html +dc.filters.TwoDimensionalFilter.html +dc.geoChoroplethChart.html +dc.heatMap.html +dc.htmlLegend.html +dc.legend.html +dc.lineChart.html +dc.logger.html +dc.marginMixin.html +dc.numberDisplay.html +dc.pieChart.html +dc.printers.html +dc.rowChart.html +dc.scatterPlot.html +dc.selectMenu.html +dc.seriesChart.html +dc.stackMixin.html +dc.sunburstChart.html +dc.textFilterWidget.html +dc.units.fp.html +dc.units.html +dc.utils.html" + +generate () { + echo "" > $1 +} + +for f in $OLDIES; do + g=`echo $f | sed s:^dc\.::` + if echo $g | grep filters > /dev/null; then + generate web/docs/html/$f $g + else + generate web/docs/html/$f ${g^} + fi +done + +generate web/docs/html/dc.html global.html diff --git a/spec/bar-chart-spec.js b/spec/bar-chart-spec.js index 26a7662ba9..8f75590e02 100644 --- a/spec/bar-chart-spec.js +++ b/spec/bar-chart-spec.js @@ -1,82 +1,82 @@ -/* global appendChartID, loadDateFixture, makeDate, cleanDateRange */ -describe('dc.barChart', function () { - var id, chart, data; - var dimension, group; +/* global appendChartID, loadDateFixture, makeDate, cleanDateRange, simulateChartBrushing */ +describe('dc.BarChart', () => { + let id, chart, data; + let dimension, group; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { return d3.time.day.utc(d.dd); }); + dimension = data.dimension(d => d3.utcDay(d.dd)); group = dimension.group(); id = 'bar-chart'; appendChartID(id); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.dimension(dimension).group(group) .width(1100).height(200) - .x(d3.time.scale.utc().domain([makeDate(2012, 0, 1), makeDate(2012, 11, 31)])) + .x(d3.scaleUtc().domain([makeDate(2012, 0, 1), makeDate(2012, 11, 31)])) .transitionDuration(0) .controlsUseVisibility(true); }); - describe('rendering', function () { - beforeEach(function () { + describe('rendering', () => { + beforeEach(() => { chart.render(); }); - it('should set bar height using y-values from data', function () { - forEachBar(function (bar, datum) { + it('should set bar height using y-values from data', () => { + forEachBar((bar, datum) => { expect(+bar.attr('y')).toBe(chart.y()(datum.data.value)); }); }); - it('should set bar width to the minimum for a relatively small chart', function () { - forEachBar(function (bar) { + it('should set bar width to the minimum for a relatively small chart', () => { + forEachBar(bar => { expect(+bar.attr('width')).toBe(1); }); }); - it('should preserve method chaining', function () { + it('should preserve method chaining', () => { expect(chart.render()).toEqual(chart); }); - it('should not display bar labels without setting renderLabel(true)', function () { + it('should not display bar labels without setting renderLabel(true)', () => { expect(chart.selectAll('text.barLabel').size()).toBe(0); }); - describe('with centered bars', function () { - beforeEach(function () { + describe('with centered bars', () => { + beforeEach(() => { chart.centerBar(true).render(); }); - it('should position bars centered around their data points', function () { - var halfBarWidth = 0.5; - forEachBar(function (bar, datum) { - var barPosition = chart.x()(datum.data.key); + it('should position bars centered around their data points', () => { + const halfBarWidth = 0.5; + forEachBar((bar, datum) => { + const barPosition = chart.x()(datum.data.key); expect(+bar.attr('x')).toBeCloseTo(barPosition - halfBarWidth, 3); }); }); }); - describe('without centered bars', function () { - it('should position bars starting at their data points', function () { - forEachBar(function (bar, datum) { - var barPosition = chart.x()(datum.data.key); + describe('without centered bars', () => { + it('should position bars starting at their data points', () => { + forEachBar((bar, datum) => { + const barPosition = chart.x()(datum.data.key); expect(+bar.attr('x')).toBeCloseTo(barPosition, 3); }); }); }); - describe('with bar labels', function () { - beforeEach(function () { + describe('with bar labels', () => { + beforeEach(() => { chart.renderLabel(true).render(); }); - it('should generate a label for each datum', function () { + it('should generate a label for each datum', () => { expect(chart.selectAll('text.barLabel').size()).toBe(6); }); - it('should generate labels with positions corresponding to their data', function () { + it('should generate labels with positions corresponding to their data', () => { expect(nthStack(0).nthLabel(0).attr('x')).toBeWithinDelta(405, 1); expect(nthStack(0).nthLabel(0).attr('y')).toBeWithinDelta(104, 1); expect(nthStack(0).nthLabel(0).text()).toBe('1'); @@ -91,65 +91,61 @@ describe('dc.barChart', function () { }); }); - describe('with custom bar labels', function () { - beforeEach(function () { - chart.label(function () { - return 'custom label'; - }).render(); + describe('with custom bar labels', () => { + beforeEach(() => { + chart.label(() => 'custom label').render(); }); - it('should render a label for each datum', function () { + it('should render a label for each datum', () => { expect(chart.selectAll('text.barLabel').size()).toBe(6); }); - it('should use the custom function for each label', function () { + it('should use the custom function for each label', () => { chart.selectAll('text.barLabel').each(function () { expect(d3.select(this).text()).toBe('custom label'); }); }); - describe('with labels disabled', function () { - beforeEach(function () { + describe('with labels disabled', () => { + beforeEach(() => { chart.renderLabel(false).render(); }); - it('should not display labels', function () { + it('should not display labels', () => { expect(chart.selectAll('text.barLabel').size()).toBe(0); }); }); }); - describe('and then switching the group at runtime', function () { - beforeEach(function () { + describe('and then switching the group at runtime', () => { + beforeEach(() => { chart.rescale(); // BUG: barWidth cannot change after initial rendering - var domain = [makeDate(2012, 4, 20), makeDate(2012, 7, 15)]; + const domain = [makeDate(2012, 4, 20), makeDate(2012, 7, 15)]; - chart.x(d3.time.scale.utc().domain(domain)) - .group(dimension.group().reduceSum(function (d) { - return +d.nvalue; - })) + chart.x(d3.scaleUtc().domain(domain)) + .group(dimension.group().reduceSum(d => +d.nvalue)) .elasticY(true) .centerBar(false) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .yAxis().ticks(5); chart.render(); }); - it('should generate a bar for each datum', function () { + it('should generate a bar for each datum', () => { expect(chart.selectAll('rect.bar').size()).toBe(6); }); - it('should automatically resize the bar widths', function () { - forEachBar(function (bar) { + it('should automatically resize the bar widths', () => { + forEachBar(bar => { expect(bar.attr('width')).toBe('9'); }); }); function nthYAxisText (n) { - return d3.select(chart.selectAll('g.y text')[0][n]); + return d3.select(chart.selectAll('g.y text').nodes()[n]); } - it('should generate bars with positions corresponding to their data', function () { + it('should generate bars with positions corresponding to their data', () => { expect(nthStack(0).nthBar(0).attr('x')).toBeWithinDelta(58, 1); expect(nthStack(0).nthBar(0).attr('y')).toBeWithinDelta(84, 1); expect(nthStack(0).nthBar(0).attr('height')).toBeWithinDelta(30, 1); @@ -163,52 +159,52 @@ describe('dc.barChart', function () { expect(nthStack(0).nthBar(5).attr('height')).toBeWithinDelta(23, 1); }); - it('should generate the y-axis domain dynamically', function () { - expect(nthYAxisText(0).text()).toMatch(/-10/); - expect(nthYAxisText(1).text()).toMatch(/-5/); + it('should generate the y-axis domain dynamically', () => { + expect(nthYAxisText(0).text()).toMatch(/[\-−]10/); + expect(nthYAxisText(1).text()).toMatch(/[\-−]5/); expect(nthYAxisText(2).text()).toBe('0'); }); }); - describe('with an ordinal x domain', function () { - var stateDimension; + describe('with an ordinal x domain', () => { + let stateDimension; - beforeEach(function () { - stateDimension = data.dimension(function (d) { return d.state; }); - var stateGroup = stateDimension.group(); - var ordinalDomainValues = ['California', 'Colorado', 'Delaware', 'Ontario', 'Mississippi', 'Oklahoma']; + beforeEach(() => { + stateDimension = data.dimension(d => d.state); + const stateGroup = stateDimension.group(); + const ordinalDomainValues = ['California', 'Colorado', 'Delaware', 'Ontario', 'Mississippi', 'Oklahoma']; chart.rescale(); // BUG: barWidth cannot change after initial rendering chart.dimension(stateDimension) .group(stateGroup) .xUnits(dc.units.ordinal) - .x(d3.scale.ordinal().domain(ordinalDomainValues)) + .x(d3.scaleBand().domain(ordinalDomainValues)) .barPadding(0) .outerPadding(0.1) .render(); }); - it('should automatically disable the brush', function () { + it('should automatically disable the brush', () => { expect(chart.brushOn()).toBeFalsy(); }); - it('should generate a bar for each ordinal domain value', function () { + it('should generate a bar for each ordinal domain value', () => { expect(chart.selectAll('rect.bar').size()).toBe(6); }); - it('should size the bars proportionally to the graph', function () { + it('should size the bars proportionally to the graph', () => { expect(+chart.select('rect.bar').attr('width')).toBe(164); }); - it('should position the bar based on the ordinal range', function () { + it('should position the bar based on the ordinal range', () => { expect(nthStack(0).nthBar(0).attr('x')).toBeWithinDelta(16, 1); expect(nthStack(0).nthBar(3).attr('x')).toBeWithinDelta(674, 1); expect(nthStack(0).nthBar(5).attr('x')).toBeWithinDelta(509, 1); }); - it('should fade deselected bars', function () { + it('should fade deselected bars', () => { chart.filter('Ontario').filter('Colorado').redraw(); expect(nthStack(0).nthBar(0).classed('deselected')).toBeTruthy(); expect(nthStack(0).nthBar(1).classed('deselected')).toBeFalsy(); @@ -216,176 +212,207 @@ describe('dc.barChart', function () { expect(stateDimension.top(Infinity).length).toBe(3); }); - it('should respect the ordering of the specified domain', function () { + it('should respect the ordering of the specified domain', () => { // Note that bar chart works differently from pie chart. The bar objects (the // actual DOM nodes) don't get reordered by the custom ordering, but they are // placed so that they are drawn in the order specified. - var ontarioXPos = nthStack(0).nthBar(5).attr('x'); - var mississippiXPos = nthStack(0).nthBar(3).attr('x'); - var oklahomaXPos = nthStack(0).nthBar(4).attr('x'); + const ontarioXPos = nthStack(0).nthBar(5).attr('x'); + const mississippiXPos = nthStack(0).nthBar(3).attr('x'); + const oklahomaXPos = nthStack(0).nthBar(4).attr('x'); expect(ontarioXPos).toBeLessThan(mississippiXPos); expect(mississippiXPos).toBeLessThan(oklahomaXPos); }); - describe('with elasticY enabled', function () { - beforeEach(function () { + describe('with elasticY enabled', () => { + beforeEach(() => { chart.elasticY(true).render(); }); - it('should use all ordinal keys to determine the maximum y', function () { + it('should use all ordinal keys to determine the maximum y', () => { expect(chart.y().domain()).toEqual([0, 3]); }); }); - describe('with an unspecified domain', function () { - beforeEach(function () { - chart.x(d3.scale.ordinal()).render(); + describe('with an unspecified domain', () => { + beforeEach(() => { + chart.x(d3.scaleBand()).render(); }); - it('should use alphabetical ordering', function () { - var data = chart.selectAll('rect.bar').data(); - var expectedData = ['California', 'Colorado', 'Delaware', 'Mississippi', 'Oklahoma', 'Ontario']; + it('should use alphabetical ordering', () => { + const data02 = chart.selectAll('rect.bar').data(); + const expectedData = ['California', 'Colorado', 'Delaware', 'Mississippi', 'Oklahoma', 'Ontario']; - expect(data.map(function (datum) { return datum.x; })).toEqual(expectedData); + expect(data02.map(datum => datum.x)).toEqual(expectedData); - var oldX = -Infinity; - forEachBar(function (bar) { + let oldX = -Infinity; + forEachBar(bar => { expect(bar.attr('x')).toBeGreaterThan(oldX); oldX = bar.attr('x'); }); }); }); - describe('redrawing after changing the value accessor', function () { - beforeEach(function () { - chart.valueAccessor(function () { return 30; }); + describe('redrawing after changing the value accessor', () => { + beforeEach(() => { + chart.valueAccessor(() => 30); chart.redraw(); }); - it('should position bars based on ordinal range', function () { + it('should position bars based on ordinal range', () => { expect(nthStack(0).nthBar(0).attr('height')).toBe('1600'); expect(nthStack(0).nthBar(1).attr('height')).toBe('1600'); expect(nthStack(0).nthBar(2).attr('height')).toBe('1600'); }); }); - describe('clicking', function () { - it('causes other dimension to be filtered', function () { + describe('clicking', () => { + it('causes other dimension to be filtered', () => { expect(dimension.top(Infinity).length).toEqual(10); // fake a click - var abar = chart.selectAll('rect.bar:nth-child(3)'); - abar.on('click')(abar.datum()); + const abar = chart.selectAll('rect.bar:nth-child(3)'); + dc.d3compat.callHandler(abar.on('click'), null, {}, abar.datum()); expect(dimension.top(Infinity).length).toEqual(1); }); }); - describe('clicking bar labels', function () { - beforeEach(function () { + describe('clicking bar labels', () => { + beforeEach(() => { chart.renderLabel(true).render(); }); - it('causes other dimension to be filtered', function () { + it('causes other dimension to be filtered', () => { expect(dimension.top(Infinity).length).toEqual(10); // fake a click - var alabel = chart.select('text.barLabel'); - alabel.on('click')(alabel.datum()); + const alabel = chart.select('text.barLabel'); + dc.d3compat.callHandler(alabel.on('click'), null, {}, alabel.datum()); expect(dimension.top(Infinity).length).toEqual(3); }); }); }); - describe('with a linear x domain', function () { - beforeEach(function () { - var linearDimension = data.dimension(function (d) { return +d.value; }); - var linearGroup = linearDimension.group(); + describe('d3.scaleOrdinal() deprecation for ordinal x domain', () => { + let stateDimension; + + beforeEach(() => { + spyOn(dc.logger, 'warn'); + + stateDimension = data.dimension(d => d.state); + const stateGroup = stateDimension.group(); + const ordinalDomainValues = ['California', 'Colorado', 'Delaware', 'Ontario', 'Mississippi', 'Oklahoma']; + + chart.rescale(); // BUG: barWidth cannot change after initial rendering + + chart.dimension(stateDimension) + .group(stateGroup) + .xUnits(dc.units.ordinal) + .x(d3.scaleOrdinal().domain(ordinalDomainValues)) + .barPadding(0) + .outerPadding(0.1) + .render(); + }); + + it('should work with a warning', () => { + expect(dc.logger.warn).toHaveBeenCalled(); + + expect(typeof chart.x().bandwidth).toEqual('function'); + expect(nthStack(0).nthBar(0).attr('x')).toBeWithinDelta(16, 1); + expect(nthStack(0).nthBar(3).attr('x')).toBeWithinDelta(674, 1); + expect(nthStack(0).nthBar(5).attr('x')).toBeWithinDelta(509, 1); + }); + }); + + describe('with a linear x domain', () => { + beforeEach(() => { + const linearDimension = data.dimension(d => +d.value); + const linearGroup = linearDimension.group(); chart.rescale(); // BUG: barWidth cannot change after initial rendering chart.dimension(linearDimension) .group(linearGroup) .xUnits(dc.units.integers) - .x(d3.scale.linear().domain([20, 70])) + .x(d3.scaleLinear().domain([20, 70])) .render(); }); - it('should generate the correct number of bars', function () { + it('should generate the correct number of bars', () => { expect(chart.selectAll('rect.bar').size()).toBe(5); }); - it('should auto size bar width', function () { - forEachBar(function (bar) { + it('should auto size bar width', () => { + forEachBar(bar => { expect(bar.attr('width')).toBe('18'); }); }); - it('should position bars based on linear range', function () { + it('should position bars based on linear range', () => { expect(nthStack(0).nthBar(0).attr('x')).toBeWithinDelta(40, 1); expect(nthStack(0).nthBar(2).attr('x')).toBeWithinDelta(489, 1); expect(nthStack(0).nthBar(4).attr('x')).toBeWithinDelta(938, 1); }); - describe('with a custom click handler', function () { - beforeEach(function () { + describe('with a custom click handler', () => { + beforeEach(() => { chart.brushOn(false) - .on('renderlet', function (_chart) { - _chart.selectAll('rect.bar').on('click', _chart.onClick); + .on('renderlet', _chart => { + _chart.selectAll('rect.bar').on('click', dc.d3compat.eventHandler(d => _chart.onClick(d))); }) .render(); }); - it('clicking causes another dimension to be filtered', function () { + it('clicking causes another dimension to be filtered', () => { expect(dimension.top(Infinity).length).toEqual(10); - var abar = chart.selectAll('rect.bar:nth-child(3)'); - abar.on('click')(abar.datum()); + const abar = chart.selectAll('rect.bar:nth-child(3)'); + dc.d3compat.callHandler(abar.on('click'), null, {}, abar.datum()); expect(dimension.top(Infinity).length).toEqual(3); }); }); }); - describe('with stacked data', function () { - describe('with positive data', function () { - beforeEach(function () { - var idGroup = dimension.group().reduceSum(function (d) { return d.id; }); - var sumGroup = dimension.group().reduceSum(function (d) { return d.value; }); + describe('with stacked data', () => { + describe('with positive data', () => { + beforeEach(() => { + const idGroup = dimension.group().reduceSum(d => d.id); + const sumGroup = dimension.group().reduceSum(d => d.value); chart .brushOn(false) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) .group(idGroup, 'stack 0') - .title('stack 0', function (d) { return 'stack 0: ' + d.value; }) + .title('stack 0', d => `stack 0: ${d.value}`) .stack(sumGroup, 'stack 1') - .title('stack 1', function (d) { return 'stack 1: ' + d.value; }) - .stack(sumGroup, 'stack 2', function (d) { return 3; }) + .title('stack 1', d => `stack 1: ${d.value}`) + .stack(sumGroup, 'stack 2', d => 3) .elasticY(true) .renderLabel(true) .render(); }); - it('should set the y domain to encompass all stacks', function () { + it('should set the y domain to encompass all stacks', () => { expect(chart.y().domain()).toEqual([0, 152]); }); - it('should generate each stack using its associated group', function () { + it('should generate each stack using its associated group', () => { expect(nthStack(0).selectAll('rect.bar').size()).toBe(6); expect(nthStack(1).selectAll('rect.bar').size()).toBe(6); expect(nthStack(2).selectAll('rect.bar').size()).toBe(6); }); - it('should render the correct number of stacks', function () { + it('should render the correct number of stacks', () => { expect(chart.selectAll('.stack').size()).toBe(3); }); - it('should display one label for each stack', function () { + it('should display one label for each stack', () => { expect(chart.selectAll('text.barLabel').size()).toBe(6); }); - it('should generate labels with total value of stack', function () { + it('should generate labels with total value of stack', () => { expect(nthStack(2).nthLabel(0).text()).toBe('48'); expect(nthStack(2).nthLabel(3).text()).toBe('51'); expect(nthStack(2).nthLabel(5).text()).toBe('92'); }); - it('should stack the bars', function () { + it('should stack the bars', () => { expect(+nthStack(0).nthBar(2).attr('y')).toBe(142); expect(+nthStack(0).nthBar(4).attr('y')).toBe(144); @@ -396,116 +423,116 @@ describe('dc.barChart', function () { expect(+nthStack(2).nthBar(4).attr('y')).toBe(83); }); - it('should have its own title accessor', function () { + it('should have its own title accessor', () => { expect(chart.title()({value: 1})).toBe('stack 0: 1'); expect(chart.title('stack 0')({value: 2})).toBe('stack 0: 2'); expect(chart.title('stack 1')({value: 3})).toBe('stack 1: 3'); }); - it('should have titles rendered for extra stacks', function () { - nthStack(1).forEachBar(function (bar, datum) { - expect(bar.selectAll('title')[0].length).toBe(1); - expect(bar.select('title').text()).toBe('stack 1: ' + datum.data.value); + it('should have titles rendered for extra stacks', () => { + nthStack(1).forEachBar((bar, datum) => { + expect(bar.selectAll('title').nodes().length).toBe(1); + expect(bar.select('title').text()).toBe(`stack 1: ${datum.data.value}`); }); }); - it('should default to first stack title for untitled stacks', function () { - nthStack(2).forEachBar(function (bar, datum) { - expect(bar.select('title').text()).toBe('stack 0: ' + datum.data.value); + it('should default to first stack title for untitled stacks', () => { + nthStack(2).forEachBar((bar, datum) => { + expect(bar.select('title').text()).toBe(`stack 0: ${datum.data.value}`); }); }); - describe('extra redraws', function () { - beforeEach(function () { + describe('extra redraws', () => { + beforeEach(() => { chart.redraw(); chart.redraw(); }); - it('should not create extra title elements', function () { - nthStack(1).forEachBar(function (bar, datum) { - expect(bar.selectAll('title')[0].length).toBe(1); + it('should not create extra title elements', () => { + nthStack(1).forEachBar((bar, datum) => { + expect(bar.selectAll('title').nodes().length).toBe(1); }); }); }); - describe('with title rendering disabled', function () { - beforeEach(function () { + describe('with title rendering disabled', () => { + beforeEach(() => { chart.renderTitle(false).render(); }); - it('should not generate title elements', function () { + it('should not generate title elements', () => { expect(chart.selectAll('rect.bar title').empty()).toBeTruthy(); }); }); - describe('stack hiding', function () { - describe('first stack', function () { - beforeEach(function () { + describe('stack hiding', () => { + describe('first stack', () => { + beforeEach(() => { chart.hideStack('stack 0').render(); }); - it('should hide the stack', function () { + it('should hide the stack', () => { expect(nthStack(0).nthBar(0).attr('height')).toBe('52'); expect(nthStack(0).nthBar(1).attr('height')).toBe('78'); }); - it('should show the stack', function () { + it('should show the stack', () => { chart.showStack('stack 0').render(); expect(nthStack(0).nthBar(0).attr('height')).toBe('1'); expect(nthStack(0).nthBar(1).attr('height')).toBe('6'); }); }); - describe('any other stack', function () { - beforeEach(function () { - chart.title('stack 2', function (d) { return 'stack 2: ' + d.value; }); + describe('any other stack', () => { + beforeEach(() => { + chart.title('stack 2', d => `stack 2: ${d.value}`); chart.hideStack('stack 1').render(); }); - it('should hide the stack', function () { + it('should hide the stack', () => { expect(nthStack(1).nthBar(0).attr('height')).toBe('24'); expect(nthStack(1).nthBar(1).attr('height')).toBe('24'); }); - it('should show the stack', function () { + it('should show the stack', () => { chart.showStack('stack 1').render(); expect(nthStack(1).nthBar(0).attr('height')).toBe('46'); expect(nthStack(1).nthBar(1).attr('height')).toBe('70'); }); - it('should still show the title for a visible stack', function () { - nthStack(1).forEachBar(function (bar, datum) { - expect(bar.select('title').text()).toBe('stack 2: ' + datum.data.value); + it('should still show the title for a visible stack', () => { + nthStack(1).forEachBar((bar, datum) => { + expect(bar.select('title').text()).toBe(`stack 2: ${datum.data.value}`); }); }); }); - describe('hiding all the stacks', function () { - beforeEach(function () { + describe('hiding all the stacks', () => { + beforeEach(() => { chart.hideStack('stack 0') .hideStack('stack 1') .hideStack('stack 2') .render(); }); - it('should show a blank graph', function () { + it('should show a blank graph', () => { expect(chart.selectAll('rect.bar').size()).toBe(0); }); }); }); }); - describe('with mixed positive and negative data', function () { - beforeEach(function () { - var mixedGroup = dimension.group().reduceSum(function (d) { return d.nvalue; }); + describe('with mixed positive and negative data', () => { + beforeEach(() => { + const mixedGroup = dimension.group().reduceSum(d => d.nvalue); chart.group(mixedGroup).stack(mixedGroup).stack(mixedGroup); - chart.x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + chart.x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.margins({top: 30, right: 50, bottom: 30, left: 30}) .yAxisPadding(5) .elasticY(true) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .yAxis().ticks(5); chart.rescale(); // BUG: barWidth cannot change after initial rendering @@ -513,17 +540,17 @@ describe('dc.barChart', function () { chart.render(); }); - it('should generate a bar for each datum across all stacks', function () { + it('should generate a bar for each datum across all stacks', () => { expect(chart.selectAll('rect.bar').size()).toBe(18); }); - it('should automatically size the bar widths', function () { - forEachBar(function (bar) { + it('should automatically size the bar widths', () => { + forEachBar(bar => { expect(bar.attr('width')).toBe('9'); }); }); - it('should generate negative bars for stack 0', function () { + it('should generate negative bars for stack 0', () => { expect(nthStack(0).nthBar(0).attr('x')).toBeWithinDelta(58, 1); expect(nthStack(0).nthBar(0).attr('y')).toBeWithinDelta(73, 1); expect(nthStack(0).nthBar(0).attr('height')).toBeWithinDelta(8, 1); @@ -537,7 +564,7 @@ describe('dc.barChart', function () { expect(nthStack(0).nthBar(5).attr('height')).toBeWithinDelta(6, 1); }); - it('should generate negative bar for stack 1', function () { + it('should generate negative bar for stack 1', () => { expect(nthStack(1).nthBar(0).attr('x')).toBeWithinDelta(58, 1); expect(nthStack(1).nthBar(0).attr('y')).toBeWithinDelta(81, 1); expect(nthStack(1).nthBar(0).attr('height')).toBeWithinDelta(7, 1); @@ -551,77 +578,91 @@ describe('dc.barChart', function () { expect(nthStack(1).nthBar(5).attr('height')).toBeWithinDelta(6, 1); }); - it('should generate y axis domain dynamically', function () { - var nthText = function (n) { return d3.select(chart.selectAll('g.axis.y .tick text')[0][n]); }; + it('should generate y axis domain dynamically', () => { + const nthText = function (n) { + return d3.select(chart.selectAll('g.axis.y .tick text').nodes()[n]); + }; - expect(nthText(0).text()).toBe('-20'); + expect(nthText(0).text()).toMatch(/[\-−]20/); expect(nthText(1).text()).toBe('0'); expect(nthText(2).text()).toBe('20'); }); }); - describe('with negative data', function () { - beforeEach(function () { - var negativeGroup = dimension.group().reduceSum(function (d) { return -Math.abs(d.nvalue); }); + describe('with negative data', () => { + beforeEach(() => { + const negativeGroup = dimension.group().reduceSum(d => -Math.abs(d.nvalue)); chart.group(negativeGroup).stack(negativeGroup).stack(negativeGroup); - chart.x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + chart.x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.margins({top: 30, right: 50, bottom: 30, left: 30}) .elasticY(true) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .yAxis().ticks(3); chart.render(); }); - it('should generate y axis domain dynamically', function () { - var nthText = function (n) { return d3.select(chart.selectAll('g.axis.y .tick text')[0][n]); }; + it('should generate y axis domain dynamically', () => { + const nthText = function (n) { + return d3.select(chart.selectAll('g.axis.y .tick text').nodes()[n]); + }; - expect(nthText(0).text()).toBe('-30'); - expect(nthText(1).text()).toBe('-20'); - expect(nthText(2).text()).toBe('-10'); + // d3@5 and d3@6 uses different characters to format negative numbers + expect(nthText(0).text()).toMatch(/[\-−]30/); + expect(nthText(1).text()).toMatch(/[\-−]20/); + expect(nthText(2).text()).toMatch(/[\-−]10/); expect(nthText(3).text()).toBe('0'); }); }); }); - it('should not be focused by default', function () { + it('should not be focused by default', () => { expect(chart.refocused()).toBeFalsy(); }); - describe('when focused', function () { - beforeEach(function () { - chart.elasticY(true).gap(1).xUnits(d3.time.days.utc); + describe('when focused', () => { + beforeEach(() => { + chart.elasticY(true).gap(1).xUnits(d3.utcDays); chart.focus([makeDate(2012, 5, 11), makeDate(2012, 6, 9)]); }); - it('should render the one (focused) bar', function () { + it('should render the one (focused) bar', () => { expect(chart.selectAll('rect.bar').size()).toBe(1); }); - it('should resize the bar width according to the focused width', function () { + it('should resize the bar width according to the focused width', () => { expect(chart.select('rect.bar').attr('width')).toBe('35'); }); - it('should reset the y-axis domain based on the focus range', function () { + it('should reset the y-axis domain based on the focus range', () => { expect(chart.y().domain()).toEqual([0, 1]); }); - it('should redraw the x-axis scale and ticks', function () { - expect(xAxisText().slice(0,4)).toEqual(['Mon 11', 'Wed 13', 'Fri 15', 'Jun 17']); + it('should redraw the x-axis scale and ticks', () => { + expect(xAxisText().slice(0, 4)).toEqual(['Mon 11', 'Wed 13', 'Fri 15', 'Jun 17']); }); - it('should set its focus flag', function () { + it('should set its focus flag', () => { expect(chart.refocused()).toBeTruthy(); }); - it('should reset the focus when focused to null', function () { + describe('with evadeDomainFilter', () => { + beforeEach(() => { + chart.evadeDomainFilter(true).redraw(); + }); + it('should still reset the y-axis domain based on the focus range', () => { + expect(chart.y().domain()).toEqual([0, 1]); + }); + }); + + it('should reset the focus when focused to null', () => { chart.focus(null); itBehavesLikeItWasReset(); }); - it('should reset the focus when focused to []', function () { + it('should reset the focus when focused to []', () => { chart.focus([]); itBehavesLikeItWasReset(); }); @@ -630,138 +671,140 @@ describe('dc.barChart', function () { expect(chart.refocused()).toBeFalsy(); expect(chart.x().domain()).toEqual([makeDate(2012, 0, 1), makeDate(2012, 11, 31)]); - expect(xAxisText().slice(0,4)).toEqual(['2012', 'February', 'March', 'April']); + expect(xAxisText().slice(0, 4)).toEqual(['2012', 'February', 'March', 'April']); } function xAxisText () { - return chart.selectAll('g.x text')[0].map(function (x) { return d3.select(x).text(); }); + return chart.selectAll('g.x text').nodes().map(x => d3.select(x).text()); } }); - describe('legend hovering', function () { - var firstItem; + describe('legend hovering', () => { + let firstItem; - beforeEach(function () { + beforeEach(() => { chart.stack(group) - .legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) + .legend(new dc.Legend().x(400).y(10).itemHeight(13).gap(5)) .render(); firstItem = chart.select('g.dc-legend g.dc-legend-item'); - firstItem.on('mouseover')(firstItem.datum()); + dc.d3compat.callHandler(firstItem.on('mouseover'), null, {}, firstItem.datum()); }); - describe('when a legend item is hovered over', function () { - it('should highlight corresponding lines and areas', function () { - nthStack(0).forEachBar(function (bar) { + describe('when a legend item is hovered over', () => { + it('should highlight corresponding lines and areas', () => { + nthStack(0).forEachBar(bar => { expect(bar.classed('highlight')).toBeTruthy(); }); }); - it('should fade out non-corresponding lines and areas', function () { - nthStack(1).forEachBar(function (bar) { + it('should fade out non-corresponding lines and areas', () => { + nthStack(1).forEachBar(bar => { expect(bar.classed('fadeout')).toBeTruthy(); }); }); }); - describe('when a legend item is hovered out', function () { - it('should remove highlighting from corresponding lines and areas', function () { - firstItem.on('mouseout')(firstItem.datum()); - nthStack(0).forEachBar(function (bar) { + describe('when a legend item is hovered out', () => { + it('should remove highlighting from corresponding lines and areas', () => { + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); + nthStack(0).forEachBar(bar => { expect(bar.classed('highlight')).toBeFalsy(); }); }); - it('should fade in non-corresponding lines and areas', function () { - firstItem.on('mouseout')(firstItem.datum()); - nthStack(1).forEachBar(function (bar) { + it('should fade in non-corresponding lines and areas', () => { + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); + nthStack(1).forEachBar(bar => { expect(bar.classed('fadeout')).toBeFalsy(); }); }); }); }); - describe('filtering', function () { - beforeEach(function () { - d3.select('#' + id).append('span').attr('class', 'filter').style('visibility', 'hidden'); - d3.select('#' + id).append('a').attr('class', 'reset').style('visibility', 'hidden'); + describe('filtering', () => { + beforeEach(() => { + d3.select(`#${id}`).append('span').attr('class', 'filter').style('visibility', 'hidden'); + d3.select(`#${id}`).append('a').attr('class', 'reset').style('visibility', 'hidden'); chart.filter([makeDate(2012, 5, 1), makeDate(2012, 5, 30)]).redraw(); - dc.dateFormat = d3.time.format.utc('%m/%d/%Y'); + dc.config.dateFormat = d3.utcFormat('%m/%d/%Y'); chart.redraw(); }); - it('should set the chart filter', function () { + it('should set the chart filter', () => { expect(chart.filter()).toEqual([makeDate(2012, 5, 1), makeDate(2012, 5, 30)]); }); - it('should enable the reset link after rendering', function () { + it('should enable the reset link after rendering', () => { expect(chart.select('a.reset').style('visibility')).not.toBe('none'); }); - it('should set the filter printer', function () { + it('should set the filter printer', () => { expect(chart.filterPrinter()).not.toBeNull(); }); - it('should show the filter info', function () { + it('should show the filter info', () => { expect(chart.select('span.filter').style('visibility')).toBe('visible'); }); - it('should set filter text after slice selection', function () { + it('should set filter text after slice selection', () => { expect(chart.select('span.filter').text()).toBe('[06/01/2012 -> 06/30/2012]'); }); - describe('when a brush is defined', function () { - it('should position the brush with an offset', function () { + describe('when a brush is defined', () => { + it('should position the brush with an offset', () => { expect(chart.select('g.brush').attr('transform')).toMatchTranslate(chart.margins().left, 10); }); - it('should create a fancy brush resize handle', function () { - chart.select('g.brush').selectAll('.resize path').each(function (d, i) { + it('should create a fancy brush resize handle', () => { + const selectAll = chart.select('g.brush').selectAll('path.custom-brush-handle'); + expect(selectAll.size()).toBe(2); + selectAll.each(function (d, i) { if (i === 0) { expect(d3.select(this).attr('d')) - .toMatchPath('M0.5,53 A6,6 0 0 1 6.5,59 V100 A6,6 0 0 1 0.5,106 ZM2.5,61 V98 M4.5,61 V98'); + .toMatchPath('M-0.5,53 A6,6 0 0 0 -6.5,59 V100 A6,6 0 0 0 -0.5,106 ZM-2.5,61 V98 M-4.5,61 V98'); } else { expect(d3.select(this).attr('d')) - .toMatchPath('M-0.5,53 A6,6 0 0 0 -6.5,59 V100 A6,6 0 0 0 -0.5,106 ZM-2.5,61 V98 M-4.5,61 V98'); + .toMatchPath('M0.5,53 A6,6 0 0 1 6.5,59 V100 A6,6 0 0 1 0.5,106 ZM2.5,61 V98 M4.5,61 V98'); } }); }); - it('should stretch the background', function () { - expect(+chart.select('g.brush rect.background').attr('width')).toBe(1020); + it('should stretch the background', () => { + expect(+chart.select('g.brush rect.overlay').attr('width')).toBe(1020); }); - it('should set the background height to the chart height', function () { - expect(+chart.select('g.brush rect.background').attr('height')).toBe(160); + it('should set the background height to the chart height', () => { + expect(+chart.select('g.brush rect.overlay').attr('height')).toBe(160); }); - it('should set extent height to the chart height', function () { - expect(+chart.select('g.brush rect.extent').attr('height')).toBe(160); + it('should set extent height to the chart height', () => { + expect(+chart.select('g.brush rect.selection').attr('height')).toBe(160); }); - it('should set extent width based on filter set', function () { - expect(chart.select('g.brush rect.extent').attr('width')).toBeWithinDelta(81, 1); + it('should set extent width based on filter set', () => { + expect(chart.select('g.brush rect.selection').attr('width')).toBeWithinDelta(81, 1); }); - it('should push unselected bars to the background', function () { + it('should push unselected bars to the background', () => { expect(nthStack(0).nthBar(0).classed('deselected')).toBeTruthy(); expect(nthStack(0).nthBar(1).classed('deselected')).toBeFalsy(); expect(nthStack(0).nthBar(3).classed('deselected')).toBeTruthy(); }); - it('should push the selected bars to the foreground', function () { + it('should push the selected bars to the foreground', () => { expect(nthStack(0).nthBar(1).classed('deselected')).toBeFalsy(); }); - describe('after reset', function () { - beforeEach(function () { + describe('after reset', () => { + beforeEach(() => { chart.filterAll(); chart.redraw(); }); - it('should push all bars to the foreground', function () { + it('should push all bars to the foreground', () => { chart.selectAll('rect.bar').each(function () { - var bar = d3.select(this); + const bar = d3.select(this); expect(bar.classed('deselected')).toBeFalsy(); }); }); @@ -769,91 +812,91 @@ describe('dc.barChart', function () { }); }); - describe('a chart with a large domain', function () { - beforeEach(function () { - chart.x(d3.time.scale.utc().domain([makeDate(2000, 0, 1), makeDate(2012, 11, 31)])); + describe('a chart with a large domain', () => { + beforeEach(() => { + chart.x(d3.scaleUtc().domain([makeDate(2000, 0, 1), makeDate(2012, 11, 31)])); }); - describe('when filters are applied', function () { - beforeEach(function () { - data.dimension(function (d) { return d.value; }).filter(66); + describe('when filters are applied', () => { + beforeEach(() => { + data.dimension(d => d.value).filter(66); chart.redraw(); }); - it('should not deselect any bars', function () { - forEachBar(function (bar) { + it('should not deselect any bars', () => { + forEachBar(bar => { expect(bar.classed('deselected')).toBeFalsy(); }); }); - it('should set the bars to the minimum bar width', function () { - forEachBar(function (bar) { + it('should set the bars to the minimum bar width', () => { + forEachBar(bar => { expect(+bar.attr('width')).toBe(1); }); }); }); }); - describe('a chart with a linear numerical domain', function () { - beforeEach(function () { - var numericalDimension = data.dimension(function (d) { return +d.value; }); + describe('a chart with a linear numerical domain', () => { + beforeEach(() => { + const numericalDimension = data.dimension(d => +d.value); chart.dimension(numericalDimension).group(numericalDimension.group()); - chart.x(d3.scale.linear().domain([10, 80])).elasticY(true); + chart.x(d3.scaleLinear().domain([10, 80])).elasticY(true); chart.render(); }); it('should base the y-axis height on the maximum value in the data', function () { - var yAxisMax = 3.0; - var ticks = chart.selectAll('g.y g.tick'); - var tickValues = ticks[0].map(function (tick) { return +d3.select(tick).text(); }); - var maxTickValue = Math.max.apply(this, tickValues); + const yAxisMax = 3.0; + const ticks = chart.selectAll('g.y g.tick'); + const tickValues = ticks.nodes().map(tick => +d3.select(tick).text()); + const maxTickValue = Math.max.apply(this, tickValues); expect(maxTickValue).toBe(yAxisMax); }); - describe('when filters are applied', function () { - beforeEach(function () { - data.dimension(function (d) { return d.countrycode; }).filter('CA'); + describe('when filters are applied', () => { + beforeEach(() => { + data.dimension(d => d.countrycode).filter('CA'); chart.redraw(); }); it('should rescale the y-axis after applying a filter', function () { - var yAxisMax = 1.0; - var ticks = chart.selectAll('g.y g.tick'); - var tickValues = ticks[0].map(function (tick) { return +d3.select(tick).text(); }); - var maxTickValue = Math.max.apply(this, tickValues); + const yAxisMax = 1.0; + const ticks = chart.selectAll('g.y g.tick'); + const tickValues = ticks.nodes().map(tick => +d3.select(tick).text()); + const maxTickValue = Math.max.apply(this, tickValues); expect(maxTickValue).toBe(yAxisMax); }); }); }); }); - describe('with another ordinal domain', function () { - beforeEach(function () { - var rows = []; + describe('with another ordinal domain', () => { + beforeEach(() => { + const rows = []; rows.push({State: 'CA', 'Population': 2704659}); rows.push({State: 'TX', 'Population': 1827307}); data = crossfilter(rows); dimension = data.dimension(dc.pluck('State')); group = dimension.group().reduceSum(dc.pluck('Population')); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.xUnits(dc.units.ordinal) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .transitionDuration(0) .dimension(dimension) .group(group, 'Population'); chart.render(); }); - it('should not overlap bars', function () { - var x = numAttr('x'), wid = numAttr('width'); + it('should not overlap bars', () => { + const x = numAttr('x'), wid = numAttr('width'); expect(x(nthStack(0).nthBar(0)) + wid(nthStack(0).nthBar(0))) .toBeLessThan(x(nthStack(0).nthBar(1))); }); }); - describe('with yetnother ordinal domain', function () { - beforeEach(function () { - var rows = [{ + describe('with yetnother ordinal domain', () => { + beforeEach(() => { + const rows = [{ name: 'Venezuela', sale: 300 }, { @@ -879,31 +922,27 @@ describe('dc.barChart', function () { sale: 37 }]; data = crossfilter(rows); - dimension = data.dimension(function (d) { - return d.name; - }); - group = dimension.group().reduceSum(function (d) { - return d.sale; - }); - chart = dc.barChart('#' + id); + dimension = data.dimension(d => d.name); + group = dimension.group().reduceSum(d => d.sale); + chart = new dc.BarChart(`#${id}`); chart.transitionDuration(0) .outerPadding(0) .dimension(dimension) .group(group) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .xUnits(dc.units.ordinal); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 7; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 7; ++i) { checkBarOverlap(i); } }); }); - describe('with changing number of bars', function () { - beforeEach(function () { - var rows1 = [ + describe('with changing number of bars', () => { + beforeEach(() => { + const rows1 = [ {x: 1, y: 3}, {x: 2, y: 9}, {x: 5, y: 10}, @@ -911,29 +950,25 @@ describe('dc.barChart', function () { ]; data = crossfilter(rows1); - dimension = data.dimension(function (d) { - return d.x; - }); - group = dimension.group().reduceSum(function (d) { - return d.y; - }); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.width(500).transitionDuration(0) - .x(d3.scale.linear().domain([0,7])) + .x(d3.scaleLinear().domain([0,7])) .elasticY(true) .dimension(dimension) .group(group); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 3; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 3; ++i) { checkBarOverlap(i); } }); - describe('with bars added', function () { - beforeEach(function () { - var rows2 = [ + describe('with bars added', () => { + beforeEach(() => { + const rows2 = [ {x: 7, y: 4}, {x: 12, y: 9} ]; @@ -942,17 +977,58 @@ describe('dc.barChart', function () { chart.x().domain([0,13]); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 5; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 5; ++i) { checkBarOverlap(i); } }); }); }); - - describe('with changing number of bars and elasticX', function () { - beforeEach(function () { - var rows1 = [ + describe('with elasticX and x-axis padding', () => { + const date = makeDate(2012, 5, 1); + beforeEach(() => { + const rows = [ + {x: date, y: 4}, + ]; + data = crossfilter(rows); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); + chart = new dc.BarChart(`#${id}`); + chart.width(500) + .transitionDuration(0) + .x(d3.scaleUtc()) + .elasticY(true).elasticX(true) + .dimension(dimension) + .group(group); + chart.render(); + }); + // note: these tests assume that the bar width is not included in the + // chart width, so they should be broken when #792 is fixed + it('should render the right xAxisMax/Min when no padding', () => { + expect(chart.xAxisMin()).toEqual(date); + expect(chart.xAxisMax()).toEqual(date); + }); + it('should render the right xAxisMax/Min when 10 day padding', () => { + chart.xAxisPadding(10) + .render(); + const expectedStartDate = d3.utcDay.offset(date, -10); + const expectedEndDate = d3.utcDay.offset(date, 10); + expect(chart.xAxisMin()).toEqual(expectedStartDate); + expect(chart.xAxisMax()).toEqual(expectedEndDate); + }); + it('should render the right xAxisMax/Min when 2 month padding', () => { + chart.xAxisPaddingUnit('month') + .xAxisPadding(2) + .render(); + const expectedStartDate = d3.utcMonth.offset(date, -2); + const expectedEndDate = d3.utcMonth.offset(date, 2); + expect(chart.xAxisMin()).toEqual(expectedStartDate); + expect(chart.xAxisMax()).toEqual(expectedEndDate); + }); + }); + describe('with changing number of bars and elasticX', () => { + beforeEach(() => { + const rows1 = [ {x: 1, y: 3}, {x: 2, y: 9}, {x: 5, y: 10}, @@ -960,29 +1036,25 @@ describe('dc.barChart', function () { ]; data = crossfilter(rows1); - dimension = data.dimension(function (d) { - return d.x; - }); - group = dimension.group().reduceSum(function (d) { - return d.y; - }); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.width(500).transitionDuration(0) - .x(d3.scale.linear()) + .x(d3.scaleLinear()) .elasticY(true).elasticX(true) .dimension(dimension) .group(group); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 3; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 3; ++i) { checkBarOverlap(i); } }); - describe('with bars added', function () { - beforeEach(function () { - var rows2 = [ + describe('with bars added', () => { + beforeEach(() => { + const rows2 = [ {x: 7, y: 4}, {x: 12, y: 9} ]; @@ -990,17 +1062,17 @@ describe('dc.barChart', function () { data.add(rows2); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 5; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 5; ++i) { checkBarOverlap(i); } }); }); }); - describe('with changing number of ordinal bars and elasticX', function () { - beforeEach(function () { - var rows1 = [ + describe('with changing number of ordinal bars and elasticX', () => { + beforeEach(() => { + const rows1 = [ {x: 'a', y: 3}, {x: 'b', y: 9}, {x: 'e', y: 10}, @@ -1008,30 +1080,26 @@ describe('dc.barChart', function () { ]; data = crossfilter(rows1); - dimension = data.dimension(function (d) { - return d.x; - }); - group = dimension.group().reduceSum(function (d) { - return d.y; - }); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.width(500).transitionDuration(0) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .xUnits(dc.units.ordinal) .elasticY(true).elasticX(true) .dimension(dimension) .group(group); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 3; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 3; ++i) { checkBarOverlap(i); } }); - describe('with bars added', function () { - beforeEach(function () { - var rows2 = [ + describe('with bars added', () => { + beforeEach(() => { + const rows2 = [ {x: 'g', y: 4}, {x: 'l', y: 9} ]; @@ -1039,62 +1107,63 @@ describe('dc.barChart', function () { data.add(rows2); chart.render(); }); - it('should not overlap bars', function () { - for (var i = 0; i < 5; ++i) { + it('should not overlap bars', () => { + for (let i = 0; i < 5; ++i) { checkBarOverlap(i); } }); }); }); - describe('brushing with bars centered and rounding enabled', function () { - beforeEach(function () { + describe('brushing with bars centered and rounding enabled', () => { + beforeEach(() => { chart .brushOn(true) - .round(d3.time.month.utc.round) + .round(d3.utcMonth.round) .centerBar(true); }); - describe('with alwaysUseRounding disabled', function () { - var consoleWarnSpy; + describe('with alwaysUseRounding disabled', () => { + let consoleWarnSpy; - beforeEach(function () { + beforeEach(() => { chart.alwaysUseRounding(false); consoleWarnSpy = spyOn(console, 'warn'); chart.render(); - chart.brush().extent([makeDate(2012, 6, 1), makeDate(2012, 7, 15)]); - chart.brush().event(chart.root()); + + simulateChartBrushing(chart, [makeDate(2012, 6, 1), makeDate(2012, 7, 15)]); }); - it('should log a warning indicating that brush rounding was disabled', function () { + it('should log a warning indicating that brush rounding was disabled', () => { expect(consoleWarnSpy.calls.mostRecent().args[0]).toMatch(/brush rounding is disabled/); }); - it('should not round the brush', function () { + it('should not round the brush', () => { jasmine.clock().tick(100); - var filter = cleanDateRange(chart.filter()); + const filter = cleanDateRange(chart.filter()); expect(filter).toEqual([makeDate(2012, 6, 1), makeDate(2012, 7, 15)]); }); }); - describe('with alwaysUseRounding enabled', function () { - beforeEach(function () { + describe('with alwaysUseRounding enabled', () => { + beforeEach(() => { chart.alwaysUseRounding(true); chart.render(); - chart.brush().extent([makeDate(2012, 6, 1), makeDate(2012, 7, 15)]); - chart.brush().event(chart.root()); + + simulateChartBrushing(chart, [makeDate(2012, 6, 1), makeDate(2012, 7, 15)]); }); - it('should round the brush', function () { + it('should round the brush', () => { jasmine.clock().tick(100); - expect(chart.brush().extent()).toEqual([makeDate(2012, 6, 1), makeDate(2012, 7, 1)]); + const filter = cleanDateRange(chart.filter()); + expect(filter).toEqual([makeDate(2012, 6, 1), makeDate(2012, 7, 1)]); }); }); }); - describe('check ordering option of the x axis', function () { - beforeEach(function () { - var rows = [ + describe('check ordering option of the x axis', () => { + beforeEach(() => { + const rows = [ {x: 'a', y: 1}, {x: 'b', y: 3}, {x: 'd', y: 4}, @@ -1104,16 +1173,12 @@ describe('dc.barChart', function () { id = 'bar-chart'; appendChartID(id); data = crossfilter(rows); - dimension = data.dimension(function (d) { - return d.x; - }); - group = dimension.group().reduceSum(function (d) { - return d.y; - }); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.width(500).transitionDuration(0) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .xUnits(dc.units.ordinal) .elasticY(true).elasticX(true) .dimension(dimension) @@ -1121,38 +1186,44 @@ describe('dc.barChart', function () { chart.render(); }); - it('should be ordered by default alphabetical order', function () { - var data = chart.data()['0'].values; - var expectedData = ['a', 'b', 'c', 'd']; - expect(data.map(function (d) { return d.x; })).toEqual(expectedData); + it('should be ordered by default alphabetical order', () => { + const data02 = chart.data()['0'].values; + const expectedData = ['a', 'b', 'c', 'd']; + expect(data02.map(d => d.x)).toEqual(expectedData); }); - it('should be ordered by value increasing', function () { - chart.ordering(function (d) { return d.value; }); + it('should be ordered by value increasing', () => { + chart.ordering(d => d.value); chart.redraw(); expect(xAxisText()).toEqual(['a', 'c', 'b', 'd']); }); - it('should be ordered by value decreasing', function () { - chart.ordering(function (d) { return -d.value; }); + it('should be ordered by value decreasing', () => { + chart.ordering(d => -d.value); chart.redraw(); expect(xAxisText()).toEqual(['d', 'b', 'c', 'a']); }); - it('should be ordered by alphabetical order', function () { - chart.ordering(function (d) { return d.key; }); + it('should be ordered by alphabetical order', () => { + function reverseGroup (_group) { + return { + all: () => Array.from(_group.all()).reverse() + }; + } + chart.group(reverseGroup(group)); + chart.ordering(d => d.key); chart.redraw(); expect(xAxisText()).toEqual(['a', 'b', 'c', 'd']); }); function xAxisText () { - return chart.selectAll('g.x text')[0].map(function (x) { return d3.select(x).text(); }); + return chart.selectAll('g.x text').nodes().map(x => d3.select(x).text()); } }); - describe('ordering with stacks', function () { - beforeEach(function () { - var rows = [ + describe('ordering with stacks', () => { + beforeEach(() => { + const rows = [ {x: 'a', y: 1, z: 10}, {x: 'b', y: 3, z: 20}, {x: 'd', y: 4, z: 30}, @@ -1162,19 +1233,13 @@ describe('dc.barChart', function () { id = 'bar-chart'; appendChartID(id); data = crossfilter(rows); - dimension = data.dimension(function (d) { - return d.x; - }); - group = dimension.group().reduceSum(function (d) { - return d.y; - }); - var group2 = dimension.group().reduceSum(function (d) { - return d.z; - }); + dimension = data.dimension(d => d.x); + group = dimension.group().reduceSum(d => d.y); + const group2 = dimension.group().reduceSum(d => d.z); - chart = dc.barChart('#' + id); + chart = new dc.BarChart(`#${id}`); chart.width(500).transitionDuration(0) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .xUnits(dc.units.ordinal) .elasticY(true).elasticX(true) .dimension(dimension) @@ -1183,46 +1248,121 @@ describe('dc.barChart', function () { chart.render(); }); - it('should be ordered by default alphabetical order', function () { - var data = chart.data()['0'].values; - var expectedData = ['a', 'b', 'c', 'd']; - expect(data.map(function (d) { return d.x; })).toEqual(expectedData); + it('should be ordered by default alphabetical order', () => { + const data02 = chart.data()['0'].values; + const expectedData = ['a', 'b', 'c', 'd']; + expect(data02.map(d => d.x)).toEqual(expectedData); }); // note: semantics are kind of screwy here: which stack do you want to sort // by when you order by value? right now it's all of them together. - it('should be ordered by value increasing', function () { - chart.ordering(function (d) { return d.value; }); + it('should be ordered by value increasing', () => { + chart.ordering(d => d.value); chart.redraw(); expect(xAxisText()).toEqual(['a', 'c', 'b', 'd']); }); - it('should be ordered by value decreasing', function () { - chart.ordering(function (d) { return -d.value; }); + it('should be ordered by value decreasing', () => { + chart.ordering(d => -d.value); chart.redraw(); expect(xAxisText()).toEqual(['c', 'd', 'b', 'a']); }); - it('should be ordered by alphabetical order', function () { - chart.ordering(function (d) { return d.key; }); + it('should be ordered by alphabetical order', () => { + chart.ordering(d => d.key); chart.redraw(); expect(xAxisText()).toEqual(['a', 'b', 'c', 'd']); }); function xAxisText () { - return chart.selectAll('g.x text')[0].map(function (x) { return d3.select(x).text(); }); + return chart.selectAll('g.x text').nodes().map(x => d3.select(x).text()); + } + }); + + describe('accessibility bar chart', () => { + + function removeEmptyBins (sourceGroup) { + return { + all:function () { + return sourceGroup.all().filter( d => d.value !== 0); + } + }; } + + it('internal elements are focusable by keyboard', () => { + chart.keyboardAccessible(true); + chart.render(); + chart.selectAll('rect.bar').each(function () { + const bar = d3.select(this); + expect(bar.attr('tabindex')).toEqual('0'); + }); + }); + + it('initial internal elements are clickable by pressing enter', () => { + chart.keyboardAccessible(true); + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('rect.bar').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + + it('newly added internal elements are also clickable from keyboard', () => { + chart.keyboardAccessible(true); + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + + const event = new Event('keydown'); + event.keyCode = 13; + + const stateDimension = data.dimension(d => d.state); + const regionDimension = data.dimension(d => d.region); + const stateGroup = stateDimension.group().reduceSum(d => +d.value); + const ordinalDomainValues = ['California', 'Colorado', 'Delaware', 'Ontario', 'Mississippi', 'Oklahoma']; + + chart + .dimension(stateDimension) + .group(removeEmptyBins(stateGroup)) + .xUnits(dc.units.ordinal) + .x(d3.scaleBand().domain(ordinalDomainValues)) + .elasticX(true) + .barPadding(0) + .outerPadding(0.1) + .transitionDuration(0) + .render(); + + //force creation of new elements on existing chart + regionDimension.filterExact('West'); + chart.redraw(); + regionDimension.filterAll(); + chart.redraw(); + + chart.selectAll('rect.bar').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + + }); + }); function nthStack (n) { - var stack = d3.select(chart.selectAll('.stack')[0][n]); + const stack = d3.select(chart.selectAll('.stack').nodes()[n]); - stack.nthBar = function (n) { - return d3.select(this.selectAll('rect.bar')[0][n]); + stack.nthBar = function (i) { + return d3.select(this.selectAll('rect.bar').nodes()[i]); }; - stack.nthLabel = function (n) { - return d3.select(this.selectAll('text.barLabel')[0][n]); + stack.nthLabel = function (i) { + return d3.select(this.selectAll('text.barLabel').nodes()[i]); }; stack.forEachBar = function (assertions) { @@ -1248,7 +1388,7 @@ describe('dc.barChart', function () { } function checkBarOverlap (n) { - var x = numAttr('x'), wid = numAttr('width'); + const x = numAttr('x'), wid = numAttr('width'); expect(x(nthStack(0).nthBar(n)) + wid(nthStack(0).nthBar(n))) .toBeLessThan(x(nthStack(0).nthBar(n + 1))); } diff --git a/spec/base-mixin-spec.js b/spec/base-mixin-spec.js index 6a6d63b18c..d11caeeee0 100644 --- a/spec/base-mixin-spec.js +++ b/spec/base-mixin-spec.js @@ -1,15 +1,11 @@ /* global appendChartID, flushAllD3Transitions, loadDateFixture */ -describe('dc.baseMixin', function () { - var id, chart, dimension, group, addFilterHandler, removeFilterHandler, hasFilterHandler, resetFilterHandler; +describe('dc.baseMixin', () => { + let id, chart, dimension, group, addFilterHandler, removeFilterHandler, hasFilterHandler, resetFilterHandler; - beforeEach(function () { - var data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { - return d3.time.day.utc(d.dd); - }); - group = dimension.group().reduceSum(function (d) { - return d.value; - }); + beforeEach(() => { + const data = crossfilter(loadDateFixture()); + dimension = data.dimension(d => d3.utcDay(d.dd)); + group = dimension.group().reduceSum(d => d.value); chart = dc.baseMixin({}) .options({ @@ -19,7 +15,7 @@ describe('dc.baseMixin', function () { }); id = 'base-chart'; appendChartID(id); - chart.anchor('#' + id) + chart.anchor(`#${id}`) .resetSvg(); // so that renderlets can fire addFilterHandler = chart.addFilterHandler(); hasFilterHandler = chart.hasFilterHandler(); @@ -27,126 +23,167 @@ describe('dc.baseMixin', function () { resetFilterHandler = chart.resetFilterHandler(); }); - describe('renderlets', function () { - var firstRenderlet, secondRenderlet, thirdRenderlet, - pretransition; - beforeEach(function () { - var expectedCallbackSignature = function (callbackChart) { + describe('renderlets', () => { + it('should not execute a renderlet until after the render transitions', done => { + const firstRenderlet = jasmine.createSpy().and.callFake(callbackChart => { expect(callbackChart).toBe(chart); - }; - firstRenderlet = jasmine.createSpy().and.callFake(expectedCallbackSignature); - secondRenderlet = jasmine.createSpy().and.callFake(expectedCallbackSignature); - thirdRenderlet = jasmine.createSpy().and.callFake(expectedCallbackSignature); - pretransition = jasmine.createSpy().and.callFake(expectedCallbackSignature); - chart.renderlet(firstRenderlet); // still testing renderlet event-namespace generation here - chart.renderlet(secondRenderlet); - chart.on('renderlet.third', thirdRenderlet); - chart.on('pretransition.pret', pretransition); - }); - - it('should not execute a renderlet until after the render transitions', function () { + done(); + }); + chart.renderlet(firstRenderlet); chart.render(); expect(firstRenderlet).not.toHaveBeenCalled(); flushAllD3Transitions(); - expect(firstRenderlet).toHaveBeenCalled(); + // Test will wait until firstRenderlet has been called }); - it('should not execute a renderlet until after the redraw transitions', function () { + it('should not execute a renderlet until after the redraw transitions', done => { + const firstRenderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(callbackChart).toBe(chart); + done(); + }); + chart.renderlet(firstRenderlet); chart.redraw(); expect(firstRenderlet).not.toHaveBeenCalled(); flushAllD3Transitions(); - expect(firstRenderlet).toHaveBeenCalled(); + // Test will wait until firstRenderlet has been called }); - it('should execute pretransition event before the render transitions', function () { + it('should execute pretransition event before the render transitions', () => { + const pretransition = jasmine.createSpy(); + chart.on('pretransition.pret', pretransition); chart.render(); - expect(pretransition).toHaveBeenCalled(); + expect(pretransition).toHaveBeenCalledWith(chart); flushAllD3Transitions(); }); - it('should execute pretransition event before the redraw transitions', function () { + it('should execute pretransition event before the redraw transitions', () => { + const pretransition = jasmine.createSpy(); + chart.on('pretransition.pret', pretransition); chart.redraw(); - expect(pretransition).toHaveBeenCalled(); + expect(pretransition).toHaveBeenCalledWith(chart); flushAllD3Transitions(); }); - it('should execute each renderlet after a render', function () { + it('should execute each renderlet after a render', done => { + let count = 0; + const renderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(callbackChart).toBe(chart); + count++; + if (count === 2) { + done(); + } + }); + const firstRenderlet = renderlet; + chart.renderlet(firstRenderlet); + chart.renderlet(firstRenderlet); chart.render(); flushAllD3Transitions(); - expect(firstRenderlet).toHaveBeenCalled(); - expect(secondRenderlet).toHaveBeenCalled(); + // Test will wait till firstRenderlet and secondRenderlet both have been called }); - it('should execute each renderlet after a redraw', function () { + it('should execute each renderlet after a redraw', done => { + let count = 0; + const renderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(callbackChart).toBe(chart); + count++; + if (count === 2) { + done(); + } + }); + const firstRenderlet = renderlet; + chart.renderlet(firstRenderlet); + chart.renderlet(firstRenderlet); chart.redraw(); flushAllD3Transitions(); - expect(firstRenderlet).toHaveBeenCalled(); - expect(secondRenderlet).toHaveBeenCalled(); + // Test will wait till firstRenderlet and secondRenderlet both have been called }); - it('should execute a named renderlet after a render', function () { + it('should execute a named renderlet after a render', done => { + const thirdRenderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(callbackChart).toBe(chart); + done(); + }); + chart.on('renderlet.third', thirdRenderlet); chart.render(); + expect(thirdRenderlet).not.toHaveBeenCalled(); flushAllD3Transitions(); - expect(thirdRenderlet).toHaveBeenCalled(); + // Test will wait until thirdRenderlet has been called }); - it('should execute a named renderlet after a redraw', function () { + it('should execute a named renderlet after a redraw', done => { + const thirdRenderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(callbackChart).toBe(chart); + done(); + }); + chart.on('renderlet.third', thirdRenderlet); chart.redraw(); flushAllD3Transitions(); - expect(thirdRenderlet).toHaveBeenCalled(); + // Test will wait until thirdRenderlet has been called }); - it('should remove a named renderlet expect no call after a redraw', function () { + it('should remove a named renderlet expect no call after a redraw', done => { + const thirdRenderlet = jasmine.createSpy(); + const secondRenderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(thirdRenderlet).not.toHaveBeenCalled(); + done(); + }); + chart.on('renderlet.third' , secondRenderlet); + chart.renderlet(secondRenderlet); chart.on('renderlet.third'); chart.redraw(); flushAllD3Transitions(); - expect(secondRenderlet).toHaveBeenCalled(); - expect(thirdRenderlet).not.toHaveBeenCalled(); + // Test will wait until secondRenderlet has been called }); - it('should remove a named renderlet and expect no call after a redraw', function () { + it('should remove a named renderlet and expect no call after a render', done => { + const thirdRenderlet = jasmine.createSpy(); + const secondRenderlet = jasmine.createSpy().and.callFake(callbackChart => { + expect(thirdRenderlet).not.toHaveBeenCalled(); + done(); + }); + chart.on('renderlet.third' , secondRenderlet); + chart.renderlet(secondRenderlet); chart.on('renderlet.third'); chart.render(); flushAllD3Transitions(); - expect(secondRenderlet).toHaveBeenCalled(); - expect(thirdRenderlet).not.toHaveBeenCalled(); + // Test will wait until secondRenderlet has been called }); }); - describe('event listeners', function () { - describe('on render', function () { - var preRenderSpy, postRenderSpy; - beforeEach(function () { - var expectedCallbackSignature = function (callbackChart) { - expect(callbackChart).toBe(chart); - }; - - preRenderSpy = jasmine.createSpy().and.callFake(expectedCallbackSignature); - postRenderSpy = jasmine.createSpy().and.callFake(expectedCallbackSignature); - + describe('event listeners', () => { + describe('on render', () => { + it('should execute the preRender callback', () => { + const preRenderSpy = jasmine.createSpy(); chart.on('preRender', preRenderSpy); - chart.on('postRender', postRenderSpy); - }); - - it('should execute the preRender callback', function () { chart.render(); flushAllD3Transitions(); - expect(preRenderSpy).toHaveBeenCalled(); + expect(preRenderSpy).toHaveBeenCalledWith(chart); }); - it('should execute the postRender callback', function () { + it('should execute the postRender callback', done => { + const preRenderSpy = jasmine.createSpy(); + const postRender = function (callbackChart) { + // By now preRender must have been called + expect(preRenderSpy).toHaveBeenCalledWith(chart); + + expect(callbackChart).toBe(chart); + done(); + }; + + chart.on('preRender', preRenderSpy); + chart.on('postRender', postRender); chart.render(); flushAllD3Transitions(); - expect(postRenderSpy).toHaveBeenCalled(); + // Test case will wait until postRender has been called }); }); - describe('on filter double', function () { - var filterSpy, filterSpy2, filter; - beforeEach(function () { + describe('on filter double', () => { + let filterSpy, filterSpy2, filter; + beforeEach(() => { filter = '1'; - var expectedCallbackSignature = function (callbackChart, callbackFilter) { + const expectedCallbackSignature = function (callbackChart, callbackFilter) { expect(callbackChart).toBe(chart); expect(callbackFilter).toEqual(filter); }; @@ -157,28 +194,28 @@ describe('dc.baseMixin', function () { chart.on('filtered.two', filterSpy2); }); - it('should execute first callback after setting through #filter', function () { + it('should execute first callback after setting through #filter', () => { chart.filter(filter); expect(filterSpy).toHaveBeenCalled(); }); - it('should execute second callback after setting through #filter', function () { + it('should execute second callback after setting through #filter', () => { chart.filter(filter); expect(filterSpy2).toHaveBeenCalled(); }); - it('should not execute callback after reading from #filter', function () { + it('should not execute callback after reading from #filter', () => { chart.filter(); expect(filterSpy).not.toHaveBeenCalled(); }); }); - describe('on filter', function () { - var filterSpy, filter; - beforeEach(function () { + describe('on filter', () => { + let filterSpy, filter; + beforeEach(() => { filter = '1'; - var expectedCallbackSignature = function (callbackChart, callbackFilter) { + const expectedCallbackSignature = function (callbackChart, callbackFilter) { expect(callbackChart).toBe(chart); expect(callbackFilter).toEqual(filter); }; @@ -187,106 +224,104 @@ describe('dc.baseMixin', function () { chart.on('filtered', filterSpy); }); - it('should execute callback after setting through #filter', function () { + it('should execute callback after setting through #filter', () => { chart.filter(filter); expect(filterSpy).toHaveBeenCalled(); }); - it('should not execute callback after reading from #filter', function () { + it('should not execute callback after reading from #filter', () => { chart.filter(); expect(filterSpy).not.toHaveBeenCalled(); }); }); - describe('on redraw', function () { - var preRedrawSpy, postRedrawSpy; - beforeEach(function () { - var expectedCallbackSignature = function (callbackChart) { - expect(callbackChart).toBe(chart); - }; - - preRedrawSpy = jasmine.createSpy().and.callFake(expectedCallbackSignature); - postRedrawSpy = jasmine.createSpy().and.callFake(expectedCallbackSignature); - + describe('on redraw', () => { + it('should execute the preRedraw callback before transitions', () => { + const preRedrawSpy = jasmine.createSpy(); chart.on('preRedraw', preRedrawSpy); - chart.on('postRedraw', postRedrawSpy); - }); - - it('should execute the preRedraw callback before transitions', function () { chart.redraw(); - expect(preRedrawSpy).toHaveBeenCalled(); + expect(preRedrawSpy).toHaveBeenCalledWith(chart); flushAllD3Transitions(); }); - it('should execute the postRedraw callback after transitions', function () { + it('should execute the postRedraw callback after transitions', done => { + const preRedrawSpy = jasmine.createSpy(); + const postRedraw = function (callbackChart) { + // By now preRedraw must have been called + expect(preRedrawSpy).toHaveBeenCalledWith(chart); + + expect(callbackChart).toBe(chart); + done(); + }; + const postRedrawSpy = jasmine.createSpy().and.callFake(postRedraw); + chart.on('preRedraw', preRedrawSpy); + chart.on('postRedraw', postRedraw); chart.redraw(); expect(postRedrawSpy).not.toHaveBeenCalled(); flushAllD3Transitions(); - expect(postRedrawSpy).toHaveBeenCalled(); + // The test case will wait till postRedraw has been called }); }); }); - describe('validations', function () { + describe('validations', () => { - it('should require dimension', function () { + it('should require dimension', () => { try { dc.baseMixin({}).group(group).render(); throw new Error('That should\'ve thrown'); } catch (e) { - expect(e instanceof dc.errors.InvalidStateException).toBeTruthy(); + expect(e instanceof dc.InvalidStateException).toBeTruthy(); } }); - it('should require group', function () { + it('should require group', () => { try { dc.baseMixin({}).dimension(dimension).render(); throw new Error('That should\'ve thrown'); } catch (e) { - expect(e instanceof dc.errors.InvalidStateException).toBeTruthy(); + expect(e instanceof dc.InvalidStateException).toBeTruthy(); } }); }); - describe('anchoring chart to dom', function () { - var id; - - beforeEach(function () { + describe('anchoring chart to dom', () => { + beforeEach(() => { id = 'chart-id'; }); - describe('using a d3-created dom element', function () { - var anchorDiv; + describe('using a d3-created dom element', () => { + let anchorDiv; - beforeEach(function () { + beforeEach(() => { anchorDiv = d3.select('body').append('div').attr('id', id).node(); chart.anchor(anchorDiv); }); - it('should register the chart', function () { + it('should register the chart', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should return the node, when anchor is called', function () { + it('should return the node, when anchor is called', () => { expect(chart.anchor()).toEqual(anchorDiv); }); - it('should return the id, when anchorName is called', function () { + it('should return the id, when anchorName is called', () => { expect(chart.anchorName()).toEqual(id); }); - describe('without an id', function () { - beforeEach(function () { - d3.select('#' + id).remove(); + describe('without an id', () => { + beforeEach(() => { + d3.select(`#${id}`).remove(); anchorDiv = d3.select('body').append('div').attr('class', 'no-id').node(); chart.anchor(anchorDiv); }); - it('should return the node, when anchor is called', function () { + it('should return the node, when anchor is called', () => { expect(chart.anchor()).toEqual(anchorDiv); }); - it('should return a valid, selectable id', function () { + it('should return a valid, selectable id', () => { // see http://stackoverflow.com/questions/70579/what-are-valid-values-for-the-id-attribute-in-html expect(chart.anchorName()).toMatch(/^[a-zA-Z][a-zA-Z0-9_:.-]*$/); }); @@ -294,38 +329,38 @@ describe('dc.baseMixin', function () { }); }); - describe('using a d3 selection', function () { - var anchorDiv; + describe('using a d3 selection', () => { + let anchorDiv; - beforeEach(function () { + beforeEach(() => { anchorDiv = d3.select('body').append('div').attr('id', id); chart.anchor(anchorDiv); }); - it('should register the chart', function () { + it('should register the chart', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should return the node, when anchor is called', function () { + it('should return the node, when anchor is called', () => { expect(chart.anchor()).toEqual(anchorDiv.node()); }); - it('should return the id, when anchorName is called', function () { + it('should return the id, when anchorName is called', () => { expect(chart.anchorName()).toEqual(id); }); - describe('without an id', function () { - beforeEach(function () { - d3.select('#' + id).remove(); + describe('without an id', () => { + beforeEach(() => { + d3.select(`#${id}`).remove(); anchorDiv = d3.select('body').append('div').attr('class', 'no-id').node(); chart.anchor(anchorDiv); }); - it('should return the node, when anchor is called', function () { + it('should return the node, when anchor is called', () => { expect(chart.anchor()).toEqual(anchorDiv); }); - it('should return a valid, selectable id', function () { + it('should return a valid, selectable id', () => { // see http://stackoverflow.com/questions/70579/what-are-valid-values-for-the-id-attribute-in-html expect(chart.anchorName()).toMatch(/^[a-zA-Z][a-zA-Z0-9_:.-]*$/); }); @@ -333,84 +368,82 @@ describe('dc.baseMixin', function () { }); }); - describe('using an id selector', function () { - beforeEach(function () { + describe('using an id selector', () => { + beforeEach(() => { d3.select('body').append('div').attr('id', id); - chart.anchor('#' + id); + chart.anchor(`#${id}`); }); - it('should add the dc chart class to its parent div', function () { + it('should add the dc chart class to its parent div', () => { expect(chart.root().classed('dc-chart')).toBeTruthy(); }); - it('should return the id selector when anchor is called', function () { - expect(chart.anchor()).toEqual('#' + id); + it('should return the id selector when anchor is called', () => { + expect(chart.anchor()).toEqual(`#${id}`); }); - it('should return the id when anchorName is called', function () { + it('should return the id when anchorName is called', () => { expect(chart.anchorName()).toEqual(id); }); }); }); - describe('calculation of dimensions', function () { - var dimdiv, bodyWidth; - beforeEach(function () { + describe('calculation of dimensions', () => { + let dimdiv; + beforeEach(() => { dimdiv = appendChartID('dimensionTest'); chart.anchor('#dimensionTest'); - bodyWidth = d3.select('body')[0][0].getBoundingClientRect().width; }); - describe('when set to a falsy on a sized div', function () { - var h0, w0; - beforeEach(function () { - dimdiv.style({ - height: '220px', - width: '230px' - }); + describe('when set to a falsy on a sized div', () => { + let h0, w0; + beforeEach(() => { + dimdiv + .style('height', '220px') + .style('width', '230px'); chart.width(null).height(null).render(); w0 = chart.width(); h0 = chart.height(); }); - it('should set the height to the div size', function () { - expect(chart.height()).toBeCloseTo(220,1); + it('should set the height to the div size', () => { + expect(chart.height()).toBeCloseTo(220, 1); }); - it('should set the width to the div size', function () { - expect(chart.width()).toBeCloseTo(230,1); + it('should set the width to the div size', () => { + expect(chart.width()).toBeCloseTo(230, 1); }); - describe('and redrawn', function () { - beforeEach(function () { + describe('and redrawn', () => { + beforeEach(() => { chart.redraw(); }); - it('should keep the size the same', function () { - expect(chart.height()).toEqual(h0,1); + it('should keep the size the same', () => { + expect(chart.height()).toEqual(h0, 1); expect(chart.width()).toEqual(w0); }); }); - describe('and minimums set', function () { - beforeEach(function () { + describe('and minimums set', () => { + beforeEach(() => { chart.minHeight(234).minWidth(976) .render(); }); - it('should set the height to the minimum', function () { - expect(chart.height()).toBeCloseTo(234,1); + it('should set the height to the minimum', () => { + expect(chart.height()).toBeCloseTo(234, 1); }); - it('should set the width to the minimum', function () { - expect(chart.width()).toBeCloseTo(976,1); + it('should set the width to the minimum', () => { + expect(chart.width()).toBeCloseTo(976, 1); }); }); }); - describe('when set to a falsy on an unsized div with junk in it', function () { - var h0, w0; - beforeEach(function () { + describe('when set to a falsy on an unsized div with junk in it', () => { + let h0, w0; + beforeEach(() => { dimdiv.append('h1').text('helL0'); chart.width(null).height(null) .render() @@ -419,61 +452,103 @@ describe('dc.baseMixin', function () { h0 = chart.height(); }); - it('should set the height to at least the default minimum', function () { + it('should set the height to at least the default minimum', () => { expect(chart.height()).not.toBeLessThan(200); }); - it('should set the width to at least the default minimum', function () { + it('should set the width to at least the default minimum', () => { expect(chart.width()).not.toBeLessThan(200); }); - describe('and redrawn', function () { - beforeEach(function () { + describe('and redrawn', () => { + beforeEach(() => { chart.redraw(); }); - it('should keep the size the same', function () { + it('should keep the size the same', () => { expect(chart.height()).toEqual(h0); expect(chart.width()).toEqual(w0); }); }); }); - describe('when set with a number', function () { - beforeEach(function () { + describe('when set with a number', () => { + beforeEach(() => { chart.width(300).height(301).render(); }); - it('should set the height', function () { + it('should set the height', () => { expect(chart.height()).toEqual(301); }); - it('should set the width', function () { + it('should set the width', () => { expect(chart.width()).toEqual(300); }); }); - describe('when set to a callback function', function () { - var setterSpy; - beforeEach(function () { + describe('when set to a callback function', () => { + let setterSpy; + beforeEach(() => { setterSpy = jasmine.createSpy().and.returnValue(800); chart.width(setterSpy).render(); }); - it('should not execute callback before width() is called', function () { + it('should not execute callback before width() is called', () => { expect(setterSpy).not.toHaveBeenCalled(); }); - it('should ask the callback for the width', function () { + it('should ask the callback for the width', () => { expect(chart.width()).toEqual(800); expect(setterSpy).toHaveBeenCalled(); }); }); }); - describe('filter handling', function () { - var filter, notFilter; - beforeEach(function () { + describe('viewbox resizing strategy', () => { + beforeEach(() => { + chart + .width(600) + .height(400) + .resetSvg(); + }); + it('useViewBoxResizing defaults false', () => { + expect(chart.useViewBoxResizing()).toBeFalsy(); + }); + + it('svg has no viewbox when useViewBoxResizing is false', () => { + expect(chart.svg().attr('viewBox')).toBeNull(); + }); + + it('svg has width, height when useViewBoxResizing is false', () => { + expect(chart.svg().attr('width')).toBe('600'); + expect(chart.svg().attr('height')).toBe('400'); + }); + + describe('with viewbox enabled', () => { + beforeEach(() => { + chart + .useViewBoxResizing(true) + .resetSvg(); + }); + + it('has useViewBoxResizing set', () => { + expect(chart.useViewBoxResizing()).toBeTruthy(); + }); + + it('svg has viewbox encoding width and height', () => { + expect(chart.svg().attr('viewBox')).toEqual('0 0 600 400'); + }); + + it('svg does not have width, height attributes', () => { + expect(chart.svg().attr('width')).toBeNull(); + expect(chart.svg().attr('height')).toBeNull(); + }); + }); + }); + + describe('filter handling', () => { + let filter, notFilter; + beforeEach(() => { // 1 && 0 should handle most cases. Could be true/false booleans... filter = 1; notFilter = 0; @@ -483,39 +558,37 @@ describe('dc.baseMixin', function () { chart.resetFilterHandler(resetFilterHandler); chart.filterAll(); }); - it('with the default hasFilterHandler', function () { + it('with the default hasFilterHandler', () => { chart.filter(filter); expect(chart.hasFilter(filter)).toBeTruthy(); expect(chart.hasFilter(notFilter)).toBeFalsy(); }); - it('with a truthy hasFilterHandler', function () { + it('with a truthy hasFilterHandler', () => { chart.filter(filter); - chart.hasFilterHandler(function () { return true; }); + chart.hasFilterHandler(() => true); expect(chart.hasFilter(filter)).toBeTruthy(); expect(chart.hasFilter(notFilter)).toBeTruthy(); }); - it('with a falsy hasFilterHandler', function () { + it('with a falsy hasFilterHandler', () => { chart.filter(filter); - chart.hasFilterHandler(function () { return false; }); + chart.hasFilterHandler(() => false); expect(chart.hasFilter(filter)).toBeFalsy(); expect(chart.hasFilter(notFilter)).toBeFalsy(); }); - it('with the default addFilterHandler', function () { + it('with the default addFilterHandler', () => { chart.filter(filter); expect(chart.hasFilter(filter)).toBeTruthy(); expect(chart.filters().length).toEqual(1); }); - it('with a noop addFilterHandler', function () { - chart.addFilterHandler(function (filters, filter) { - return filters; - }); + it('with a noop addFilterHandler', () => { + chart.addFilterHandler((filters, f) => filters); chart.filter(filter); expect(chart.hasFilter(filter)).toBeFalsy(); expect(chart.hasFilter(notFilter)).toBeFalsy(); expect(chart.filters().length).toEqual(0); }); - it('with a static addFilterHandler', function () { - chart.addFilterHandler(function (filters, filter) { + it('with a static addFilterHandler', () => { + chart.addFilterHandler((filters, f) => { filters.push(notFilter); return filters; }); @@ -524,7 +597,7 @@ describe('dc.baseMixin', function () { expect(chart.hasFilter(notFilter)).toBeTruthy(); expect(chart.filters().length).toEqual(1); }); - it('with the default removeFilterHandler', function () { + it('with the default removeFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); expect(chart.filters().length).toEqual(2); @@ -537,12 +610,10 @@ describe('dc.baseMixin', function () { expect(chart.hasFilter(notFilter)).toBeFalsy(); expect(chart.filters().length).toEqual(0); }); - it('with a noop removeFilterHandler', function () { + it('with a noop removeFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); - chart.removeFilterHandler(function (filters, filter) { - return filters; - }); + chart.removeFilterHandler((filters, f) => filters); expect(chart.filters().length).toEqual(2); chart.filter(filter); expect(chart.hasFilter(filter)).toBeTruthy(); @@ -553,10 +624,10 @@ describe('dc.baseMixin', function () { expect(chart.hasFilter(notFilter)).toBeTruthy(); expect(chart.filters().length).toEqual(2); }); - it('with a shift removeFilterHandler', function () { + it('with a shift removeFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); - chart.removeFilterHandler(function (filters, filter) { + chart.removeFilterHandler((filters, f) => { if (filters.length > 0) { filters.shift(); } @@ -572,7 +643,7 @@ describe('dc.baseMixin', function () { expect(chart.hasFilter(notFilter)).toBeFalsy(); expect(chart.filters().length).toEqual(0); }); - it('with the default resetFilterHandler', function () { + it('with the default resetFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); chart.filter(null); @@ -580,21 +651,19 @@ describe('dc.baseMixin', function () { expect(chart.hasFilter(notFilter)).toBeFalsy(); expect(chart.filters().length).toEqual(0); }); - it('with a noop resetFilterHandler', function () { + it('with a noop resetFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); - chart.resetFilterHandler(function (filters) { - return filters; - }); + chart.resetFilterHandler(filters => filters); chart.filter(null); expect(chart.hasFilter(filter)).toBeTruthy(); expect(chart.hasFilter(notFilter)).toBeTruthy(); expect(chart.filters().length).toEqual(2); }); - it('with a shift resetFilterHandler', function () { + it('with a shift resetFilterHandler', () => { chart.filter(filter); chart.filter(notFilter); - chart.resetFilterHandler(function (filters) { + chart.resetFilterHandler(filters => { filters.shift(); return filters; }); @@ -608,4 +677,34 @@ describe('dc.baseMixin', function () { expect(chart.filters().length).toEqual(0); }); }); + + describe('accessibility base svg', () => { + + it('should have default description when keyboardAccessible is true', () => { + chart + .keyboardAccessible(true) + .resetSvg(); + + expect(chart.svg().attr('tabindex')).toEqual('0'); + expect(chart.svg().node().firstChild.innerHTML).toEqual('BaseMixin'); + }); + + it('should have custom description if svgDescription is set', () => { + chart + .svgDescription('I am a chart') + .resetSvg(); + + expect(chart.svg().attr('tabindex')).toEqual('0'); + expect(chart.svg().node().firstChild.innerHTML).toEqual('I am a chart'); + }); + + it('should not have accessibility features if not explicitly enabled', () => { + chart + .resetSvg(); + + expect(chart.svg().attr('tabindex')).toBeNull(); + }); + + + }) }); diff --git a/spec/biggish-data-spec.js b/spec/biggish-data-spec.js index 27d0653edf..cbbecbc633 100644 --- a/spec/biggish-data-spec.js +++ b/spec/biggish-data-spec.js @@ -1,49 +1,42 @@ /* global appendChartID */ -/* jscs:disable maximumLineLength*/ -/* jshint maxlen: false */ +/* eslint "max-len": 0 */ function biggishData () { return JSON.parse('[{"k":1,"t":"2015-01-09T20:00:00.0000000","n":65},{"k":1,"t":"2015-01-09T21:00:00.0000000","n":0},{"k":1,"t":"2015-01-09T22:00:00.0000000","n":22},{"k":1,"t":"2015-01-09T23:00:00.0000000","n":0},{"k":1,"t":"2015-01-12T19:00:00.0000000","n":0},{"k":1,"t":"2015-01-12T20:00:00.0000000","n":49},{"k":1,"t":"2015-01-12T21:00:00.0000000","n":0},{"k":1,"t":"2015-01-13T14:00:00.0000000","n":0},{"k":1,"t":"2015-01-13T15:00:00.0000000","n":98},{"k":1,"t":"2015-01-13T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-13T18:00:00.0000000","n":0},{"k":1,"t":"2015-01-13T19:00:00.0000000","n":420},{"k":1,"t":"2015-01-13T20:00:00.0000000","n":0},{"k":1,"t":"2015-01-14T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-14T17:00:00.0000000","n":62},{"k":1,"t":"2015-01-14T18:00:00.0000000","n":50},{"k":1,"t":"2015-01-14T19:00:00.0000000","n":0},{"k":1,"t":"2015-01-15T13:00:00.0000000","n":0},{"k":1,"t":"2015-01-15T14:00:00.0000000","n":23},{"k":1,"t":"2015-01-15T15:00:00.0000000","n":0},{"k":1,"t":"2015-01-16T15:00:00.0000000","n":0},{"k":1,"t":"2015-01-16T16:00:00.0000000","n":91},{"k":1,"t":"2015-01-16T17:00:00.0000000","n":0},{"k":1,"t":"2015-01-16T20:00:00.0000000","n":0},{"k":1,"t":"2015-01-16T21:00:00.0000000","n":20},{"k":1,"t":"2015-01-16T22:00:00.0000000","n":0},{"k":1,"t":"2015-01-19T13:00:00.0000000","n":0},{"k":1,"t":"2015-01-19T14:00:00.0000000","n":64},{"k":1,"t":"2015-01-19T15:00:00.0000000","n":0},{"k":1,"t":"2015-01-19T16:00:00.0000000","n":65},{"k":1,"t":"2015-01-19T17:00:00.0000000","n":0},{"k":1,"t":"2015-01-21T14:00:00.0000000","n":0},{"k":1,"t":"2015-01-21T15:00:00.0000000","n":57},{"k":1,"t":"2015-01-21T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-21T17:00:00.0000000","n":0},{"k":1,"t":"2015-01-21T18:00:00.0000000","n":58},{"k":1,"t":"2015-01-21T19:00:00.0000000","n":0},{"k":1,"t":"2015-01-22T13:00:00.0000000","n":0},{"k":1,"t":"2015-01-22T14:00:00.0000000","n":59},{"k":1,"t":"2015-01-22T15:00:00.0000000","n":101},{"k":1,"t":"2015-01-22T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-22T18:00:00.0000000","n":0},{"k":1,"t":"2015-01-22T19:00:00.0000000","n":94},{"k":1,"t":"2015-01-22T20:00:00.0000000","n":0},{"k":1,"t":"2015-01-23T15:00:00.0000000","n":0},{"k":1,"t":"2015-01-23T16:00:00.0000000","n":355},{"k":1,"t":"2015-01-23T17:00:00.0000000","n":0},{"k":1,"t":"2015-01-23T18:00:00.0000000","n":91},{"k":1,"t":"2015-01-23T19:00:00.0000000","n":0},{"k":1,"t":"2015-01-23T21:00:00.0000000","n":0},{"k":1,"t":"2015-01-23T22:00:00.0000000","n":112},{"k":1,"t":"2015-01-23T23:00:00.0000000","n":0},{"k":1,"t":"2015-01-28T14:00:00.0000000","n":0},{"k":1,"t":"2015-01-28T15:00:00.0000000","n":107},{"k":1,"t":"2015-01-28T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-28T17:00:00.0000000","n":0},{"k":1,"t":"2015-01-28T18:00:00.0000000","n":78},{"k":1,"t":"2015-01-28T19:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T01:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T02:00:00.0000000","n":135},{"k":1,"t":"2015-01-29T03:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T14:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T15:00:00.0000000","n":67},{"k":1,"t":"2015-01-29T16:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T20:00:00.0000000","n":0},{"k":1,"t":"2015-01-29T21:00:00.0000000","n":49},{"k":1,"t":"2015-01-29T22:00:00.0000000","n":0},{"k":1,"t":"2015-01-30T14:00:00.0000000","n":0},{"k":1,"t":"2015-01-30T15:00:00.0000000","n":57},{"k":1,"t":"2015-01-30T16:00:00.0000000","n":0},{"k":1,"t":"2015-02-03T15:00:00.0000000","n":0},{"k":1,"t":"2015-02-03T16:00:00.0000000","n":144},{"k":1,"t":"2015-02-03T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-04T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-04T15:00:00.0000000","n":210},{"k":1,"t":"2015-02-04T16:00:00.0000000","n":0},{"k":1,"t":"2015-02-04T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-04T18:00:00.0000000","n":62},{"k":1,"t":"2015-02-04T19:00:00.0000000","n":0},{"k":1,"t":"2015-02-05T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-05T15:00:00.0000000","n":105},{"k":1,"t":"2015-02-05T16:00:00.0000000","n":0},{"k":1,"t":"2015-02-05T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-05T18:00:00.0000000","n":277},{"k":1,"t":"2015-02-05T19:00:00.0000000","n":0},{"k":1,"t":"2015-02-06T15:00:00.0000000","n":0},{"k":1,"t":"2015-02-06T16:00:00.0000000","n":253},{"k":1,"t":"2015-02-06T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-06T18:00:00.0000000","n":64},{"k":1,"t":"2015-02-06T19:00:00.0000000","n":0},{"k":1,"t":"2015-02-09T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-09T15:00:00.0000000","n":123},{"k":1,"t":"2015-02-09T16:00:00.0000000","n":184},{"k":1,"t":"2015-02-09T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-10T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-10T15:00:00.0000000","n":100},{"k":1,"t":"2015-02-10T16:00:00.0000000","n":271},{"k":1,"t":"2015-02-10T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-10T19:00:00.0000000","n":0},{"k":1,"t":"2015-02-10T20:00:00.0000000","n":72},{"k":1,"t":"2015-02-10T21:00:00.0000000","n":0},{"k":1,"t":"2015-02-11T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-11T15:00:00.0000000","n":117},{"k":1,"t":"2015-02-11T16:00:00.0000000","n":294},{"k":1,"t":"2015-02-11T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-11T18:00:00.0000000","n":61},{"k":1,"t":"2015-02-11T19:00:00.0000000","n":624},{"k":1,"t":"2015-02-11T20:00:00.0000000","n":0},{"k":1,"t":"2015-02-11T21:00:00.0000000","n":56},{"k":1,"t":"2015-02-11T22:00:00.0000000","n":0},{"k":1,"t":"2015-02-12T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-12T15:00:00.0000000","n":112},{"k":1,"t":"2015-02-12T16:00:00.0000000","n":295},{"k":1,"t":"2015-02-12T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-12T18:00:00.0000000","n":0},{"k":1,"t":"2015-02-12T19:00:00.0000000","n":126},{"k":1,"t":"2015-02-12T20:00:00.0000000","n":513},{"k":1,"t":"2015-02-12T21:00:00.0000000","n":0},{"k":1,"t":"2015-02-13T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-13T15:00:00.0000000","n":198},{"k":1,"t":"2015-02-13T16:00:00.0000000","n":270},{"k":1,"t":"2015-02-13T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-13T18:00:00.0000000","n":528},{"k":1,"t":"2015-02-13T19:00:00.0000000","n":2274},{"k":1,"t":"2015-02-13T20:00:00.0000000","n":834},{"k":1,"t":"2015-02-13T21:00:00.0000000","n":372},{"k":1,"t":"2015-02-13T22:00:00.0000000","n":372},{"k":1,"t":"2015-02-13T23:00:00.0000000","n":0},{"k":1,"t":"2015-02-17T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-17T15:00:00.0000000","n":119},{"k":1,"t":"2015-02-17T16:00:00.0000000","n":135},{"k":1,"t":"2015-02-17T17:00:00.0000000","n":67},{"k":1,"t":"2015-02-17T18:00:00.0000000","n":0},{"k":1,"t":"2015-02-18T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-18T15:00:00.0000000","n":137},{"k":1,"t":"2015-02-18T16:00:00.0000000","n":254},{"k":1,"t":"2015-02-18T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-18T18:00:00.0000000","n":64},{"k":1,"t":"2015-02-18T19:00:00.0000000","n":0},{"k":1,"t":"2015-02-18T20:00:00.0000000","n":53},{"k":1,"t":"2015-02-18T21:00:00.0000000","n":0},{"k":1,"t":"2015-02-19T12:00:00.0000000","n":0},{"k":1,"t":"2015-02-19T13:00:00.0000000","n":86},{"k":1,"t":"2015-02-19T14:00:00.0000000","n":210},{"k":1,"t":"2015-02-19T15:00:00.0000000","n":338},{"k":1,"t":"2015-02-19T16:00:00.0000000","n":0},{"k":1,"t":"2015-02-19T17:00:00.0000000","n":149},{"k":1,"t":"2015-02-19T18:00:00.0000000","n":0},{"k":1,"t":"2015-02-20T11:00:00.0000000","n":0},{"k":1,"t":"2015-02-20T12:00:00.0000000","n":44},{"k":1,"t":"2015-02-20T13:00:00.0000000","n":0},{"k":1,"t":"2015-02-22T00:00:00.0000000","n":0},{"k":1,"t":"2015-02-22T01:00:00.0000000","n":458},{"k":1,"t":"2015-02-22T02:00:00.0000000","n":0},{"k":1,"t":"2015-02-23T12:00:00.0000000","n":0},{"k":1,"t":"2015-02-23T13:00:00.0000000","n":87},{"k":1,"t":"2015-02-23T14:00:00.0000000","n":0},{"k":1,"t":"2015-02-23T15:00:00.0000000","n":0},{"k":1,"t":"2015-02-23T16:00:00.0000000","n":142},{"k":1,"t":"2015-02-23T17:00:00.0000000","n":0},{"k":1,"t":"2015-02-24T01:00:00.0000000","n":0},{"k":1,"t":"2015-02-24T02:00:00.0000000","n":235},{"k":1,"t":"2015-02-24T03:00:00.0000000","n":0},{"k":1,"t":"2015-02-24T13:00:00.0000000","n":0},{"k":1,"t":"2015-02-24T14:00:00.0000000","n":638},{"k":1,"t":"2015-02-24T15:00:00.0000000","n":0},{"k":1,"t":"2015-02-25T11:00:00.0000000","n":0},{"k":1,"t":"2015-02-25T12:00:00.0000000","n":56},{"k":1,"t":"2015-02-25T13:00:00.0000000","n":0},{"k":1,"t":"2015-02-25T14:00:00.0000000","n":1083},{"k":1,"t":"2015-02-25T15:00:00.0000000","n":0},{"k":1,"t":"2015-02-27T16:00:00.0000000","n":0},{"k":1,"t":"2015-02-27T17:00:00.0000000","n":196},{"k":1,"t":"2015-02-27T18:00:00.0000000","n":50},{"k":1,"t":"2015-02-27T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-03T13:00:00.0000000","n":0},{"k":1,"t":"2015-03-03T14:00:00.0000000","n":207},{"k":1,"t":"2015-03-03T15:00:00.0000000","n":526},{"k":1,"t":"2015-03-03T16:00:00.0000000","n":270},{"k":1,"t":"2015-03-03T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-03T20:00:00.0000000","n":0},{"k":1,"t":"2015-03-03T21:00:00.0000000","n":60},{"k":1,"t":"2015-03-03T22:00:00.0000000","n":0},{"k":1,"t":"2015-03-04T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-04T18:00:00.0000000","n":62},{"k":1,"t":"2015-03-04T19:00:00.0000000","n":532},{"k":1,"t":"2015-03-04T20:00:00.0000000","n":0},{"k":1,"t":"2015-03-05T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-05T18:00:00.0000000","n":478},{"k":1,"t":"2015-03-05T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-05T20:00:00.0000000","n":0},{"k":1,"t":"2015-03-05T21:00:00.0000000","n":42},{"k":1,"t":"2015-03-05T22:00:00.0000000","n":0},{"k":1,"t":"2015-03-06T02:00:00.0000000","n":0},{"k":1,"t":"2015-03-06T03:00:00.0000000","n":74},{"k":1,"t":"2015-03-06T04:00:00.0000000","n":0},{"k":1,"t":"2015-03-09T11:00:00.0000000","n":0},{"k":1,"t":"2015-03-09T12:00:00.0000000","n":61},{"k":1,"t":"2015-03-09T13:00:00.0000000","n":107},{"k":1,"t":"2015-03-09T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-09T15:00:00.0000000","n":70},{"k":1,"t":"2015-03-09T16:00:00.0000000","n":0},{"k":1,"t":"2015-03-10T01:00:00.0000000","n":0},{"k":1,"t":"2015-03-10T02:00:00.0000000","n":70},{"k":1,"t":"2015-03-10T03:00:00.0000000","n":0},{"k":1,"t":"2015-03-10T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-10T18:00:00.0000000","n":141},{"k":1,"t":"2015-03-10T19:00:00.0000000","n":98},{"k":1,"t":"2015-03-10T20:00:00.0000000","n":94},{"k":1,"t":"2015-03-10T21:00:00.0000000","n":0},{"k":1,"t":"2015-03-12T15:00:00.0000000","n":0},{"k":1,"t":"2015-03-12T16:00:00.0000000","n":133},{"k":1,"t":"2015-03-12T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-16T13:00:00.0000000","n":0},{"k":1,"t":"2015-03-16T14:00:00.0000000","n":45},{"k":1,"t":"2015-03-16T15:00:00.0000000","n":0},{"k":1,"t":"2015-03-17T12:00:00.0000000","n":0},{"k":1,"t":"2015-03-17T13:00:00.0000000","n":274},{"k":1,"t":"2015-03-17T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-17T15:00:00.0000000","n":55},{"k":1,"t":"2015-03-17T16:00:00.0000000","n":0},{"k":1,"t":"2015-03-18T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-18T15:00:00.0000000","n":50},{"k":1,"t":"2015-03-18T16:00:00.0000000","n":50},{"k":1,"t":"2015-03-18T17:00:00.0000000","n":803},{"k":1,"t":"2015-03-18T18:00:00.0000000","n":0},{"k":1,"t":"2015-03-18T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-18T20:00:00.0000000","n":611},{"k":1,"t":"2015-03-18T21:00:00.0000000","n":0},{"k":1,"t":"2015-03-19T11:00:00.0000000","n":0},{"k":1,"t":"2015-03-19T12:00:00.0000000","n":185},{"k":1,"t":"2015-03-19T13:00:00.0000000","n":0},{"k":1,"t":"2015-03-19T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-19T15:00:00.0000000","n":158},{"k":1,"t":"2015-03-19T16:00:00.0000000","n":0},{"k":1,"t":"2015-03-20T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-20T18:00:00.0000000","n":19},{"k":1,"t":"2015-03-20T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-23T18:00:00.0000000","n":0},{"k":1,"t":"2015-03-23T19:00:00.0000000","n":67},{"k":1,"t":"2015-03-23T20:00:00.0000000","n":0},{"k":1,"t":"2015-03-24T10:00:00.0000000","n":0},{"k":1,"t":"2015-03-24T11:00:00.0000000","n":134},{"k":1,"t":"2015-03-24T12:00:00.0000000","n":0},{"k":1,"t":"2015-03-25T12:00:00.0000000","n":0},{"k":1,"t":"2015-03-25T13:00:00.0000000","n":93},{"k":1,"t":"2015-03-25T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-25T15:00:00.0000000","n":121},{"k":1,"t":"2015-03-25T16:00:00.0000000","n":0},{"k":1,"t":"2015-03-25T17:00:00.0000000","n":452},{"k":1,"t":"2015-03-25T18:00:00.0000000","n":0},{"k":1,"t":"2015-03-26T12:00:00.0000000","n":0},{"k":1,"t":"2015-03-26T13:00:00.0000000","n":731},{"k":1,"t":"2015-03-26T14:00:00.0000000","n":0},{"k":1,"t":"2015-03-26T17:00:00.0000000","n":0},{"k":1,"t":"2015-03-26T18:00:00.0000000","n":207},{"k":1,"t":"2015-03-26T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-30T19:00:00.0000000","n":0},{"k":1,"t":"2015-03-30T20:00:00.0000000","n":83},{"k":1,"t":"2015-03-30T21:00:00.0000000","n":0},{"k":1,"t":"2015-03-31T18:00:00.0000000","n":0},{"k":1,"t":"2015-03-31T19:00:00.0000000","n":56},{"k":1,"t":"2015-03-31T20:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T11:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T12:00:00.0000000","n":49},{"k":1,"t":"2015-04-01T13:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T16:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T17:00:00.0000000","n":94},{"k":1,"t":"2015-04-01T18:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T20:00:00.0000000","n":0},{"k":1,"t":"2015-04-01T21:00:00.0000000","n":356},{"k":1,"t":"2015-04-01T22:00:00.0000000","n":0},{"k":1,"t":"2015-04-02T14:00:00.0000000","n":0},{"k":1,"t":"2015-04-02T15:00:00.0000000","n":136},{"k":1,"t":"2015-04-02T16:00:00.0000000","n":61},{"k":1,"t":"2015-04-02T17:00:00.0000000","n":640},{"k":1,"t":"2015-04-02T18:00:00.0000000","n":0},{"k":1,"t":"2015-04-03T11:00:00.0000000","n":0},{"k":1,"t":"2015-04-03T12:00:00.0000000","n":95},{"k":1,"t":"2015-04-03T13:00:00.0000000","n":78},{"k":1,"t":"2015-04-03T14:00:00.0000000","n":101},{"k":1,"t":"2015-04-03T15:00:00.0000000","n":0},{"k":1,"t":"2015-04-03T16:00:00.0000000","n":270},{"k":1,"t":"2015-04-03T17:00:00.0000000","n":21},{"k":1,"t":"2015-04-03T18:00:00.0000000","n":0},{"k":1,"t":"2015-04-07T14:00:00.0000000","n":0},{"k":1,"t":"2015-04-07T15:00:00.0000000","n":264},{"k":2,"t":"2015-01-10T01:00:00.0000000","n":90},{"k":2,"t":"2015-01-10T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-10T03:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T04:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T05:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T06:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T07:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T08:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T09:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T10:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T11:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T12:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T13:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T14:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T15:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T16:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T17:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T18:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T19:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T20:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T21:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T22:00:00.0000000","n":2339},{"k":2,"t":"2015-01-10T23:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T00:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T01:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T02:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T03:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T04:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T05:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T06:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T07:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T08:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T09:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T10:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T11:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T12:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T13:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T14:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T15:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T16:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T17:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T18:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T19:00:00.0000000","n":2339},{"k":2,"t":"2015-01-11T20:00:00.0000000","n":1163},{"k":2,"t":"2015-01-11T21:00:00.0000000","n":1163},{"k":2,"t":"2015-01-11T22:00:00.0000000","n":1173},{"k":2,"t":"2015-01-11T23:00:00.0000000","n":406},{"k":2,"t":"2015-01-12T00:00:00.0000000","n":2102},{"k":2,"t":"2015-01-12T01:00:00.0000000","n":1584},{"k":2,"t":"2015-01-12T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-12T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-12T13:00:00.0000000","n":116},{"k":2,"t":"2015-01-12T14:00:00.0000000","n":336},{"k":2,"t":"2015-01-12T15:00:00.0000000","n":412},{"k":2,"t":"2015-01-12T16:00:00.0000000","n":0},{"k":2,"t":"2015-01-12T17:00:00.0000000","n":0},{"k":2,"t":"2015-01-12T18:00:00.0000000","n":101},{"k":2,"t":"2015-01-12T19:00:00.0000000","n":0},{"k":2,"t":"2015-01-12T20:00:00.0000000","n":124},{"k":2,"t":"2015-01-12T21:00:00.0000000","n":136},{"k":2,"t":"2015-01-12T22:00:00.0000000","n":0},{"k":2,"t":"2015-01-13T13:00:00.0000000","n":0},{"k":2,"t":"2015-01-13T14:00:00.0000000","n":146},{"k":2,"t":"2015-01-13T15:00:00.0000000","n":181},{"k":2,"t":"2015-01-13T16:00:00.0000000","n":0},{"k":2,"t":"2015-01-13T17:00:00.0000000","n":44},{"k":2,"t":"2015-01-13T18:00:00.0000000","n":0},{"k":2,"t":"2015-01-13T19:00:00.0000000","n":114},{"k":2,"t":"2015-01-13T20:00:00.0000000","n":0},{"k":2,"t":"2015-01-14T13:00:00.0000000","n":0},{"k":2,"t":"2015-01-14T14:00:00.0000000","n":66},{"k":2,"t":"2015-01-14T15:00:00.0000000","n":0},{"k":2,"t":"2015-01-14T16:00:00.0000000","n":132},{"k":2,"t":"2015-01-14T17:00:00.0000000","n":294},{"k":2,"t":"2015-01-14T18:00:00.0000000","n":0},{"k":2,"t":"2015-01-14T19:00:00.0000000","n":180},{"k":2,"t":"2015-01-14T20:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T00:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T01:00:00.0000000","n":136},{"k":2,"t":"2015-01-15T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T15:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T16:00:00.0000000","n":50},{"k":2,"t":"2015-01-15T17:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T21:00:00.0000000","n":0},{"k":2,"t":"2015-01-15T22:00:00.0000000","n":80},{"k":2,"t":"2015-01-15T23:00:00.0000000","n":0},{"k":2,"t":"2015-01-16T13:00:00.0000000","n":0},{"k":2,"t":"2015-01-16T14:00:00.0000000","n":256},{"k":2,"t":"2015-01-16T15:00:00.0000000","n":529},{"k":2,"t":"2015-01-16T16:00:00.0000000","n":583},{"k":2,"t":"2015-01-16T17:00:00.0000000","n":529},{"k":2,"t":"2015-01-16T18:00:00.0000000","n":0},{"k":2,"t":"2015-01-16T19:00:00.0000000","n":597},{"k":2,"t":"2015-01-16T20:00:00.0000000","n":769},{"k":2,"t":"2015-01-16T21:00:00.0000000","n":597},{"k":2,"t":"2015-01-16T22:00:00.0000000","n":597},{"k":2,"t":"2015-01-16T23:00:00.0000000","n":0},{"k":2,"t":"2015-01-17T10:00:00.0000000","n":0},{"k":2,"t":"2015-01-17T11:00:00.0000000","n":120},{"k":2,"t":"2015-01-17T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-19T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-19T13:00:00.0000000","n":54},{"k":2,"t":"2015-01-19T14:00:00.0000000","n":116},{"k":2,"t":"2015-01-19T15:00:00.0000000","n":0},{"k":2,"t":"2015-01-19T16:00:00.0000000","n":204},{"k":2,"t":"2015-01-19T17:00:00.0000000","n":49},{"k":2,"t":"2015-01-19T18:00:00.0000000","n":128},{"k":2,"t":"2015-01-19T19:00:00.0000000","n":0},{"k":2,"t":"2015-01-19T20:00:00.0000000","n":50},{"k":2,"t":"2015-01-19T21:00:00.0000000","n":0},{"k":2,"t":"2015-01-20T09:00:00.0000000","n":0},{"k":2,"t":"2015-01-20T10:00:00.0000000","n":413},{"k":2,"t":"2015-01-20T11:00:00.0000000","n":990},{"k":2,"t":"2015-01-20T12:00:00.0000000","n":603},{"k":2,"t":"2015-01-20T13:00:00.0000000","n":603},{"k":2,"t":"2015-01-20T14:00:00.0000000","n":603},{"k":2,"t":"2015-01-20T15:00:00.0000000","n":717},{"k":2,"t":"2015-01-20T16:00:00.0000000","n":0},{"k":2,"t":"2015-01-20T17:00:00.0000000","n":43},{"k":2,"t":"2015-01-20T18:00:00.0000000","n":90},{"k":2,"t":"2015-01-20T19:00:00.0000000","n":0},{"k":2,"t":"2015-01-21T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-21T13:00:00.0000000","n":1268},{"k":2,"t":"2015-01-21T14:00:00.0000000","n":666},{"k":2,"t":"2015-01-21T15:00:00.0000000","n":666},{"k":2,"t":"2015-01-21T16:00:00.0000000","n":666},{"k":2,"t":"2015-01-21T17:00:00.0000000","n":666},{"k":2,"t":"2015-01-21T18:00:00.0000000","n":420},{"k":2,"t":"2015-01-21T19:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T01:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T02:00:00.0000000","n":68},{"k":2,"t":"2015-01-22T03:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T13:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T14:00:00.0000000","n":60},{"k":2,"t":"2015-01-22T15:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T18:00:00.0000000","n":0},{"k":2,"t":"2015-01-22T19:00:00.0000000","n":45},{"k":2,"t":"2015-01-22T20:00:00.0000000","n":0},{"k":2,"t":"2015-01-23T11:00:00.0000000","n":0},{"k":2,"t":"2015-01-23T12:00:00.0000000","n":927},{"k":2,"t":"2015-01-23T13:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T14:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T15:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T16:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T17:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T18:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T19:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T20:00:00.0000000","n":713},{"k":2,"t":"2015-01-23T21:00:00.0000000","n":671},{"k":2,"t":"2015-01-23T22:00:00.0000000","n":0},{"k":2,"t":"2015-01-24T21:00:00.0000000","n":0},{"k":2,"t":"2015-01-24T22:00:00.0000000","n":46},{"k":2,"t":"2015-01-24T23:00:00.0000000","n":0},{"k":2,"t":"2015-01-26T09:00:00.0000000","n":0},{"k":2,"t":"2015-01-26T10:00:00.0000000","n":59},{"k":2,"t":"2015-01-26T11:00:00.0000000","n":0},{"k":2,"t":"2015-01-26T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-26T13:00:00.0000000","n":927},{"k":2,"t":"2015-01-26T14:00:00.0000000","n":753},{"k":2,"t":"2015-01-26T15:00:00.0000000","n":681},{"k":2,"t":"2015-01-26T16:00:00.0000000","n":681},{"k":2,"t":"2015-01-26T17:00:00.0000000","n":681},{"k":2,"t":"2015-01-26T18:00:00.0000000","n":801},{"k":2,"t":"2015-01-26T19:00:00.0000000","n":811},{"k":2,"t":"2015-01-26T20:00:00.0000000","n":681},{"k":2,"t":"2015-01-26T21:00:00.0000000","n":727},{"k":2,"t":"2015-01-26T22:00:00.0000000","n":82},{"k":2,"t":"2015-01-26T23:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T03:00:00.0000000","n":52},{"k":2,"t":"2015-01-27T04:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T11:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T12:00:00.0000000","n":363},{"k":2,"t":"2015-01-27T13:00:00.0000000","n":58},{"k":2,"t":"2015-01-27T14:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T15:00:00.0000000","n":58},{"k":2,"t":"2015-01-27T16:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T17:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T18:00:00.0000000","n":44},{"k":2,"t":"2015-01-27T19:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T20:00:00.0000000","n":0},{"k":2,"t":"2015-01-27T21:00:00.0000000","n":54},{"k":2,"t":"2015-01-27T22:00:00.0000000","n":0},{"k":2,"t":"2015-01-28T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-28T13:00:00.0000000","n":326},{"k":2,"t":"2015-01-28T14:00:00.0000000","n":490},{"k":2,"t":"2015-01-28T15:00:00.0000000","n":66},{"k":2,"t":"2015-01-28T16:00:00.0000000","n":44},{"k":2,"t":"2015-01-28T17:00:00.0000000","n":0},{"k":2,"t":"2015-01-28T18:00:00.0000000","n":168},{"k":2,"t":"2015-01-28T19:00:00.0000000","n":362},{"k":2,"t":"2015-01-28T20:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T00:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T01:00:00.0000000","n":54},{"k":2,"t":"2015-01-29T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T12:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T13:00:00.0000000","n":60},{"k":2,"t":"2015-01-29T14:00:00.0000000","n":152},{"k":2,"t":"2015-01-29T15:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T16:00:00.0000000","n":80},{"k":2,"t":"2015-01-29T17:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T18:00:00.0000000","n":70},{"k":2,"t":"2015-01-29T19:00:00.0000000","n":254},{"k":2,"t":"2015-01-29T20:00:00.0000000","n":171},{"k":2,"t":"2015-01-29T21:00:00.0000000","n":40},{"k":2,"t":"2015-01-29T22:00:00.0000000","n":0},{"k":2,"t":"2015-01-29T23:00:00.0000000","n":0},{"k":2,"t":"2015-01-30T00:00:00.0000000","n":150},{"k":2,"t":"2015-01-30T01:00:00.0000000","n":40},{"k":2,"t":"2015-01-30T02:00:00.0000000","n":0},{"k":2,"t":"2015-01-30T07:00:00.0000000","n":0},{"k":2,"t":"2015-01-30T08:00:00.0000000","n":52},{"k":2,"t":"2015-01-30T09:00:00.0000000","n":51},{"k":2,"t":"2015-01-30T10:00:00.0000000","n":0},{"k":2,"t":"2015-01-30T11:00:00.0000000","n":0},{"k":2,"t":"2015-01-30T12:00:00.0000000","n":243},{"k":2,"t":"2015-01-30T13:00:00.0000000","n":678},{"k":2,"t":"2015-01-30T14:00:00.0000000","n":678},{"k":2,"t":"2015-01-30T15:00:00.0000000","n":892},{"k":2,"t":"2015-01-30T16:00:00.0000000","n":852},{"k":2,"t":"2015-01-30T17:00:00.0000000","n":678},{"k":2,"t":"2015-01-30T18:00:00.0000000","n":741},{"k":2,"t":"2015-01-30T19:00:00.0000000","n":801},{"k":2,"t":"2015-01-30T20:00:00.0000000","n":709},{"k":2,"t":"2015-01-30T21:00:00.0000000","n":755},{"k":2,"t":"2015-01-30T22:00:00.0000000","n":98},{"k":2,"t":"2015-01-30T23:00:00.0000000","n":0},{"k":2,"t":"2015-02-01T14:00:00.0000000","n":0},{"k":2,"t":"2015-02-01T15:00:00.0000000","n":149},{"k":2,"t":"2015-02-01T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-01T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-01T18:00:00.0000000","n":62},{"k":2,"t":"2015-02-01T19:00:00.0000000","n":0},{"k":2,"t":"2015-02-02T03:00:00.0000000","n":0},{"k":2,"t":"2015-02-02T04:00:00.0000000","n":40},{"k":2,"t":"2015-02-02T05:00:00.0000000","n":0},{"k":2,"t":"2015-02-02T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-02T13:00:00.0000000","n":889},{"k":2,"t":"2015-02-02T14:00:00.0000000","n":673},{"k":2,"t":"2015-02-02T15:00:00.0000000","n":44},{"k":2,"t":"2015-02-02T16:00:00.0000000","n":330},{"k":2,"t":"2015-02-02T17:00:00.0000000","n":766},{"k":2,"t":"2015-02-02T18:00:00.0000000","n":578},{"k":2,"t":"2015-02-02T19:00:00.0000000","n":750},{"k":2,"t":"2015-02-02T20:00:00.0000000","n":975},{"k":2,"t":"2015-02-02T21:00:00.0000000","n":692},{"k":2,"t":"2015-02-02T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T01:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T02:00:00.0000000","n":64},{"k":2,"t":"2015-02-03T03:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T13:00:00.0000000","n":311},{"k":2,"t":"2015-02-03T14:00:00.0000000","n":472},{"k":2,"t":"2015-02-03T15:00:00.0000000","n":210},{"k":2,"t":"2015-02-03T16:00:00.0000000","n":513},{"k":2,"t":"2015-02-03T17:00:00.0000000","n":184},{"k":2,"t":"2015-02-03T18:00:00.0000000","n":174},{"k":2,"t":"2015-02-03T19:00:00.0000000","n":152},{"k":2,"t":"2015-02-03T20:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T21:00:00.0000000","n":74},{"k":2,"t":"2015-02-03T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-03T23:00:00.0000000","n":0},{"k":2,"t":"2015-02-04T00:00:00.0000000","n":44},{"k":2,"t":"2015-02-04T01:00:00.0000000","n":66},{"k":2,"t":"2015-02-04T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-04T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-04T13:00:00.0000000","n":225},{"k":2,"t":"2015-02-04T14:00:00.0000000","n":96},{"k":2,"t":"2015-02-04T15:00:00.0000000","n":234},{"k":2,"t":"2015-02-04T16:00:00.0000000","n":184},{"k":2,"t":"2015-02-04T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-04T18:00:00.0000000","n":580},{"k":2,"t":"2015-02-04T19:00:00.0000000","n":140},{"k":2,"t":"2015-02-04T20:00:00.0000000","n":204},{"k":2,"t":"2015-02-04T21:00:00.0000000","n":366},{"k":2,"t":"2015-02-04T22:00:00.0000000","n":62},{"k":2,"t":"2015-02-04T23:00:00.0000000","n":0},{"k":2,"t":"2015-02-05T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-05T03:00:00.0000000","n":112},{"k":2,"t":"2015-02-05T04:00:00.0000000","n":64},{"k":2,"t":"2015-02-05T05:00:00.0000000","n":192},{"k":2,"t":"2015-02-05T06:00:00.0000000","n":0},{"k":2,"t":"2015-02-05T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-05T13:00:00.0000000","n":227},{"k":2,"t":"2015-02-05T14:00:00.0000000","n":48},{"k":2,"t":"2015-02-05T15:00:00.0000000","n":341},{"k":2,"t":"2015-02-05T16:00:00.0000000","n":42},{"k":2,"t":"2015-02-05T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-05T18:00:00.0000000","n":431},{"k":2,"t":"2015-02-05T19:00:00.0000000","n":178},{"k":2,"t":"2015-02-05T20:00:00.0000000","n":48},{"k":2,"t":"2015-02-05T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-06T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-06T13:00:00.0000000","n":182},{"k":2,"t":"2015-02-06T14:00:00.0000000","n":98},{"k":2,"t":"2015-02-06T15:00:00.0000000","n":67},{"k":2,"t":"2015-02-06T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-06T17:00:00.0000000","n":54},{"k":2,"t":"2015-02-06T18:00:00.0000000","n":40},{"k":2,"t":"2015-02-06T19:00:00.0000000","n":164},{"k":2,"t":"2015-02-06T20:00:00.0000000","n":72},{"k":2,"t":"2015-02-06T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-09T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-09T03:00:00.0000000","n":90},{"k":2,"t":"2015-02-09T04:00:00.0000000","n":0},{"k":2,"t":"2015-02-09T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-09T13:00:00.0000000","n":312},{"k":2,"t":"2015-02-09T14:00:00.0000000","n":56},{"k":2,"t":"2015-02-09T15:00:00.0000000","n":107},{"k":2,"t":"2015-02-09T16:00:00.0000000","n":96},{"k":2,"t":"2015-02-09T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-09T18:00:00.0000000","n":135},{"k":2,"t":"2015-02-09T19:00:00.0000000","n":171},{"k":2,"t":"2015-02-09T20:00:00.0000000","n":253},{"k":2,"t":"2015-02-09T21:00:00.0000000","n":260},{"k":2,"t":"2015-02-09T22:00:00.0000000","n":328},{"k":2,"t":"2015-02-09T23:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T00:00:00.0000000","n":169},{"k":2,"t":"2015-02-10T01:00:00.0000000","n":178},{"k":2,"t":"2015-02-10T02:00:00.0000000","n":81},{"k":2,"t":"2015-02-10T03:00:00.0000000","n":408},{"k":2,"t":"2015-02-10T04:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T05:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T06:00:00.0000000","n":184},{"k":2,"t":"2015-02-10T07:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T09:00:00.0000000","n":151},{"k":2,"t":"2015-02-10T10:00:00.0000000","n":192},{"k":2,"t":"2015-02-10T11:00:00.0000000","n":48},{"k":2,"t":"2015-02-10T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T14:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T15:00:00.0000000","n":84},{"k":2,"t":"2015-02-10T16:00:00.0000000","n":422},{"k":2,"t":"2015-02-10T17:00:00.0000000","n":360},{"k":2,"t":"2015-02-10T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-10T19:00:00.0000000","n":170},{"k":2,"t":"2015-02-10T20:00:00.0000000","n":475},{"k":2,"t":"2015-02-10T21:00:00.0000000","n":528},{"k":2,"t":"2015-02-10T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-11T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-11T18:00:00.0000000","n":512},{"k":2,"t":"2015-02-11T19:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T03:00:00.0000000","n":56},{"k":2,"t":"2015-02-12T04:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T13:00:00.0000000","n":82},{"k":2,"t":"2015-02-12T14:00:00.0000000","n":152},{"k":2,"t":"2015-02-12T15:00:00.0000000","n":42},{"k":2,"t":"2015-02-12T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-12T19:00:00.0000000","n":42},{"k":2,"t":"2015-02-12T20:00:00.0000000","n":82},{"k":2,"t":"2015-02-12T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T01:00:00.0000000","n":54},{"k":2,"t":"2015-02-13T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T13:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T14:00:00.0000000","n":41},{"k":2,"t":"2015-02-13T15:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-13T19:00:00.0000000","n":40},{"k":2,"t":"2015-02-13T20:00:00.0000000","n":0},{"k":2,"t":"2015-02-16T13:00:00.0000000","n":0},{"k":2,"t":"2015-02-16T14:00:00.0000000","n":84},{"k":2,"t":"2015-02-16T15:00:00.0000000","n":0},{"k":2,"t":"2015-02-16T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-16T19:00:00.0000000","n":70},{"k":2,"t":"2015-02-16T20:00:00.0000000","n":64},{"k":2,"t":"2015-02-16T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-17T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-17T03:00:00.0000000","n":86},{"k":2,"t":"2015-02-17T04:00:00.0000000","n":0},{"k":2,"t":"2015-02-17T13:00:00.0000000","n":0},{"k":2,"t":"2015-02-17T14:00:00.0000000","n":188},{"k":2,"t":"2015-02-17T15:00:00.0000000","n":144},{"k":2,"t":"2015-02-17T16:00:00.0000000","n":490},{"k":2,"t":"2015-02-17T17:00:00.0000000","n":155},{"k":2,"t":"2015-02-17T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-17T19:00:00.0000000","n":398},{"k":2,"t":"2015-02-17T20:00:00.0000000","n":224},{"k":2,"t":"2015-02-17T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T09:00:00.0000000","n":886},{"k":2,"t":"2015-02-18T10:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T12:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T13:00:00.0000000","n":452},{"k":2,"t":"2015-02-18T14:00:00.0000000","n":44},{"k":2,"t":"2015-02-18T15:00:00.0000000","n":70},{"k":2,"t":"2015-02-18T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T17:00:00.0000000","n":98},{"k":2,"t":"2015-02-18T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T19:00:00.0000000","n":356},{"k":2,"t":"2015-02-18T20:00:00.0000000","n":44},{"k":2,"t":"2015-02-18T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-18T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-19T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T09:00:00.0000000","n":885},{"k":2,"t":"2015-02-19T10:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T11:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T12:00:00.0000000","n":859},{"k":2,"t":"2015-02-19T13:00:00.0000000","n":662},{"k":2,"t":"2015-02-19T14:00:00.0000000","n":662},{"k":2,"t":"2015-02-19T15:00:00.0000000","n":80},{"k":2,"t":"2015-02-19T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T18:00:00.0000000","n":140},{"k":2,"t":"2015-02-19T19:00:00.0000000","n":52},{"k":2,"t":"2015-02-19T20:00:00.0000000","n":62},{"k":2,"t":"2015-02-19T21:00:00.0000000","n":128},{"k":2,"t":"2015-02-19T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-19T23:00:00.0000000","n":47},{"k":2,"t":"2015-02-20T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-20T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-20T09:00:00.0000000","n":1806},{"k":2,"t":"2015-02-20T10:00:00.0000000","n":662},{"k":2,"t":"2015-02-20T11:00:00.0000000","n":662},{"k":2,"t":"2015-02-20T12:00:00.0000000","n":662},{"k":2,"t":"2015-02-20T13:00:00.0000000","n":662},{"k":2,"t":"2015-02-20T14:00:00.0000000","n":717},{"k":2,"t":"2015-02-20T15:00:00.0000000","n":732},{"k":2,"t":"2015-02-20T16:00:00.0000000","n":653},{"k":2,"t":"2015-02-20T17:00:00.0000000","n":735},{"k":2,"t":"2015-02-20T18:00:00.0000000","n":58},{"k":2,"t":"2015-02-20T19:00:00.0000000","n":0},{"k":2,"t":"2015-02-20T20:00:00.0000000","n":44},{"k":2,"t":"2015-02-20T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-20T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-20T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-21T00:00:00.0000000","n":120},{"k":2,"t":"2015-02-21T01:00:00.0000000","n":147},{"k":2,"t":"2015-02-21T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T05:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T06:00:00.0000000","n":144},{"k":2,"t":"2015-02-21T07:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T09:00:00.0000000","n":887},{"k":2,"t":"2015-02-21T10:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-21T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-22T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-22T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-22T09:00:00.0000000","n":887},{"k":2,"t":"2015-02-22T10:00:00.0000000","n":0},{"k":2,"t":"2015-02-22T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-22T17:00:00.0000000","n":65},{"k":2,"t":"2015-02-22T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-22T23:00:00.0000000","n":0},{"k":2,"t":"2015-02-23T00:00:00.0000000","n":70},{"k":2,"t":"2015-02-23T01:00:00.0000000","n":134},{"k":2,"t":"2015-02-23T02:00:00.0000000","n":0},{"k":2,"t":"2015-02-23T04:00:00.0000000","n":0},{"k":2,"t":"2015-02-23T05:00:00.0000000","n":272},{"k":2,"t":"2015-02-23T06:00:00.0000000","n":622},{"k":2,"t":"2015-02-23T07:00:00.0000000","n":622},{"k":2,"t":"2015-02-23T08:00:00.0000000","n":795},{"k":2,"t":"2015-02-23T09:00:00.0000000","n":1615},{"k":2,"t":"2015-02-23T10:00:00.0000000","n":1017},{"k":2,"t":"2015-02-23T11:00:00.0000000","n":537},{"k":2,"t":"2015-02-23T12:00:00.0000000","n":537},{"k":2,"t":"2015-02-23T13:00:00.0000000","n":637},{"k":2,"t":"2015-02-23T14:00:00.0000000","n":575},{"k":2,"t":"2015-02-23T15:00:00.0000000","n":1345},{"k":2,"t":"2015-02-23T16:00:00.0000000","n":633},{"k":2,"t":"2015-02-23T17:00:00.0000000","n":158},{"k":2,"t":"2015-02-23T18:00:00.0000000","n":164},{"k":2,"t":"2015-02-23T19:00:00.0000000","n":240},{"k":2,"t":"2015-02-23T20:00:00.0000000","n":98},{"k":2,"t":"2015-02-23T21:00:00.0000000","n":0},{"k":2,"t":"2015-02-23T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-23T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-24T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T09:00:00.0000000","n":887},{"k":2,"t":"2015-02-24T10:00:00.0000000","n":577},{"k":2,"t":"2015-02-24T11:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T15:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T16:00:00.0000000","n":62},{"k":2,"t":"2015-02-24T17:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-24T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-25T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-25T08:00:00.0000000","n":0},{"k":2,"t":"2015-02-25T09:00:00.0000000","n":890},{"k":2,"t":"2015-02-25T10:00:00.0000000","n":0},{"k":2,"t":"2015-02-25T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-25T17:00:00.0000000","n":138},{"k":2,"t":"2015-02-25T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-26T13:00:00.0000000","n":0},{"k":2,"t":"2015-02-26T14:00:00.0000000","n":202},{"k":2,"t":"2015-02-26T15:00:00.0000000","n":40},{"k":2,"t":"2015-02-26T16:00:00.0000000","n":0},{"k":2,"t":"2015-02-26T17:00:00.0000000","n":40},{"k":2,"t":"2015-02-26T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-26T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-26T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-27T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-27T18:00:00.0000000","n":0},{"k":2,"t":"2015-02-27T19:00:00.0000000","n":172},{"k":2,"t":"2015-02-27T20:00:00.0000000","n":0},{"k":2,"t":"2015-02-27T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-27T23:00:00.0000000","n":43},{"k":2,"t":"2015-02-28T00:00:00.0000000","n":0},{"k":2,"t":"2015-02-28T22:00:00.0000000","n":0},{"k":2,"t":"2015-02-28T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-01T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-01T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-01T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-02T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T16:00:00.0000000","n":50},{"k":2,"t":"2015-03-02T17:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T19:00:00.0000000","n":42},{"k":2,"t":"2015-03-02T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T21:00:00.0000000","n":102},{"k":2,"t":"2015-03-02T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-02T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-03T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T08:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T09:00:00.0000000","n":891},{"k":2,"t":"2015-03-03T10:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T13:00:00.0000000","n":64},{"k":2,"t":"2015-03-03T14:00:00.0000000","n":491},{"k":2,"t":"2015-03-03T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T21:00:00.0000000","n":156},{"k":2,"t":"2015-03-03T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-03T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-04T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T02:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T03:00:00.0000000","n":54},{"k":2,"t":"2015-03-04T04:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T08:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T09:00:00.0000000","n":889},{"k":2,"t":"2015-03-04T10:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T13:00:00.0000000","n":224},{"k":2,"t":"2015-03-04T14:00:00.0000000","n":116},{"k":2,"t":"2015-03-04T15:00:00.0000000","n":90},{"k":2,"t":"2015-03-04T16:00:00.0000000","n":160},{"k":2,"t":"2015-03-04T17:00:00.0000000","n":61},{"k":2,"t":"2015-03-04T18:00:00.0000000","n":531},{"k":2,"t":"2015-03-04T19:00:00.0000000","n":326},{"k":2,"t":"2015-03-04T20:00:00.0000000","n":58},{"k":2,"t":"2015-03-04T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-04T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-05T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-05T17:00:00.0000000","n":0},{"k":2,"t":"2015-03-05T18:00:00.0000000","n":62},{"k":2,"t":"2015-03-05T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-05T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-05T22:00:00.0000000","n":54},{"k":2,"t":"2015-03-05T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-06T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-06T15:00:00.0000000","n":56},{"k":2,"t":"2015-03-06T16:00:00.0000000","n":1120},{"k":2,"t":"2015-03-06T17:00:00.0000000","n":48},{"k":2,"t":"2015-03-06T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-06T19:00:00.0000000","n":198},{"k":2,"t":"2015-03-06T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-06T21:00:00.0000000","n":105},{"k":2,"t":"2015-03-06T22:00:00.0000000","n":52},{"k":2,"t":"2015-03-06T23:00:00.0000000","n":43},{"k":2,"t":"2015-03-07T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-09T11:00:00.0000000","n":0},{"k":2,"t":"2015-03-09T12:00:00.0000000","n":181},{"k":2,"t":"2015-03-09T13:00:00.0000000","n":0},{"k":2,"t":"2015-03-09T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-09T16:00:00.0000000","n":280},{"k":2,"t":"2015-03-09T17:00:00.0000000","n":393},{"k":2,"t":"2015-03-09T18:00:00.0000000","n":123},{"k":2,"t":"2015-03-09T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-09T20:00:00.0000000","n":156},{"k":2,"t":"2015-03-09T21:00:00.0000000","n":47},{"k":2,"t":"2015-03-09T22:00:00.0000000","n":43},{"k":2,"t":"2015-03-09T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T13:00:00.0000000","n":286},{"k":2,"t":"2015-03-10T14:00:00.0000000","n":327},{"k":2,"t":"2015-03-10T15:00:00.0000000","n":307},{"k":2,"t":"2015-03-10T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T19:00:00.0000000","n":40},{"k":2,"t":"2015-03-10T20:00:00.0000000","n":40},{"k":2,"t":"2015-03-10T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-10T23:00:00.0000000","n":207},{"k":2,"t":"2015-03-11T00:00:00.0000000","n":96},{"k":2,"t":"2015-03-11T01:00:00.0000000","n":0},{"k":2,"t":"2015-03-11T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-11T13:00:00.0000000","n":139},{"k":2,"t":"2015-03-11T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-12T13:00:00.0000000","n":0},{"k":2,"t":"2015-03-12T14:00:00.0000000","n":440},{"k":2,"t":"2015-03-12T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-12T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-12T20:00:00.0000000","n":175},{"k":2,"t":"2015-03-12T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-13T08:00:00.0000000","n":0},{"k":2,"t":"2015-03-13T09:00:00.0000000","n":166},{"k":2,"t":"2015-03-13T10:00:00.0000000","n":956},{"k":2,"t":"2015-03-13T11:00:00.0000000","n":979},{"k":2,"t":"2015-03-13T12:00:00.0000000","n":70},{"k":2,"t":"2015-03-13T13:00:00.0000000","n":244},{"k":2,"t":"2015-03-13T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-13T15:00:00.0000000","n":42},{"k":2,"t":"2015-03-13T16:00:00.0000000","n":48},{"k":2,"t":"2015-03-13T17:00:00.0000000","n":425},{"k":2,"t":"2015-03-13T18:00:00.0000000","n":491},{"k":2,"t":"2015-03-13T19:00:00.0000000","n":141},{"k":2,"t":"2015-03-13T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-16T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-16T15:00:00.0000000","n":46},{"k":2,"t":"2015-03-16T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-16T17:00:00.0000000","n":195},{"k":2,"t":"2015-03-16T18:00:00.0000000","n":1968},{"k":2,"t":"2015-03-16T19:00:00.0000000","n":48},{"k":2,"t":"2015-03-16T20:00:00.0000000","n":168},{"k":2,"t":"2015-03-16T21:00:00.0000000","n":225},{"k":2,"t":"2015-03-16T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-16T23:00:00.0000000","n":213},{"k":2,"t":"2015-03-17T00:00:00.0000000","n":343},{"k":2,"t":"2015-03-17T01:00:00.0000000","n":224},{"k":2,"t":"2015-03-17T02:00:00.0000000","n":216},{"k":2,"t":"2015-03-17T03:00:00.0000000","n":0},{"k":2,"t":"2015-03-17T04:00:00.0000000","n":213},{"k":2,"t":"2015-03-17T05:00:00.0000000","n":168},{"k":2,"t":"2015-03-17T06:00:00.0000000","n":360},{"k":2,"t":"2015-03-17T07:00:00.0000000","n":150},{"k":2,"t":"2015-03-17T08:00:00.0000000","n":264},{"k":2,"t":"2015-03-17T09:00:00.0000000","n":158},{"k":2,"t":"2015-03-17T10:00:00.0000000","n":153},{"k":2,"t":"2015-03-17T11:00:00.0000000","n":310},{"k":2,"t":"2015-03-17T12:00:00.0000000","n":348},{"k":2,"t":"2015-03-17T13:00:00.0000000","n":631},{"k":2,"t":"2015-03-17T14:00:00.0000000","n":237},{"k":2,"t":"2015-03-17T15:00:00.0000000","n":103},{"k":2,"t":"2015-03-17T16:00:00.0000000","n":289},{"k":2,"t":"2015-03-17T17:00:00.0000000","n":54},{"k":2,"t":"2015-03-17T18:00:00.0000000","n":42},{"k":2,"t":"2015-03-17T19:00:00.0000000","n":158},{"k":2,"t":"2015-03-17T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-17T21:00:00.0000000","n":241},{"k":2,"t":"2015-03-17T22:00:00.0000000","n":43},{"k":2,"t":"2015-03-17T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-18T13:00:00.0000000","n":0},{"k":2,"t":"2015-03-18T14:00:00.0000000","n":88},{"k":2,"t":"2015-03-18T15:00:00.0000000","n":48},{"k":2,"t":"2015-03-18T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-18T17:00:00.0000000","n":533},{"k":2,"t":"2015-03-18T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-18T19:00:00.0000000","n":62},{"k":2,"t":"2015-03-18T20:00:00.0000000","n":498},{"k":2,"t":"2015-03-18T21:00:00.0000000","n":48},{"k":2,"t":"2015-03-18T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-18T23:00:00.0000000","n":528},{"k":2,"t":"2015-03-19T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T01:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T02:00:00.0000000","n":48},{"k":2,"t":"2015-03-19T03:00:00.0000000","n":48},{"k":2,"t":"2015-03-19T04:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T05:00:00.0000000","n":532},{"k":2,"t":"2015-03-19T06:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T07:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T08:00:00.0000000","n":48},{"k":2,"t":"2015-03-19T09:00:00.0000000","n":48},{"k":2,"t":"2015-03-19T10:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T11:00:00.0000000","n":1239},{"k":2,"t":"2015-03-19T12:00:00.0000000","n":754},{"k":2,"t":"2015-03-19T13:00:00.0000000","n":697},{"k":2,"t":"2015-03-19T14:00:00.0000000","n":537},{"k":2,"t":"2015-03-19T15:00:00.0000000","n":98},{"k":2,"t":"2015-03-19T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T17:00:00.0000000","n":584},{"k":2,"t":"2015-03-19T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-19T20:00:00.0000000","n":48},{"k":2,"t":"2015-03-19T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-20T13:00:00.0000000","n":0},{"k":2,"t":"2015-03-20T14:00:00.0000000","n":66},{"k":2,"t":"2015-03-20T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-20T16:00:00.0000000","n":42},{"k":2,"t":"2015-03-20T17:00:00.0000000","n":0},{"k":2,"t":"2015-03-20T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-21T00:00:00.0000000","n":120},{"k":2,"t":"2015-03-21T01:00:00.0000000","n":144},{"k":2,"t":"2015-03-21T02:00:00.0000000","n":0},{"k":2,"t":"2015-03-21T05:00:00.0000000","n":0},{"k":2,"t":"2015-03-21T06:00:00.0000000","n":144},{"k":2,"t":"2015-03-21T07:00:00.0000000","n":0},{"k":2,"t":"2015-03-22T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-22T21:00:00.0000000","n":398},{"k":2,"t":"2015-03-22T22:00:00.0000000","n":602},{"k":2,"t":"2015-03-22T23:00:00.0000000","n":575},{"k":2,"t":"2015-03-23T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-23T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-23T19:00:00.0000000","n":41},{"k":2,"t":"2015-03-23T20:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T13:00:00.0000000","n":120},{"k":2,"t":"2015-03-24T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T15:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T16:00:00.0000000","n":40},{"k":2,"t":"2015-03-24T17:00:00.0000000","n":40},{"k":2,"t":"2015-03-24T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T19:00:00.0000000","n":363},{"k":2,"t":"2015-03-24T20:00:00.0000000","n":363},{"k":2,"t":"2015-03-24T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T22:00:00.0000000","n":0},{"k":2,"t":"2015-03-24T23:00:00.0000000","n":42},{"k":2,"t":"2015-03-25T00:00:00.0000000","n":0},{"k":2,"t":"2015-03-25T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-25T17:00:00.0000000","n":216},{"k":2,"t":"2015-03-25T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-25T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-25T20:00:00.0000000","n":82},{"k":2,"t":"2015-03-25T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-25T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T00:00:00.0000000","n":264},{"k":2,"t":"2015-03-26T01:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T13:00:00.0000000","n":257},{"k":2,"t":"2015-03-26T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T17:00:00.0000000","n":42},{"k":2,"t":"2015-03-26T18:00:00.0000000","n":42},{"k":2,"t":"2015-03-26T19:00:00.0000000","n":383},{"k":2,"t":"2015-03-26T20:00:00.0000000","n":382},{"k":2,"t":"2015-03-26T21:00:00.0000000","n":0},{"k":2,"t":"2015-03-26T23:00:00.0000000","n":0},{"k":2,"t":"2015-03-27T00:00:00.0000000","n":196},{"k":2,"t":"2015-03-27T01:00:00.0000000","n":41},{"k":2,"t":"2015-03-27T02:00:00.0000000","n":0},{"k":2,"t":"2015-03-27T10:00:00.0000000","n":0},{"k":2,"t":"2015-03-27T11:00:00.0000000","n":104},{"k":2,"t":"2015-03-27T12:00:00.0000000","n":82},{"k":2,"t":"2015-03-27T13:00:00.0000000","n":82},{"k":2,"t":"2015-03-27T14:00:00.0000000","n":164},{"k":2,"t":"2015-03-27T15:00:00.0000000","n":82},{"k":2,"t":"2015-03-27T16:00:00.0000000","n":82},{"k":2,"t":"2015-03-27T17:00:00.0000000","n":143},{"k":2,"t":"2015-03-27T18:00:00.0000000","n":82},{"k":2,"t":"2015-03-27T19:00:00.0000000","n":0},{"k":2,"t":"2015-03-28T11:00:00.0000000","n":0},{"k":2,"t":"2015-03-28T12:00:00.0000000","n":85},{"k":2,"t":"2015-03-28T13:00:00.0000000","n":0},{"k":2,"t":"2015-03-30T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-30T13:00:00.0000000","n":59},{"k":2,"t":"2015-03-30T14:00:00.0000000","n":0},{"k":2,"t":"2015-03-31T12:00:00.0000000","n":0},{"k":2,"t":"2015-03-31T13:00:00.0000000","n":64},{"k":2,"t":"2015-03-31T14:00:00.0000000","n":83},{"k":2,"t":"2015-03-31T15:00:00.0000000","n":62},{"k":2,"t":"2015-03-31T16:00:00.0000000","n":0},{"k":2,"t":"2015-03-31T18:00:00.0000000","n":0},{"k":2,"t":"2015-03-31T19:00:00.0000000","n":126},{"k":2,"t":"2015-03-31T20:00:00.0000000","n":0},{"k":2,"t":"2015-04-01T11:00:00.0000000","n":0},{"k":2,"t":"2015-04-01T12:00:00.0000000","n":95},{"k":2,"t":"2015-04-01T13:00:00.0000000","n":95},{"k":2,"t":"2015-04-01T14:00:00.0000000","n":144},{"k":2,"t":"2015-04-01T15:00:00.0000000","n":137},{"k":2,"t":"2015-04-01T16:00:00.0000000","n":0},{"k":2,"t":"2015-04-01T17:00:00.0000000","n":462},{"k":2,"t":"2015-04-01T18:00:00.0000000","n":0},{"k":2,"t":"2015-04-02T11:00:00.0000000","n":0},{"k":2,"t":"2015-04-02T12:00:00.0000000","n":177},{"k":2,"t":"2015-04-02T13:00:00.0000000","n":0},{"k":2,"t":"2015-04-03T12:00:00.0000000","n":0},{"k":2,"t":"2015-04-03T13:00:00.0000000","n":128},{"k":2,"t":"2015-04-03T14:00:00.0000000","n":0},{"k":2,"t":"2015-04-06T11:00:00.0000000","n":0},{"k":2,"t":"2015-04-06T12:00:00.0000000","n":40},{"k":2,"t":"2015-04-06T13:00:00.0000000","n":0},{"k":2,"t":"2015-04-06T14:00:00.0000000","n":72},{"k":2,"t":"2015-04-06T15:00:00.0000000","n":0},{"k":2,"t":"2015-04-06T16:00:00.0000000","n":0},{"k":2,"t":"2015-04-06T17:00:00.0000000","n":130},{"k":2,"t":"2015-04-06T18:00:00.0000000","n":0},{"k":2,"t":"2015-04-07T11:00:00.0000000","n":0},{"k":2,"t":"2015-04-07T12:00:00.0000000","n":176},{"k":2,"t":"2015-04-07T13:00:00.0000000","n":0},{"k":2,"t":"2015-04-08T11:00:00.0000000","n":0},{"k":2,"t":"2015-04-08T12:00:00.0000000","n":66},{"k":3,"t":"2015-01-10T01:00:00.0000000","n":86},{"k":3,"t":"2015-01-10T02:00:00.0000000","n":0},{"k":3,"t":"2015-01-10T03:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T04:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T05:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T06:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T07:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T08:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T09:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T10:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T11:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T12:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T13:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T14:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T15:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T16:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T17:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T18:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T19:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T20:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T21:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T22:00:00.0000000","n":2334},{"k":3,"t":"2015-01-10T23:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T00:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T01:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T02:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T03:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T04:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T05:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T06:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T07:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T08:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T09:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T10:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T11:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T12:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T13:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T14:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T15:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T16:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T17:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T18:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T19:00:00.0000000","n":2334},{"k":3,"t":"2015-01-11T20:00:00.0000000","n":1189},{"k":3,"t":"2015-01-11T21:00:00.0000000","n":1189},{"k":3,"t":"2015-01-11T22:00:00.0000000","n":1196},{"k":3,"t":"2015-01-11T23:00:00.0000000","n":429},{"k":3,"t":"2015-01-12T00:00:00.0000000","n":2118},{"k":3,"t":"2015-01-12T01:00:00.0000000","n":1590},{"k":3,"t":"2015-01-12T02:00:00.0000000","n":0},{"k":3,"t":"2015-01-12T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-12T13:00:00.0000000","n":125},{"k":3,"t":"2015-01-12T14:00:00.0000000","n":0},{"k":3,"t":"2015-01-12T15:00:00.0000000","n":76},{"k":3,"t":"2015-01-12T16:00:00.0000000","n":0},{"k":3,"t":"2015-01-12T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-12T18:00:00.0000000","n":101},{"k":3,"t":"2015-01-12T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-13T13:00:00.0000000","n":0},{"k":3,"t":"2015-01-13T14:00:00.0000000","n":52},{"k":3,"t":"2015-01-13T15:00:00.0000000","n":63},{"k":3,"t":"2015-01-13T16:00:00.0000000","n":62},{"k":3,"t":"2015-01-13T17:00:00.0000000","n":44},{"k":3,"t":"2015-01-13T18:00:00.0000000","n":0},{"k":3,"t":"2015-01-13T19:00:00.0000000","n":230},{"k":3,"t":"2015-01-13T20:00:00.0000000","n":0},{"k":3,"t":"2015-01-13T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-14T00:00:00.0000000","n":60},{"k":3,"t":"2015-01-14T01:00:00.0000000","n":0},{"k":3,"t":"2015-01-14T13:00:00.0000000","n":0},{"k":3,"t":"2015-01-14T14:00:00.0000000","n":66},{"k":3,"t":"2015-01-14T15:00:00.0000000","n":0},{"k":3,"t":"2015-01-14T16:00:00.0000000","n":130},{"k":3,"t":"2015-01-14T17:00:00.0000000","n":294},{"k":3,"t":"2015-01-14T18:00:00.0000000","n":0},{"k":3,"t":"2015-01-14T19:00:00.0000000","n":180},{"k":3,"t":"2015-01-14T20:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T00:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T01:00:00.0000000","n":136},{"k":3,"t":"2015-01-15T02:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T15:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T16:00:00.0000000","n":50},{"k":3,"t":"2015-01-15T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T20:00:00.0000000","n":40},{"k":3,"t":"2015-01-15T21:00:00.0000000","n":0},{"k":3,"t":"2015-01-15T22:00:00.0000000","n":80},{"k":3,"t":"2015-01-15T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-16T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-16T13:00:00.0000000","n":62},{"k":3,"t":"2015-01-16T14:00:00.0000000","n":701},{"k":3,"t":"2015-01-16T15:00:00.0000000","n":628},{"k":3,"t":"2015-01-16T16:00:00.0000000","n":769},{"k":3,"t":"2015-01-16T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-16T18:00:00.0000000","n":0},{"k":3,"t":"2015-01-16T19:00:00.0000000","n":606},{"k":3,"t":"2015-01-16T20:00:00.0000000","n":804},{"k":3,"t":"2015-01-16T21:00:00.0000000","n":606},{"k":3,"t":"2015-01-16T22:00:00.0000000","n":606},{"k":3,"t":"2015-01-16T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-17T10:00:00.0000000","n":0},{"k":3,"t":"2015-01-17T11:00:00.0000000","n":127},{"k":3,"t":"2015-01-17T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-18T14:00:00.0000000","n":0},{"k":3,"t":"2015-01-18T15:00:00.0000000","n":75},{"k":3,"t":"2015-01-18T16:00:00.0000000","n":0},{"k":3,"t":"2015-01-19T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-19T13:00:00.0000000","n":54},{"k":3,"t":"2015-01-19T14:00:00.0000000","n":142},{"k":3,"t":"2015-01-19T15:00:00.0000000","n":0},{"k":3,"t":"2015-01-19T16:00:00.0000000","n":220},{"k":3,"t":"2015-01-19T17:00:00.0000000","n":49},{"k":3,"t":"2015-01-19T18:00:00.0000000","n":128},{"k":3,"t":"2015-01-19T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-19T20:00:00.0000000","n":50},{"k":3,"t":"2015-01-19T21:00:00.0000000","n":0},{"k":3,"t":"2015-01-20T09:00:00.0000000","n":0},{"k":3,"t":"2015-01-20T10:00:00.0000000","n":823},{"k":3,"t":"2015-01-20T11:00:00.0000000","n":604},{"k":3,"t":"2015-01-20T12:00:00.0000000","n":604},{"k":3,"t":"2015-01-20T13:00:00.0000000","n":650},{"k":3,"t":"2015-01-20T14:00:00.0000000","n":604},{"k":3,"t":"2015-01-20T15:00:00.0000000","n":727},{"k":3,"t":"2015-01-20T16:00:00.0000000","n":0},{"k":3,"t":"2015-01-20T17:00:00.0000000","n":43},{"k":3,"t":"2015-01-20T18:00:00.0000000","n":90},{"k":3,"t":"2015-01-20T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-21T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-21T13:00:00.0000000","n":787},{"k":3,"t":"2015-01-21T14:00:00.0000000","n":787},{"k":3,"t":"2015-01-21T15:00:00.0000000","n":875},{"k":3,"t":"2015-01-21T16:00:00.0000000","n":787},{"k":3,"t":"2015-01-21T17:00:00.0000000","n":787},{"k":3,"t":"2015-01-21T18:00:00.0000000","n":494},{"k":3,"t":"2015-01-21T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T01:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T02:00:00.0000000","n":68},{"k":3,"t":"2015-01-22T03:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T13:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T14:00:00.0000000","n":71},{"k":3,"t":"2015-01-22T15:00:00.0000000","n":171},{"k":3,"t":"2015-01-22T16:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T18:00:00.0000000","n":0},{"k":3,"t":"2015-01-22T19:00:00.0000000","n":101},{"k":3,"t":"2015-01-22T20:00:00.0000000","n":0},{"k":3,"t":"2015-01-23T11:00:00.0000000","n":0},{"k":3,"t":"2015-01-23T12:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T13:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T14:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T15:00:00.0000000","n":883},{"k":3,"t":"2015-01-23T16:00:00.0000000","n":1230},{"k":3,"t":"2015-01-23T17:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T18:00:00.0000000","n":882},{"k":3,"t":"2015-01-23T19:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T20:00:00.0000000","n":850},{"k":3,"t":"2015-01-23T21:00:00.0000000","n":708},{"k":3,"t":"2015-01-23T22:00:00.0000000","n":112},{"k":3,"t":"2015-01-23T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-24T21:00:00.0000000","n":0},{"k":3,"t":"2015-01-24T22:00:00.0000000","n":46},{"k":3,"t":"2015-01-24T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-25T08:00:00.0000000","n":0},{"k":3,"t":"2015-01-25T09:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T10:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T11:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T12:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T13:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T14:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T15:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T16:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T17:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T18:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T19:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T20:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T21:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T22:00:00.0000000","n":1124},{"k":3,"t":"2015-01-25T23:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T00:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T01:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T02:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T03:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T04:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T05:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T06:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T07:00:00.0000000","n":1124},{"k":3,"t":"2015-01-26T08:00:00.0000000","n":409},{"k":3,"t":"2015-01-26T09:00:00.0000000","n":409},{"k":3,"t":"2015-01-26T10:00:00.0000000","n":409},{"k":3,"t":"2015-01-26T11:00:00.0000000","n":409},{"k":3,"t":"2015-01-26T12:00:00.0000000","n":409},{"k":3,"t":"2015-01-26T13:00:00.0000000","n":1129},{"k":3,"t":"2015-01-26T14:00:00.0000000","n":1201},{"k":3,"t":"2015-01-26T15:00:00.0000000","n":1441},{"k":3,"t":"2015-01-26T16:00:00.0000000","n":834},{"k":3,"t":"2015-01-26T17:00:00.0000000","n":720},{"k":3,"t":"2015-01-26T18:00:00.0000000","n":840},{"k":3,"t":"2015-01-26T19:00:00.0000000","n":850},{"k":3,"t":"2015-01-26T20:00:00.0000000","n":720},{"k":3,"t":"2015-01-26T21:00:00.0000000","n":766},{"k":3,"t":"2015-01-26T22:00:00.0000000","n":132},{"k":3,"t":"2015-01-26T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T02:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T03:00:00.0000000","n":52},{"k":3,"t":"2015-01-27T04:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T11:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T12:00:00.0000000","n":444},{"k":3,"t":"2015-01-27T13:00:00.0000000","n":502},{"k":3,"t":"2015-01-27T14:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T15:00:00.0000000","n":58},{"k":3,"t":"2015-01-27T16:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T18:00:00.0000000","n":44},{"k":3,"t":"2015-01-27T19:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T20:00:00.0000000","n":0},{"k":3,"t":"2015-01-27T21:00:00.0000000","n":68},{"k":3,"t":"2015-01-27T22:00:00.0000000","n":0},{"k":3,"t":"2015-01-28T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-28T13:00:00.0000000","n":326},{"k":3,"t":"2015-01-28T14:00:00.0000000","n":490},{"k":3,"t":"2015-01-28T15:00:00.0000000","n":136},{"k":3,"t":"2015-01-28T16:00:00.0000000","n":44},{"k":3,"t":"2015-01-28T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-28T18:00:00.0000000","n":168},{"k":3,"t":"2015-01-28T19:00:00.0000000","n":378},{"k":3,"t":"2015-01-28T20:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T00:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T01:00:00.0000000","n":54},{"k":3,"t":"2015-01-29T02:00:00.0000000","n":96},{"k":3,"t":"2015-01-29T03:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T12:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T13:00:00.0000000","n":60},{"k":3,"t":"2015-01-29T14:00:00.0000000","n":152},{"k":3,"t":"2015-01-29T15:00:00.0000000","n":303},{"k":3,"t":"2015-01-29T16:00:00.0000000","n":80},{"k":3,"t":"2015-01-29T17:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T18:00:00.0000000","n":70},{"k":3,"t":"2015-01-29T19:00:00.0000000","n":298},{"k":3,"t":"2015-01-29T20:00:00.0000000","n":171},{"k":3,"t":"2015-01-29T21:00:00.0000000","n":40},{"k":3,"t":"2015-01-29T22:00:00.0000000","n":0},{"k":3,"t":"2015-01-29T23:00:00.0000000","n":0},{"k":3,"t":"2015-01-30T00:00:00.0000000","n":150},{"k":3,"t":"2015-01-30T01:00:00.0000000","n":40},{"k":3,"t":"2015-01-30T02:00:00.0000000","n":0},{"k":3,"t":"2015-01-30T07:00:00.0000000","n":0},{"k":3,"t":"2015-01-30T08:00:00.0000000","n":130},{"k":3,"t":"2015-01-30T09:00:00.0000000","n":51},{"k":3,"t":"2015-01-30T10:00:00.0000000","n":0},{"k":3,"t":"2015-01-30T11:00:00.0000000","n":0},{"k":3,"t":"2015-01-30T12:00:00.0000000","n":615},{"k":3,"t":"2015-01-30T13:00:00.0000000","n":615},{"k":3,"t":"2015-01-30T14:00:00.0000000","n":615},{"k":3,"t":"2015-01-30T15:00:00.0000000","n":905},{"k":3,"t":"2015-01-30T16:00:00.0000000","n":1073},{"k":3,"t":"2015-01-30T17:00:00.0000000","n":615},{"k":3,"t":"2015-01-30T18:00:00.0000000","n":896},{"k":3,"t":"2015-01-30T19:00:00.0000000","n":836},{"k":3,"t":"2015-01-30T20:00:00.0000000","n":744},{"k":3,"t":"2015-01-30T21:00:00.0000000","n":946},{"k":3,"t":"2015-01-30T22:00:00.0000000","n":108},{"k":3,"t":"2015-01-30T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-01T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-01T15:00:00.0000000","n":149},{"k":3,"t":"2015-02-01T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-01T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-01T18:00:00.0000000","n":62},{"k":3,"t":"2015-02-01T19:00:00.0000000","n":0},{"k":3,"t":"2015-02-02T03:00:00.0000000","n":0},{"k":3,"t":"2015-02-02T04:00:00.0000000","n":40},{"k":3,"t":"2015-02-02T05:00:00.0000000","n":0},{"k":3,"t":"2015-02-02T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-02T13:00:00.0000000","n":566},{"k":3,"t":"2015-02-02T14:00:00.0000000","n":558},{"k":3,"t":"2015-02-02T15:00:00.0000000","n":627},{"k":3,"t":"2015-02-02T16:00:00.0000000","n":741},{"k":3,"t":"2015-02-02T17:00:00.0000000","n":850},{"k":3,"t":"2015-02-02T18:00:00.0000000","n":662},{"k":3,"t":"2015-02-02T19:00:00.0000000","n":249},{"k":3,"t":"2015-02-02T20:00:00.0000000","n":857},{"k":3,"t":"2015-02-02T21:00:00.0000000","n":815},{"k":3,"t":"2015-02-02T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T01:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T02:00:00.0000000","n":64},{"k":3,"t":"2015-02-03T03:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T13:00:00.0000000","n":160},{"k":3,"t":"2015-02-03T14:00:00.0000000","n":502},{"k":3,"t":"2015-02-03T15:00:00.0000000","n":304},{"k":3,"t":"2015-02-03T16:00:00.0000000","n":482},{"k":3,"t":"2015-02-03T17:00:00.0000000","n":244},{"k":3,"t":"2015-02-03T18:00:00.0000000","n":174},{"k":3,"t":"2015-02-03T19:00:00.0000000","n":152},{"k":3,"t":"2015-02-03T20:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T21:00:00.0000000","n":74},{"k":3,"t":"2015-02-03T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-03T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-04T00:00:00.0000000","n":44},{"k":3,"t":"2015-02-04T01:00:00.0000000","n":66},{"k":3,"t":"2015-02-04T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-04T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-04T15:00:00.0000000","n":356},{"k":3,"t":"2015-02-04T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-04T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-04T18:00:00.0000000","n":468},{"k":3,"t":"2015-02-04T19:00:00.0000000","n":92},{"k":3,"t":"2015-02-04T20:00:00.0000000","n":108},{"k":3,"t":"2015-02-04T21:00:00.0000000","n":342},{"k":3,"t":"2015-02-04T22:00:00.0000000","n":62},{"k":3,"t":"2015-02-04T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T03:00:00.0000000","n":118},{"k":3,"t":"2015-02-05T04:00:00.0000000","n":64},{"k":3,"t":"2015-02-05T05:00:00.0000000","n":192},{"k":3,"t":"2015-02-05T06:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T13:00:00.0000000","n":120},{"k":3,"t":"2015-02-05T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T15:00:00.0000000","n":78},{"k":3,"t":"2015-02-05T16:00:00.0000000","n":42},{"k":3,"t":"2015-02-05T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-05T18:00:00.0000000","n":580},{"k":3,"t":"2015-02-05T19:00:00.0000000","n":0},{"k":3,"t":"2015-02-06T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-06T13:00:00.0000000","n":182},{"k":3,"t":"2015-02-06T14:00:00.0000000","n":98},{"k":3,"t":"2015-02-06T15:00:00.0000000","n":65},{"k":3,"t":"2015-02-06T16:00:00.0000000","n":209},{"k":3,"t":"2015-02-06T17:00:00.0000000","n":54},{"k":3,"t":"2015-02-06T18:00:00.0000000","n":40},{"k":3,"t":"2015-02-06T19:00:00.0000000","n":180},{"k":3,"t":"2015-02-06T20:00:00.0000000","n":72},{"k":3,"t":"2015-02-06T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-07T15:00:00.0000000","n":0},{"k":3,"t":"2015-02-07T16:00:00.0000000","n":69},{"k":3,"t":"2015-02-07T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-08T15:00:00.0000000","n":0},{"k":3,"t":"2015-02-08T16:00:00.0000000","n":69},{"k":3,"t":"2015-02-08T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T03:00:00.0000000","n":90},{"k":3,"t":"2015-02-09T04:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T13:00:00.0000000","n":256},{"k":3,"t":"2015-02-09T14:00:00.0000000","n":106},{"k":3,"t":"2015-02-09T15:00:00.0000000","n":192},{"k":3,"t":"2015-02-09T16:00:00.0000000","n":222},{"k":3,"t":"2015-02-09T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-09T19:00:00.0000000","n":44},{"k":3,"t":"2015-02-09T20:00:00.0000000","n":194},{"k":3,"t":"2015-02-09T21:00:00.0000000","n":212},{"k":3,"t":"2015-02-09T22:00:00.0000000","n":183},{"k":3,"t":"2015-02-09T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T03:00:00.0000000","n":48},{"k":3,"t":"2015-02-10T04:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T09:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T10:00:00.0000000","n":48},{"k":3,"t":"2015-02-10T11:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T15:00:00.0000000","n":159},{"k":3,"t":"2015-02-10T16:00:00.0000000","n":414},{"k":3,"t":"2015-02-10T17:00:00.0000000","n":48},{"k":3,"t":"2015-02-10T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-10T19:00:00.0000000","n":48},{"k":3,"t":"2015-02-10T20:00:00.0000000","n":268},{"k":3,"t":"2015-02-10T21:00:00.0000000","n":312},{"k":3,"t":"2015-02-10T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-11T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-11T15:00:00.0000000","n":168},{"k":3,"t":"2015-02-11T16:00:00.0000000","n":238},{"k":3,"t":"2015-02-11T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-11T18:00:00.0000000","n":558},{"k":3,"t":"2015-02-11T19:00:00.0000000","n":504},{"k":3,"t":"2015-02-11T20:00:00.0000000","n":0},{"k":3,"t":"2015-02-12T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-12T03:00:00.0000000","n":56},{"k":3,"t":"2015-02-12T04:00:00.0000000","n":0},{"k":3,"t":"2015-02-12T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-12T13:00:00.0000000","n":142},{"k":3,"t":"2015-02-12T14:00:00.0000000","n":166},{"k":3,"t":"2015-02-12T15:00:00.0000000","n":194},{"k":3,"t":"2015-02-12T16:00:00.0000000","n":317},{"k":3,"t":"2015-02-12T17:00:00.0000000","n":60},{"k":3,"t":"2015-02-12T18:00:00.0000000","n":122},{"k":3,"t":"2015-02-12T19:00:00.0000000","n":113},{"k":3,"t":"2015-02-12T20:00:00.0000000","n":686},{"k":3,"t":"2015-02-12T21:00:00.0000000","n":60},{"k":3,"t":"2015-02-12T22:00:00.0000000","n":76},{"k":3,"t":"2015-02-12T23:00:00.0000000","n":76},{"k":3,"t":"2015-02-13T00:00:00.0000000","n":44},{"k":3,"t":"2015-02-13T01:00:00.0000000","n":62},{"k":3,"t":"2015-02-13T02:00:00.0000000","n":79},{"k":3,"t":"2015-02-13T03:00:00.0000000","n":119},{"k":3,"t":"2015-02-13T04:00:00.0000000","n":48},{"k":3,"t":"2015-02-13T05:00:00.0000000","n":0},{"k":3,"t":"2015-02-13T06:00:00.0000000","n":49},{"k":3,"t":"2015-02-13T07:00:00.0000000","n":56},{"k":3,"t":"2015-02-13T08:00:00.0000000","n":100},{"k":3,"t":"2015-02-13T09:00:00.0000000","n":0},{"k":3,"t":"2015-02-13T13:00:00.0000000","n":0},{"k":3,"t":"2015-02-13T14:00:00.0000000","n":41},{"k":3,"t":"2015-02-13T15:00:00.0000000","n":92},{"k":3,"t":"2015-02-13T16:00:00.0000000","n":210},{"k":3,"t":"2015-02-13T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-13T18:00:00.0000000","n":333},{"k":3,"t":"2015-02-13T19:00:00.0000000","n":373},{"k":3,"t":"2015-02-13T20:00:00.0000000","n":715},{"k":3,"t":"2015-02-13T21:00:00.0000000","n":438},{"k":3,"t":"2015-02-13T22:00:00.0000000","n":333},{"k":3,"t":"2015-02-13T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-14T14:00:00.0000000","n":0},{"k":3,"t":"2015-02-14T15:00:00.0000000","n":50},{"k":3,"t":"2015-02-14T16:00:00.0000000","n":66},{"k":3,"t":"2015-02-14T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-15T15:00:00.0000000","n":0},{"k":3,"t":"2015-02-15T16:00:00.0000000","n":140},{"k":3,"t":"2015-02-15T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T07:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T08:00:00.0000000","n":68},{"k":3,"t":"2015-02-16T09:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T13:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T14:00:00.0000000","n":84},{"k":3,"t":"2015-02-16T15:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-16T19:00:00.0000000","n":70},{"k":3,"t":"2015-02-16T20:00:00.0000000","n":64},{"k":3,"t":"2015-02-16T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-17T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-17T03:00:00.0000000","n":86},{"k":3,"t":"2015-02-17T04:00:00.0000000","n":0},{"k":3,"t":"2015-02-17T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-17T13:00:00.0000000","n":363},{"k":3,"t":"2015-02-17T14:00:00.0000000","n":404},{"k":3,"t":"2015-02-17T15:00:00.0000000","n":78},{"k":3,"t":"2015-02-17T16:00:00.0000000","n":545},{"k":3,"t":"2015-02-17T17:00:00.0000000","n":56},{"k":3,"t":"2015-02-17T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-17T19:00:00.0000000","n":225},{"k":3,"t":"2015-02-17T20:00:00.0000000","n":116},{"k":3,"t":"2015-02-17T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T09:00:00.0000000","n":886},{"k":3,"t":"2015-02-18T10:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T12:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T13:00:00.0000000","n":655},{"k":3,"t":"2015-02-18T14:00:00.0000000","n":44},{"k":3,"t":"2015-02-18T15:00:00.0000000","n":201},{"k":3,"t":"2015-02-18T16:00:00.0000000","n":254},{"k":3,"t":"2015-02-18T17:00:00.0000000","n":98},{"k":3,"t":"2015-02-18T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T19:00:00.0000000","n":424},{"k":3,"t":"2015-02-18T20:00:00.0000000","n":44},{"k":3,"t":"2015-02-18T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-18T22:00:00.0000000","n":48},{"k":3,"t":"2015-02-18T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-19T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T09:00:00.0000000","n":885},{"k":3,"t":"2015-02-19T10:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T11:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T12:00:00.0000000","n":927},{"k":3,"t":"2015-02-19T13:00:00.0000000","n":910},{"k":3,"t":"2015-02-19T14:00:00.0000000","n":954},{"k":3,"t":"2015-02-19T15:00:00.0000000","n":418},{"k":3,"t":"2015-02-19T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T17:00:00.0000000","n":149},{"k":3,"t":"2015-02-19T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T19:00:00.0000000","n":52},{"k":3,"t":"2015-02-19T20:00:00.0000000","n":62},{"k":3,"t":"2015-02-19T21:00:00.0000000","n":139},{"k":3,"t":"2015-02-19T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-19T23:00:00.0000000","n":47},{"k":3,"t":"2015-02-20T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-20T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-20T09:00:00.0000000","n":1644},{"k":3,"t":"2015-02-20T10:00:00.0000000","n":758},{"k":3,"t":"2015-02-20T11:00:00.0000000","n":758},{"k":3,"t":"2015-02-20T12:00:00.0000000","n":758},{"k":3,"t":"2015-02-20T13:00:00.0000000","n":758},{"k":3,"t":"2015-02-20T14:00:00.0000000","n":813},{"k":3,"t":"2015-02-20T15:00:00.0000000","n":926},{"k":3,"t":"2015-02-20T16:00:00.0000000","n":808},{"k":3,"t":"2015-02-20T17:00:00.0000000","n":758},{"k":3,"t":"2015-02-20T18:00:00.0000000","n":68},{"k":3,"t":"2015-02-20T19:00:00.0000000","n":0},{"k":3,"t":"2015-02-20T20:00:00.0000000","n":60},{"k":3,"t":"2015-02-20T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-20T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-20T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-21T00:00:00.0000000","n":117},{"k":3,"t":"2015-02-21T01:00:00.0000000","n":143},{"k":3,"t":"2015-02-21T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T05:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T06:00:00.0000000","n":140},{"k":3,"t":"2015-02-21T07:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T09:00:00.0000000","n":887},{"k":3,"t":"2015-02-21T10:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-21T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-22T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T01:00:00.0000000","n":376},{"k":3,"t":"2015-02-22T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T09:00:00.0000000","n":887},{"k":3,"t":"2015-02-22T10:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T17:00:00.0000000","n":65},{"k":3,"t":"2015-02-22T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-22T23:00:00.0000000","n":0},{"k":3,"t":"2015-02-23T00:00:00.0000000","n":80},{"k":3,"t":"2015-02-23T01:00:00.0000000","n":134},{"k":3,"t":"2015-02-23T02:00:00.0000000","n":0},{"k":3,"t":"2015-02-23T04:00:00.0000000","n":0},{"k":3,"t":"2015-02-23T05:00:00.0000000","n":734},{"k":3,"t":"2015-02-23T06:00:00.0000000","n":734},{"k":3,"t":"2015-02-23T07:00:00.0000000","n":734},{"k":3,"t":"2015-02-23T08:00:00.0000000","n":734},{"k":3,"t":"2015-02-23T09:00:00.0000000","n":1621},{"k":3,"t":"2015-02-23T10:00:00.0000000","n":702},{"k":3,"t":"2015-02-23T11:00:00.0000000","n":702},{"k":3,"t":"2015-02-23T12:00:00.0000000","n":826},{"k":3,"t":"2015-02-23T13:00:00.0000000","n":633},{"k":3,"t":"2015-02-23T14:00:00.0000000","n":633},{"k":3,"t":"2015-02-23T15:00:00.0000000","n":1171},{"k":3,"t":"2015-02-23T16:00:00.0000000","n":844},{"k":3,"t":"2015-02-23T17:00:00.0000000","n":633},{"k":3,"t":"2015-02-23T18:00:00.0000000","n":164},{"k":3,"t":"2015-02-23T19:00:00.0000000","n":246},{"k":3,"t":"2015-02-23T20:00:00.0000000","n":98},{"k":3,"t":"2015-02-23T21:00:00.0000000","n":0},{"k":3,"t":"2015-02-23T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-23T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-24T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T01:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T02:00:00.0000000","n":235},{"k":3,"t":"2015-02-24T03:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T09:00:00.0000000","n":887},{"k":3,"t":"2015-02-24T10:00:00.0000000","n":580},{"k":3,"t":"2015-02-24T11:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T13:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T14:00:00.0000000","n":645},{"k":3,"t":"2015-02-24T15:00:00.0000000","n":88},{"k":3,"t":"2015-02-24T16:00:00.0000000","n":62},{"k":3,"t":"2015-02-24T17:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-24T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-25T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T08:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T09:00:00.0000000","n":890},{"k":3,"t":"2015-02-25T10:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T13:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T14:00:00.0000000","n":1083},{"k":3,"t":"2015-02-25T15:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-25T17:00:00.0000000","n":138},{"k":3,"t":"2015-02-25T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-26T13:00:00.0000000","n":0},{"k":3,"t":"2015-02-26T14:00:00.0000000","n":208},{"k":3,"t":"2015-02-26T15:00:00.0000000","n":40},{"k":3,"t":"2015-02-26T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-26T17:00:00.0000000","n":40},{"k":3,"t":"2015-02-26T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-26T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-26T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-27T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-27T16:00:00.0000000","n":0},{"k":3,"t":"2015-02-27T17:00:00.0000000","n":158},{"k":3,"t":"2015-02-27T18:00:00.0000000","n":0},{"k":3,"t":"2015-02-27T19:00:00.0000000","n":172},{"k":3,"t":"2015-02-27T20:00:00.0000000","n":0},{"k":3,"t":"2015-02-27T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-27T23:00:00.0000000","n":43},{"k":3,"t":"2015-02-28T00:00:00.0000000","n":0},{"k":3,"t":"2015-02-28T22:00:00.0000000","n":0},{"k":3,"t":"2015-02-28T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-01T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-01T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-01T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-02T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T15:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T16:00:00.0000000","n":50},{"k":3,"t":"2015-03-02T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T19:00:00.0000000","n":61},{"k":3,"t":"2015-03-02T20:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T21:00:00.0000000","n":102},{"k":3,"t":"2015-03-02T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-02T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-03T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T03:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T04:00:00.0000000","n":57},{"k":3,"t":"2015-03-03T05:00:00.0000000","n":45},{"k":3,"t":"2015-03-03T06:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T08:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T09:00:00.0000000","n":891},{"k":3,"t":"2015-03-03T10:00:00.0000000","n":44},{"k":3,"t":"2015-03-03T11:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T13:00:00.0000000","n":64},{"k":3,"t":"2015-03-03T14:00:00.0000000","n":705},{"k":3,"t":"2015-03-03T15:00:00.0000000","n":532},{"k":3,"t":"2015-03-03T16:00:00.0000000","n":233},{"k":3,"t":"2015-03-03T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T20:00:00.0000000","n":48},{"k":3,"t":"2015-03-03T21:00:00.0000000","n":167},{"k":3,"t":"2015-03-03T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-03T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-04T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T02:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T03:00:00.0000000","n":54},{"k":3,"t":"2015-03-04T04:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T07:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T08:00:00.0000000","n":57},{"k":3,"t":"2015-03-04T09:00:00.0000000","n":889},{"k":3,"t":"2015-03-04T10:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T13:00:00.0000000","n":276},{"k":3,"t":"2015-03-04T14:00:00.0000000","n":68},{"k":3,"t":"2015-03-04T15:00:00.0000000","n":90},{"k":3,"t":"2015-03-04T16:00:00.0000000","n":160},{"k":3,"t":"2015-03-04T17:00:00.0000000","n":61},{"k":3,"t":"2015-03-04T18:00:00.0000000","n":563},{"k":3,"t":"2015-03-04T19:00:00.0000000","n":326},{"k":3,"t":"2015-03-04T20:00:00.0000000","n":58},{"k":3,"t":"2015-03-04T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-04T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-05T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T11:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T12:00:00.0000000","n":52},{"k":3,"t":"2015-03-05T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T18:00:00.0000000","n":502},{"k":3,"t":"2015-03-05T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-05T22:00:00.0000000","n":54},{"k":3,"t":"2015-03-05T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T02:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T03:00:00.0000000","n":74},{"k":3,"t":"2015-03-06T04:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T15:00:00.0000000","n":61},{"k":3,"t":"2015-03-06T16:00:00.0000000","n":1120},{"k":3,"t":"2015-03-06T17:00:00.0000000","n":48},{"k":3,"t":"2015-03-06T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T19:00:00.0000000","n":273},{"k":3,"t":"2015-03-06T20:00:00.0000000","n":0},{"k":3,"t":"2015-03-06T21:00:00.0000000","n":105},{"k":3,"t":"2015-03-06T22:00:00.0000000","n":52},{"k":3,"t":"2015-03-06T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-07T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-09T10:00:00.0000000","n":0},{"k":3,"t":"2015-03-09T11:00:00.0000000","n":45},{"k":3,"t":"2015-03-09T12:00:00.0000000","n":181},{"k":3,"t":"2015-03-09T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-09T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-09T15:00:00.0000000","n":70},{"k":3,"t":"2015-03-09T16:00:00.0000000","n":104},{"k":3,"t":"2015-03-09T17:00:00.0000000","n":393},{"k":3,"t":"2015-03-09T18:00:00.0000000","n":123},{"k":3,"t":"2015-03-09T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-09T20:00:00.0000000","n":156},{"k":3,"t":"2015-03-09T21:00:00.0000000","n":47},{"k":3,"t":"2015-03-09T22:00:00.0000000","n":43},{"k":3,"t":"2015-03-09T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T01:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T02:00:00.0000000","n":73},{"k":3,"t":"2015-03-10T03:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T13:00:00.0000000","n":302},{"k":3,"t":"2015-03-10T14:00:00.0000000","n":391},{"k":3,"t":"2015-03-10T15:00:00.0000000","n":307},{"k":3,"t":"2015-03-10T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T18:00:00.0000000","n":173},{"k":3,"t":"2015-03-10T19:00:00.0000000","n":138},{"k":3,"t":"2015-03-10T20:00:00.0000000","n":134},{"k":3,"t":"2015-03-10T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-10T23:00:00.0000000","n":43},{"k":3,"t":"2015-03-11T00:00:00.0000000","n":48},{"k":3,"t":"2015-03-11T01:00:00.0000000","n":0},{"k":3,"t":"2015-03-11T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-11T13:00:00.0000000","n":139},{"k":3,"t":"2015-03-11T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-11T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-11T20:00:00.0000000","n":549},{"k":3,"t":"2015-03-11T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-12T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-12T14:00:00.0000000","n":484},{"k":3,"t":"2015-03-12T15:00:00.0000000","n":46},{"k":3,"t":"2015-03-12T16:00:00.0000000","n":137},{"k":3,"t":"2015-03-12T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-12T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-12T20:00:00.0000000","n":175},{"k":3,"t":"2015-03-12T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-13T08:00:00.0000000","n":0},{"k":3,"t":"2015-03-13T09:00:00.0000000","n":184},{"k":3,"t":"2015-03-13T10:00:00.0000000","n":1076},{"k":3,"t":"2015-03-13T11:00:00.0000000","n":1216},{"k":3,"t":"2015-03-13T12:00:00.0000000","n":944},{"k":3,"t":"2015-03-13T13:00:00.0000000","n":630},{"k":3,"t":"2015-03-13T14:00:00.0000000","n":383},{"k":3,"t":"2015-03-13T15:00:00.0000000","n":425},{"k":3,"t":"2015-03-13T16:00:00.0000000","n":383},{"k":3,"t":"2015-03-13T17:00:00.0000000","n":808},{"k":3,"t":"2015-03-13T18:00:00.0000000","n":874},{"k":3,"t":"2015-03-13T19:00:00.0000000","n":524},{"k":3,"t":"2015-03-13T20:00:00.0000000","n":383},{"k":3,"t":"2015-03-13T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-16T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-16T15:00:00.0000000","n":87},{"k":3,"t":"2015-03-16T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-16T17:00:00.0000000","n":0},{"k":3,"t":"2015-03-16T18:00:00.0000000","n":1755},{"k":3,"t":"2015-03-16T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-16T20:00:00.0000000","n":168},{"k":3,"t":"2015-03-16T21:00:00.0000000","n":96},{"k":3,"t":"2015-03-16T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T03:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T04:00:00.0000000","n":44},{"k":3,"t":"2015-03-17T05:00:00.0000000","n":48},{"k":3,"t":"2015-03-17T06:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T07:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T08:00:00.0000000","n":48},{"k":3,"t":"2015-03-17T09:00:00.0000000","n":48},{"k":3,"t":"2015-03-17T10:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T11:00:00.0000000","n":96},{"k":3,"t":"2015-03-17T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T13:00:00.0000000","n":819},{"k":3,"t":"2015-03-17T14:00:00.0000000","n":66},{"k":3,"t":"2015-03-17T15:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T16:00:00.0000000","n":49},{"k":3,"t":"2015-03-17T17:00:00.0000000","n":54},{"k":3,"t":"2015-03-17T18:00:00.0000000","n":42},{"k":3,"t":"2015-03-17T19:00:00.0000000","n":158},{"k":3,"t":"2015-03-17T20:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-17T22:00:00.0000000","n":43},{"k":3,"t":"2015-03-17T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-18T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-18T14:00:00.0000000","n":40},{"k":3,"t":"2015-03-18T15:00:00.0000000","n":0},{"k":3,"t":"2015-03-18T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-18T17:00:00.0000000","n":56},{"k":3,"t":"2015-03-18T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-18T19:00:00.0000000","n":223},{"k":3,"t":"2015-03-18T20:00:00.0000000","n":812},{"k":3,"t":"2015-03-18T21:00:00.0000000","n":54},{"k":3,"t":"2015-03-18T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-19T10:00:00.0000000","n":0},{"k":3,"t":"2015-03-19T11:00:00.0000000","n":697},{"k":3,"t":"2015-03-19T12:00:00.0000000","n":816},{"k":3,"t":"2015-03-19T13:00:00.0000000","n":697},{"k":3,"t":"2015-03-19T14:00:00.0000000","n":590},{"k":3,"t":"2015-03-19T15:00:00.0000000","n":98},{"k":3,"t":"2015-03-19T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-19T17:00:00.0000000","n":53},{"k":3,"t":"2015-03-19T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-20T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-20T14:00:00.0000000","n":66},{"k":3,"t":"2015-03-20T15:00:00.0000000","n":0},{"k":3,"t":"2015-03-20T16:00:00.0000000","n":42},{"k":3,"t":"2015-03-20T17:00:00.0000000","n":325},{"k":3,"t":"2015-03-20T18:00:00.0000000","n":325},{"k":3,"t":"2015-03-20T19:00:00.0000000","n":325},{"k":3,"t":"2015-03-20T20:00:00.0000000","n":325},{"k":3,"t":"2015-03-20T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-20T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-21T00:00:00.0000000","n":117},{"k":3,"t":"2015-03-21T01:00:00.0000000","n":140},{"k":3,"t":"2015-03-21T02:00:00.0000000","n":0},{"k":3,"t":"2015-03-21T05:00:00.0000000","n":0},{"k":3,"t":"2015-03-21T06:00:00.0000000","n":138},{"k":3,"t":"2015-03-21T07:00:00.0000000","n":0},{"k":3,"t":"2015-03-22T20:00:00.0000000","n":0},{"k":3,"t":"2015-03-22T21:00:00.0000000","n":399},{"k":3,"t":"2015-03-22T22:00:00.0000000","n":639},{"k":3,"t":"2015-03-22T23:00:00.0000000","n":626},{"k":3,"t":"2015-03-23T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-23T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-23T13:00:00.0000000","n":68},{"k":3,"t":"2015-03-23T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-23T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-23T19:00:00.0000000","n":41},{"k":3,"t":"2015-03-23T20:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T11:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T12:00:00.0000000","n":63},{"k":3,"t":"2015-03-24T13:00:00.0000000","n":120},{"k":3,"t":"2015-03-24T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T15:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T16:00:00.0000000","n":40},{"k":3,"t":"2015-03-24T17:00:00.0000000","n":40},{"k":3,"t":"2015-03-24T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T19:00:00.0000000","n":369},{"k":3,"t":"2015-03-24T20:00:00.0000000","n":369},{"k":3,"t":"2015-03-24T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-24T23:00:00.0000000","n":42},{"k":3,"t":"2015-03-25T00:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T15:00:00.0000000","n":121},{"k":3,"t":"2015-03-25T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T17:00:00.0000000","n":783},{"k":3,"t":"2015-03-25T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T20:00:00.0000000","n":124},{"k":3,"t":"2015-03-25T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-25T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T00:00:00.0000000","n":264},{"k":3,"t":"2015-03-26T01:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T02:00:00.0000000","n":167},{"k":3,"t":"2015-03-26T03:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T13:00:00.0000000","n":505},{"k":3,"t":"2015-03-26T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T17:00:00.0000000","n":42},{"k":3,"t":"2015-03-26T18:00:00.0000000","n":249},{"k":3,"t":"2015-03-26T19:00:00.0000000","n":383},{"k":3,"t":"2015-03-26T20:00:00.0000000","n":382},{"k":3,"t":"2015-03-26T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-26T23:00:00.0000000","n":0},{"k":3,"t":"2015-03-27T00:00:00.0000000","n":196},{"k":3,"t":"2015-03-27T01:00:00.0000000","n":41},{"k":3,"t":"2015-03-27T02:00:00.0000000","n":0},{"k":3,"t":"2015-03-27T10:00:00.0000000","n":0},{"k":3,"t":"2015-03-27T11:00:00.0000000","n":104},{"k":3,"t":"2015-03-27T12:00:00.0000000","n":102},{"k":3,"t":"2015-03-27T13:00:00.0000000","n":102},{"k":3,"t":"2015-03-27T14:00:00.0000000","n":184},{"k":3,"t":"2015-03-27T15:00:00.0000000","n":102},{"k":3,"t":"2015-03-27T16:00:00.0000000","n":102},{"k":3,"t":"2015-03-27T17:00:00.0000000","n":456},{"k":3,"t":"2015-03-27T18:00:00.0000000","n":456},{"k":3,"t":"2015-03-27T19:00:00.0000000","n":354},{"k":3,"t":"2015-03-27T20:00:00.0000000","n":354},{"k":3,"t":"2015-03-27T21:00:00.0000000","n":354},{"k":3,"t":"2015-03-27T22:00:00.0000000","n":0},{"k":3,"t":"2015-03-28T11:00:00.0000000","n":0},{"k":3,"t":"2015-03-28T12:00:00.0000000","n":85},{"k":3,"t":"2015-03-28T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-29T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-29T13:00:00.0000000","n":80},{"k":3,"t":"2015-03-29T14:00:00.0000000","n":56},{"k":3,"t":"2015-03-29T15:00:00.0000000","n":102},{"k":3,"t":"2015-03-29T16:00:00.0000000","n":140},{"k":3,"t":"2015-03-29T17:00:00.0000000","n":100},{"k":3,"t":"2015-03-29T18:00:00.0000000","n":156},{"k":3,"t":"2015-03-29T19:00:00.0000000","n":100},{"k":3,"t":"2015-03-29T20:00:00.0000000","n":124},{"k":3,"t":"2015-03-29T21:00:00.0000000","n":116},{"k":3,"t":"2015-03-29T22:00:00.0000000","n":72},{"k":3,"t":"2015-03-29T23:00:00.0000000","n":140},{"k":3,"t":"2015-03-30T00:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T01:00:00.0000000","n":132},{"k":3,"t":"2015-03-30T02:00:00.0000000","n":124},{"k":3,"t":"2015-03-30T03:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T04:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T05:00:00.0000000","n":116},{"k":3,"t":"2015-03-30T06:00:00.0000000","n":88},{"k":3,"t":"2015-03-30T07:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T08:00:00.0000000","n":116},{"k":3,"t":"2015-03-30T09:00:00.0000000","n":124},{"k":3,"t":"2015-03-30T10:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T11:00:00.0000000","n":92},{"k":3,"t":"2015-03-30T12:00:00.0000000","n":116},{"k":3,"t":"2015-03-30T13:00:00.0000000","n":0},{"k":3,"t":"2015-03-30T14:00:00.0000000","n":0},{"k":3,"t":"2015-03-30T15:00:00.0000000","n":40},{"k":3,"t":"2015-03-30T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-30T19:00:00.0000000","n":0},{"k":3,"t":"2015-03-30T20:00:00.0000000","n":90},{"k":3,"t":"2015-03-30T21:00:00.0000000","n":0},{"k":3,"t":"2015-03-31T12:00:00.0000000","n":0},{"k":3,"t":"2015-03-31T13:00:00.0000000","n":64},{"k":3,"t":"2015-03-31T14:00:00.0000000","n":143},{"k":3,"t":"2015-03-31T15:00:00.0000000","n":62},{"k":3,"t":"2015-03-31T16:00:00.0000000","n":0},{"k":3,"t":"2015-03-31T18:00:00.0000000","n":0},{"k":3,"t":"2015-03-31T19:00:00.0000000","n":237},{"k":3,"t":"2015-03-31T20:00:00.0000000","n":0},{"k":3,"t":"2015-04-01T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-01T12:00:00.0000000","n":140},{"k":3,"t":"2015-04-01T13:00:00.0000000","n":95},{"k":3,"t":"2015-04-01T14:00:00.0000000","n":144},{"k":3,"t":"2015-04-01T15:00:00.0000000","n":277},{"k":3,"t":"2015-04-01T16:00:00.0000000","n":0},{"k":3,"t":"2015-04-01T17:00:00.0000000","n":478},{"k":3,"t":"2015-04-01T18:00:00.0000000","n":0},{"k":3,"t":"2015-04-01T23:00:00.0000000","n":0},{"k":3,"t":"2015-04-02T00:00:00.0000000","n":74},{"k":3,"t":"2015-04-02T01:00:00.0000000","n":0},{"k":3,"t":"2015-04-02T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-02T12:00:00.0000000","n":274},{"k":3,"t":"2015-04-02T13:00:00.0000000","n":0},{"k":3,"t":"2015-04-02T14:00:00.0000000","n":0},{"k":3,"t":"2015-04-02T15:00:00.0000000","n":134},{"k":3,"t":"2015-04-02T16:00:00.0000000","n":68},{"k":3,"t":"2015-04-02T17:00:00.0000000","n":264},{"k":3,"t":"2015-04-02T18:00:00.0000000","n":96},{"k":3,"t":"2015-04-02T19:00:00.0000000","n":0},{"k":3,"t":"2015-04-03T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-03T12:00:00.0000000","n":95},{"k":3,"t":"2015-04-03T13:00:00.0000000","n":206},{"k":3,"t":"2015-04-03T14:00:00.0000000","n":111},{"k":3,"t":"2015-04-03T15:00:00.0000000","n":0},{"k":3,"t":"2015-04-06T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-06T12:00:00.0000000","n":40},{"k":3,"t":"2015-04-06T13:00:00.0000000","n":0},{"k":3,"t":"2015-04-06T14:00:00.0000000","n":72},{"k":3,"t":"2015-04-06T15:00:00.0000000","n":58},{"k":3,"t":"2015-04-06T16:00:00.0000000","n":0},{"k":3,"t":"2015-04-06T17:00:00.0000000","n":134},{"k":3,"t":"2015-04-06T18:00:00.0000000","n":0},{"k":3,"t":"2015-04-07T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-07T12:00:00.0000000","n":279},{"k":3,"t":"2015-04-07T13:00:00.0000000","n":0},{"k":3,"t":"2015-04-07T14:00:00.0000000","n":69},{"k":3,"t":"2015-04-07T15:00:00.0000000","n":264},{"k":3,"t":"2015-04-07T16:00:00.0000000","n":0},{"k":3,"t":"2015-04-08T11:00:00.0000000","n":0},{"k":3,"t":"2015-04-08T12:00:00.0000000","n":66}]'); } -/* jscs:enable maximumLineLength*/ -/* jshint maxlen: 140 */ -describe('dc.barChart.biggish', function () { - beforeEach(function () { +describe('dc.barChart.biggish', () => { + beforeEach(() => { appendChartID('stack-chart'); appendChartID('range-chart'); - var chartAttemptSeries = dc.lineChart('#stack-chart'); - var chartRange = dc.barChart('#range-chart'); + const chartAttemptSeries = new dc.LineChart('#stack-chart'); + const chartRange = new dc.BarChart('#range-chart'); - var dateFormat = d3.time.format.iso; + const data = biggishData(); - var xfilter; - - var data = biggishData(); - - data.forEach(function (row) { + data.forEach(row => { // coerce k(ind) into a number row.k = +row.k; // convert event time into d3 date format - row.dd = dateFormat.parse(row.t); + row.dd = d3.isoParse(row.t); // pre-calculate the day of the time - row.day = d3.time.day(row.dd); + row.day = d3.utcDay(row.dd); // precalculate the hour of the time - row.hour = d3.time.hour(row.dd); + row.hour = d3.utcHour(row.dd); // coerce n(umber of attempts) into a number row.n = +row.n; }); - xfilter = crossfilter(data); + const xfilter = crossfilter(data); // hour dimension (across all kinds) - var dimHour = xfilter.dimension(function (row) { return row.hour; }); + const dimHour = xfilter.dimension(row => row.hour); // grouping used by the range chart (sum of number of attempts for all kinds per hour) - var groupHourSum = dimHour.group().reduceSum(function (row) { return row.n; }); + const groupHourSum = dimHour.group().reduceSum(row => row.n); // groupings used by the stacked bar chart (one value for each kind) - var groupHourSeries = dimHour.group().reduce( - function (p, v) { + const groupHourSeries = dimHour.group().reduce( + (p, v) => { switch (v.k) { case 1: p.hma += v.n; @@ -57,7 +50,7 @@ describe('dc.barChart.biggish', function () { } // switch return p; }, - function (p, v) { + (p, v) => { switch (v.k) { case 1: p.hma -= v.n; @@ -71,25 +64,23 @@ describe('dc.barChart.biggish', function () { } // switch return p; }, - function () { - return { - hma: 0, - bfa: 0, - uha: 0 - }; - } + () => ({ + hma: 0, + bfa: 0, + uha: 0 + }) ); // calculate day extent (two element array of first and last items in the range) - of the hour data - var extentDay = d3.extent(data, function (row) { return row.day; }); + const extentDay = d3.extent(data, row => row.day); // select the following day for the end of the extent - extentDay[1] = d3.time.day.offset(extentDay[1], 1); + extentDay[1] = d3.utcDay.offset(extentDay[1], 1); chartAttemptSeries .margins({top: 30, right: 50, bottom: 25, left: 40}) .renderArea(true) .height(200) - .x(d3.time.scale().domain(extentDay)) + .x(d3.scaleUtc().domain(extentDay)) .renderHorizontalGridLines(true) .rangeChart(chartRange) .transitionDuration(1000) @@ -100,12 +91,12 @@ describe('dc.barChart.biggish', function () { chartAttemptSeries .dimension(dimHour) .group(groupHourSeries, 'Brute Force') - .valueAccessor(function (d) { return d.value.bfa; }) - .stack(groupHourSeries, 'Horizontal Movement', function (d) { return d.value.hma; }) - .stack(groupHourSeries, 'User Account Hacking', function (d) { return d.value.uha; }) - .xUnits(d3.time.hours); + .valueAccessor(d => d.value.bfa) + .stack(groupHourSeries, 'Horizontal Movement', d => d.value.hma) + .stack(groupHourSeries, 'User Account Hacking', d => d.value.uha) + .xUnits(d3.utcHours); - chartAttemptSeries.legend(dc.legend().horizontal(true).x(50).y(0).itemWidth(150).gap(5)); + chartAttemptSeries.legend(new dc.Legend().horizontal(true).x(50).y(0).itemWidth(150).gap(5)); chartRange .height(80) @@ -113,10 +104,10 @@ describe('dc.barChart.biggish', function () { .group(groupHourSum) .centerBar(true) .gap(1) - .xUnits(d3.time.hours) - .round(d3.time.hour.round) + .xUnits(d3.utcHours) + .round(d3.utcHour.round) .alwaysUseRounding(true) - .x(d3.time.scale().domain(extentDay)) + .x(d3.scaleUtc().domain(extentDay)) // hide the range chart's y axis // note: breaks function chaining by returning the yAxis @@ -128,8 +119,8 @@ describe('dc.barChart.biggish', function () { }); - describe('smoke test for #909', function () { - it('doesn\'t die', function () { + describe('smoke test for #909', () => { + it('doesn\'t die', () => { expect(true).toBeTruthy(); }); }); diff --git a/spec/box-plot-spec.js b/spec/box-plot-spec.js index b55cbffc7e..a32caa6728 100644 --- a/spec/box-plot-spec.js +++ b/spec/box-plot-spec.js @@ -1,22 +1,22 @@ /* global appendChartID, loadBoxPlotFixture */ -describe('dc.boxPlot', function () { - var id, chart; - var data, dimension, group; +describe('dc.BoxPlot', () => { + let id, chart; + let data, dimension, group; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadBoxPlotFixture()); - dimension = data.dimension(function (d) { return d.countrycode; }); + dimension = data.dimension(d => d.countrycode); group = dimension.group().reduce( - function (p, v) { p.push(+v.value); return p; }, - function (p, v) { p.splice(p.indexOf(+v.value), 1); return p; }, - function () { return []; } + (p, v) => { p.push(+v.value); return p; }, + (p, v) => { p.splice(p.indexOf(+v.value), 1); return p; }, + () => [] ); id = 'boxplot'; appendChartID(id); - chart = dc.boxPlot('#' + id); + chart = new dc.BoxPlot(`#${id}`); chart .dimension(dimension) .group(group) @@ -25,67 +25,164 @@ describe('dc.boxPlot', function () { .margins({top: 0, right: 0, bottom: 0, left: 0}) .boxPadding(0) .transitionDuration(0) - .y(d3.scale.linear().domain([0, 144])) + .transitionDelay(0) + .y(d3.scaleLinear().domain([0, 144])) .ordinalColors(['#01','#02']); }); - describe('rendering the box plot', function () { - beforeEach(function () { + describe('rendering the box plot', () => { + beforeEach(() => { chart.render(); }); - it('should create a non-empty SVG node', function () { + it('should create a non-empty SVG node', () => { expect(chart.svg().empty()).toBeFalsy(); }); - it('should create one outlier circle per outlier', function () { + it('should create normal outlier circles (by default)', () => { expect(chart.selectAll('circle.outlier').size()).toBe(2); }); - it('should create an offset box for each dimension in the group', function () { - expect(box(0).attr('transform')).toMatchTranslate(50,0); - expect(box(1).attr('transform')).toMatchTranslate(150,0); + it('should not create bold outlier circles (by default)', () => { + expect(chart.selectAll('circle.outlierBold').size()).toBe(0); }); - it('should correctly place median line', function () { + it('should not create data points (by default)', () => { + expect(chart.selectAll('circle.data').size()).toBe(0); + }); + + it('should not create tooltips (by default)', () => { + expect(chart.selectAll('circle.data').select('title').size()).toBe(0); + }); + + it('should create an offset box for each dimension in the group', () => { + expect(box(0).attr('transform')).toMatchTranslate(50, 0); + expect(box(1).attr('transform')).toMatchTranslate(150, 0); + }); + + it('should correctly place median line', () => { expect(box(1).selectAll('line.median').attr('y1')).toBe('100'); expect(box(1).selectAll('line.median').attr('y2')).toBe('100'); }); - it('should set the median value correctly', function () { + it('should set the median value correctly', () => { expect(box(1).boxText(1).text()).toBe('44'); }); - it('should place the left box line at the x origin', function () { + it('should place the left box line at the x origin', () => { expect(box(1).select('rect.box').attr('x')).toBe('0'); }); - describe('the width of the box plot', function () { - it('should default to being based on the rangeBand', function () { + describe('with showOutliers disabled', () => { + beforeEach(() => { + chart.showOutliers(false).render(); + }); + + it('should not create any outlier circles ', () => { + expect(chart.selectAll('circle.outlier').size()).toBe(0); + expect(chart.selectAll('circle.outlierBold').size()).toBe(0); + }); + }); + + describe('with renderDataPoints enabled', () => { + beforeEach(() => { + chart + .renderDataPoints(true) + .renderTitle(true) + .boxWidth(100) + .render(); + }); + + it('should create one data point per data value (non-outlier)', () => { + expect(chart.selectAll('circle.data').size()).toBe(12); + }); + it('should create a tooltip for each data value (non-outlier)', () => { + expect(chart.selectAll('circle.data').select('title').size()).toBe(12); + }); + it('should display the data between 10 to 90 of the box (by default)', () => { + const w = box(1).select('rect.box').attr('width'); + const min = (w / 2) - (w * chart.dataWidthPortion() / 2); + const max = (w / 2) + (w * chart.dataWidthPortion() / 2); + chart.selectAll('circle.data').each(function () { + expect(d3.select(this).attr('cx')).toBeGreaterThan(min - 0.1); + expect(d3.select(this).attr('cx')).toBeLessThan(max + 0.1); + }); + }); + + describe('and dataWidthPortion set to 50%', () => { + beforeEach(() => { + chart + .dataWidthPortion(0.5) + .render(); + }); + + it('should display the data between 25 to 75 of the box', () => { + const w = box(1).select('rect.box').attr('width'); + const min = (w / 2) - (w * chart.dataWidthPortion() / 2); + const max = (w / 2) + (w * chart.dataWidthPortion() / 2); + chart.selectAll('circle.data').each(function () { + expect(d3.select(this).attr('cx')).toBeGreaterThan(min - 0.1); + expect(d3.select(this).attr('cx')).toBeLessThan(max + 0.1); + }); + }); + }); + + describe('and dataWidthPortion set to 10%', () => { + beforeEach(() => { + chart + .dataWidthPortion(0.1) + .render(); + }); + + it('should display the data between 45 to 55 of the box', () => { + const w = box(1).select('rect.box').attr('width'); + const min = (w / 2) - (w * chart.dataWidthPortion() / 2); + const max = (w / 2) + (w * chart.dataWidthPortion() / 2); + chart.selectAll('circle.data').each(function () { + expect(d3.select(this).attr('cx')).toBeGreaterThan(min - 0.1); + expect(d3.select(this).attr('cx')).toBeLessThan(max + 0.1); + }); + }); + }); + }); + + describe('with boldOutlier enabled', () => { + beforeEach(() => { + chart.boldOutlier(true).render(); + }); + + it('should create bold outlier circles', () => { + expect(chart.selectAll('circle.outlierBold').size()).toBe(2); + }); + it('should not create normal outlier circles ', () => { + expect(chart.selectAll('circle.outlier').size()).toBe(0); + }); + }); + + describe('the width of the box plot', () => { + it('should default to being based on the rangeBand', () => { expect(box(1).select('rect.box').attr('width')).toBe('100'); }); - it('should be settable to a number', function () { + it('should be settable to a number', () => { chart.boxWidth(150).render(); expect(box(1).select('rect.box').attr('width')).toBe('150'); }); - it('should be settable to a function', function () { - chart.boxWidth(function (innerChartWidth, xUnits) { - return innerChartWidth / (xUnits + 2); - }).render(); + it('should be settable to a function', () => { + chart.boxWidth((innerChartWidth, xUnits) => innerChartWidth / (xUnits + 2)).render(); expect(box(1).select('rect.box').attr('width')).toBe('75'); }); }); - describe('the tickFormat of the box plot', function () { - it('should default to whole number', function () { + describe('the tickFormat of the box plot', () => { + it('should default to whole number', () => { expect(box(1).boxText(1).text()).toBe('44'); expect(box(1).whiskerText(0).text()).toBe('22'); expect(box(1).whiskerText(1).text()).toBe('66'); }); - it('should be settable to a d3.format', function () { + it('should be settable to a d3.format', () => { chart.tickFormat(d3.format('.2f')).render(); expect(box(1).boxText(1).text()).toBe('44.00'); expect(box(1).whiskerText(0).text()).toBe('22.00'); @@ -93,117 +190,148 @@ describe('dc.boxPlot', function () { }); }); - it('should place interquartile range lines after the first and before the fourth quartile', function () { + it('should place interquartile range lines after the first and before the fourth quartile', () => { expect(box(1).select('rect.box').attr('y')).toBe('94.5'); expect(box(1).select('rect.box').attr('height')).toBe('16.5'); }); - it('should label the interquartile range lines using their calculated values', function () { + it('should label the interquartile range lines using their calculated values', () => { expect(box(1).boxText(0).text()).toBe('33'); expect(box(1).boxText(2).text()).toBe('50'); }); - it('should place the whiskers at 1.5x the interquartile range', function () { + it('should place the whiskers at 1.5x the interquartile range', () => { expect(box(1).whiskerLine(0).attr('y1')).toBe('122'); expect(box(1).whiskerLine(0).attr('y2')).toBe('122'); expect(box(1).whiskerLine(1).attr('y1')).toBeWithinDelta(78); expect(box(1).whiskerLine(1).attr('y2')).toBeWithinDelta(78); }); - it('should label the whiskers using their calculated values', function () { + it('should label the whiskers using their calculated values', () => { expect(box(1).whiskerText(0).text()).toBe('22'); expect(box(1).whiskerText(1).text()).toBe('66'); }); - it('should assign a fill color to the boxes', function () { + it('should assign a fill color to the boxes', () => { expect(box(0).select('rect.box').attr('fill')).toBe('#01'); expect(box(1).select('rect.box').attr('fill')).toBe('#02'); }); - describe('when a box has no data', function () { - var firstBox; + describe('when a box has no data', () => { + let firstBox; - beforeEach(function () { + beforeEach(() => { firstBox = chart.select('g.box').node(); - var otherDimension = data.dimension(function (d) { return d.countrycode; }); + const otherDimension = data.dimension(d => d.countrycode); otherDimension.filter('US'); chart.redraw(); }); - it('should not attempt to render that box', function () { + it('should not attempt to render that box', () => { expect(chart.selectAll('g.box').size()).toBe(1); }); - it('should not animate the removed box into another box', function () { + it('should not animate the removed box into another box', () => { expect(chart.select('g.box').node()).not.toBe(firstBox); }); - describe('with elasticX enabled', function () { - beforeEach(function () { + describe('with elasticX enabled', () => { + beforeEach(() => { chart.elasticX(true).render(); }); - it('should not represent the box in the chart domain', function () { + it('should not represent the box in the chart domain', () => { expect(chart.selectAll('.axis.x .tick').size()).toBe(1); }); }); - describe('when elasticX is disabled', function () { - beforeEach(function () { + describe('when elasticX is disabled', () => { + beforeEach(() => { chart.elasticX(false).render(); }); - it('should represent the box in the chart domain', function () { + it('should represent the box in the chart domain', () => { expect(chart.selectAll('.axis.x .tick').size()).toBe(2); }); }); }); }); - describe('events', function () { - beforeEach(function () { + describe('events', () => { + beforeEach(() => { chart.render(); }); - describe('filtering the box plot', function () { - beforeEach(function () { + describe('filtering the box plot', () => { + beforeEach(() => { chart.filter('CA').redraw(); }); - it('should select the boxes corresponding to the filtered value', function () { + it('should select the boxes corresponding to the filtered value', () => { box(0).each(function (d) { expect(d3.select(this).classed('selected')).toBeTruthy(); }); }); - it('should deselect the boxes not corresponding to the filtered value', function () { + it('should deselect the boxes not corresponding to the filtered value', () => { box(1).each(function (d) { expect(d3.select(this).classed('deselected')).toBeTruthy(); }); }); }); - describe('clicking on a box', function () { - beforeEach(function () { - box(0).on('click').call(chart, box(0).datum()); + describe('clicking on a box', () => { + beforeEach(() => { + dc.d3compat.callHandler(box(0).on('click'), chart, {}, box(0).datum()); }); - it('should apply a filter to the chart', function () { + it('should apply a filter to the chart', () => { expect(chart.hasFilter('CA')).toBeTruthy(); }); }); }); + describe('accessibility scatter plot', () => { + + it('internal elements are focusable by keyboard', () => { + chart.keyboardAccessible(true); + chart.render(); + chart.selectAll('circle').each(function () { + const circle = d3.select(this); + expect(circle.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + chart.keyboardAccessible(true); + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + // only boxes are valid targets for keydown events + chart.selectAll('g.box').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + + }); + function box (n) { - var nthBox = d3.select(chart.selectAll('g.box')[0][n]); - nthBox.boxText = function (n) { - return d3.select(this.selectAll('text.box')[0][n]); + const nthBox = d3.select(chart.selectAll('g.box').nodes()[n]); + nthBox.boxText = function (i) { + return d3.select(this.selectAll('text.box').nodes()[i]); }; - nthBox.whiskerLine = function (n) { - return d3.select(this.selectAll('line.whisker')[0][n]); + nthBox.whiskerLine = function (i) { + return d3.select(this.selectAll('line.whisker').nodes()[i]); }; - nthBox.whiskerText = function (n) { - return d3.select(this.selectAll('text.whisker')[0][n]); + nthBox.whiskerText = function (i) { + return d3.select(this.selectAll('text.whisker').nodes()[i]); }; return nthBox; } diff --git a/spec/bubble-chart-spec.js b/spec/bubble-chart-spec.js index d22bd76dd5..98acd6eca3 100644 --- a/spec/bubble-chart-spec.js +++ b/spec/bubble-chart-spec.js @@ -1,136 +1,120 @@ -/* global appendChartID, loadDateFixture */ -describe('dc.bubbleChart', function () { - var id, chart, data; - var dateFixture; - var dimension, group; - var countryDimension; - var width = 900, height = 350; - - beforeEach(function () { +/* global appendChartID, loadDateFixture, loadIrisFixture, makeDate */ +describe('dc.bubbleChart', () => { + let id, chart, data; + let dateFixture; + let dimension, group; + let countryDimension; + const width = 900, height = 350; + + beforeEach(() => { dateFixture = loadDateFixture(); data = crossfilter(dateFixture); - dimension = data.dimension(function (d) { - return d.status; - }); + dimension = data.dimension(d => d.status); group = dimension.group() .reduce( //add - function (p, v) { + (p, v) => { ++p.count; p.value += +v.value; return p; }, //remove - function (p, v) { + (p, v) => { --p.count; p.value -= +v.value; return p; }, //init - function () { - return {count: 0, value: 0}; - } + () => ({count: 0, value: 0}) ) - .order(function (d) {return d.value;}); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + .order(d => d.value); + countryDimension = data.dimension(d => d.countrycode); id = 'bubble-chart'; appendChartID(id); - chart = dc.bubbleChart('#' + id); + chart = new dc.BubbleChart(`#${id}`); chart.dimension(dimension).group(group) .width(width).height(height) .colors(['#a60000', '#ff0000', '#ff4040', '#ff7373', '#67e667', '#39e639', '#00cc00']) .colorDomain([0,220]) - .colorAccessor(function (p) { - return p.value.value; - }) - .keyAccessor(function (p) { - return p.value.value; - }) - .valueAccessor(function (p) { - return p.value.count; - }) - .radiusValueAccessor(function (p) { - return p.value.count; - }) - .x(d3.scale.linear().domain([0, 300])) - .y(d3.scale.linear().domain([0, 10])) - .r(d3.scale.linear().domain([0, 30])) + .colorAccessor(p => p.value.value) + .keyAccessor(p => p.value.value) + .valueAccessor(p => p.value.count) + .radiusValueAccessor(p => p.value.count) + .x(d3.scaleLinear().domain([0, 300])) + .y(d3.scaleLinear().domain([0, 10])) + .r(d3.scaleLinear().domain([0, 30])) .maxBubbleRelativeSize(0.3) .transitionDuration(0) .renderLabel(true) .renderTitle(true) - .title(function (p) { - return p.key + ': {count:' + p.value.count + ',value:' + p.value.value + '}'; - }); + .title(p => `${p.key}: {count:${p.value.count},value:${p.value.value}}`); }); - it('assigns colors', function () { + it('assigns colors', () => { expect(chart.colors()).not.toBeNull(); }); - it('sets the radius scale', function () { + it('sets the radius scale', () => { expect(chart.r()).not.toBeNull(); }); - it('sets the radius value accessor', function () { + it('sets the radius value accessor', () => { expect(chart.radiusValueAccessor()).not.toBeNull(); }); - it('sets the x units', function () { + it('sets the x units', () => { expect(chart.xUnits()).toBe(dc.units.integers); }); - it('creates the x axis', function () { + it('creates the x axis', () => { expect(chart.xAxis()).not.toBeNull(); }); - it('creates the y axis', function () { + it('creates the y axis', () => { expect(chart.yAxis()).not.toBeNull(); }); - describe('render', function () { - beforeEach(function () { + describe('render', () => { + beforeEach(() => { chart.render(); }); - it('generates right number of bubbles', function () { - expect(chart.selectAll('circle.bubble')[0].length).toBe(2); + it('generates right number of bubbles', () => { + expect(chart.selectAll('circle.bubble').nodes().length).toBe(2); }); - it('calculates right cx for each bubble', function () { + it('calculates right cx for each bubble', () => { chart.selectAll('g.node').each(function (d, i) { if (i === 0) { - expect(d3.select(this).attr('transform')).toMatchTranslate(601.3333333333334,155,3); + expect(d3.select(this).attr('transform')).toMatchTranslate(601.3333333333334, 155, 3); } if (i === 1) { - expect(d3.select(this).attr('transform')).toMatchTranslate(541.2,155); + expect(d3.select(this).attr('transform')).toMatchTranslate(541.2, 155); } }); }); - it('generates opaque groups and circles for each bubble', function () { + it('generates opaque groups and circles for each bubble', () => { chart.selectAll('g.node').each(function (d, i) { expect(d3.select(this).attr('opacity')).toBeNull(); expect(d3.select(this).select('circle').attr('opacity')).toBe('1'); }); }); - it('calculates right r for each bubble', function () { + it('calculates right r for each bubble', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { - expect(Number(d3.select(this).attr('r'))).toBeCloseTo(49.33333333333333,3); + expect(Number(d3.select(this).attr('r'))).toBeCloseTo(49.33333333333333, 3); } if (i === 1) { - expect(Number(d3.select(this).attr('r'))).toBeCloseTo(49.33333333333333,3); + expect(Number(d3.select(this).attr('r'))).toBeCloseTo(49.33333333333333, 3); } }); }); - it('attaches each bubble with index based class', function () { + it('attaches each bubble with index based class', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { expect(d3.select(this).attr('class')).toBe('bubble _0'); @@ -141,11 +125,11 @@ describe('dc.bubbleChart', function () { }); }); - it('generates right number of labels', function () { - expect(chart.selectAll('g.node text')[0].length).toBe(2); + it('generates right number of labels', () => { + expect(chart.selectAll('g.node text').nodes().length).toBe(2); }); - it('creates correct label for each bubble', function () { + it('creates correct label for each bubble', () => { chart.selectAll('g.node text').each(function (d, i) { if (i === 0) { expect(d3.select(this).text()).toBe('F'); @@ -156,11 +140,11 @@ describe('dc.bubbleChart', function () { }); }); - it('generates right number of titles', function () { - expect(chart.selectAll('g.node title')[0].length).toBe(2); + it('generates right number of titles', () => { + expect(chart.selectAll('g.node title').nodes().length).toBe(2); }); - it('creates correct title for each bubble', function () { + it('creates correct title for each bubble', () => { chart.selectAll('g.node title').each(function (d, i) { if (i === 0) { expect(d3.select(this).text()).toBe('F: {count:5,value:220}'); @@ -171,38 +155,38 @@ describe('dc.bubbleChart', function () { }); }); - it('fills bubbles with correct colors', function () { + it('fills bubbles with correct colors', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { - expect(d3.select(this).attr('fill')).toBe('#00cc00'); + expect(d3.select(this).attr('fill')).toMatch(/#00cc00/i); } if (i === 1) { - expect(d3.select(this).attr('fill')).toBe('#00cc00'); + expect(d3.select(this).attr('fill')).toMatch(/#00cc00/i); } }); }); }); - describe('bubble chart w/o label & title', function () { - beforeEach(function () { + describe('bubble chart w/o label & title', () => { + beforeEach(() => { chart.renderLabel(false).renderTitle(false).render(); }); - it('generates right number of labels', function () { - expect(chart.selectAll('g.node text')[0].length).toBe(0); + it('generates right number of labels', () => { + expect(chart.selectAll('g.node text').nodes().length).toBe(0); }); - it('generates right number of titles', function () { - expect(chart.selectAll('g.node title')[0].length).toBe(0); + it('generates right number of titles', () => { + expect(chart.selectAll('g.node title').nodes().length).toBe(0); }); }); - describe('with filter', function () { - beforeEach(function () { + describe('with filter', () => { + beforeEach(() => { chart.filter('F').render(); }); - it('deselects bubble based on filter value', function () { + it('deselects bubble based on filter value', () => { chart.selectAll('g.node').each(function (d, i) { if (i === 0) { expect(d3.select(this).attr('class')).toBe('node selected'); @@ -213,7 +197,7 @@ describe('dc.bubbleChart', function () { }); }); - it('handles multi-selection highlight', function () { + it('handles multi-selection highlight', () => { chart.filter('T'); chart.redraw(); chart.selectAll('g.node').each(function (d, i) { @@ -222,14 +206,14 @@ describe('dc.bubbleChart', function () { }); }); - describe('update', function () { - beforeEach(function () { + describe('update', () => { + beforeEach(() => { chart.render(); countryDimension.filter('CA'); chart.redraw(); }); - it('creates correct label for each bubble', function () { + it('creates correct label for each bubble', () => { chart.selectAll('g.node title').each(function (d, i) { if (i === 0) { expect(d3.select(this).text()).toBe('F: {count:0,value:0}'); @@ -240,25 +224,25 @@ describe('dc.bubbleChart', function () { }); }); - it('fills bubbles with correct colors', function () { + it('fills bubbles with correct colors', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { - expect(d3.select(this).attr('fill')).toBe('#a60000'); + expect(d3.select(this).attr('fill')).toMatch(/#a60000/i); } if (i === 1) { - expect(d3.select(this).attr('fill')).toBe('#ff4040'); + expect(d3.select(this).attr('fill')).toMatch(/#ff4040/i); } }); }); - describe('with bubble sorting', function () { - beforeEach(function () { + describe('with bubble sorting', () => { + beforeEach(() => { chart .sortBubbleSize(true) .render(); }); - it('creates correct label for each bubble', function () { + it('creates correct label for each bubble', () => { chart.selectAll('g.node title').each(function (d, i) { if (i === 0) { expect(d3.select(this).text()).toBe('T: {count:2,value:77}'); @@ -269,35 +253,61 @@ describe('dc.bubbleChart', function () { }); }); - it('fills bubbles with correct colors', function () { + it('fills bubbles with correct colors', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { - expect(d3.select(this).attr('fill')).toBe('#ff4040'); + expect(d3.select(this).attr('fill')).toMatch(/#ff4040/i); } if (i === 1) { - expect(d3.select(this).attr('fill')).toBe('#a60000'); + expect(d3.select(this).attr('fill')).toMatch(/#a60000/i); } }); }); }); + describe('with empty bins removed', () => { + beforeEach(() => { + chart.group(removeEmptyBins(group)) + .redraw(); + }); + + it('creates the right number of bubbles', () => { + expect(chart.selectAll('g.node').size()).toBe(1); + }); + + it('creates correct label for each bubble', () => { + expect(chart.selectAll('g.node title').text()).toBe('T: {count:2,value:77}'); + }); + + it('fills bubbles with correct colors', () => { + expect(chart.selectAll('circle.bubble').attr('fill')).toMatch(/#ff4040/i); + }); + function removeEmptyBins (sourceGroup) { + return { + all: function () { + return sourceGroup.all().filter(d => d.value.count !== 0); + } + }; + } + + }); }); - describe('with no filter', function () { - beforeEach(function () { + describe('with no filter', () => { + beforeEach(() => { countryDimension.filter('ZZ'); chart.render(); }); - it('sets invisible if bubble has 0 r', function () { + it('sets invisible if bubble has 0 r', () => { chart.selectAll('g.node text').each(function (d, i) { expect(Number(d3.select(this).attr('opacity'))).toBe(0); }); }); }); - describe('with elastic axises', function () { - beforeEach(function () { + describe('with elastic axises', () => { + beforeEach(() => { chart.elasticY(true) .yAxisPadding(3) .elasticX(true) @@ -305,67 +315,61 @@ describe('dc.bubbleChart', function () { .render(); }); - it('auto calculates x range based on width', function () { + it('auto calculates x range based on width', () => { expect(chart.x().range()[0]).toBe(0); expect(chart.x().range()[1]).toBe(820); }); - it('sets the x domain', function () { + it('sets the x domain', () => { expect(chart.x().domain()[0]).toBe(178); expect(chart.x().domain()[1]).toBe(240); }); - it('auto calculates y range based on height', function () { + it('auto calculates y range based on height', () => { expect(chart.y().range()[0]).toBe(310); expect(chart.y().range()[1]).toBe(0); }); - it('sets the y domain', function () { + it('sets the y domain', () => { expect(chart.y().domain()[0]).toBe(2); expect(chart.y().domain()[1]).toBe(8); }); }); - describe('renderlet', function () { - var renderlet; + describe('renderlet', () => { + let renderlet; - beforeEach(function () { + beforeEach(() => { // spyOn doesn't seem to work with plain functions - renderlet = jasmine.createSpy('renderlet', function (chart) { - chart.selectAll('circle').attr('fill', 'red'); + renderlet = jasmine.createSpy('renderlet', _chart => { + _chart.selectAll('circle').attr('fill', 'red'); }); renderlet.and.callThrough(); chart.on('renderlet', renderlet); }); - it('is invoked with render', function () { + it('is invoked with render', () => { chart.render(); expect(chart.selectAll('circle').attr('fill')).toBe('red'); expect(renderlet).toHaveBeenCalled(); }); - it('is invoked with redraw', function () { + it('is invoked with redraw', () => { chart.render().redraw(); expect(chart.selectAll('circle').attr('fill')).toBe('red'); expect(renderlet.calls.count()).toEqual(2); }); }); - describe('non-unique keys', function () { + describe('non-unique keys', () => { // plot all rows as (value, nvalue) - a common scatterplot scenario - beforeEach(function () { - var rowDimension = data.dimension(function (d, i) { - return i; - }); - var rowGroup = rowDimension.group(); + beforeEach(() => { + const rowDimension = data.dimension((d, i) => i); + const rowGroup = rowDimension.group(); chart.dimension(rowDimension).group(rowGroup) - .keyAccessor(function (kv) { - return +dateFixture[kv.key].value; - }) - .valueAccessor(function (kv) { - return +dateFixture[kv.key].nvalue; - }) + .keyAccessor(kv => +dateFixture[kv.key].value) + .valueAccessor(kv => +dateFixture[kv.key].nvalue) .elasticY(true) .yAxisPadding(2) .elasticX(true) @@ -374,77 +378,374 @@ describe('dc.bubbleChart', function () { chart.render(); }); - it('generates right number of bubbles', function () { - expect(chart.selectAll('circle.bubble')[0].length).toBe(10); + it('generates right number of bubbles', () => { + expect(chart.selectAll('circle.bubble').nodes().length).toBe(10); }); - it('auto calculates x range based on width', function () { + it('auto calculates x range based on width', () => { expect(chart.x().range()[0]).toBe(0); expect(chart.x().range()[1]).toBe(820); }); - it('sets the x domain', function () { + it('sets the x domain', () => { expect(chart.x().domain()[0]).toBe(20); expect(chart.x().domain()[1]).toBe(68); }); - it('auto calculates y range based on height', function () { + it('auto calculates y range based on height', () => { expect(chart.y().range()[0]).toBe(310); expect(chart.y().range()[1]).toBe(0); }); - it('sets the y domain', function () { + it('sets the y domain', () => { expect(chart.y().domain()[0]).toBe(-7); expect(chart.y().domain()[1]).toBe(12); }); }); - describe('with logarithmic scales', function () { - beforeEach(function () { - var rowDimension = data.dimension(function (d, i) { - return i; - }); - var rowGroup = rowDimension.group(); + describe('with logarithmic scales', () => { + beforeEach(() => { + const rowDimension = data.dimension((d, i) => i); + const rowGroup = rowDimension.group(); chart .dimension(rowDimension) .group(rowGroup) - .keyAccessor(function (kv) { - return 0; - }) - .valueAccessor(function (kv) { - return 0; - }) - .x(d3.scale.log().domain([1, 300])) - .y(d3.scale.log().domain([1, 10])) + .keyAccessor(kv => 0) + .valueAccessor(kv => 0) + .x(d3.scaleLog().domain([1, 300])) + .y(d3.scaleLog().domain([1, 10])) .elasticX(false) .elasticY(false); + chart.render(); }); - it('renders without errors', function () { - chart.render(); + it('renders without errors', () => { chart.selectAll('g.node').each(function (d, i) { - expect(d3.select(this).attr('transform')).toMatchTranslate(0,0); + expect(d3.select(this).attr('transform')).toMatchTranslate(0, 0); }); }); }); - describe('with minimum radius', function () { - beforeEach(function () { + describe('with a date-based scale', () => { + beforeEach(() => { + dimension = data.dimension(d => d3.utcDay(d.dd)); + group = dimension.group(); + + chart + .dimension(dimension) + .group(group) + .x(d3.scaleUtc().domain([makeDate(2012, 0, 1), makeDate(2012, 11, 31)])) + .elasticX(true) + .elasticY(true) + .keyAccessor(kv => kv.key) + .valueAccessor(kv => kv.value) + .radiusValueAccessor(kv => kv.value) + .colors(d3.scaleOrdinal().range(['#a60000', '#ff0000', '#ff4040', '#ff7373', '#67e667', '#39e639', '#00cc00'])) + .colorAccessor(kv => kv.key) + .render(); + }); + + it('draws bubbles in appropriate locations', () => { + const coords = [ + [0, 310], [149.1, 310], [170.4, 0], [394, 310], [489.9, 155], [820, 155], + ]; + chart.selectAll('g.node').each(function (d, i) { + expect(d3.select(this).attr('transform')) + .toMatchTranslate(coords[i][0], coords[i][1], 1); + }); + }); + it('calculates elastic x axis exactly', () => { + expect(chart.x().domain()).toEqual([makeDate(2012, 4, 25), makeDate(2012, 7, 10)]); + }); + + describe('with 10 day padding', () => { + beforeEach(() => { + chart.xAxisPaddingUnit(d3.utcDay) + .xAxisPadding(10) + .render(); + }); + it('should stretch the domain appropriately', () => { + expect(chart.x().domain()).toEqual([makeDate(2012, 4, 15), makeDate(2012, 7, 20)]); + }); + }); + + describe('with 2 month padding', () => { + beforeEach(() => { + chart.xAxisPaddingUnit(d3.utcMonth) + .xAxisPadding(2) + .render(); + }); + it('should stretch the domain appropriately', () => { + expect(chart.x().domain()).toEqual([makeDate(2012, 2, 25), makeDate(2012, 9, 10)]); + }); + }); + }); + + describe('with minimum radius', () => { + beforeEach(() => { chart .minRadius(1) .render(); }); - it('shows smaller bubbles', function () { + it('shows smaller bubbles', () => { chart.selectAll('circle.bubble').each(function (d, i) { if (i === 0) { - expect(Number(d3.select(this).attr('r'))).toBeCloseTo(41.83333333333333,3); + expect(Number(d3.select(this).attr('r'))).toBeCloseTo(41.83333333333333, 3); } if (i === 1) { - expect(Number(d3.select(this).attr('r'))).toBeCloseTo(41.83333333333333,3); + expect(Number(d3.select(this).attr('r'))).toBeCloseTo(41.83333333333333, 3); + } + }); + }); + }); + + describe('iris filtering', () => { + /* eslint camelcase: 0 */ + // 2-chart version of from http://bl.ocks.org/gordonwoodhull/14c623b95993808d69620563508edba6 + let irisData, heatMap, sepalDim, sepalGroup; + beforeEach(() => { + irisData = loadIrisFixture(); + + const fields = { + sl: 'sepal_length', + sw: 'sepal_width', + pl: 'petal_length', + pw: 'petal_width' + }; + const species = ['setosa', 'versicolor', 'virginica']; + + irisData.forEach(d => { + Object.keys(fields).forEach(ab => { + d[fields[ab]] = +d[fields[ab]]; + }); + }); + // autogenerate a key function for an extent + function key_function (extent) { + const div = extent[1] - extent[0] < 5 ? 2 : 1; + return function (k) { + return Math.floor(k * div) / div; + }; + } + + const extents = {}; + const keyfuncs = {}; + Object.keys(fields).forEach(ab => { + extents[ab] = d3.extent(irisData, d => d[fields[ab]]); + keyfuncs[ab] = key_function(extents[ab]); + }); + data = crossfilter(irisData); + function duo_key (ab1, ab2) { + return function (d) { + return [keyfuncs[ab1](d[fields[ab1]]), keyfuncs[ab2](d[fields[ab2]])]; + }; + } + function key_part (i) { + return function (kv) { + return kv.key[i]; + }; + } + function reduce_species (grp) { + grp.reduce( + (p, v) => { + p[v.species]++; + p.total++; + return p; + }, (p, v) => { + p[v.species]--; + p.total--; + return p; + }, () => { + const init = {total: 0}; + species.forEach(s => { init[s] = 0; }); + return init; + } + ); + } + function max_species (d) { + let max = 0, i = -1; + species.forEach((s, j) => { + if (d.value[s] > max) { + max = d.value[s]; + i = j; + } + }); + return i >= 0 ? species[i] : null; + } + function initialize_bubble (bubbleChart) { + bubbleChart + .transitionDuration(0) + .width(400) + .height(400) + .x(d3.scaleLinear()).xAxisPadding(0.5) + .y(d3.scaleLinear()).yAxisPadding(0.5) + .elasticX(true) + .elasticY(true) + .keyAccessor(key_part(0)) + .valueAccessor(key_part(1)) + .radiusValueAccessor(kv => kv.value.total) + .elasticRadius(true) + .excludeElasticZero(false) + .colors(d3.scaleOrdinal() + .domain(species.concat('none')) + .range(['#e41a1c','#377eb8','#4daf4a', '#f8f8f8'])) + .colorAccessor(d => max_species(d) || 'none') + .label(d => d.value.total) + .title(d => JSON.stringify(d.value, null, 2)); + } + function initialize_heatmap (htMap) { + htMap + .transitionDuration(0) + .width(400) + .height(400) + .xBorderRadius(15).yBorderRadius(15) + .keyAccessor(key_part(0)) + .valueAccessor(key_part(1)) + .colors(d3.scaleOrdinal() + .domain(species.concat('none')) + .range(['#e41a1c','#377eb8','#4daf4a', '#f8f8f8'])) + .colorAccessor(d => max_species(d) || 'none'); + } + + const heatId = 'heat-map'; + appendChartID(heatId); + + heatMap = new dc.HeatMap(`#${heatId}`); + sepalDim = data.dimension(duo_key('sl', 'sw')); sepalGroup = sepalDim.group(); + const petalDim = data.dimension(duo_key('pl', 'pw')), petalGroup = petalDim.group(); + + reduce_species(sepalGroup); + reduce_species(petalGroup); + initialize_bubble(chart.dimension(sepalDim).group(sepalGroup)); + initialize_heatmap(heatMap.dimension(petalDim).group(petalGroup)); + chart.render(); + heatMap.render(); + }); + // return brand-new objects and keys every time + function clone_group (grp) { + function clone_kvs (all) { + return all.map(kv => ({ + key: kv.key.slice(0), + value: Object.assign({}, kv.value) + })); + } + return { + all: function () { + return clone_kvs(grp.all()); + }, + top: function (N) { + return clone_kvs(grp.top(N)); } + }; + } + + function testBubbleRadiiCol3 (_chart) { + const bubbles = _chart.selectAll('circle.bubble').nodes(); + const expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34.5, 16.1, 0, 0, 16.1, 59.1, 34.5, 16.1, 96, 0, 22.2, 0, 0, 0, 0]; + bubbles.forEach((b, i) => { + expect(+d3.select(b).attr('r')).toBeWithinDelta(expected[i], 0.1); + }); + } + function testBubbleTitlesCol3 (_chart) { + const titles = _chart.selectAll('g.node title').nodes(); + const expected = [ + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 4, 'setosa': 0, 'versicolor': 0, 'virginica': 4}, {'total': 1, 'setosa': 0, 'versicolor': 0, 'virginica': 1}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 1, 'setosa': 0, 'versicolor': 0, 'virginica': 1}, {'total': 8, 'setosa': 0, 'versicolor': 1, 'virginica': 7}, + {'total': 4, 'setosa': 0, 'versicolor': 0, 'virginica': 4}, {'total': 1, 'setosa': 0, 'versicolor': 0, 'virginica': 1}, + {'total': 14, 'setosa': 0, 'versicolor': 1, 'virginica': 13}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 2, 'setosa': 0, 'versicolor': 0, 'virginica': 2}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}, + {'total': 0, 'setosa': 0, 'versicolor': 0, 'virginica': 0}]; + titles.forEach((t, i) => { + expect(JSON.parse(d3.select(t).text())).toEqual(expected[i]); + }); + } + function testBubbleLabelsCol3 (_chart) { + const labels = _chart.selectAll('g.node text').nodes(); + const expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 1, 8, 4, 1, 14, 0, 2, 0, 0, 0, 0]; + labels.forEach((l, i) => { + expect(+d3.select(l).text()).toBe(expected[i]); + }); + } + describe('column filtering with straight crossfilter', () => { + beforeEach(() => { + const axisLabel = d3.select(heatMap.selectAll('.cols.axis text').nodes()[3]); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, axisLabel.datum()); + d3.timerFlush(); + }); + it('updates bubble radii correctly', () => { + testBubbleRadiiCol3(chart); + }); + it('updates bubble titles correctly', () => { + testBubbleTitlesCol3(chart); + }); + it('updates bubble labels correctly', () => { + testBubbleLabelsCol3(chart); }); }); + describe('column filtering with cloned results', () => { + beforeEach(() => { + chart.group(clone_group(sepalGroup)); + chart.render(); + const axisLabel = d3.select(heatMap.selectAll('.cols.axis text').nodes()[3]); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, axisLabel.datum()); + d3.timerFlush(); + }); + it('updates bubble radii correctly', () => { + testBubbleRadiiCol3(chart); + }); + it('updates bubble titles correctly', () => { + testBubbleTitlesCol3(chart); + }); + it('updates bubble labels correctly', () => { + testBubbleLabelsCol3(chart); + }); + }); + }); + + describe('accessibility bubble chart', () => { + + it('DOM order follows x values if keyboardAccessible is set', () => { + // default (alphabetical) sort order would put F ahead of T in DOM order + // keyboardAccessible should instead re-order DOM elements based on x-value + // T value is 198; F value is 220 + chart.keyboardAccessible(true); + chart.render(); + expect(document.querySelectorAll('.node text')[0].innerHTML).toEqual('T') + }); + + it('internal elements are focusable by keyboard', () => { + chart.keyboardAccessible(true); + chart.render(); + chart.selectAll('circle').each(function () { + const bubble = d3.select(this); + expect(bubble.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + chart.keyboardAccessible(true); + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('circle').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + }); }); diff --git a/spec/bubble-overlay-spec.js b/spec/bubble-overlay-spec.js index bd17afd653..74f959bf73 100644 --- a/spec/bubble-overlay-spec.js +++ b/spec/bubble-overlay-spec.js @@ -1,101 +1,141 @@ /* global appendChartID, loadDateFixture */ -describe('dc.bubbleOverlay', function () { - var chart, data; - var dimension, group; - - describe('creation', function () { - beforeEach(function () { - data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) {return d.state;}); - group = dimension.group().reduceSum(function (d) {return d.value;}); - - var id = 'bubble-overlay'; - var parent = appendChartID(id); - var svg = parent.append('svg'); - - chart = dc.bubbleOverlay('#' + id) - .svg(svg) - .dimension(dimension) - .group(group) - .width(300) - .height(200) - .transitionDuration(0) - .title(function (d) {return 'Title: ' + d.key;}) - .r(d3.scale.linear().domain([0, 500])) - .ordinalColors(['blue']) - .point('California', 100, 120) - .point('Colorado', 300, 120) - .point('Delaware', 500, 220) - .point('Ontario', 180, 90) - .point('Mississippi', 120, 220) - .point('Oklahoma', 200, 350); - - chart.render(); - }); - - it('should generate an instance of the dc chart', function () { +describe('dc.bubbleOverlay', () => { + let chart, data; + let dimension, group; + + beforeEach(() => { + data = crossfilter(loadDateFixture()); + dimension = data.dimension(d => d.state); + group = dimension.group().reduceSum(d => d.value); + + const id = 'bubble-overlay'; + const parent = appendChartID(id); + const width = 600, height = 400; + const svg = parent.append('svg') + .attr('width', width) + .attr('height', height); + + chart = new dc.BubbleOverlay(`#${id}`) + .svg(svg) + .dimension(dimension) + .group(group) + .width(width) + .height(height) + .transitionDuration(0) + .title(d => `Title: ${d.key}`) + .r(d3.scaleLinear().domain([0, 100])) + .maxBubbleRelativeSize(0.1) + .ordinalColors(['blue']) + .point('California', 100, 120) + .point('Colorado', 300, 120) + .point('Delaware', 500, 220) + .point('Ontario', 180, 90) + .point('Mississippi', 120, 220) + .point('Oklahoma', 200, 350); + + chart.render(); + }); + + describe('creation', () => { + it('should generate an instance of the dc chart', () => { expect(dc.instanceOfChart(chart)).toBeTruthy(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should generate the correct number of overlay groups', function () { - expect(chart.selectAll('g.node')[0].length).toEqual(6); + it('should generate the correct number of overlay groups', () => { + expect(chart.selectAll('g.node').nodes().length).toEqual(6); }); - it('should generate a correct class name for the overlay groups', function () { - expect(d3.select(chart.selectAll('g.node')[0][0]).attr('class')).toEqual('node california'); - expect(d3.select(chart.selectAll('g.node')[0][3]).attr('class')).toEqual('node ontario'); + it('should generate a correct class name for the overlay groups', () => { + expect(d3.select(chart.selectAll('g.node').nodes()[0]).attr('class')).toEqual('node california'); + expect(d3.select(chart.selectAll('g.node').nodes()[3]).attr('class')).toEqual('node ontario'); }); - it('should generate the correct number of overlay bubbles', function () { - expect(chart.selectAll('circle.bubble')[0].length).toEqual(6); + it('should generate the correct number of overlay bubbles', () => { + expect(chart.selectAll('circle.bubble').nodes().length).toEqual(6); }); - it('should generate a correct translate for overlay groups', function () { - expect(d3.select(chart.selectAll('g.node')[0][0]).attr('transform')).toMatchTranslate(100, 120); - expect(d3.select(chart.selectAll('g.node')[0][3]).attr('transform')).toMatchTranslate(180, 90); + it('should generate a correct translate for overlay groups', () => { + expect(d3.select(chart.selectAll('g.node').nodes()[0]).attr('transform')).toMatchTranslate(100, 120); + expect(d3.select(chart.selectAll('g.node').nodes()[3]).attr('transform')).toMatchTranslate(180, 90); }); - it('should generate correct radii for circles', function () { - expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('r')).toEqual('34.64'); - expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('r')).toEqual('22.32'); + it('should generate correct radii for circles', () => { + expect(d3.select(chart.selectAll('circle.bubble').nodes()[0]).attr('r')).toEqual('87'); + expect(d3.select(chart.selectAll('circle.bubble').nodes()[3]).attr('r')).toEqual('48.5'); }); - it('should generate correct labels', function () { - expect(d3.select(chart.selectAll('g.node text')[0][0]).text()).toEqual('California'); - expect(d3.select(chart.selectAll('g.node text')[0][3]).text()).toEqual('Ontario'); + it('should generate correct labels', () => { + expect(d3.select(chart.selectAll('g.node text').nodes()[0]).text()).toEqual('California'); + expect(d3.select(chart.selectAll('g.node text').nodes()[3]).text()).toEqual('Ontario'); }); - it('should generate the label only once', function () { + it('should generate the label only once', () => { chart.redraw(); - expect(chart.selectAll('g.node text')[0].length).toEqual(6); + expect(chart.selectAll('g.node text').nodes().length).toEqual(6); }); - it('generate the correct titles', function () { - expect(d3.select(chart.selectAll('g.node title')[0][0]).text()).toEqual('Title: California'); - expect(d3.select(chart.selectAll('g.node title')[0][3]).text()).toEqual('Title: Ontario'); + it('generate the correct titles', () => { + expect(d3.select(chart.selectAll('g.node title').nodes()[0]).text()).toEqual('Title: California'); + expect(d3.select(chart.selectAll('g.node title').nodes()[3]).text()).toEqual('Title: Ontario'); }); - it('should only generate titles once', function () { + it('should only generate titles once', () => { chart.redraw(); - expect(chart.selectAll('g.node title')[0].length).toEqual(6); + expect(chart.selectAll('g.node title').nodes().length).toEqual(6); }); - it('should fill circles with the specified colors', function () { - expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('fill')).toEqual('blue'); - expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('fill')).toEqual('blue'); + it('should fill circles with the specified colors', () => { + expect(d3.select(chart.selectAll('circle.bubble').nodes()[0]).attr('fill')).toEqual('blue'); + expect(d3.select(chart.selectAll('circle.bubble').nodes()[3]).attr('fill')).toEqual('blue'); }); - it('should highlight the filtered bubbles', function () { + it('should highlight the filtered bubbles', () => { chart.filter('Colorado'); chart.filter('California'); chart.redraw(); - expect(d3.select(chart.selectAll('g.node')[0][0]).attr('class')).toEqual('node california selected'); - expect(d3.select(chart.selectAll('g.node')[0][1]).attr('class')).toEqual('node colorado selected'); - expect(d3.select(chart.selectAll('g.node')[0][3]).attr('class')).toEqual('node ontario deselected'); + expect(d3.select(chart.selectAll('g.node').nodes()[0]).attr('class')).toEqual('node california selected'); + expect(d3.select(chart.selectAll('g.node').nodes()[1]).attr('class')).toEqual('node colorado selected'); + expect(d3.select(chart.selectAll('g.node').nodes()[3]).attr('class')).toEqual('node ontario deselected'); + }); + }); + + describe('filtering another dimension', () => { + let regionDim; + beforeEach(() => { + regionDim = data.dimension(d => d.region); + }); + function expectRadii (expected) { + const circles = chart.selectAll('circle.bubble').nodes(); + circles.forEach((c, i) => { + expect(+d3.select(c).attr('r')).toBeWithinDelta(expected[i], 0.1); + }); + } + describe('without elastic radius', () => { + it('should have reasonable radii', () => { + expectRadii([87, 21, 26.5, 48.5, 48.5, 37.5]); + }); + it('filtering should zero out some radii', () => { + regionDim.filter('Central'); + dc.redrawAll(); + expectRadii([0, 0, 0, 37.5, 48.5, 0]); + }); + }); + describe('with elastic radius', () => { + beforeEach(() => { + chart.elasticRadius(true).render(); + }); + it('should lock to the minimum and maximum radius sizes', () => { + expectRadii([60, 10, 14.1, 30.8, 30.8, 22.5]); + }); + it('filtering should lock the remaining bubbles to min and max radius sizes', () => { + regionDim.filter('Central'); + dc.redrawAll(); + expectRadii([0, 0, 0, 10, 60, 0]); + }); }); }); }); diff --git a/spec/cap-mixin-spec.js b/spec/cap-mixin-spec.js new file mode 100644 index 0000000000..905b566651 --- /dev/null +++ b/spec/cap-mixin-spec.js @@ -0,0 +1,153 @@ +/* global loadDateFixture */ +describe('dc.capMixin', () => { + let data, dimension, group; + let mixin, total; + + beforeEach(() => { + data = crossfilter(loadDateFixture()); + dimension = data.dimension(d => +d.value); + group = dimension.group().reduceSum(d => Math.abs(+d.nvalue)); + total = d3.sum(group.all().map(dc.pluck('value'))); + + const CapMixinTester = dc.CapMixin(dc.BaseMixin); + mixin = new CapMixinTester(); + + mixin.dimension(dimension) + .group(group); + }); + + describe('with no capping and default ordering', () => { + it('should include everything', () => { + expect(mixin.data().length).toBe(5); + }); + it('should be in descending value order', () => { + expect(mixin.data().map(dc.pluck('value'))).toEqual([12, 9, 8, 4, 2]); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + }); + + describe('with no capping and descending key ordering', () => { + beforeEach(() => { + mixin.ordering(kv => -kv.key); + }); + it('should include everything', () => { + expect(mixin.data().length).toBe(5); + }); + it('should be in reverse key order', () => { + expect(mixin.data().map(dc.pluck('key'))).toEqual([66, 55, 44, 33, 22]); + }); + }); + + describe('with descending value ordering', () => { + beforeEach(() => { + mixin.ordering(kv => -kv.value); + }); + describe('and no capping', () => { + it('should include everything', () => { + expect(mixin.data().length).toBe(5); + }); + it('should be in reverse key order', () => { + expect(mixin.data().map(dc.pluck('key'))).toEqual([22, 44, 55, 66, 33]); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + }); + describe('and cap(3)', () => { + beforeEach(() => { + mixin.cap(3); + }); + it('should have 3 front elements plus others element', () => { + expect(mixin.data().length).toBe(4); + expect(mixin.data().map(dc.pluck('key'))).toEqual([22, 44, 55, 'Others']); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + + describe('and taking from back', () => { + beforeEach(() => { + mixin.takeFront(false); + }); + it('should have 3 back elements plus others element', () => { + expect(mixin.data().length).toBe(4); + expect(mixin.data().map(dc.pluck('key'))).toEqual([55, 66, 33, 'Others']); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + }); + + describe('and no othersGrouper', () => { + beforeEach(() => { + mixin.othersGrouper(null); + }); + it('should have 3 front elements', () => { + expect(mixin.data().length).toBe(3); + expect(mixin.data().map(dc.pluck('key'))).toEqual([22, 44, 55]); + }); + it('should sum to correct number', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(29); + }); + }); + }); + }); + + describe('with ascending value ordering', () => { + beforeEach(() => { + mixin.ordering(kv => kv.value); + }); + describe('and no capping', () => { + it('should include everything', () => { + expect(mixin.data().length).toBe(5); + }); + it('should be in reverse key order', () => { + expect(mixin.data().map(dc.pluck('key'))).toEqual([33, 66, 55, 44, 22]); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + }); + describe('and cap(3)', () => { + beforeEach(() => { + mixin.cap(3); + }); + it('should have 3 front elements plus others element', () => { + expect(mixin.data().length).toBe(4); + expect(mixin.data().map(dc.pluck('key'))).toEqual([33, 66, 55, 'Others']); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + + describe('and taking from back', () => { + beforeEach(() => { + mixin.takeFront(false); + }); + it('should have 3 back elements plus others element', () => { + expect(mixin.data().length).toBe(4); + expect(mixin.data().map(dc.pluck('key'))).toEqual([55, 44, 22, 'Others']); + }); + it('should sum to total', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(total); + }); + }); + + describe('and no othersGrouper', () => { + beforeEach(() => { + mixin.othersGrouper(null); + }); + it('should have 3 front elements', () => { + expect(mixin.data().length).toBe(3); + expect(mixin.data().map(dc.pluck('key'))).toEqual([33, 66, 55]); + }); + it('should sum to correct number', () => { + expect(d3.sum(mixin.data().map(dc.pluck('value')))).toEqual(14); + }); + }); + }); + }); +}); + diff --git a/spec/cbox-menu-spec.js b/spec/cbox-menu-spec.js new file mode 100644 index 0000000000..e127ac1456 --- /dev/null +++ b/spec/cbox-menu-spec.js @@ -0,0 +1,230 @@ +/* global appendChartID, loadDateFixture */ +describe('dc.cboxMenu', () => { + let id, chart; + let data, regionDimension, regionGroup; + let stateDimension, stateGroup; + + beforeEach(() => { + data = crossfilter(loadDateFixture()); + regionDimension = data.dimension(d => d.region); + stateDimension = data.dimension(d => d.state); + + regionGroup = regionDimension.group(); + stateGroup = stateDimension.group(); + + id = 'cbox-menu'; + appendChartID(id); + + chart = new dc.CboxMenu(`#${id}`); + chart.dimension(stateDimension) + .group(stateGroup) + .transitionDuration(0); + chart.render(); + }); + + describe('generation', () => { + it('we get something', () => { + expect(chart).not.toBeNull(); + }); + it('should be registered', () => { + expect(dc.hasChart(chart)).toBeTruthy(); + }); + it('sets order', () => { + expect(chart.order()).toBeDefined(); + }); + it('sets prompt text', () => { + expect(chart.promptText()).toBe('Select all'); + }); + it('creates an unordered list', () => { + expect(chart.selectAll('ul').nodes().length).toEqual(1); + }); + it('creates .dc-cbox-item class elements for each item', () => { + expect(chart.selectAll('li.dc-cbox-item').nodes().length).toEqual(stateGroup.all().length); + }); + it('creates an extra item for the select all option', () => { + expect(chart.selectAll('li').nodes().length).toEqual(stateGroup.all().length + 1); + }); + it('creates input elements within each list item', () => { + expect(chart.selectAll('li input').nodes().length).toEqual(stateGroup.all().length + 1); + }); + // check labels and IDs + it('creates input elements with IDs and labels with the corresponding "for" attribute', () => { + const str = chart.selectAll('input').nodes().map(e => e.id).join('--'); + expect(str).toMatch(/^(input_\d+_\d+--)+input_\d+_all$/); + expect(str).toEqual(chart.selectAll('label').nodes().map(e => e.getAttribute('for')).join('--')); + }); + + // Single select + it('creates radio buttons by default', () => { + expect(chart.selectAll('input[type=checkbox]').nodes().length).toEqual(0); + expect(chart.selectAll('.dc-cbox-item input[type=radio]').nodes().length).toEqual(stateGroup.all().length); + }); + it('uses a radio button for the select all option', () => { + expect(chart.selectAll('input[type=radio]').nodes().length).toEqual(stateGroup.all().length + 1); + }); + // select all: + it('creates a select all option with default prompt text', () => { + const option = chart.selectAll('li label').nodes().pop(); + expect(option.textContent).toEqual('Select all'); + }); + it('creates a select all option with no value', () => { + const option = chart.selectAll('li input').nodes().pop(); + expect(option.name).toMatch(/^domain_\d+$/); + expect(option.getAttribute('value')).toBeNull(); + }); + // multiple select + it('can be made into a multiple', () => { + chart.multiple(true).redraw(); + expect(chart.selectAll('.dc-cbox-item input[type=checkbox]').nodes().length).toEqual(stateGroup.all().length); + }); + it('does not use radio buttons for multiples', () => { + chart.multiple(true).redraw(); + expect(chart.selectAll('.dc-cbox-item input[type=radio]').nodes().length).toEqual(0); + }); + // select all multiple: + it('has a reset button in multiple mode', () => { + chart.multiple(true).redraw(); + const option = chart.selectAll('li input').nodes().pop(); + expect(option.type).toEqual('reset'); + expect(chart.selectAll('input[type=reset]').nodes().length).toEqual(1); + }); + it('creates prompt option with default prompt text', () => { + chart.multiple(true).redraw(); + const option = chart.selectAll('li input').nodes().pop(); + expect(option.textContent).toEqual('Select all'); + }); + + }); + + describe('select options', () => { + let firstOption, lastOption, lastIndex; + beforeEach(() => { + lastIndex = stateGroup.all().length - 1; + firstOption = getOption(chart, 0); + lastOption = getOption(chart, lastIndex); + }); + it('display title as default option text', () => { + expect(firstOption.textContent).toEqual('California: 3'); + }); + it('text property can be changed by changing title', () => { + chart.title(d => d.key).redraw(); + firstOption = getOption(chart, 0); + expect(firstOption.textContent).toEqual('California'); + }); + it('are ordered by ascending group key by default', () => { + expect(firstOption.textContent).toEqual('California: 3'); + expect(lastOption.textContent).toEqual('Ontario: 2'); + }); + it('order can be changed by changing order function', () => { + chart.order((a, b) => a.key.length - b.key.length); + chart.redraw(); + lastOption = getOption(chart, lastIndex); + expect(lastOption.textContent).toEqual('Mississippi: 2'); + }); + }); + + describe('regular single select', () => { + describe('selecting an option', () => { + it('filters dimension based on selected option\'s value', () => { + chart.onChange(stateGroup.all()[0].key); + expect(chart.filter()).toEqual('California'); + }); + it('replaces filter on second selection', () => { + chart.onChange(stateGroup.all()[0].key); + chart.onChange(stateGroup.all()[1].key); + expect(chart.filter()).toEqual('Colorado'); + expect(chart.filters().length).toEqual(1); + }); + it('actually filters dimension', () => { + chart.onChange(stateGroup.all()[0].key); + expect(regionGroup.all()[0].value).toEqual(0); + expect(regionGroup.all()[3].value).toEqual(2); + }); + it('removes filter when prompt option is selected', () => { + chart.onChange(null); + expect(chart.hasFilter()).not.toBeTruthy(); + expect(regionGroup.all()[0].value).toEqual(1); + }); + }); + + describe('redraw with existing filter', () => { + it('selects option corresponding to active filter', () => { + chart.onChange(stateGroup.all()[0].key); + chart.redraw(); + expect(chart.selectAll('input').nodes()[0].value).toEqual('California'); + }); + }); + + afterEach(() => { + chart.onChange(null); + }); + }); + + describe('multiple select', () => { + beforeEach(() => { + chart.multiple(true); + chart.onChange([stateGroup.all()[0].key, stateGroup.all()[1].key]); + }); + it('adds filters based on selections', () => { + expect(chart.filters()).toEqual(['California', 'Colorado']); + expect(chart.filters().length).toEqual(2); + }); + it('actually filters dimension', () => { + expect(regionGroup.all()[3].value).toEqual(2); + expect(regionGroup.all()[4].value).toEqual(2); + }); + it('removes all filters when prompt option is selected', () => { + chart.onChange(null); + expect(chart.hasFilter()).not.toBeTruthy(); + expect(regionGroup.all()[0].value).toEqual(1); + }); + it('selects all options corresponding to active filters on redraw', () => { + const selectedOptions = getSelectedOptions(chart); + expect(selectedOptions.length).toEqual(2); + expect(selectedOptions.map(d => d.value)).toEqual(['California', 'Colorado']); + }); + it('does not deselect previously filtered options when new option is added', () => { + chart.onChange([stateGroup.all()[0].key, stateGroup.all()[1].key, stateGroup.all()[5].key]); + + const selectedOptions = getSelectedOptions(chart); + expect(selectedOptions.length).toEqual(3); + expect(selectedOptions.map(d => d.value)).toEqual(['California', 'Colorado', 'Ontario']); + }); + + afterEach(() => { + chart.onChange(null); + }); + }); + + describe('filterDisplayed', () => { + it('only displays options whose value > 0 by default', () => { + regionDimension.filter('South'); + chart.redraw(); + expect(chart.selectAll('.dc-cbox-item').nodes().length).toEqual(1); + expect(getOption(chart, 0).textContent).toEqual('California: 2'); + }); + it('can be overridden', () => { + regionDimension.filter('South'); + chart.filterDisplayed(d => true).redraw(); + expect(chart.selectAll('.dc-cbox-item').nodes().length).toEqual(stateGroup.all().length); + expect(getOption(chart, stateGroup.all().length - 1).textContent).toEqual('Ontario: 0'); + }); + it('retains order with filtered options', () => { + regionDimension.filter('Central'); + chart.redraw(); + expect(getOption(chart, 0).textContent).toEqual('Mississippi: 2'); + expect(getOption(chart, 1).textContent).toEqual('Ontario: 1'); + }); + afterEach(() => { + regionDimension.filterAll(); + }); + }); + + function getSelectedOptions (_chart) { + return _chart.selectAll('.dc-cbox-item input').nodes().filter(d => d.value && d.checked); + } + + function getOption (_chart, i) { + return _chart.selectAll('.dc-cbox-item label').nodes()[i]; + } +}); diff --git a/spec/color-spec.js b/spec/color-spec.js index e46924c5e5..1c0b47dcd8 100644 --- a/spec/color-spec.js +++ b/spec/color-spec.js @@ -1,5 +1,5 @@ -/* global loadDateFixture */ -describe('dc.colorMixin', function () { +/* global loadDateFixture, compareVersions */ +describe('dc.colorMixin', () => { function colorTest (chart, domain, test) { chart.colorDomain(domain); return (test || domain).map(chart.getColor); @@ -7,80 +7,136 @@ describe('dc.colorMixin', function () { function identity (d) { return d; } - describe('with ordinal domain' , function () { - var chart, domain; + const ColorMixinTester = dc.ColorMixin(dc.BaseMixin); - beforeEach(function () { - chart = dc.colorMixin({}); + describe('deprecation', () => { + it('issues a one time warning when using default color scheme', () => { + spyOn(dc.logger, 'warnOnce'); + + new ColorMixinTester(); // eslint-disable-line no-new + + expect(dc.logger.warnOnce).toHaveBeenCalled(); + }); + + it('does not issue a warning when default color scheme has been changed', () => { + const origColors = dc.config.defaultColors(); + + spyOn(dc.logger, 'warnOnce'); + + dc.config.defaultColors(d3.schemeSet1); + new ColorMixinTester(); // eslint-disable-line no-new + + expect(dc.logger.warnOnce).not.toHaveBeenCalled(); + + // Restore original colors + dc.config.defaultColors(origColors); + }); + }); + + describe('with ordinal domain' , () => { + let chart, domain; + + beforeEach(() => { + chart = new ColorMixinTester(); chart.colorAccessor(identity); domain = ['a','b','c','d','e']; }); - it('default', function () { - expect(colorTest(chart,domain)).toEqual(['#3182bd','#6baed6','#9ecae1','#c6dbef','#e6550d']); + it('default', () => { + expect(colorTest(chart, domain)) + .toMatchColors(dc.config.defaultColors().slice(0, 5)); }); - it('custom', function () { - chart.colors(d3.scale.category10()); - expect(colorTest(chart,domain)).toEqual(['#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd']); + it('custom', () => { + chart.colors(d3.scaleOrdinal(d3.schemeCategory10)); + expect(colorTest(chart, domain)).toMatchColors(['#1f77b4','#ff7f0e','#2ca02c','#d62728','#9467bd']); }); - it('ordinal', function () { + it('ordinal', () => { chart.ordinalColors(['red','green','blue']); - expect(colorTest(chart,domain)).toEqual(['red','green','blue','red','green']); + expect(colorTest(chart, domain)).toMatchColors(['red','green','blue','red','green']); }); - it('linear', function () { + it('linear', () => { // GIGO: mapping ordinal domain to linear scale is nonsensical - // actually it gets scaled to NaN and then d3 corrects it - chart.linearColors(['#FF0000','#00FF00']); - expect(colorTest(chart,domain)).toEqual(['#000000', '#000000', '#000000', '#000000', '#000000']); + // d3 pre-5.8: scaled to NaN and corrected to black; 5.8+: scale returns undefined + chart.linearColors(['#ff0000','#00ff00']); + if (compareVersions(d3.version, '5.8') === -1) { + expect(colorTest(chart, domain)).toMatchColors(['#000000', '#000000', '#000000', '#000000', '#000000']); + } else { + expect(colorTest(chart, domain)).toEqual([undefined, undefined, undefined, undefined, undefined]); + } }); }); - describe('with numeric domain' , function () { - var chart, domain, test; + describe('with numeric domain' , () => { + // These tests try to validate an interesting case. In an Ordinal scale if we try to map a key + // that is not there, it is added to the domain. + // Please see https://github.com/d3/d3-scale/blob/master/README.md#_ordinal + // Linear scales work differently. + let chart, domain, test, expectedColorIndices; - beforeEach(function () { - chart = dc.colorChart({}); + beforeEach(() => { + chart = new ColorMixinTester(); chart.colorAccessor(identity); - domain = [1,100]; - test = [0,1,50,100,101,1]; + domain = [1, 100]; + // It has items that are not part of the domain. + // domain would get modified when all these values are mapped + test = [0, 1, 50, 100, 101, 1]; + + // Expected color indices corresponding to test values based on the final domain + expectedColorIndices = [2, 0, 3, 1, 4, 0]; }); - it('default', function () { - expect(colorTest(chart,domain,test)).toEqual(['#9ecae1','#3182bd','#c6dbef','#6baed6','#e6550d','#3182bd']); + it('updates the domain corresponding to unknown values', () => { + colorTest(chart, domain, test); + expect(chart.colors().domain()).toEqual([1, 100, 0, 50, 101]); }); - it('custom', function () { - chart.colors(d3.scale.category10()); - expect(colorTest(chart,domain,test)).toEqual(['#2ca02c', '#1f77b4', '#d62728', '#ff7f0e', '#9467bd', '#1f77b4']); + it('default', () => { + const expected = expectedColorIndices.map(c => dc.config.defaultColors()[c]); + expect(colorTest(chart, domain, test)).toMatchColors(expected); }); - it('ordinal', function () { + it('custom', () => { + chart.colors(d3.scaleOrdinal(d3.schemeCategory10)); + const expected = expectedColorIndices.map(c => d3.schemeCategory10[c]); + expect(colorTest(chart, domain, test)).toMatchColors(expected); + }); + + it('ordinal', () => { chart.ordinalColors(['red','green','blue']); - expect(colorTest(chart,domain,test)).toEqual(['blue', 'red', 'red', 'green', 'green', 'red']); + // If there are lesser number of colors in range than the number of domain items, it starts reusing + expect(colorTest(chart, domain, test)).toMatchColors(['blue', 'red', 'red', 'green', 'green', 'red']); }); - it('linear', function () { + it('linear', () => { + // interpolateHcl (note the adjustment for one changed value for d3 5.1) chart.linearColors(['#4575b4','#ffffbf']); - expect(colorTest(chart,domain,test)).toEqual(['#4773b3', '#4575b4', '#4dc6c1', '#ffffbf', '#ffffc0', '#4575b4']); + + let changedInD3v51 = 'rgb(88, 198, 186)'; + // https://github.com/omichelsen/compare-versions + if (compareVersions(d3.version, '5.1') === -1) { + // d3 is older than v5.1 + changedInD3v51 = 'rgb(77, 198, 193)'; + } + + expect(colorTest(chart, domain, test)) + .toMatchColors(['#4773b3', '#4575b4', changedInD3v51, '#ffffbf', '#ffffc0', '#4575b4']); }); }); - describe('calculateColorDomain' , function () { - var chart; - - beforeEach(function () { - var data = crossfilter(loadDateFixture()); - var valueDimension = data.dimension(function (d) { - return d.value; - }); - var valueGroup = valueDimension.group(); - chart = dc.colorChart(dc.baseChart({})) - .colorAccessor(function (d) {return d.value;}) + describe('calculateColorDomain' , () => { + let chart; + + beforeEach(() => { + const data = crossfilter(loadDateFixture()); + const valueDimension = data.dimension(d => d.value); + const valueGroup = valueDimension.group(); + chart = new ColorMixinTester() + .colorAccessor(d => d.value) .group(valueGroup); }); - it('check domain', function () { + it('check domain', () => { chart.calculateColorDomain(); expect(chart.colorDomain()).toEqual([1,3]); }); diff --git a/spec/composite-chart-spec.js b/spec/composite-chart-spec.js index d8b3aa4645..6beb1978cd 100644 --- a/spec/composite-chart-spec.js +++ b/spec/composite-chart-spec.js @@ -1,290 +1,335 @@ -/* global appendChartID, loadDateFixture, makeDate */ -describe('dc.compositeChart', function () { - var id, chart, data, dateDimension, dateValueSumGroup, dateValueNegativeSumGroup, +/* global appendChartID, loadDateFixture, makeDate, simulateChartBrushing */ +describe('dc.compositeChart', () => { + let id, chart, data, dateDimension, dateValueSumGroup, dateValueNegativeSumGroup, dateIdSumGroup, dateIdNegativeSumGroup, dateGroup; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - dateDimension = data.dimension(function (d) { return d3.time.day.utc(d.dd); }); - dateValueSumGroup = dateDimension.group().reduceSum(function (d) { return d.value; }); - dateValueNegativeSumGroup = dateDimension.group().reduceSum(function (d) { return -d.value; }); - dateIdSumGroup = dateDimension.group().reduceSum(function (d) { return d.id; }); - dateIdNegativeSumGroup = dateDimension.group().reduceSum(function (d) { return -d.id; }); + dateDimension = data.dimension(d => d3.utcDay(d.dd)); + dateValueSumGroup = dateDimension.group().reduceSum(d => d.value); + dateValueNegativeSumGroup = dateDimension.group().reduceSum(d => -d.value); + dateIdSumGroup = dateDimension.group().reduceSum(d => d.id); + dateIdNegativeSumGroup = dateDimension.group().reduceSum(d => -d.id); dateGroup = dateDimension.group(); id = 'composite-chart'; appendChartID(id); - chart = dc.compositeChart('#' + id); + chart = new dc.CompositeChart(`#${id}`); chart .dimension(dateDimension) .group(dateIdSumGroup) .width(500) .height(150) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) .transitionDuration(0) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .shareColors(true) .compose([ - dc.barChart(chart) + new dc.BarChart(chart) .centerBar(true) .group(dateValueSumGroup, 'Date Value Group Bar') .gap(1), - dc.lineChart(chart) + new dc.LineChart(chart) .group(dateIdSumGroup, 'Date ID Group') .stack(dateValueSumGroup, 'Date Value Group Line 1') .stack(dateValueSumGroup, 'Date Value Group Line 2') .hidableStacks(true), - dc.lineChart(chart) + new dc.LineChart(chart) .group(dateGroup, 'Date Group') ]); }); - it('should registered the chart with DC', function () { + it('should registered the chart with DC', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should set a dimension on the chart', function () { + it('should set a dimension on the chart', () => { expect(chart.dimension()).toBe(dateDimension); }); - it('should set a group on the chart', function () { + it('should set a group on the chart', () => { expect(chart.group()).toBe(dateIdSumGroup); }); - it('should set a width on the chart', function () { + it('should set a width on the chart', () => { expect(chart.width()).toBe(500); + + chart.children().forEach(child => { + expect(child.width()).toBe(500); + }); }); - it('should set a height on the chart', function () { + it('should set a height on the chart', () => { expect(chart.height()).toBe(150); + + chart.children().forEach(child => { + expect(child.height()).toBe(150); + }); }); - it('should have zero transition duration', function () { + it('should have zero transition duration', () => { expect(chart.transitionDuration()).toBe(0); }); - it('should set the margins of the chart', function () { + it('should set the margins of the chart', () => { expect(chart.margins()).not.toBeNull(); + + chart.children().forEach(child => { + expect(child.margins()).toBe(chart.margins()); + }); }); - it('should set a domain', function () { + it('should set a domain', () => { expect(chart.x()).toBeDefined(); }); - it('should set the x domain to endpoint dates', function () { + it('should set the x domain to endpoint dates', () => { expect(chart.x().domain()[0].getTime()).toBe(makeDate(2012, 4, 20).getTime()); expect(chart.x().domain()[1].getTime()).toBe(makeDate(2012, 7, 15).getTime()); }); - it('should set the x units', function () { - expect(chart.xUnits()).toBe(d3.time.days.utc); + it('should set the x units', () => { + expect(chart.xUnits()).toBe(d3.utcDays); }); - it('should create the x axis', function () { + it('should create the x axis', () => { expect(chart.xAxis()).not.toBeNull(); }); - it('should create the y axis', function () { + it('should create the y axis', () => { expect(chart.yAxis()).not.toBeNull(); }); - it('should create the brush', function () { + it('should create the brush', () => { expect(chart.select('g.brush')).not.toBeNull(); }); - it('does not set round by default', function () { + it('does not set round by default', () => { expect(chart.round()).not.toBeDefined(); }); - it('can change round', function () { - chart.round(d3.time.day.utc.round); + it('can change round', () => { + chart.round(d3.utcDay.round); expect(chart.round()).not.toBeNull(); }); - it('has a default value for x', function () { + it('has a default value for x', () => { expect(chart.keyAccessor()).not.toBeNull(); }); - it('has a default value for y', function () { + it('has a default value for y', () => { expect(chart.valueAccessor()).not.toBeNull(); }); - describe('rendering the chart', function () { - beforeEach(function () { + it('should not allow calling yAxisMin', () => { + expect(chart.yAxisMin).toThrowError(); + }); + + it('should not allow calling yAxisMax', () => { + expect(chart.yAxisMax).toThrowError(); + }); + + describe('rendering the chart', () => { + beforeEach(() => { chart.render(); }); - it('should create a root SVG element', function () { + it('should create a root SVG element', () => { expect(chart.svg().empty()).toBeFalsy(); }); - it('should create a root SVG group element', function () { + it('should create a root SVG group element', () => { expect(chart.g().empty()).toBeFalsy(); }); - it('should size the chart to the full height of the chart', function () { + it('should size the chart to the full height of the chart', () => { expect(chart.select('svg').attr('height')).toBe('150'); }); - it('should set x range to width', function () { + it('should set x range to width', () => { expect(chart.x().range()).toEqual([0, 420]); }); - it('should set y domain', function () { + it('should set y domain', () => { expect(chart.y()).toBeDefined(); }); - it('should set y range to height by default', function () { + it('should set y range to height by default', () => { expect(chart.y().range()).toEqual([110, 0]); }); - it('should automatically size the y domain based on height', function () { + it('should automatically size the y domain based on height', () => { expect(chart.y().domain()).toEqual([0, 281]); }); - it('should place the x axis at the bottom', function () { - expect(chart.select('svg g g.x').attr('transform')).toMatchTranslate(30,120); + it('should place the x axis at the bottom', () => { + expect(chart.select('svg g g.x').attr('transform')).toMatchTranslate(30, 120); }); - it('should place the y axis to the left', function () { - expect(chart.select('svg g g.y').attr('transform')).toMatchTranslate(30,10); + it('should place the y axis to the left', () => { + expect(chart.select('svg g g.y').attr('transform')).toMatchTranslate(30, 10); }); - it('should create a separate g for each subchart', function () { + it('should create a separate g for each subchart', () => { expect(chart.selectAll('g.sub').size()).toBe(3); }); - it('should index each subchart g by css class', function () { - expect(d3.select(chart.selectAll('g.sub')[0][0]).attr('class')).toBe('sub _0'); - expect(d3.select(chart.selectAll('g.sub')[0][1]).attr('class')).toBe('sub _1'); + it('should index each subchart g by css class', () => { + expect(d3.select(chart.selectAll('g.sub').nodes()[0]).attr('class')).toBe('sub _0'); + expect(d3.select(chart.selectAll('g.sub').nodes()[1]).attr('class')).toBe('sub _1'); }); - it('should generate sub line chart paths', function () { + it('should generate sub line chart paths', () => { expect(chart.selectAll('g.sub path.line').size()).not.toBe(0); chart.selectAll('g.sub path.line').each(function (d, i) { switch (i) { - case 0: - expect(d3.select(this).attr('d')) - .toMatchPath('M24.137931034482758,110L91.72413793103448,108L101.37931034482757,103L202.75862068965515,' + - '108L246.20689655172413,104L395.8620689655172,105'); - break; - case 1: - expect(d3.select(this).attr('d')) - .toMatchPath('M24.137931034482758,92L91.72413793103448,82L101.37931034482757,52L202.75862068965515,' + - '91L246.20689655172413,83L395.8620689655172,75'); - break; + case 0: + expect(d3.select(this).attr('d')) + .toMatchPath('M24.137931034482758,110L91.72413793103448,108L101.37931034482757,103L202.75862068965515,' + + '108L246.20689655172413,104L395.8620689655172,105'); + break; + case 1: + expect(d3.select(this).attr('d')) + .toMatchPath('M24.137931034482758,92L91.72413793103448,82L101.37931034482757,52L202.75862068965515,' + + '91L246.20689655172413,83L395.8620689655172,75'); + break; } }); }); - it('should generate sub bar charts', function () { + it('should generate sub bar charts', () => { expect(chart.selectAll('g.sub g._0 rect').size()).toBe(6); }); - it('should render sub bar chart', function () { + it('should render sub bar chart', () => { expect(chart.selectAll('g.sub rect.bar').size()).not.toBe(0); chart.selectAll('g.sub rect.bar').each(function (d, i) { switch (i) { - case 0: - expect(d3.select(this).attr('x')).toBeCloseTo('22.637931034482758', 3); - expect(d3.select(this).attr('y')).toBe('93'); - expect(d3.select(this).attr('width')).toBe('3'); - expect(d3.select(this).attr('height')).toBe('17'); - break; - case 5: - expect(d3.select(this).attr('x')).toBeCloseTo('394.3620689655172', 3); - expect(d3.select(this).attr('y')).toBe('80'); - expect(d3.select(this).attr('width')).toBe('3'); - expect(d3.select(this).attr('height')).toBe('30'); - break; + case 0: + expect(d3.select(this).attr('x')).toBeCloseTo('22.637931034482758', 3); + expect(d3.select(this).attr('y')).toBe('93'); + expect(d3.select(this).attr('width')).toBe('3'); + expect(d3.select(this).attr('height')).toBe('17'); + break; + case 5: + expect(d3.select(this).attr('x')).toBeCloseTo('394.3620689655172', 3); + expect(d3.select(this).attr('y')).toBe('80'); + expect(d3.select(this).attr('width')).toBe('3'); + expect(d3.select(this).attr('height')).toBe('30'); + break; } }); }); - describe('the chart clip paths', function () { - it('should create only one defs', function () { + describe('the chart clip paths', () => { + it('should create only one defs', () => { expect(chart.selectAll('defs').size()).toBe(1); }); - it('should create only one clip path', function () { + it('should create only one clip path', () => { expect(chart.selectAll('defs #composite-chart-clip').size()).toBe(1); }); - it('should create only one clip rect', function () { + it('should create only one clip rect', () => { expect(chart.selectAll('defs #composite-chart-clip rect').size()).toBe(1); }); - it('should have the correct size', function () { - var rect = chart.select('defs #composite-chart-clip rect'); + it('should have the correct size', () => { + const rect = chart.select('defs #composite-chart-clip rect'); expect(rect.attr('width')).toBe('420'); expect(rect.attr('height')).toBe('110'); }); - it('should have clip path refs', function () { + it('should have clip path refs', () => { expect(chart.selectAll('g.chart-body').size()).not.toBe(0); chart.selectAll('g.chart-body').each(function () { - expect(d3.select(this).attr('clip-path')).toMatchUrl(window.location.href + '#composite-chart-clip'); + expect(d3.select(this).attr('clip-path')).toMatchUrl(`${window.location.href}#composite-chart-clip`); }); }); }); - describe('the chart brush', function () { + describe('the chart brush', () => { - it('should be positioned with the chart left margin', function () { - expect(chart.select('g.brush').attr('transform')).toMatchTranslate(chart.margins().left,10); + it('should be positioned with the chart left margin', () => { + expect(chart.select('g.brush').attr('transform')).toMatchTranslate(chart.margins().left, 10); }); - it('should have a resize handle', function () { - expect(chart.selectAll('g.brush .resize path').size()).not.toBe(0); - chart.selectAll('g.brush .resize path').each(function (d, i) { + it('should have a resize handle', () => { + const selectAll = chart.select('g.brush').selectAll('path.custom-brush-handle'); + expect(selectAll.size()).toBe(2); + selectAll.each(function (d, i) { if (i === 0) { expect(d3.select(this).attr('d')) - .toMatchPath('M0.5,36.666666666666664A6,6 0 0 1 6.5,42.666666666666664V67.33333333333333A6,' + - '6 0 0 1 0.5,73.33333333333333ZM2.5,44.666666666666664V65.33333333333333M4.5,' + - '44.666666666666664V65.33333333333333'); + .toMatchPath('M-0.5,36.666666666666664A6,6 0 0 0 -6.5,42.666666666666664V67.33333333333333A6,' + + '6 0 0 0 -0.5,73.33333333333333ZM-2.5,44.666666666666664V65.33333333333333M-4.5,' + + '44.666666666666664V65.33333333333333'); } else { expect(d3.select(this).attr('d')) - .toMatchPath('M-0.5,36.666666666666664A6,6 0 0 0 -6.5,42.666666666666664V67.33333333333333A6,' + - '6 0 0 0 -0.5,73.33333333333333ZM-2.5,44.666666666666664V65.33333333333333M-4.5,' + - '44.666666666666664V65.33333333333333'); + .toMatchPath('M0.5,36.666666666666664A6,6 0 0 1 6.5,42.666666666666664V67.33333333333333A6,' + + '6 0 0 1 0.5,73.33333333333333ZM2.5,44.666666666666664V65.33333333333333M4.5,' + + '44.666666666666664V65.33333333333333'); } }); }); - it('should stretch the background', function () { - expect(chart.select('g.brush rect.background').attr('width')).toBe('420'); + it('should stretch the background', () => { + expect(chart.select('g.brush rect.overlay').attr('width')).toBe('420'); }); - it('should set the height of background to height of chart', function () { - expect(chart.select('g.brush rect.background').attr('height')).toBe('110'); + it('should set the height of background to height of chart', () => { + expect(chart.select('g.brush rect.overlay').attr('height')).toBe('110'); }); - it('should set the extent height to chart height', function () { - expect(chart.select('g.brush rect.extent').attr('height')).toBe('110'); - }); + describe('when filtering the chart', () => { + let filter1, filter2; + + beforeEach(() => { + filter1 = [makeDate(2012, 5, 1), makeDate(2012, 5, 30)]; + filter2 = [makeDate(2012, 6, 10), makeDate(2012, 6, 20)]; + chart.filter(filter1).redraw(); + }); - describe('when filtering the chart', function () { - beforeEach(function () { - chart.filter([makeDate(2012, 5, 1), makeDate(2012, 5, 30)]).redraw(); + it('should set the extent height to chart height', () => { + expect(chart.select('g.brush rect.selection').attr('height')).toBe('110'); }); - it('should set extent width to chart width based on filter set', function () { - expect(chart.select('g.brush rect.extent').attr('width')).toBe('140'); + it('should set extent width to chart width based on filter set', () => { + expect(chart.select('g.brush rect.selection').attr('width')).toBe('140'); }); - it('should fade filtered bars into the background', function () { + it('should fade filtered bars into the background', () => { expect(chart.selectAll('g.sub rect.deselected').size()).toBe(4); }); + + it('should set the same filter for each children', () => { + for (let i = 0; i < chart.children().length; ++i) { + expect(chart.children()[i].filter()).toEqual(filter1); + } + }); + + it('should reset filters for each children', () => { + chart.filter(null); + for (let i = 0; i < chart.children().length; ++i) { + expect(chart.children()[i].filter()).toEqual(null); + } + }); + + it('should replace filters for each children', () => { + chart.replaceFilter(filter2); + for (let i = 0; i < chart.children().length; ++i) { + expect(chart.children()[i].filter()).toEqual(filter2); + } + }); }); - describe('after filtering all', function () { - beforeEach(function () { + describe('after filtering all', () => { + beforeEach(() => { chart.filterAll(); chart.redraw(); }); - it('should bring all bars to the foreground', function () { + it('should bring all bars to the foreground', () => { chart.selectAll('g rect.bar').each(function (d) { expect(d3.select(this).attr('class')).toBe('bar'); }); @@ -292,26 +337,26 @@ describe('dc.compositeChart', function () { }); }); - describe('legends composed of subchart groups', function () { - beforeEach(function () { - chart.legend(dc.legend().x(200).y(10).itemHeight(13).gap(5)).render(); + describe('legends composed of subchart groups', () => { + beforeEach(() => { + chart.legend(new dc.Legend().x(200).y(10).itemHeight(13).gap(5)).render(); }); - it('should generate a legend item for each subchart', function () { + it('should generate a legend item for each subchart', () => { expect(chart.selectAll('g.dc-legend g.dc-legend-item').size()).toBe(5); }); - it('should generate legend labels for each sub-chart', function () { + it('should generate legend labels for each sub-chart', () => { expect(chart.selectAll('g.dc-legend-item text').size()).toBe(5); }); - it('should be placed according to its own legend option, ignoring the sub-charts', function () { - expect(chart.select('g.dc-legend').attr('transform')).toMatchTranslate(200,10); + it('should be placed according to its own legend option, ignoring the sub-charts', () => { + expect(chart.select('g.dc-legend').attr('transform')).toMatchTranslate(200, 10); }); - it('should generate legend labels with their associated group text', function () { + it('should generate legend labels with their associated group text', () => { function legendText (n) { - return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item text')[0][n]).text(); + return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item text').nodes()[n]).text(); } expect(legendText(0)).toBe('Date Value Group Bar'); expect(legendText(1)).toBe('Date ID Group'); @@ -320,157 +365,145 @@ describe('dc.compositeChart', function () { expect(legendText(4)).toBe('Date Group'); }); - it('should properly delegate highlighting to its children', function () { - var firstItem = chart.select('g.dc-legend g.dc-legend-item'); + it('should properly delegate highlighting to its children', () => { + const firstItem = chart.select('g.dc-legend g.dc-legend-item'); - firstItem.on('mouseover')(firstItem.datum()); + dc.d3compat.callHandler(firstItem.on('mouseover'), null, {}, firstItem.datum()); expect(chart.selectAll('rect.highlight').size()).toBe(6); expect(chart.selectAll('path.fadeout').size()).toBe(4); - firstItem.on('mouseout')(firstItem.datum()); + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); expect(chart.selectAll('rect.highlight').size()).toBe(0); expect(chart.selectAll('path.fadeout').size()).toBe(0); }); - it('should hide hidable child stacks', function () { - var dateValueGroupLine2 = d3.select(chart.selectAll('g.dc-legend g.dc-legend-item')[0][3]); + it('should hide hidable child stacks', () => { + const dateValueGroupLine2 = d3.select(chart.selectAll('g.dc-legend g.dc-legend-item').nodes()[3]); - dateValueGroupLine2.on('click')(dateValueGroupLine2.datum()); + dc.d3compat.callHandler(dateValueGroupLine2.on('click'), null, {}, dateValueGroupLine2.datum()); expect(dateValueGroupLine2.text()).toBe('Date Value Group Line 2'); - expect(d3.select(chart.selectAll('g.dc-legend g.dc-legend-item')[0][3]).classed('fadeout')).toBeTruthy(); + expect(d3.select(chart.selectAll('g.dc-legend g.dc-legend-item').nodes()[3]).classed('fadeout')).toBeTruthy(); expect(chart.selectAll('path.line').size()).toEqual(3); }); }); }); - describe('no elastic', function () { - beforeEach(function () { - chart.y(d3.scale.linear().domain([-200, 200])); + describe('no elastic', () => { + beforeEach(() => { + chart.y(d3.scaleLinear().domain([-200, 200])); chart.render(); }); - it('should respect manually applied domain', function () { + it('should respect manually applied domain', () => { expect(chart.y().domain()[0]).toBe(-200); expect(chart.y().domain()[1]).toBe(200); }); }); - describe('elastic chart axes', function () { - beforeEach(function () { - data.dimension(function (d) { - return d.countrycode; - }).filter('CA'); + describe('elastic chart axes', () => { + beforeEach(() => { + data.dimension(d => d.countrycode).filter('CA'); chart.elasticY(true).elasticX(true).render(); }); - it('should adjust the y axis, combining all child charts maxs & mins', function () { + it('should adjust the y axis, combining all child charts maxs & mins', () => { expect(chart.y().domain()[1]).toBe(115); }); - it('should set the x domain', function () { + it('should set the x domain', () => { expect(chart.x().domain()[0].getTime() >= 1337904000000).toBeTruthy(); expect(chart.x().domain()[1].getTime() >= 1344556800000).toBeTruthy(); }); }); - describe('subchart renderlets', function () { - beforeEach(function () { - chart.children()[0].on('renderlet', function (chart) { - chart.selectAll('rect.bar').attr('width', function (d) { - return 10; - }); + describe('subchart renderlets', () => { + beforeEach(() => { + chart.children()[0].on('renderlet', _chart => { + _chart.selectAll('rect.bar').attr('width', d => 10); }); chart.render(); }); - it('should trigger the sub-chart renderlet', function () { - expect(d3.select(chart.selectAll('rect')[0][0]).attr('width')).toBe('10'); + it('should trigger the sub-chart renderlet', () => { + expect(d3.select(chart.selectAll('rect').nodes()[0]).attr('width')).toBe('10'); }); }); - describe('when two subcharts share the same group', function () { - beforeEach(function () { - var dimension = data.dimension(function (d) { - return d.status; - }); - var group = dimension.group().reduce( - function (p, v) { + describe('when two subcharts share the same group', () => { + beforeEach(() => { + const dimension = data.dimension(d => d.status); + const group = dimension.group().reduce( + (p, v) => { ++p.count; p.value += +v.value; return p; }, - function (p, v) { + (p, v) => { --p.count; p.value -= +v.value; return p; }, - function () { - return {count: 0, value: 0}; - } + () => ({count: 0, value: 0}) ); chart .brushOn(false) .dimension(dimension) .shareTitle(false) - .x(d3.scale.ordinal()) + .x(d3.scaleBand()) .xUnits(dc.units.ordinal) .compose([ - dc.lineChart(chart) + new dc.LineChart(chart) .group(group, 'Series 1') - .valueAccessor(function (d) { - return d.value.count; - }) - .title(function (d) { - var value = d.value.count; + .valueAccessor(d => d.value.count) + .title(d => { + let value = d.value.count; if (isNaN(value)) { value = 0; } - return 'Count: ' + d3.format('d')(value); + return `Count: ${d3.format('d')(value)}`; }), - dc.lineChart(chart) + new dc.LineChart(chart) .group(group, 'Series 2') - .valueAccessor(function (d) { - return d.value.value; - }) - .title(function (d) { - var value = d.value.value; + .valueAccessor(d => d.value.value) + .title(d => { + let value = d.value.value; if (isNaN(value)) { value = 0; } - return 'Value: ' + d3.format('d')(value); + return `Value: ${d3.format('d')(value)}`; }) ]).render(); }); - it('should set a tooltip based on the shared group', function () { + it('should set a tooltip based on the shared group', () => { expect(chart.select('.sub._0 .dc-tooltip._0 .dot title').text()).toBe('Count: 5'); expect(chart.select('.sub._1 .dc-tooltip._0 .dot title').text()).toBe('Value: 220'); }); }); - describe('subchart title rendering', function () { - beforeEach(function () { + describe('subchart title rendering', () => { + beforeEach(() => { chart.renderTitle(false); chart.render(); }); - it('should respect boolean flag when title not set', function () { + it('should respect boolean flag when title not set', () => { expect(chart.select('.sub._0 .dc-tooltip._0 .dot').empty()).toBeTruthy(); expect(chart.select('.sub._1 .dc-tooltip._0 .dot').empty()).toBeTruthy(); }); }); - describe('the y-axes', function () { - describe('when composing charts with both left and right y-axes', function () { - var rightChart; + describe('the y-axes', () => { + describe('when composing charts with both left and right y-axes', () => { + let rightChart; - beforeEach(function () { + beforeEach(() => { chart .compose([ - dc.barChart(chart) + new dc.BarChart(chart) .group(dateValueSumGroup, 'Date Value Group'), - rightChart = dc.lineChart(chart) + rightChart = new dc.LineChart(chart) .group(dateIdSumGroup, 'Date ID Group') .stack(dateValueSumGroup, 'Date Value Group') .stack(dateValueSumGroup, 'Date Value Group') @@ -479,11 +512,11 @@ describe('dc.compositeChart', function () { .render(); }); - it('should render two y-axes', function () { + it('should render two y-axes', () => { expect(chart.selectAll('.axis').size()).toBe(3); }); - it('should render a right and a left label', function () { + it('should render a right and a left label', () => { chart.yAxisLabel('Left Label').rightYAxisLabel('Right Label').render(); expect(chart.selectAll('.y-axis-label').size()).toBe(2); @@ -491,245 +524,349 @@ describe('dc.compositeChart', function () { expect(chart.selectAll('.y-axis-label.yr-label').empty()).toBeFalsy(); }); - it('should scale "right" charts according to the right y-axis' , function () { + it('should scale "right" charts according to the right y-axis' , () => { expect(rightChart.y()).toBe(chart.rightY()); }); - it('should set the domain of the right axis', function () { + it('should set the domain of the right axis', () => { expect(rightChart.yAxisMin()).toBe(0); expect(rightChart.yAxisMax()).toBe(281); }); - it('domain', function () { + it('domain', () => { expect(chart.rightY().domain()).toEqual([0, 281]); expect(chart.y().domain()).toEqual([0, 132]); }); - it('should set "right" chart y-axes to the composite chart right y-axis', function () { + it('should set "right" chart y-axes to the composite chart right y-axis', () => { expect(rightChart.yAxis()).toBe(chart.rightYAxis()); }); - describe('horizontal gridlines', function () { - beforeEach(function () { + describe('horizontal gridlines', () => { + beforeEach(() => { chart.yAxis().ticks(3); chart.rightYAxis().ticks(6); chart.renderHorizontalGridLines(true).render(); }); - it('should draw left horizontal gridlines by default', function () { + it('should draw left horizontal gridlines by default', () => { expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(3); }); - it('should allow right horizontal gridlines to be used', function () { + it('should allow right horizontal gridlines to be used', () => { chart.useRightAxisGridLines(true).render(); expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(6); }); }); }); - describe('when composing charts with just a left axis', function () { - beforeEach(function () { + describe('when composing charts with just a left axis', () => { + beforeEach(() => { chart.yAxis().ticks(4); chart.compose([ - dc.lineChart(chart).group(dateGroup) + new dc.LineChart(chart).group(dateGroup) ]).renderHorizontalGridLines(true).render(); }); - it('should only render a left y axis', function () { + it('should only render a left y axis', () => { expect(chart.selectAll('.axis.y').empty()).toBeFalsy(); expect(chart.selectAll('.axis.yr').empty()).toBeTruthy(); }); - it('should only draw left horizontal gridlines', function () { + it('should only draw left horizontal gridlines', () => { expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(4); }); }); - describe('when composing charts with just a right axis', function () { - beforeEach(function () { - chart.yAxis().ticks(7); + describe('when composing charts with just a right axis', () => { + beforeEach(() => { chart.compose([ - dc.lineChart(chart).group(dateGroup).useRightYAxis(true) - ]).renderHorizontalGridLines(true).render(); + new dc.LineChart(chart).group(dateGroup).useRightYAxis(true) + ]).renderHorizontalGridLines(true); + chart.rightYAxis().ticks(7); + chart.render(); }); - it('should only render a right y axis', function () { + it('should only render a right y axis', () => { expect(chart.selectAll('.axis.y').empty()).toBeTruthy(); expect(chart.selectAll('.axis.yr').empty()).toBeFalsy(); }); - it('should only draw the right horizontal gridlines', function () { + it('should only draw the right horizontal gridlines', () => { expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(7); }); }); - describe('when composing a left axis chart with negative values', function () { - var leftChart, rightChart; - beforeEach(function () { + describe('when composing a left axis chart with negative values', () => { + let leftChart, rightChart; + beforeEach(() => { chart .compose([ - leftChart = dc.barChart(chart) + leftChart = new dc.BarChart(chart) .group(dateValueNegativeSumGroup, 'Date Value Group'), - rightChart = dc.lineChart(chart) + rightChart = new dc.LineChart(chart) .group(dateIdSumGroup, 'Date ID Group') .useRightYAxis(true) ]) .render(); }); - it('the axis baselines shouldn\'t match', function () { + it('the axis baselines shouldn\'t match', () => { expect(leftChart.y()(0)).not.toEqual(rightChart.y()(0)); }); - describe('with alignYAxes', function () { - beforeEach(function () { + describe('with alignYAxes', () => { + beforeEach(() => { chart.alignYAxes(true) .elasticY(true) .render(); }); - it('the axis baselines should match', function () { + it('the axis baselines should match', () => { expect(leftChart.y()(0)).toEqual(rightChart.y()(0)); }); - it('the series heights should be equal', function () { + it('the series heights should be equal', () => { expect(plotHeight(leftChart)).toEqual(plotHeight(rightChart)); }); }); }); - describe('when composing a right axis chart with negative values', function () { - var leftChart, rightChart; - beforeEach(function () { + describe('when composing a right axis chart with negative values', () => { + let leftChart, rightChart; + beforeEach(() => { chart .compose([ - leftChart = dc.barChart(chart) + leftChart = new dc.BarChart(chart) .group(dateIdSumGroup, 'Date ID Group'), - rightChart = dc.lineChart(chart) + rightChart = new dc.LineChart(chart) .group(dateValueNegativeSumGroup, 'Date Value Group') .useRightYAxis(true) ]) .render(); }); - it('the axis baselines shouldn\'t match', function () { + it('the axis baselines shouldn\'t match', () => { expect(leftChart.y()(0)).not.toEqual(rightChart.y()(0)); }); - describe('with alignYAxes', function () { - beforeEach(function () { + describe('with alignYAxes', () => { + beforeEach(() => { chart.alignYAxes(true) .elasticY(true) .render(); }); - it('the axis baselines should match', function () { + it('the axis baselines should match', () => { expect(leftChart.y()(0)).toEqual(rightChart.y()(0)); }); - it('the series heights should be equal', function () { + it('the series heights should be equal', () => { expect(plotHeight(leftChart)).toEqual(plotHeight(rightChart)); }); }); }); - describe('when composing left and right axes charts with negative values', function () { - var leftChart, rightChart; - beforeEach(function () { + describe('when composing left and right axes charts with negative values', () => { + let leftChart, rightChart; + beforeEach(() => { chart .compose([ - leftChart = dc.barChart(chart) + leftChart = new dc.BarChart(chart) .group(dateIdNegativeSumGroup, 'Date ID Group'), - rightChart = dc.lineChart(chart) + rightChart = new dc.LineChart(chart) .group(dateValueNegativeSumGroup, 'Date Value Group') .useRightYAxis(true) ]) .render(); }); - it('the axis baselines should match', function () { + it('the axis baselines should match', () => { /* because elasticY ensures zero is included for all-negatives, due to PR #1156 */ expect(leftChart.y()(0)).toEqual(rightChart.y()(0)); }); - describe('with alignYAxes', function () { - beforeEach(function () { + describe('with alignYAxes', () => { + beforeEach(() => { chart.alignYAxes(true) .elasticY(true) .render(); }); - it('the axis baselines should match', function () { + it('the axis baselines should match', () => { expect(leftChart.y()(0)).toEqual(rightChart.y()(0)); }); - it('the series heights should be equal', function () { + it('the series heights should be equal', () => { expect(plotHeight(leftChart)).toEqual(plotHeight(rightChart)); }); }); }); - function plotHeight (chart) { - return chart.y()(chart.yAxisMax()) - chart.y()(chart.yAxisMin()); + function plotHeight (_chart) { + return _chart.y()(_chart.yAxisMax()) - _chart.y()(_chart.yAxisMin()); } }); - describe('sub-charts with different filter types', function () { - var scatterGroup, scatterDimension; - var lineGroup, lineDimension; + describe('sub-charts with different filter types', () => { + let scatterGroup, scatterDimension; + let lineGroup, lineDimension; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - scatterDimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); + scatterDimension = data.dimension(d => [+d.value, +d.nvalue]); scatterGroup = scatterDimension.group(); - lineDimension = data.dimension(function (d) { return +d.value; }); + lineDimension = data.dimension(d => +d.value); lineGroup = lineDimension.group(); chart .dimension(scatterDimension) .group(scatterGroup) - .x(d3.scale.linear().domain([0,70])) + .x(d3.scaleLinear().domain([0,70])) .brushOn(true) .compose([ - dc.scatterPlot(chart), - dc.scatterPlot(chart), - dc.lineChart(chart).dimension(lineDimension).group(lineGroup) + new dc.ScatterPlot(chart), + new dc.ScatterPlot(chart), + new dc.LineChart(chart).dimension(lineDimension).group(lineGroup) ]).render(); }); - describe('brushing', function () { - var otherDimension; + describe('brushing', () => { + let otherDimension; - beforeEach(function () { - otherDimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); - chart.brush().extent([22, 35]); - chart.brush().on('brush')(); + beforeEach(() => { + otherDimension = data.dimension(d => [+d.value, +d.nvalue]); + simulateChartBrushing(chart, [22, 35]); chart.redraw(); }); - it('should filter the child charts', function () { + it('should filter the child charts', () => { + jasmine.clock().tick(100); expect(otherDimension.top(Infinity).length).toBe(4); }); - describe('brush decreases in size', function () { - beforeEach(function () { - chart.brush().extent([22, 33]); - chart.brush().on('brush')(); + it('should set correct filters in scatter plots', () => { + jasmine.clock().tick(100); + for (let i = 0; i < 2; ++i) { + const filter = chart.children()[i].filter(); + expect(filter.filterType).toEqual('RangedTwoDimensionalFilter'); + expect(dc.utils.arraysEqual(filter, [22, 35])).toEqual(true); + } + }); + + describe('brush decreases in size', () => { + beforeEach(() => { + simulateChartBrushing(chart, [22, 33]); chart.redraw(); }); - it('should filter down to fewer points', function () { + it('should filter down to fewer points', () => { + jasmine.clock().tick(100); expect(otherDimension.top(Infinity).length).toBe(2); }); + it('should set correct filters in scatter plots', () => { + jasmine.clock().tick(100); + for (let i = 0; i < 2; ++i) { + const filter = chart.children()[i].filter(); + expect(filter.filterType).toEqual('RangedTwoDimensionalFilter'); + expect(dc.utils.arraysEqual(filter, [22, 33])).toEqual(true); + } + }); }); - describe('brush disappears', function () { - beforeEach(function () { - chart.brush().extent([22, 22]); - chart.brush().on('brush')(); + describe('brush disappears', () => { + beforeEach(() => { + simulateChartBrushing(chart, [22, 22]); chart.redraw(); }); - it('should clear all filters', function () { + it('should clear all filters', () => { expect(otherDimension.top(Infinity).length).toBe(10); }); }); + + it('should set clear filters in all children', () => { + for (let i = 0; i < chart.children().length; ++i) { + expect(chart.children()[i].filter()).toEqual(null); + } + }); + }); + }); + + describe('composite property', () => { + let originalMargins; + beforeEach(() => { + originalMargins = chart.margins(); + + chart.width(1000); + chart.height(500); + chart.margins({top: 100, right: 100, bottom: 100, left: 100}); + }); + + it('should set width on child charts', () => { + expect(chart.width()).toBe(1000); + + chart.children().forEach(child => { + expect(child.width()).toBe(1000); + }); + }); + + it('should set height on child charts', () => { + expect(chart.height()).toBe(500); + + chart.children().forEach(child => { + expect(child.height()).toBe(500); + }); + }); + + it('should set margins of child charts', () => { + expect(chart.margins()).not.toBeNull(); + expect(chart.margins()).not.toBe(originalMargins); + + chart.children().forEach(child => { + expect(child.margins()).toBe(chart.margins()); + }); + }); + }); + + describe('rescale', () => { + beforeEach(() => { + expect(chart.resizing()).toBe(true); + chart.children().forEach(child => { + expect(child.resizing()).toBe(true); + }); + + chart.render(); + + expect(chart.resizing()).toBe(false); + chart.children().forEach(child => { + expect(child.resizing()).toBe(false); + }); + + chart.rescale(); + }); + + it('should rescale child charts', () => { + expect(chart.resizing()).toBe(true); + + chart.children().forEach(child => { + expect(child.resizing()).toBe(true); + }); + }); + }); + + describe('re-compose rendered chart', () => { + beforeEach(() => { + chart.render(); + expect(chart.resizing()).toBe(false); + + chart.compose([ + new dc.LineChart(chart).group(dateGroup) + ]); + }); + + it('should rescale child charts', () => { + expect(chart.resizing()).toBe(true); + + chart.children().forEach(child => { + expect(child.resizing()).toBe(true); + }); }); }); }); diff --git a/spec/coordinate-grid-chart-spec.js b/spec/coordinate-grid-chart-spec.js index 7c133bb858..7e5dab4ac8 100644 --- a/spec/coordinate-grid-chart-spec.js +++ b/spec/coordinate-grid-chart-spec.js @@ -1,314 +1,328 @@ -/* global appendChartID, loadDateFixture, makeDate, cleanDateRange */ -describe('dc.coordinateGridChart', function () { - var chart, id; - var data, dimension, group; +/* global appendChartID, loadDateFixture, makeDate, cleanDateRange, simulateChartBrushing */ +describe('dc.coordinateGridChart', () => { + let chart, id; + let data, dimension, group; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { return d3.time.day.utc(d.dd); }); + dimension = data.dimension(d => d3.utcDay(d.dd)); group = dimension.group(); id = 'coordinate-grid-chart'; appendChartID(id); - chart = dc.lineChart('#' + id) + chart = new dc.LineChart(`#${id}`) .width(500) .height(150) .dimension(dimension) .group(group) .transitionDuration(0) + .transitionDelay(0) .brushOn(false) .margins({top: 20, bottom: 0, right: 10, left: 0}) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); }); - describe('rendering', function () { - beforeEach(function () { + describe('rendering', () => { + beforeEach(() => { chart.render(); }); - it('should create the svg', function () { + it('should create the svg', () => { expect(chart.svg().empty()).toBeFalsy(); }); - it('should create a root g', function () { + it('should create a root g', () => { expect(chart.g().empty()).toBeFalsy(); }); - it('should register the chart', function () { + it('should register the chart', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should set a dimension on the chart', function () { + it('should set a dimension on the chart', () => { expect(chart.dimension()).toBe(dimension); }); - it('should set a group on the chart', function () { + it('should set a group on the chart', () => { expect(chart.group()).toBe(group); }); - it('should set a width on the chart', function () { + it('should set a width on the chart', () => { expect(chart.width()).toBe(500); }); - it('should set a height on the chart', function () { + it('should set a height on the chart', () => { expect(chart.height()).toBe(150); }); - it('should use the height for the svg', function () { + it('should use the height for the svg', () => { expect(chart.select('svg').attr('height')).toBe('150'); }); - it('should have zero transition duration', function () { + it('should have zero transition duration', () => { expect(chart.transitionDuration()).toBe(0); }); - it('should set the margins of the chart', function () { + it('should have zero transition delay', () => { + expect(chart.transitionDelay()).toBe(0); + }); + + it('should set the margins of the chart', () => { expect(chart.margins()).not.toBeNull(); }); - it('should set an x domain', function () { + it('should set an x domain', () => { expect(chart.x()).toBeDefined(); }); - it('should set a y domain', function () { + it('should set a y domain', () => { expect(chart.y()).toBeDefined(); }); - it('should set the x domain to endpoint dates', function () { + it('should set the x domain to endpoint dates', () => { expect(chart.x().domain()).toEqual([makeDate(2012, 4, 20), makeDate(2012, 7, 15)]); }); - it('should create the brush', function () { + it('should create the brush', () => { expect(chart.select('g.brush')).not.toBeNull(); }); - it('should not set round by default', function () { + it('should not set round by default', () => { expect(chart.round()).not.toBeDefined(); }); - it('should auto-calculate x range round based on width', function () { + it('should auto-calculate x range round based on width', () => { expect(chart.x().range()[0]).toBe(0); expect(chart.x().range()[1]).toBe(490); }); - it('should auto-calculate y range round based on height', function () { + it('should auto-calculate y range round based on height', () => { expect(chart.y().range()[0]).toBe(130); expect(chart.y().range()[1]).toBe(0); }); - it('should auto-calculate y domain based on height', function () { + it('should auto-calculate y domain based on height', () => { expect(chart.y().domain()[0]).toBe(0); expect(chart.y().domain()[1]).toBe(3); }); - it('should be able to change round', function () { - chart.round(d3.time.day.utc.round); + it('should be able to change round', () => { + chart.round(d3.utcDay.round); expect(chart.round()).not.toBeNull(); }); - it('should have a default value for x', function () { + it('should have a default value for x', () => { expect(chart.keyAccessor()).not.toBeNull(); }); - it('should have a default value for y', function () { + it('should have a default value for y', () => { expect(chart.valueAccessor()).not.toBeNull(); }); - describe('renderlets', function () { - beforeEach(function () { - chart.on('renderlet', function (chart) { - chart.selectAll('path').attr('fill', 'red'); + describe('renderlets', () => { + beforeEach(() => { + chart.on('renderlet', _chart => { + _chart.selectAll('path').attr('fill', 'red'); }); }); - it('should not run immediately', function () { + it('should not run immediately', () => { expect(chart.selectAll('path').attr('fill')).not.toBe('red'); }); - it('should run when render is invoked', function () { + it('should run when render is invoked', () => { chart.render(); expect(chart.selectAll('path').attr('fill')).toBe('red'); }); - it('should run when redraw is invoked', function () { + it('should run when redraw is invoked', () => { chart.redraw(); expect(chart.selectAll('path').attr('fill')).toBe('red'); }); }); - describe('clip paths', function () { - it('should only create one def', function () { + describe('clip paths', () => { + it('should only create one def', () => { expect(chart.selectAll('defs').size()).toBe(1); }); - it('should only create one clip path', function () { + it('should only create one clip path', () => { // selecting on ID due to webkit bug #83438 expect(chart.selectAll('defs #coordinate-grid-chart-clip').size()).toBe(1); }); - it('should only create one clip rect', function () { + it('should only create one clip rect', () => { expect(chart.selectAll('defs #coordinate-grid-chart-clip rect').size()).toBe(1); }); - it('should create a clip rect based on the graph size', function () { - var rect = chart.select('defs #coordinate-grid-chart-clip rect'); + it('should create a clip rect based on the graph size', () => { + const rect = chart.select('defs #coordinate-grid-chart-clip rect'); expect(rect.attr('width')).toBe('490'); expect(rect.attr('height')).toBe('130'); }); - it('should translate the clip rect to 0,0', function () { - var rect = chart.select('defs #coordinate-grid-chart-clip rect'); - expect(rect.attr('transform')).toMatchTranslate(0,0); + it('should translate the clip rect to 0,0', () => { + const rect = chart.select('defs #coordinate-grid-chart-clip rect'); + expect(rect.attr('transform')).toMatchTranslate(0, 0); }); - it('should add clip path refs to the chart body', function () { + it('should add clip path refs to the chart body', () => { chart.selectAll('g.chart-body').each(function () { - expect(d3.select(this).attr('clip-path')).toMatchUrl(window.location.href + '#coordinate-grid-chart-clip'); + expect(d3.select(this).attr('clip-path')).toMatchUrl(`${window.location.href}#coordinate-grid-chart-clip`); }); }); - describe('setting clipPadding(20)', function () { + describe('setting clipPadding(20)', () => { - beforeEach(function () { + beforeEach(() => { chart.clipPadding(20); chart.render(); }); - it('should update the clip rect based on the graph size and clipPadding', function () { - var rect = chart.select('defs #coordinate-grid-chart-clip rect'); + it('should update the clip rect based on the graph size and clipPadding', () => { + const rect = chart.select('defs #coordinate-grid-chart-clip rect'); expect(rect.attr('width')).toBe('530'); expect(rect.attr('height')).toBe('170'); }); - it('should translate the clip rect to -20,-20', function () { - var rect = chart.select('defs #coordinate-grid-chart-clip rect'); - expect(rect.attr('transform')).toMatchTranslate(-20,-20); + it('should translate the clip rect to -20,-20', () => { + const rect = chart.select('defs #coordinate-grid-chart-clip rect'); + expect(rect.attr('transform')).toMatchTranslate(-20, -20); }); }); - describe('with a complex selector', function () { - beforeEach(function () { + describe('with a complex selector', () => { + beforeEach(() => { appendChartID('coordinate-grid').append('div').attr('class', 'chart'); - chart = dc.lineChart('#coordinate-grid .chart') + chart = new dc.LineChart('#coordinate-grid .chart') .width(500) .height(150) .dimension(dimension) .group(group) .transitionDuration(0) + .transitionDelay(0) .brushOn(false) .margins({top: 20, bottom: 0, right: 10, left: 0}) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.render(); }); - it('should generate a valid clippath id', function () { - var rect = chart.select('defs #coordinate-grid--chart-clip rect'); + it('should generate a valid clippath id', () => { + const rect = chart.select('defs #coordinate-grid--chart-clip rect'); expect(rect.empty()).toBeFalsy(); }); }); - describe('with a selector containing brackets', function () { - beforeEach(function () { - appendChartID('coordinate-grid').append('div').attr('class', 'chart').attr('foo', 'bar'); - chart = dc.lineChart('#coordinate-grid .chart[foo=bar]') + describe('with a selector containing brackets', () => { + beforeEach(() => { + appendChartID('coordinate-grid').append('div').attr('class', 'chart').attr('foo', '5bar'); + chart = new dc.LineChart('#coordinate-grid .chart[foo="5bar"]') .width(500) .height(150) .dimension(dimension) .group(group) .transitionDuration(0) + .transitionDelay(0) .brushOn(false) .margins({top: 20, bottom: 0, right: 10, left: 0}) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.render(); }); - it('should generate a valid clippath id', function () { - var rect = chart.select('defs #coordinate-grid--chart-foo-bar--clip rect'); + it('should generate a valid clippath id', () => { + const rect = chart.select('defs #coordinate-grid--chart-foo--5bar---clip rect'); expect(rect.empty()).toBeFalsy(); }); }); - describe('redrawing at a different size', function () { - beforeEach(function () { + describe('redrawing at a different size', () => { + beforeEach(() => { chart.width(300).height(400).redraw(); }); - it('should change the clippath to the new size', function () { - var rect = chart.select('defs #coordinate-grid-chart-clip rect'); + it('should change the clippath to the new size', () => { + const rect = chart.select('defs #coordinate-grid-chart-clip rect'); expect(rect.attr('width')).toBe('290'); expect(rect.attr('height')).toBe('380'); }); }); }); - describe('when an x function is not provided', function () { - it('should trigger a descriptive exception', function () { + describe('when an x function is not provided', () => { + it('should trigger a descriptive exception', () => { try { - dc.coordinateGridChart({}).group({}).dimension({}).render(); + new dc.CoordinateGridMixin().group({}).dimension({}).render(); expect('exception').toBe('thrown'); } catch (e) { - expect(e instanceof dc.errors.InvalidStateException).toBeTruthy(); + expect(e instanceof dc.InvalidStateException).toBeTruthy(); expect(e.message).toMatch(/Mandatory attribute chart.x is missing on chart\[#.+\]/); } }); }); - describe('x-axis', function () { - it('should place an x axis at the bottom', function () { - expect(chart.select('g.x').attr('transform')).toMatchTranslate(0,150); + describe('x-axis', () => { + it('should place an x axis at the bottom', () => { + expect(chart.select('g.x').attr('transform')).toMatchTranslate(0, 150); }); - it('should update x axis position when the chart height is changed', function () { + it('should update x axis position when the chart height is changed', () => { chart.elasticX(true).height(400).redraw(); - expect(chart.select('g.x').attr('transform')).toMatchTranslate(0,400); + expect(chart.select('g.x').attr('transform')).toMatchTranslate(0, 400); }); - describe('labels', function () { - beforeEach(function () { + describe('labels', () => { + beforeEach(() => { expect(chart.effectiveHeight()).toBe(130); chart.xAxisLabel('X Label').render(); }); - it('should set the x-axis label', function () { + it('should set the x-axis label', () => { expect(chart.selectAll('text.x-axis-label').text()).toBe('X Label'); }); - it('should adjust the chart height accordingly due to label padding', function () { + it('should adjust the chart height accordingly due to label padding', () => { expect(chart.effectiveHeight()).toBe(118); }); - describe('with custom padding', function () { - beforeEach(function () { + describe('with custom padding', () => { + beforeEach(() => { chart.xAxisLabel('Custom X Label', 50).render(); }); - it('should adjust the chart height with respect to the custom padding', function () { + it('should adjust the chart height with respect to the custom padding', () => { expect(chart.effectiveHeight()).toBe(80); }); }); - describe('reset axis label', function () { - beforeEach(function () { + describe('reset axis label', () => { + beforeEach(() => { chart.elasticX(true).xAxisLabel('New X Label').redraw(); }); - it('should change the x-axis label', function () { + it('should change the x-axis label', () => { expect(chart.selectAll('text.x-axis-label').text()).toBe('New X Label'); }); }); }); }); - describe('y-axes', function () { - describe('grid lines', function () { - beforeEach(function () { + describe('y-axes', () => { + describe('grid lines', () => { + beforeEach(() => { + // The calculations have changed internally for tick count from D3v3 to D3v4 + // By default it guesses 10 ticks and computes from there. In v3 it ends up with 7 in v4 + // it is 16. For 9 as well as 11 both the versions agree. + chart.yAxis().ticks(9); chart .renderHorizontalGridLines(true) .renderVerticalGridLines(true) + .transitionDuration(300) .render(); }); - describe('horizontal grid lines', function () { - it('should draw lines associated with the data shown on the right y-axis', function () { - var nthGridLine = function (n) { return d3.select(chart.selectAll('.grid-line.horizontal line')[0][n]); }; + describe('horizontal grid lines', () => { + it('should draw lines associated with the data shown on the y-axis', () => { + const nthGridLine = function (n) { + return d3.select(chart.selectAll('.grid-line.horizontal line').nodes()[n]); + }; expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(7); expect(nthGridLine(0).attr('y2')).toBe('130'); @@ -317,21 +331,23 @@ describe('dc.coordinateGridChart', function () { expect(nthGridLine(2).attr('y1')).toBe('87'); }); - it('should position the lines horizontally on the graph', function () { - var firstGridLine = chart.select('.grid-line.horizontal line'); + it('should position the lines horizontally on the graph', () => { + const firstGridLine = chart.select('.grid-line.horizontal line'); expect(firstGridLine.attr('x1')).toBe('1'); expect(firstGridLine.attr('x2')).toBe('490'); expect(firstGridLine.attr('y1')).toBe(firstGridLine.attr('y2')); }); - describe('with custom tick values', function () { - beforeEach(function () { + describe('with custom tick values', () => { + beforeEach(() => { chart.yAxis().tickValues([0, 1, 2]); chart.render(); }); - it('should draws lines associated with the data using the custom ticks', function () { - var nthGridLine = function (n) { return d3.select(chart.selectAll('.grid-line.horizontal line')[0][n]); }; + it('should draws lines associated with the data using the custom ticks', () => { + const nthGridLine = function (n) { + return d3.select(chart.selectAll('.grid-line.horizontal line').nodes()[n]); + }; expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(3); expect(nthGridLine(0).attr('y2')).toBe('130'); @@ -340,11 +356,29 @@ describe('dc.coordinateGridChart', function () { expect(nthGridLine(2).attr('y1')).toBe('43'); }); }); + + describe('after renderlet', () => { + let opacityValue; + beforeEach(done => { + chart.on('renderlet', _chart => { + opacityValue = _chart.select('.grid-line.horizontal line').attr('opacity'); + + done(); + }); + }); + + it('should have 0.5 opacity', () => { + expect(opacityValue).toBe('0.5'); + }); + }); + }); - describe('vertical grid lines', function () { - it('should draw lines associated with the data shown on the x-axis', function () { - var nthGridLine = function (n) { return d3.select(chart.selectAll('.grid-line.vertical line')[0][n]); }; + describe('vertical grid lines', () => { + it('should draw lines associated with the data shown on the x-axis', () => { + const nthGridLine = function (n) { + return d3.select(chart.selectAll('.grid-line.vertical line').nodes()[n]); + }; expect(chart.selectAll('.grid-line.vertical line').size()).toBe(13); expect(nthGridLine(0).attr('x2')).toBe('0'); @@ -353,21 +387,23 @@ describe('dc.coordinateGridChart', function () { expect(nthGridLine(2).attr('x1')).toBeWithinDelta(79, 1); }); - it('should position the lines vertically on the graph', function () { - var firstGridLine = chart.select('.grid-line.vertical line'); + it('should position the lines vertically on the graph', () => { + const firstGridLine = chart.select('.grid-line.vertical line'); expect(firstGridLine.attr('y1')).toBe('130'); expect(firstGridLine.attr('y2')).toBe('0'); expect(firstGridLine.attr('x1')).toBe(firstGridLine.attr('x2')); }); - describe('with custom tick values', function () { - beforeEach(function () { + describe('with custom tick values', () => { + beforeEach(() => { chart.xAxis().tickValues([makeDate(2012, 4, 21), makeDate(2012, 5, 20), makeDate(2012, 6, 1)]); chart.render(); }); - it('should draw lines associated with the data using the custom ticks', function () { - var nthGridLine = function (n) { return d3.select(chart.selectAll('.grid-line.vertical line')[0][n]); }; + it('should draw lines associated with the data using the custom ticks', () => { + const nthGridLine = function (n) { + return d3.select(chart.selectAll('.grid-line.vertical line').nodes()[n]); + }; expect(chart.selectAll('.grid-line.vertical line').size()).toBe(3); expect(nthGridLine(0).attr('x2')).toBeWithinDelta(6, 1); @@ -377,107 +413,124 @@ describe('dc.coordinateGridChart', function () { }); }); - describe('with an ordinal x axis', function () { - beforeEach(function () { - chart.x(d3.scale.ordinal()) + describe('with an ordinal x axis', () => { + beforeEach(() => { + chart.x(d3.scaleBand()) .xUnits(dc.units.ordinal) .render(); }); - it('should render without errors', function () { + it('should render without errors', () => { expect(chart.selectAll('.grid-line.vertical line').size()).toBe(6); }); }); + + describe('after renderlet', () => { + let opacityValue; + beforeEach(done => { + chart.on('renderlet', _chart => { + opacityValue = _chart.select('.grid-line.vertical line').attr('opacity'); + + done(); + }); + }); + + it('should have 0.5 opacity', () => { + expect(opacityValue).toBe('0.5'); + }); + }); }); }); - describe('a left y-axis', function () { - beforeEach(function () { + describe('a left y-axis', () => { + beforeEach(() => { chart.render(); }); - it('should render a y-axis', function () { + it('should render a y-axis', () => { expect(chart.selectAll('.axis.y').size()).toBe(1); }); - it('should orient the y-axis text to the left by default', function () { + // can't determine axis orientation in D3v4+, see d3/d3-axis#16 + /*it('should orient the y-axis text to the left by default', function () { expect(chart.yAxis().orient()).toBe('left'); - }); + });*/ - it('should place the y axis to the left', function () { - expect(chart.select('g.y').attr('transform')).toMatchTranslate(0,20); + it('should place the y axis to the left', () => { + expect(chart.select('g.y').attr('transform')).toMatchTranslate(0, 20); }); - describe('y-axis labels', function () { - beforeEach(function () { + describe('y-axis labels', () => { + beforeEach(() => { expect(chart.effectiveWidth()).toBe(490); chart.yAxisLabel('The Y Axis Label').render(); }); - it('should display provided label text', function () { + it('should display provided label text', () => { expect(chart.selectAll('text.y-axis-label.y-label').text()).toBe('The Y Axis Label'); }); - it('should change the effective width of the chart due to padding', function () { + it('should change the effective width of the chart due to padding', () => { expect(chart.effectiveWidth()).toBe(478); }); - it('should position the label to the left of the chart', function () { - expect(chart.selectAll('text.y-axis-label.y-label').attr('transform')).toMatchTransRot(12,85,-90); + it('should position the label to the left of the chart', () => { + expect(chart.selectAll('text.y-axis-label.y-label').attr('transform')).toMatchTransRot(12, 85, -90); }); - describe('with custom padding', function () { - beforeEach(function () { + describe('with custom padding', () => { + beforeEach(() => { chart.yAxisLabel('Custom Y Label', 50).render(); }); - it('should adjust the chart height with respect to the custom padding', function () { + it('should adjust the chart height with respect to the custom padding', () => { expect(chart.effectiveWidth()).toBe(440); }); }); }); }); - describe('a right y-axis', function () { - beforeEach(function () { + describe('a right y-axis', () => { + beforeEach(() => { chart.useRightYAxis(true).render(); }); - it('should render a y-axis', function () { + it('should render a y-axis', () => { expect(chart.selectAll('.axis.y').size()).toBe(1); }); - it('should orient the y-axis text to the right', function () { + // can't determine axis orientation in D3v4+, see d3/d3-axis#16 + /*it('should orient the y-axis text to the right', function () { expect(chart.yAxis().orient()).toBe('right'); - }); + });*/ - it('should position the axis to the right of the chart', function () { - expect(chart.select('.axis.y').attr('transform')).toMatchTranslate(490,20); + it('should position the axis to the right of the chart', () => { + expect(chart.select('.axis.y').attr('transform')).toMatchTranslate(490, 20); }); - describe('y-axis labels', function () { - beforeEach(function () { + describe('y-axis labels', () => { + beforeEach(() => { expect(chart.effectiveWidth()).toBe(490); chart.yAxisLabel('Right Y Axis Label').render(); }); - it('should display provided label text', function () { + it('should display provided label text', () => { expect(chart.selectAll('text.y-axis-label.y-label').text()).toBe('Right Y Axis Label'); }); - it('should change the effective width of the chart due to padding', function () { + it('should change the effective width of the chart due to padding', () => { expect(chart.effectiveWidth()).toBe(478); }); - it('should position the label to the right of the chart', function () { - expect(chart.selectAll('text.y-axis-label.y-label').attr('transform')).toMatchTransRot(488,85,90); + it('should position the label to the right of the chart', () => { + expect(chart.selectAll('text.y-axis-label.y-label').attr('transform')).toMatchTransRot(488, 85, 90); }); - describe('with custom padding', function () { - beforeEach(function () { + describe('with custom padding', () => { + beforeEach(() => { chart.yAxisLabel('Custom Y Label', 50).render(); }); - it('should adjust the chart height with respect to the custom padding', function () { + it('should adjust the chart height with respect to the custom padding', () => { expect(chart.effectiveWidth()).toBe(440); }); }); @@ -486,35 +539,31 @@ describe('dc.coordinateGridChart', function () { }); }); - describe('elastic axis', function () { - describe('with data', function () { - beforeEach(function () { - data.dimension(function (d) { - return d.countrycode; - }).filter('CA'); + describe('elastic axis', () => { + describe('with data', () => { + beforeEach(() => { + data.dimension(d => d.countrycode).filter('CA'); chart.elasticX(true).elasticY(true).render(); }); - it('should shrink the y axis', function () { + it('should shrink the y axis', () => { expect(chart.y().domain()[1]).toBe(1); }); - it('should shrink the x domain', function () { + it('should shrink the x domain', () => { expect(chart.x().domain()).toEqual([makeDate(2012, 4, 25), makeDate(2012, 7, 10)]); }); }); - describe('with no data', function () { - beforeEach(function () { - data.dimension(function (d) { - return d.countrycode; - }).filter('INVALID CODE'); + describe('with no data', () => { + beforeEach(() => { + data.dimension(d => d.countrycode).filter('INVALID CODE'); chart.elasticX(true).elasticY(true).render(); }); - it('should set y-axis to be empty', function () { + it('should set y-axis to be empty', () => { expect(chart.y().domain()[0]).toBe(0); expect(chart.y().domain()[1]).toBe(0); }); @@ -522,147 +571,135 @@ describe('dc.coordinateGridChart', function () { }); }); - describe('rescaling', function () { - var originalUnitCount; - beforeEach(function () { + describe('rescaling', () => { + let originalUnitCount; + beforeEach(() => { + expect(chart.resizing()).toBe(true); chart.render(); + expect(chart.resizing()).toBe(false); + originalUnitCount = chart.xUnitCount(); chart.x().domain([makeDate(2012, 4, 20), makeDate(2012, 6, 15)]); chart.rescale(); }); - it('should reset x unit count to reflect updated x domain', function () { + it('should reset x unit count to reflect updated x domain', () => { expect(chart.xUnitCount()).not.toEqual(originalUnitCount); }); + + it('should be resizing until render', () => { + expect(chart.resizing()).toBe(true); + chart.render(); + expect(chart.resizing()).toBe(false); + }); }); - describe('range chart setup', function () { - var rangeChart; + describe('range chart setup', () => { + let rangeChart; - beforeEach(function () { + beforeEach(() => { rangeChart = buildRangeChart(); chart.rangeChart(rangeChart); chart.render(); rangeChart.render(); }); - it('should set our chart as range chart\'s focus chart', function () { + it('should set our chart as range chart\'s focus chart', () => { expect(chart.rangeChart().focusChart()).toEqual(chart); }); }); - describe('restricting zoom out', function () { - beforeEach(function () { - chart.zoomScale([-1,10]); - chart.zoomOutRestrict(true); - }); - - it('should set the start of zoom scale extent to 1', function () { - expect(chart.zoomScale()[0]).toEqual(1); - }); - - it('sohuld leave the end of zoom scale extent unchanged', function () { - expect(chart.zoomScale()[1]).toEqual(10); - }); - }); - - describe('disabling zoom out restriction', function () { - beforeEach(function () { - chart.zoomScale([-1,10]); - chart.zoomOutRestrict(false); - }); - - it('should set the start of zoom scale extent to 0', function () { - expect(chart.zoomScale()[0]).toEqual(0); - }); - }); - - describe('setting x', function () { - var newDomain = [1,10]; - beforeEach(function () { - chart.x(d3.scale.linear().domain(newDomain)); + describe('setting x', () => { + const newDomain = [1, 10]; + beforeEach(() => { + chart.x(d3.scaleLinear().domain(newDomain)); }); - it('should reset the original x domain', function () { + it('should reset the original x domain', () => { expect(chart.xOriginalDomain()).toEqual(newDomain); }); }); - describe('x unit count', function () { - it('reflects number of units in chart domain', function () { - var domain = chart.x().domain(); + describe('x unit count', () => { + it('reflects number of units in chart domain', () => { + const domain = chart.x().domain(); expect(chart.xUnitCount()).toEqual(dc.units.integers(domain[0], domain[1], domain)); }); - describe('with fixed units', function () { - beforeEach(function () { - chart.xUnits(function (start, end, xDomain) { return 10; }); + describe('with fixed units', () => { + beforeEach(() => { + chart.xUnits((start, end, xDomain) => 10); }); - it('should return the fixed unit count', function () { + it('should return the fixed unit count', () => { expect(chart.xUnitCount()).toEqual(10); }); }); }); - describe('ordinality flag', function () { - describe('when x units are not ordinal', function () { - it('should be false', function () { + describe('ordinality flag', () => { + describe('when x units are not ordinal', () => { + it('should be false', () => { expect(chart.isOrdinal()).toBeFalsy(); }); }); - describe('when x units are ordinal', function () { - beforeEach(function () { + describe('when x units are ordinal', () => { + beforeEach(() => { chart.xUnits(dc.units.ordinal); }); - it('should be true', function () { + it('should be true', () => { expect(chart.isOrdinal()).toBeTruthy(); }); }); }); - describe('applying a filter', function () { - var filter = [makeDate(2012, 5, 20), makeDate(2012, 6, 15)]; - beforeEach(function () { + describe('applying a filter', () => { + const filter = [makeDate(2012, 5, 20), makeDate(2012, 6, 15)]; + beforeEach(() => { chart.brushOn(true); chart.render(); chart.filter(filter); }); - it('should update the brush extent', function () { - expect(chart.brush().extent()).toEqual(filter); + it('should update the brush selection', () => { + // expect(chart.getBrushSelection()).toEqual(filter); + const brushSelectionRect = chart.select('g.brush rect.selection'); + expect(brushSelectionRect.attr('x')).toBeCloseTo(chart.x()(filter[0]), 1); + expect((+brushSelectionRect.attr('x')) + (+brushSelectionRect.attr('width'))) + .toBeCloseTo(chart.x()(filter[1]), 1); }); }); - describe('removing the filter', function () { - beforeEach(function () { + describe('removing the filter', () => { + beforeEach(() => { chart.brushOn(true); chart.render(); - chart.brush().extent([makeDate(2012, 5, 20), makeDate(2012, 6, 15)]); + simulateChartBrushing(chart, [makeDate(2012, 5, 20), makeDate(2012, 6, 15)]); chart.filter(null); }); - it('should clear the brush extent', function () { - expect(chart.brush().empty()).toBeTruthy(); + it('should clear the brush selection', () => { + const brushSelectionRect = chart.select('g.brush rect.selection'); + expect(+brushSelectionRect.attr('width')).toEqual(0); }); }); - describe('rendering for the first time with mouse zoom disabled when it wasn\'t previously enabled', function () { - beforeEach(function () { + describe('rendering for the first time with mouse zoom disabled when it wasn\'t previously enabled', () => { + beforeEach(() => { chart.mouseZoomable(false); spyOn(chart, '_disableMouseZoom'); chart.render(); }); - it('should not explicitly disable mouse zooming', function () { + it('should not explicitly disable mouse zooming', () => { expect(chart._disableMouseZoom).not.toHaveBeenCalled(); }); }); - describe('rendering with mouse zoom disabled after it was previously enabled', function () { - beforeEach(function () { + describe('rendering with mouse zoom disabled after it was previously enabled', () => { + beforeEach(() => { chart.mouseZoomable(true); chart.render(); chart.mouseZoomable(false); @@ -670,29 +707,29 @@ describe('dc.coordinateGridChart', function () { chart.render(); }); - it('should explicitly disable mouse zooming', function () { + it('should explicitly disable mouse zooming', () => { expect(chart._disableMouseZoom).toHaveBeenCalled(); }); }); - describe('with mouse zoom disabled', function () { - beforeEach(function () { + describe('with mouse zoom disabled', () => { + beforeEach(() => { chart.mouseZoomable(false); chart.render(); }); - it('should not respond to double-click by refocusing', function () { + it('should not respond to double-click by refocusing', () => { doubleClick(chart); expect(chart.refocused()).toBeFalsy(); }); }); - describe('zooming', function () { - var rangeChart, zoomCallback, context; + describe('zooming', () => { + let rangeChart, zoomCallback; - context = function () { return {chart: chart, zoomCallback: zoomCallback}; }; + const context = function () { return {chart: chart, zoomCallback: zoomCallback}; }; - beforeEach(function () { + beforeEach(() => { zoomCallback = jasmine.createSpy(); chart.on('zoomed', zoomCallback); chart.mouseZoomable(true); @@ -701,160 +738,136 @@ describe('dc.coordinateGridChart', function () { chart.render(); rangeChart.render(); - spyOn(dc, 'redrawAll'); spyOn(chart, 'redraw'); spyOn(rangeChart, 'redraw'); }); - describe('when chart is zoomed via mouse interaction', function () { - beforeEach(function () { + describe('when chart is zoomed via mouse interaction', () => { + beforeEach(() => { doubleClick(chart); }); itActsLikeItZoomed(context); }); - describe('when chart is zoomed programatically via focus method', function () { - beforeEach(function () { + describe('when chart is zoomed programatically via focus method', () => { + beforeEach(() => { chart.focus([makeDate(2012, 5, 1), makeDate(2012, 5, 15)]); }); itActsLikeItZoomed(context); }); - function itActsLikeItZoomed (context) { - describe('(shared things that happen on zooming)', function () { - var chart, zoomCallback; - beforeEach(function () { - chart = context().chart; - zoomCallback = context().zoomCallback; + function itActsLikeItZoomed (ctx) { + describe('(shared things that happen on zooming)', () => { + let _chart, _zoomCallback; + beforeEach(() => { + _chart = ctx().chart; + _zoomCallback = ctx().zoomCallback; }); - it('should be flagged as refocused', function () { - expect(chart.refocused()).toBeTruthy(); + it('should be flagged as refocused', () => { + expect(_chart.refocused()).toBeTruthy(); }); - it('should update chart filter to match new x domain', function () { - var filter = cleanDateRange(chart.filter()); - expect(filter).toEqual(chart.x().domain()); + it('should update chart filter to match new x domain', () => { + const filter = cleanDateRange(_chart.filter()); + expect(filter).toEqual(_chart.x().domain()); }); - it('should be rescaled', function () { - var domain = chart.x().domain(); - expect(chart.xUnitCount()).toEqual(dc.units.integers(domain[0], domain[1], domain)); + it('should be rescaled', () => { + const domain = _chart.x().domain(); + expect(_chart.xUnitCount()).toEqual(dc.units.integers(domain[0], domain[1], domain)); }); - it('should redraw itself', function () { - expect(chart.redraw).toHaveBeenCalled(); + it('should redraw itself', () => { + expect(_chart.redraw).toHaveBeenCalled(); }); - it('should update its range chart\'s filter', function () { - expect(chart.rangeChart().filter()).toEqual(chart.filter()); + it('should update its range chart\'s filter', () => { + expect(dc.utils.arraysEqual(_chart.rangeChart().filter(), _chart.filter())).toEqual(true); }); - it('should trigger redraw on its range chart', function () { - expect(chart.rangeChart().redraw).toHaveBeenCalled(); + it('should trigger redraw on its range chart', () => { + expect(_chart.rangeChart().redraw).toHaveBeenCalled(); }); - it('should fire custom zoom listeners', function () { - expect(zoomCallback).toHaveBeenCalled(); + it('should fire custom zoom listeners', () => { + expect(_zoomCallback).toHaveBeenCalled(); }); - it('should trigger redraw on other charts in group after a brief pause', function () { - jasmine.clock().tick(100); - expect(dc.redrawAll).toHaveBeenCalledWith(chart.chartGroup()); - }); }); } }); - describe('when chart is zoomed in, then zoomed back out to original domain', function () { - beforeEach(function () { + describe('when chart is zoomed in, then zoomed back out to original domain', () => { + beforeEach(() => { chart.render(); doubleClick(chart); chart.focus(chart.xOriginalDomain()); }); - it('should not be flagged as refocused', function () { + it('should not be flagged as refocused', () => { expect(chart.refocused()).toBeFalsy(); }); }); - describe('brushing', function () { - beforeEach(function () { + describe('brushing', () => { + beforeEach(() => { chart.brushOn(true); + chart.render(); }); - describe('with mouse zoom enabled', function () { - beforeEach(function () { - spyOn(chart, '_disableMouseZoom'); - spyOn(chart, '_enableMouseZoom'); - chart.mouseZoomable(true); - chart.render(); - chart.brush().extent([makeDate(2012, 6, 1), makeDate(2012, 6, 15)]); - chart.brush().event(chart.root()); - }); - - it('should disable mouse zooming on brush start, and re-enables it afterwards', function () { - chart.brush().extent([makeDate(2012, 6, 1), makeDate(2012, 6, 15)]); - chart.brush().event(chart.root()); - expect(chart._disableMouseZoom).toHaveBeenCalled(); - expect(chart._enableMouseZoom).toHaveBeenCalled(); - }); - }); - - describe('with mouse zoom disabled', function () { - beforeEach(function () { - spyOn(chart, '_enableMouseZoom'); - chart.mouseZoomable(false); - chart.render(); - chart.brush().extent([makeDate(2012, 6, 1), makeDate(2012, 6, 15)]); - chart.brush().event(chart.root()); - }); - - it('should not enable mouse zooming', function () { - expect(chart._enableMouseZoom).not.toHaveBeenCalled(); - }); - }); - - describe('with equal dates', function () { - beforeEach(function () { - spyOn(chart, 'filter'); - chart.brush().clear(); - chart.render(); - chart.brush().event(chart.root()); + describe('with equal dates', () => { + beforeEach(() => { + simulateChartBrushing(chart, [22, 22]); }); - it('should clear the chart filter', function () { - expect(chart.filter()).toEqual(undefined); + it('should clear the chart filter', () => { + expect(chart.filter()).toBeFalsy(); }); }); }); - describe('with a range chart', function () { - var rangeChart; - var selectedRange = [makeDate(2012, 6, 1), makeDate(2012, 6, 15)]; + describe('with a range chart', () => { + let rangeChart; + const selectedRange = [makeDate(2012, 6, 1), makeDate(2012, 6, 15)]; - beforeEach(function () { + beforeEach(() => { rangeChart = buildRangeChart(); chart.rangeChart(rangeChart); chart.render(); rangeChart.render(); }); - it('should zoom the focus chart when range chart is brushed', function () { + it('range filter should execute filtered listener and zoom focus chart', () => { + spyOn(chart, 'focus').and.callThrough(); + const expectedCallbackSignature = function (callbackChart, callbackFilter) { + expect(callbackChart).toBe(rangeChart); + expect(callbackFilter).toEqual(selectedRange); + }; + const filteredCallback = jasmine.createSpy().and.callFake(expectedCallbackSignature); + rangeChart.on('filtered', filteredCallback); + expect(filteredCallback).not.toHaveBeenCalled(); + + rangeChart.filter(selectedRange); + expect(filteredCallback).toHaveBeenCalled(); + + expect(chart.focus).toHaveBeenCalled(); + const focus = cleanDateRange(chart.focus.calls.argsFor(0)[0]); + expect(focus).toEqual(selectedRange); + }); + + it('should zoom the focus chart when range chart is brushed', () => { spyOn(chart, 'focus').and.callThrough(); - rangeChart.brush().extent(selectedRange); - rangeChart.brush().event(rangeChart.g()); + simulateChartBrushing(rangeChart, selectedRange); jasmine.clock().tick(100); - // expect(chart.focus).toHaveBeenCalledWith(selectedRange); - var focus = cleanDateRange(chart.focus.calls.argsFor(0)[0]); + const focus = cleanDateRange(chart.focus.calls.argsFor(0)[0]); expect(focus).toEqual(selectedRange); }); - it('should zoom the focus chart back out when range chart is un-brushed', function () { - rangeChart.brush().extent(selectedRange); - rangeChart.brush().event(rangeChart.g()); + it('should zoom the focus chart back out when range chart is un-brushed', () => { + simulateChartBrushing(rangeChart, selectedRange); jasmine.clock().tick(100); expect(chart.x().domain()).toEqual(selectedRange); @@ -863,100 +876,99 @@ describe('dc.coordinateGridChart', function () { expect(rangeChart.x().domain()).toEqual(rangeChart.xOriginalDomain()); }); - it('should update the range chart brush to match zoomed domain of focus chart', function () { + it('should update the range chart brush to match zoomed domain of focus chart', () => { spyOn(rangeChart, 'replaceFilter'); chart.focus(selectedRange); - // expect(rangeChart.replaceFilter).toHaveBeenCalledWith(selectedRange); - var replaceFilter = cleanDateRange(rangeChart.replaceFilter.calls.argsFor(0)[0]); + const replaceFilter = cleanDateRange(rangeChart.replaceFilter.calls.argsFor(0)[0]); expect(replaceFilter).toEqual(selectedRange); }); }); - describe('with zoom restriction enabled', function () { - beforeEach(function () { + describe('with zoom restriction enabled', () => { + beforeEach(() => { chart.zoomOutRestrict(true); chart.render(); chart.focus([makeDate(2012, 8, 20), makeDate(2012, 8, 25)]); }); - it('should not be able to zoom out past its original x domain', function () { + it('should not be able to zoom out past its original x domain', () => { chart.focus([makeDate(2012, 2, 20), makeDate(2012, 9, 15)]); expect(chart.x().domain()).toEqual(chart.xOriginalDomain()); }); - describe('with a range chart', function () { - beforeEach(function () { - var rangeChart = buildRangeChart(); + describe('with a range chart', () => { + beforeEach(() => { + const rangeChart = buildRangeChart(); chart.rangeChart(rangeChart); chart.render(); rangeChart.render(); chart.focus([makeDate(2012, 8, 20), makeDate(2012, 8, 25)]); }); - it('should not be able to zoom out past its range chart origin x domain', function () { + it('should not be able to zoom out past its range chart origin x domain', () => { chart.focus([makeDate(2012, 2, 20), makeDate(2012, 9, 15)]); expect(chart.x().domain()).toEqual(chart.rangeChart().xOriginalDomain()); }); }); }); - describe('with zoom restriction disabled', function () { - beforeEach(function () { + describe('with zoom restriction disabled', () => { + beforeEach(() => { chart.zoomOutRestrict(false); chart.render(); chart.focus([makeDate(2012, 8, 20), makeDate(2012, 8, 25)]); }); - it('should be able to zoom out past its original x domain', function () { + it('should be able to zoom out past its original x domain', () => { chart.focus([makeDate(2012, 2, 20), makeDate(2012, 9, 15)]); chart.render(); expect(chart.x().domain()).toEqual([makeDate(2012, 2, 20), makeDate(2012, 9, 15)]); }); }); - describe('focus', function () { - beforeEach(function () { + describe('focus', () => { + beforeEach(() => { chart.render(); }); - describe('when called with a range argument', function () { - var focusDomain = [makeDate(2012,5,20), makeDate(2012,5,30)]; + describe('when called with a range argument', () => { + const focusDomain = [makeDate(2012, 5, 20), makeDate(2012, 5, 30)]; - beforeEach(function () { + beforeEach(() => { chart.focus(focusDomain); }); - it('should update the x domain to match specified domain', function () { + it('should update the x domain to match specified domain', () => { expect(chart.x().domain()).toEqual(focusDomain); }); }); - describe('when called with no arguments', function () { - beforeEach(function () { - chart.focus([makeDate(2012,5,1), makeDate(2012,5,2)]); + describe('when called with no arguments', () => { + beforeEach(() => { + chart.focus([makeDate(2012, 5, 1), makeDate(2012, 5, 2)]); chart.focus(); }); - it('should revert the x domain to the original domain', function () { + it('should revert the x domain to the original domain', () => { expect(chart.x().domain()).toEqual(chart.xOriginalDomain()); }); }); }); function buildRangeChart () { - var rangeId = 'range-chart'; + const rangeId = 'range-chart'; appendChartID(rangeId); - return dc.lineChart('#' + rangeId) + return new dc.LineChart(`#${rangeId}`) .dimension(dimension) - .group(dimension.group().reduceSum(function (d) { return d.id; })) - .x(d3.time.scale.utc().domain([makeDate(2012, 5, 20), makeDate(2012, 6, 15)])); + .group(dimension.group().reduceSum(d => d.id)) + .x(d3.scaleUtc().domain([makeDate(2012, 5, 20), makeDate(2012, 6, 15)])); } - function doubleClick (chart) { - var centerX = chart.root().node().clientLeft + (chart.width() / 2); - var centerY = chart.root().node().clientTop + (chart.height() / 2); - var event = document.createEvent('MouseEvents'); + function doubleClick (_chart) { + const centerX = _chart.root().node().clientLeft + (_chart.width() / 2); + const centerY = _chart.root().node().clientTop + (_chart.height() / 2); + const event = document.createEvent('MouseEvents'); event.initMouseEvent('dblclick', true, true, window, centerX, centerY, centerX, centerY, 0, false, false, false, false, 0, null); - chart.root().node().dispatchEvent(event); + _chart.root().node().dispatchEvent(event); } }); diff --git a/spec/core-spec.js b/spec/core-spec.js index 85a6889b13..e9750f3c8d 100644 --- a/spec/core-spec.js +++ b/spec/core-spec.js @@ -1,31 +1,29 @@ /* global loadDateFixture */ -describe('dc.core', function () { - var valueDimension, valueGroup; +describe('dc.core', () => { + let valueDimension, valueGroup; - beforeEach(function () { - var data = crossfilter(loadDateFixture()); - valueDimension = data.dimension(function (d) { - return d.value; - }); + beforeEach(() => { + const data = crossfilter(loadDateFixture()); + valueDimension = data.dimension(d => d.value); valueGroup = valueDimension.group(); }); - describe('version', function () { - it('should use semantic versions', function () { + describe('version', () => { + it('should use semantic versions', () => { // from https://raw.github.com/coolaj86/semver-utils/v1.0.3/semver-utils.js // |optional 'v' // | | 3 segment version // | | |optional release prefixed by '-' // | | | |optional build prefixed by '+' - var reSemver = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/; + const reSemver = /^v?((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/; expect(dc.version).toMatch(reSemver); }); }); - describe('charts', function () { - var chart; - beforeEach(function () { - chart = dc.pieChart('#id') + describe('charts', () => { + let chart; + beforeEach(() => { + chart = new dc.PieChart('#id') .dimension(valueDimension) .group(valueGroup); spyOn(chart, 'filterAll'); @@ -34,62 +32,62 @@ describe('dc.core', function () { return chart; }); - it('should register chart object', function () { + it('should register chart object', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('filterAll should invoke filter on each chart', function () { + it('filterAll should invoke filter on each chart', () => { dc.filterAll(); expect(chart.filterAll).toHaveBeenCalled(); }); - it('renderAll should invoke filter on each chart', function () { + it('renderAll should invoke filter on each chart', () => { dc.renderAll(); expect(chart.render).toHaveBeenCalled(); }); - it('should be gone after remove all', function () { + it('should be gone after remove all', () => { dc.deregisterAllCharts(); expect(dc.hasChart(chart)).toBeFalsy(); }); }); - describe('chartsRegistry', function () { - var chart; - var chartGrouped; - var chartGroup = 'testChartGroup'; - beforeEach(function () { - chart = dc.pieChart('#id') + describe('chartsRegistry', () => { + let chart; + let chartGrouped; + const chartGroup = 'testChartGroup'; + beforeEach(() => { + chart = new dc.PieChart('#id') .dimension(valueDimension) .group(valueGroup); - chartGrouped = dc.pieChart('#id2',chartGroup) + chartGrouped = new dc.PieChart('#id2', chartGroup) .dimension(valueDimension) .group(valueGroup); return chart; }); - it('should register chart object', function () { + it('should register chart object', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should not have ungrouped chart after remove', function () { + it('should not have ungrouped chart after remove', () => { dc.deregisterChart(chart); expect(dc.hasChart(chart)).toBeFalsy(); }); - it('should not have grouped chart after remove', function () { + it('should not have grouped chart after remove', () => { dc.deregisterChart(chartGrouped, chartGroup); expect(dc.hasChart(chartGrouped)).toBeFalsy(); }); - it('should have switched to an existing group', function () { + it('should have switched to an existing group', () => { chart.chartGroup(chartGroup); expect(dc.hasChart(chart)).toBeTruthy(); expect(dc.chartRegistry.list(chartGroup).indexOf(chart) > -1).toBeTruthy(); expect(dc.chartRegistry.list(null).indexOf(chart) > -1).toBeFalsy(); }); - it('should have switched to the global group', function () { + it('should have switched to the global group', () => { chart.chartGroup(null); expect(dc.hasChart(chart)).toBeTruthy(); expect(dc.chartRegistry.list(chartGroup).indexOf(chart) > -1).toBeFalsy(); @@ -97,203 +95,175 @@ describe('dc.core', function () { }); }); - describe('transition', function () { - var selections; + describe('transition', () => { + let selections; - beforeEach(function () { + beforeEach(() => { selections = { transition: function () { return this; }, duration: function () { return this; + }, + delay: function () { + return this; } }; spyOn(selections, 'transition').and.callThrough(); spyOn(selections, 'duration').and.callThrough(); + spyOn(selections, 'delay').and.callThrough(); }); - describe('normal', function () { - it('transition should be activated with duration', function () { - dc.transition(selections, 100); + describe('normal', () => { + it('transition should be activated with duration', () => { + dc.transition(selections, 100, 100); expect(selections.transition).toHaveBeenCalled(); expect(selections.duration).toHaveBeenCalled(); + expect(selections.delay).toHaveBeenCalled(); + expect(selections.duration).toHaveBeenCalledWith(100); + expect(selections.delay).toHaveBeenCalledWith(100); }); - - it('transition callback should be triggered', function () { - var triggered = false; - dc.transition(selections, 100, function () { - triggered = true; - }); - expect(triggered).toBeTruthy(); + it('with name', () => { + dc.transition(selections, 100, 100, 'transition-name'); + expect(selections.transition).toHaveBeenCalled(); + expect(selections.transition).toHaveBeenCalledWith('transition-name'); }); }); - describe('skip', function () { - it('transition should not be activated with 0 duration', function () { - dc.transition(selections, 0); + describe('skip', () => { + it('transition should not be activated with 0 duration', () => { + dc.transition(selections, 0, 0); expect(selections.transition).not.toHaveBeenCalled(); expect(selections.duration).not.toHaveBeenCalled(); + expect(selections.delay).not.toHaveBeenCalled(); }); - it('transition callback should not be triggered', function () { - var triggered = false; - dc.transition(selections, 0, function () { - triggered = true; - }); - expect(triggered).toBeFalsy(); + it('transition should not be activated with dc.disableTransitions', () => { + dc.config.disableTransitions = true; + dc.transition(selections, 100); + expect(selections.transition).not.toHaveBeenCalled(); + expect(selections.duration).not.toHaveBeenCalled(); }); - }); - }); - describe('units', function () { - describe('.integers', function () { - var result; - beforeEach(function () { - result = dc.units.integers(0, 100); - }); - it('units should be based on subtraction', function () { - expect(result).toEqual(100); + afterEach(() => { + dc.config.disableTransitions = false; }); }); - describe('.float', function () { - var result; - beforeEach(function () { - result = dc.units.fp.precision(0.001)(0.49999, 1.0); - }); - it('units should be generated according to the precision', function () { - expect(result).toEqual(501); + describe('parameters', () => { + it('duration should not be called if skipped', () => { + dc.transition(selections); + expect(selections.duration).not.toHaveBeenCalled(); }); - }); - describe('.ordinal', function () { - var result; - beforeEach(function () { - result = dc.units.ordinal('a', 'd', ['a', 'b', 'c', 'd']); - }); - it('units should be based on count', function () { - expect(result.length).toEqual(4); + it('delay should not be called if skipped', () => { + dc.transition(selections, 100); + expect(selections.delay).not.toHaveBeenCalled(); }); }); }); - describe('round', function () { - describe('.floor', function () { - var result; - beforeEach(function () { - result = dc.round.floor(0.33); + describe('units', () => { + describe('.integers', () => { + let result; + beforeEach(() => { + result = dc.units.integers(0, 100); }); - it('should floored number', function () { - expect(result).toEqual(0); + it('units should be based on subtraction', () => { + expect(result).toEqual(100); }); }); - }); - describe('override', function () { - var o; - - beforeEach(function () { - o = {foo: function () { - return 'foo'; - }, goo: function (i) { - return i; - }}; - }); - - it('wo/ override function should work as expected', function () { - expect(o.foo()).toEqual('foo'); - }); - - it('should expose existing function', function () { - dc.override(o, 'foo', function () { - return this._foo() + '2'; + describe('.float', () => { + let result; + beforeEach(() => { + result = dc.units.fp.precision(0.001)(0.49999, 1.0); + }); + it('units should be generated according to the precision', () => { + expect(result).toEqual(501); }); - - expect(o.foo()).toEqual('foo2'); }); - it('should expose existing function with args', function () { - dc.override(o, 'goo', function (i) { - return this._goo(i) + 2; + describe('.ordinal', () => { + it('should throw - it\'s a placeholder only', () => { + expect(dc.units.ordinal).toThrow(new Error('dc.units.ordinal should not be called - it is a placeholder')); }); - - expect(o.goo(1)).toEqual(3); }); }); - describe('charts w/ grouping', function () { - var chart; + describe('charts w/ grouping', () => { + let chart; - beforeEach(function () { - chart = dc.pieChart('#a', 'groupA').dimension(valueDimension).group(valueGroup); + beforeEach(() => { + chart = new dc.PieChart('#a', 'groupA').dimension(valueDimension).group(valueGroup); spyOn(chart, 'filterAll'); spyOn(chart, 'render'); - dc.pieChart('#b', 'groupA').dimension(valueDimension).group(valueGroup); - dc.bubbleChart('#c', 'groupB').dimension(valueDimension).group(valueGroup); - dc.barChart('#b1', 'groupB').dimension(valueDimension).group(valueGroup); - dc.lineChart('#b2', 'groupB').dimension(valueDimension).group(valueGroup); - dc.dataCount('#b3', 'groupB').dimension(valueDimension).group(valueGroup); - dc.dataTable('#b4', 'groupB').dimension(valueDimension).group(valueGroup); + new dc.PieChart('#b', 'groupA').dimension(valueDimension).group(valueGroup); + new dc.BubbleChart('#c', 'groupB').dimension(valueDimension).group(valueGroup); + new dc.BarChart('#b1', 'groupB').dimension(valueDimension).group(valueGroup); + new dc.LineChart('#b2', 'groupB').dimension(valueDimension).group(valueGroup); + new dc.DataCount('#b3', 'groupB').dimension(valueDimension).group(valueGroup); + new dc.DataTable('#b4', 'groupB').dimension(valueDimension).group(valueGroup); return chart; }); - it('should register chart object', function () { + it('should register chart object', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('filterAll by group should invoke filter on each chart within the group', function () { + it('filterAll by group should invoke filter on each chart within the group', () => { dc.filterAll('groupA'); expect(chart.filterAll).toHaveBeenCalled(); }); - it('renderAll by group should invoke filter on each chart within the group', function () { + it('renderAll by group should invoke filter on each chart within the group', () => { dc.renderAll('groupA'); expect(chart.render).toHaveBeenCalled(); }); - it('filterAll should not invoke filter on chart in groupA', function () { + it('filterAll should not invoke filter on chart in groupA', () => { dc.filterAll(); expect(chart.filterAll).not.toHaveBeenCalled(); }); - it('renderAll should not invoke filter on chart in groupA', function () { + it('renderAll should not invoke filter on chart in groupA', () => { dc.renderAll(); expect(chart.render).not.toHaveBeenCalled(); }); - it('should be gone after remove all', function () { + it('should be gone after remove all', () => { dc.deregisterAllCharts(); expect(dc.hasChart(chart)).toBeFalsy(); }); }); - describe('render/redraw all call back', function () { - var result; + describe('render/redraw all call back', () => { + let result; - beforeEach(function () { - dc.renderlet(function (group) { + beforeEach(() => { + dc.renderlet(group => { result.called = group ? group : true; }); result = {called: false}; }); - it('renderAll call back should be triggered', function () { + it('renderAll call back should be triggered', () => { dc.renderAll(); expect(result.called).toBeTruthy(); }); - it('redrawAll call back should be triggered', function () { + it('redrawAll call back should be triggered', () => { dc.redrawAll(); expect(result.called).toBeTruthy(); }); - it('renderAll by group call back should be triggered', function () { + it('renderAll by group call back should be triggered', () => { dc.renderAll('group'); expect('group').toEqual(result.called); }); - it('redrawAll by group call back should be triggered', function () { + it('redrawAll by group call back should be triggered', () => { dc.redrawAll('group'); expect('group').toEqual(result.called); }); diff --git a/spec/data-addition-spec.js b/spec/data-addition-spec.js index 85bd1c2248..9dcc3c6398 100644 --- a/spec/data-addition-spec.js +++ b/spec/data-addition-spec.js @@ -1,11 +1,11 @@ /* global appendChartID, loadDateFixture, loadDateFixture2, makeDate */ -describe('Dynamic data addition in crossfilter', function () { - var width = 200; - var height = 200; - var radius = 100; - var baseData, moreData; +describe('Dynamic data addition in crossfilter', () => { + const width = 200; + const height = 200; + const radius = 100; + let baseData, moreData; - beforeEach(function () { + beforeEach(() => { baseData = crossfilter(loadDateFixture()); moreData = loadDateFixture2(); }); @@ -14,108 +14,107 @@ describe('Dynamic data addition in crossfilter', function () { return (str.split(value)).length - 1; } - describe('pie chart slice addition', function () { - var valueDimension, valueGroup; - var chart; + describe('pie chart slice addition', () => { + let valueDimension, valueGroup; + let chart; + function buildPieChart (id) { - var div = appendChartID(id); + const div = appendChartID(id); div.append('a').attr('class', 'reset').style('display', 'none'); div.append('span').attr('class', 'filter').style('display', 'none'); - var chart = dc.pieChart('#' + id); - chart.dimension(valueDimension).group(valueGroup) + const pieChart = new dc.PieChart(`#${id}`); + pieChart.dimension(valueDimension).group(valueGroup) .width(width) .height(height) .radius(radius) + .ordering(kv => kv.key) .transitionDuration(0); - chart.render(); + pieChart.render(); baseData.add(moreData); - chart.expireCache(); - return chart; + pieChart.expireCache(); + return pieChart; } - beforeEach(function () { - valueDimension = baseData.dimension(function (d) { - return d.value; - }); + beforeEach(() => { + valueDimension = baseData.dimension(d => d.value); valueGroup = valueDimension.group(); chart = buildPieChart('pie-chart'); chart.redraw(); }); - it('slice g should be created with class', function () { + it('slice g should be created with class', () => { expect(chart.selectAll('svg g g.pie-slice').data().length).toEqual(7); }); - it('slice path should be created', function () { + it('slice path should be created', () => { expect(chart.selectAll('svg g g.pie-slice path').data().length).toEqual(7); }); - it('default function should be used to dynamically generate label', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][0]).text()).toEqual('11'); + it('default function should be used to dynamically generate label', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[0]).text()).toEqual('11'); }); - it('pie chart slices should be in numerical order', function () { - expect(chart.selectAll('text.pie-slice').data().map(function (slice) { return slice.data.key; })) + it('pie chart slices should be in numerical order', () => { + expect(chart.selectAll('text.pie-slice').data().map(slice => slice.data.key)) .toEqual(['11','22','33','44','55','66','76']); }); - it('default function should be used to dynamically generate title', function () { - expect(d3.select(chart.selectAll('g.pie-slice title')[0][0]).text()).toEqual('11: 1'); + it('default function should be used to dynamically generate title', () => { + expect(d3.select(chart.selectAll('g.pie-slice title').nodes()[0]).text()).toEqual('11: 1'); }); - afterEach(function () { + afterEach(() => { valueDimension.filterAll(); }); }); - describe('line chart segment addition', function () { - var timeDimension, timeGroup; - var chart; + describe('line chart segment addition', () => { + let timeDimension, timeGroup; + let chart; + function buildLineChart (id) { appendChartID(id); - var chart = dc.lineChart('#' + id); - chart.dimension(timeDimension).group(timeGroup) + const lineChart = new dc.LineChart(`#${id}`); + lineChart.dimension(timeDimension).group(timeGroup) .width(width).height(height) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) .transitionDuration(0) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .brushOn(false) .renderArea(true) .renderTitle(true); - chart.render(); + lineChart.render(); baseData.add(moreData); - chart.expireCache(); - return chart; + lineChart.expireCache(); + return lineChart; } - beforeEach(function () { - timeDimension = baseData.dimension(function (d) { - return d.dd; - }); + beforeEach(() => { + timeDimension = baseData.dimension(d => d.dd); timeGroup = timeDimension.group(); chart = buildLineChart('line-chart'); chart.render(); }); - it('number of dots should equal the size of the group', function () { - expect(chart.selectAll('circle.dot')[0].length).toEqual(timeGroup.size()); + it('number of dots should equal the size of the group', () => { + expect(chart.selectAll('circle.dot').nodes().length).toEqual(timeGroup.size()); }); - it('number of line segments should equal the size of the group', function () { - var path = chart.selectAll('path.line').attr('d'); + it('number of line segments should equal the size of the group', () => { + const path = chart.selectAll('path.line').attr('d'); expect(occurrences(path, 'L') + 1).toEqual(timeGroup.size()); }); - it('number of area segments should equal twice the size of the group', function () { - var path = chart.selectAll('path.area').attr('d'); + it('number of area segments should equal twice the size of the group', () => { + const path = chart.selectAll('path.area').attr('d'); expect(occurrences(path, 'L') + 1).toEqual(timeGroup.size() * 2); }); - describe('resetting line chart with fewer data points', function () { - beforeEach(function () { - var chart = buildLineChart('stackable-line-chart'); - chart.render(); + describe('resetting line chart with fewer data points', () => { + beforeEach(() => { + const lineChart = buildLineChart('stackable-line-chart'); + lineChart.render(); timeDimension.filterAll(); baseData.remove(); baseData.add(moreData); - chart.render(); + lineChart.render(); }); - it('it should not contain stale data points', function () { + it('it should not contain stale data points', () => { expect(chart.data()[0].values.length).toEqual(2); }); }); - afterEach(function () { + afterEach(() => { timeDimension.filterAll(); }); }); diff --git a/spec/data-count-spec.js b/spec/data-count-spec.js index bff0d789d4..b2c736144f 100644 --- a/spec/data-count-spec.js +++ b/spec/data-count-spec.js @@ -1,178 +1,188 @@ /* global appendChartID, loadDateFixture */ -describe('dc.dataCount', function () { - var data, countryDimension, groupAll; - var chart; - beforeEach(function () { +describe('dc.dataCount', () => { + let data, countryDimension, groupAll; + let chart; + beforeEach(() => { data = crossfilter(loadDateFixture()); groupAll = data.groupAll(); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + countryDimension = data.dimension(d => d.countrycode); countryDimension.filter('CA'); }); function buildChart (id) { - var chart = dc.dataCount('#' + id) + const dataCount = new dc.DataCount(`#${id}`) .transitionDuration(0) .dimension(data) .group(groupAll); - chart.render(); - d3.timer.flush(); - return chart; + dataCount.render(); + d3.timerFlush(); + return dataCount; } - describe('creation', function () { - beforeEach(function () { - var id = 'data-count'; - var div = appendChartID(id); + describe('creation', () => { + beforeEach(() => { + const id = 'data-count'; + const div = appendChartID(id); div.append('span').attr('class', 'filter-count'); div.append('span').attr('class', 'total-count'); chart = buildChart(id); }); - it('should generate something', function () { + it('should generate something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('treats dimension as synonym of crossfilter', () => { + expect(chart.dimension()).toEqual(chart.crossfilter()); + const newVal = () => {}; // Just any value will do + chart.dimension(newVal); + expect(chart.crossfilter()).toBe(newVal); + }); + it('treats group as synonym of groupAll', () => { + expect(chart.group()).toEqual(chart.groupAll()); + const newVal = () => {}; // Just any value will do + chart.group(newVal); + expect(chart.groupAll()).toBe(newVal); + }); + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should fill in the total count', function () { + it('should fill in the total count', () => { expect(chart.select('span.total-count').text()).toEqual('10'); }); - it('should fill in the filter count', function () { + it('should fill in the filter count', () => { expect(chart.select('span.filter-count').text()).toEqual('2'); }); - describe('redraw', function () { - beforeEach(function () { + describe('redraw', () => { + beforeEach(() => { countryDimension.filterAll(); chart.redraw(); return chart; }); - it('should fill in the updated total count', function () { + it('should fill in the updated total count', () => { expect(chart.select('span.total-count').text()).toEqual('10'); }); - it('should fill in the updated filter count', function () { + it('should fill in the updated filter count', () => { expect(chart.select('span.filter-count').text()).toEqual('10'); }); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('creation with html attribute', function () { - beforeEach(function () { - var id = 'data-count'; - var div = appendChartID(id); + describe('creation with html attribute', () => { + beforeEach(() => { + const id = 'data-count'; + const div = appendChartID(id); div.append('span').attr('class', 'filter-count'); div.append('span').attr('class', 'total-count'); chart = buildChart(id); chart.html({some: '%filter-count selected from %total-count',all: 'All Records Selected'}); chart.redraw(); }); - it('should generate something', function () { + it('should generate something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should fill the element replacing %filter-count and %total-count', function () { + it('should fill the element replacing %filter-count and %total-count', () => { expect(chart.root().text()).toEqual('2 selected from 10'); }); - describe('when all selected', function () { - beforeEach(function () { + describe('when all selected', () => { + beforeEach(() => { countryDimension.filterAll(); chart.redraw(); return chart; }); - it('should use html.all', function () { + it('should use html.all', () => { expect(chart.root().text()).toEqual('All Records Selected'); }); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('creation with just html.some attribute', function () { - beforeEach(function () { - var id = 'data-count'; - var div = appendChartID(id); + describe('creation with just html.some attribute', () => { + beforeEach(() => { + const id = 'data-count'; + const div = appendChartID(id); div.append('span').attr('class', 'filter-count'); div.append('span').attr('class', 'total-count'); chart = buildChart(id); chart.html({some: '%filter-count selected from %total-count'}); chart.redraw(); }); - it('should fill the element replacing %filter-count and %total-count', function () { + it('should fill the element replacing %filter-count and %total-count', () => { expect(chart.root().text()).toEqual('2 selected from 10'); }); - describe('when all selected', function () { - beforeEach(function () { + describe('when all selected', () => { + beforeEach(() => { countryDimension.filterAll(); chart.redraw(); return chart; }); - it('should use html.some for all', function () { + it('should use html.some for all', () => { expect(chart.root().text()).toEqual('10 selected from 10'); }); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('creation with just html.all attribute', function () { - beforeEach(function () { - var id = 'data-count'; - var div = appendChartID(id); + describe('creation with just html.all attribute', () => { + beforeEach(() => { + const id = 'data-count'; + const div = appendChartID(id); div.append('span').attr('class', 'filter-count'); div.append('span').attr('class', 'total-count'); chart = buildChart(id); chart.html({all: 'All Records Selected'}); chart.redraw(); }); - it('should fill in the total count', function () { + it('should fill in the total count', () => { expect(chart.select('span.total-count').text()).toEqual('10'); }); - it('should fill in the filter count', function () { + it('should fill in the filter count', () => { expect(chart.select('span.filter-count').text()).toEqual('2'); }); - describe('when all selected', function () { - beforeEach(function () { + describe('when all selected', () => { + beforeEach(() => { countryDimension.filterAll(); chart.redraw(); return chart; }); - it('should use html.all for all', function () { + it('should use html.all for all', () => { expect(chart.root().text()).toEqual('All Records Selected'); }); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('creation with formatNumber attribute', function () { - beforeEach(function () { - var id = 'data-count'; - var div = appendChartID(id); + describe('creation with formatNumber attribute', () => { + beforeEach(() => { + const id = 'data-count'; + const div = appendChartID(id); div.append('span').attr('class', 'filter-count'); div.append('span').attr('class', 'total-count'); chart = buildChart(id); chart.formatNumber(d3.format('04.1g')); chart.redraw(); }); - it('should generate something', function () { + it('should generate something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should fill in the formatted total count', function () { + it('should fill in the formatted total count', () => { expect(chart.select('span.total-count').text()).toEqual('1e+1'); }); - it('should fill in the formatted filter count', function () { + it('should fill in the formatted filter count', () => { expect(chart.select('span.filter-count').text()).toEqual('0002'); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); diff --git a/spec/data-grid-spec.js b/spec/data-grid-spec.js index 759fa73cd9..c546784632 100644 --- a/spec/data-grid-spec.js +++ b/spec/data-grid-spec.js @@ -1,122 +1,126 @@ /* global appendChartID, loadDateFixture */ -describe('dc.dataGrid', function () { - var id, chart, data; - var dateFixture; - var dimension; - var countryDimension; +describe('dc.dataGrid', () => { + let id, chart, data; + let dateFixture; + let dimension; + let countryDimension; - beforeEach(function () { + beforeEach(() => { dateFixture = loadDateFixture(); data = crossfilter(dateFixture); - dimension = data.dimension(function (d) { - return d3.time.day.utc(d.dd); - }); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + dimension = data.dimension(d => d3.utcDay(d.dd)); + countryDimension = data.dimension(d => d.countrycode); id = 'data-grid'; appendChartID(id); - chart = dc.dataGrid('#' + id) + chart = new dc.DataGrid(`#${id}`) .dimension(dimension) - .group(function (d) { - return 'Data Grid'; - }) + .group(d => 'Data Grid') .transitionDuration(0) .size(3) - .sortBy(function (d) {return d.id;}) + .sortBy(d => d.id) .order(d3.descending) - .html(function (d) { - return '
' + d.state + ':' + d.value + '
'; - }); + .html(d => `
${d.state}:${d.value}
`); chart.render(); }); - describe('creation', function () { - it('generates something', function () { + describe('creation', () => { + it('generates something', () => { expect(chart).not.toBeNull(); }); - it('registers', function () { + it('registers', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('sets size', function () { + it('sets size', () => { expect(chart.size()).toEqual(3); }); - it('sets sortBy', function () { + it('sets sortBy', () => { expect(chart.sortBy()).not.toBeNull(); }); - it('sets order', function () { + it('sets order', () => { expect(chart.order()).toBe(d3.descending); }); - it('sets the group label', function () { - expect(chart.selectAll('.dc-grid-group h1.dc-grid-label')[0][0].innerHTML).toEqual('Data Grid'); + it('sets the group label', () => { + expect(chart.selectAll('.dc-grid-group h1.dc-grid-label').nodes()[0].innerHTML).toEqual('Data Grid'); + }); + it('treats group as synonym of section', () => { + expect(chart.group()).toEqual(chart.section()); + const newSection = () => {}; + chart.group(newSection); + expect(chart.section()).toBe(newSection); + }); + it('treats htmlGroup as synonym of htmlSection', () => { + expect(chart.htmlGroup()).toEqual(chart.htmlSection()); + const newHtmlSection = () => {}; + chart.htmlGroup(newHtmlSection); + expect(chart.htmlSection()).toBe(newHtmlSection); }); - it('creates id div', function () { - expect(chart.selectAll('.dc-grid-item div#id_9')[0].length).toEqual(1); - expect(chart.selectAll('.dc-grid-item div#id_8')[0].length).toEqual(1); - expect(chart.selectAll('.dc-grid-item div#id_3')[0].length).toEqual(1); + it('creates id div', () => { + expect(chart.selectAll('.dc-grid-item div#id_9').nodes().length).toEqual(1); + expect(chart.selectAll('.dc-grid-item div#id_8').nodes().length).toEqual(1); + expect(chart.selectAll('.dc-grid-item div#id_3').nodes().length).toEqual(1); }); - it('creates div content', function () { - expect(chart.selectAll('.dc-grid-item div')[0][0].innerHTML).toEqual('Mississippi:44'); - expect(chart.selectAll('.dc-grid-item div')[0][1].innerHTML).toEqual('Mississippi:33'); - expect(chart.selectAll('.dc-grid-item div')[0][2].innerHTML).toEqual('Delaware:33'); + it('creates div content', () => { + expect(chart.selectAll('.dc-grid-item div').nodes()[0].innerHTML).toEqual('Mississippi:44'); + expect(chart.selectAll('.dc-grid-item div').nodes()[1].innerHTML).toEqual('Mississippi:33'); + expect(chart.selectAll('.dc-grid-item div').nodes()[2].innerHTML).toEqual('Delaware:33'); }); }); - describe('slicing entries', function () { - beforeEach(function () { + describe('slicing entries', () => { + beforeEach(() => { chart.beginSlice(1); chart.redraw(); }); - it('slice beginning', function () { - expect(chart.selectAll('.dc-grid-item')[0].length).toEqual(2); + it('slice beginning', () => { + expect(chart.selectAll('.dc-grid-item').nodes().length).toEqual(2); }); - it('slice beginning and end', function () { + it('slice beginning and end', () => { chart.endSlice(2); chart.redraw(); - expect(chart.selectAll('.dc-grid-item')[0].length).toEqual(1); + expect(chart.selectAll('.dc-grid-item').nodes().length).toEqual(1); }); }); - describe('external filter', function () { - beforeEach(function () { + describe('external filter', () => { + beforeEach(() => { countryDimension.filter('CA'); chart.redraw(); }); - it('renders only filtered data set', function () { - expect(chart.selectAll('.dc-grid-item div')[0].length).toEqual(2); + it('renders only filtered data set', () => { + expect(chart.selectAll('.dc-grid-item div').nodes().length).toEqual(2); }); - it('renders the correctly filtered records', function () { - expect(chart.selectAll('.dc-grid-item div')[0][0].innerHTML).toEqual('Ontario:22'); - expect(chart.selectAll('.dc-grid-item div')[0][1].innerHTML).toEqual('Ontario:55'); + it('renders the correctly filtered records', () => { + expect(chart.selectAll('.dc-grid-item div').nodes()[0].innerHTML).toEqual('Ontario:22'); + expect(chart.selectAll('.dc-grid-item div').nodes()[1].innerHTML).toEqual('Ontario:55'); }); }); - describe('renderlet', function () { - var derlet; - beforeEach(function () { - derlet = jasmine.createSpy('renderlet', function (chart) { - chart.selectAll('.dc-grid-label').text('changed'); + describe('renderlet', () => { + let derlet; + beforeEach(() => { + derlet = jasmine.createSpy('renderlet', _chart => { + _chart.selectAll('.dc-grid-label').text('changed'); }); derlet.and.callThrough(); chart.on('renderlet', derlet); }); - it('custom renderlet should be invoked with render', function () { + it('custom renderlet should be invoked with render', () => { chart.render(); expect(chart.selectAll('.dc-grid-label').text()).toEqual('changed'); expect(derlet).toHaveBeenCalled(); }); - it('custom renderlet should be invoked with redraw', function () { + it('custom renderlet should be invoked with redraw', () => { chart.redraw(); expect(chart.selectAll('.dc-grid-label').text()).toEqual('changed'); expect(derlet).toHaveBeenCalled(); }); }); - afterEach(function () { + afterEach(() => { dimension.filterAll(); countryDimension.filterAll(); }); diff --git a/spec/data-table-spec.js b/spec/data-table-spec.js index 9b7eb52326..3b4a58a71b 100644 --- a/spec/data-table-spec.js +++ b/spec/data-table-spec.js @@ -1,32 +1,28 @@ /* global appendChartID, loadDateFixture */ -describe('dc.dataTable', function () { - var id, chart, data; - var dateFixture; - var dimension; - var countryDimension; - var valueGroup; - - beforeEach(function () { +describe('dc.dataTable', () => { + let id, chart, data; + let dateFixture; + let dimension; + let countryDimension; + let valueGroup; + + beforeEach(() => { dateFixture = loadDateFixture(); data = crossfilter(dateFixture); - dimension = data.dimension(function (d) { - return d3.time.day.utc(d.dd); - }); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + dimension = data.dimension(d => d3.utcDay(d.dd)); + countryDimension = data.dimension(d => d.countrycode); valueGroup = function () { - return 'Data Table'; - }; + return 'Data Table'; + }; id = 'data-table'; appendChartID(id); - chart = dc.dataTable('#' + id) + chart = new dc.DataTable(`#${id}`) .dimension(dimension) .group(valueGroup) .transitionDuration(0) .size(3) - .sortBy(function (d) {return d.id;}) + .sortBy(d => d.id) .order(d3.descending) .columns( [function (d) { @@ -37,178 +33,190 @@ describe('dc.dataTable', function () { ); }); - describe('simple table', function () { - beforeEach(function () { + describe('simple table', () => { + beforeEach(() => { chart.render(); }); - describe('creation', function () { - it('generates something', function () { + describe('creation', () => { + it('generates something', () => { expect(chart).not.toBeNull(); }); - it('registers', function () { + it('registers', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('sets size', function () { + it('sets size', () => { expect(chart.size()).toEqual(3); }); - it('sets sortBy', function () { + it('sets sortBy', () => { expect(chart.sortBy()).not.toBeNull(); }); - it('sets order', function () { + it('sets order', () => { expect(chart.order()).toBe(d3.descending); }); - it('group should be set', function () { + it('group should be set', () => { expect(chart.group()).toEqual(valueGroup); }); - it('group tr should not be undefined', function () { - expect(typeof(chart.selectAll('tr.dc-table-group')[0][0])).not.toBe('undefined'); + it('treats group as synonym of section', () => { + expect(chart.group()).toEqual(chart.section()); + const newSection = () => {}; + chart.group(newSection); + expect(chart.section()).toBe(newSection); + }); + it('treats showGroups as synonym of showSections', () => { + expect(chart.showGroups()).toEqual(chart.showSections()); + const newVal = !(chart.showGroups()); + chart.showGroups(newVal); + expect(chart.showSections()).toBe(newVal); + }); + it('group tr should not be undefined', () => { + expect(typeof(chart.selectAll('tr.dc-table-group').nodes()[0])).not.toBe('undefined'); }); - it('sets column span set on group tr', function () { - expect(chart.selectAll('tr.dc-table-group td')[0][0].getAttribute('colspan')).toEqual('2'); + it('sets column span set on group tr', () => { + expect(chart.selectAll('tr.dc-table-group td').nodes()[0].getAttribute('colspan')).toEqual('2'); }); - it('creates id column', function () { - expect(chart.selectAll('td._0')[0][0].innerHTML).toEqual('9'); - expect(chart.selectAll('td._0')[0][1].innerHTML).toEqual('8'); - expect(chart.selectAll('td._0')[0][2].innerHTML).toEqual('3'); + it('creates id column', () => { + expect(chart.selectAll('td._0').nodes()[0].innerHTML).toEqual('9'); + expect(chart.selectAll('td._0').nodes()[1].innerHTML).toEqual('8'); + expect(chart.selectAll('td._0').nodes()[2].innerHTML).toEqual('3'); }); - it('creates status column', function () { - expect(chart.selectAll('td._1')[0][0].innerHTML).toEqual('T'); - expect(chart.selectAll('td._1')[0][1].innerHTML).toEqual('F'); - expect(chart.selectAll('td._1')[0][2].innerHTML).toEqual('T'); + it('creates status column', () => { + expect(chart.selectAll('td._1').nodes()[0].innerHTML).toEqual('T'); + expect(chart.selectAll('td._1').nodes()[1].innerHTML).toEqual('F'); + expect(chart.selectAll('td._1').nodes()[2].innerHTML).toEqual('T'); }); }); - describe('slicing entries', function () { - beforeEach(function () { + describe('slicing entries', () => { + beforeEach(() => { chart.beginSlice(1); chart.redraw(); }); - it('slice beginning', function () { - expect(chart.selectAll('tr.dc-table-row')[0].length).toEqual(2); + it('slice beginning', () => { + expect(chart.selectAll('tr.dc-table-row').nodes().length).toEqual(2); }); - it('slice beginning and end', function () { + it('slice beginning and end', () => { chart.endSlice(2); chart.redraw(); - expect(chart.selectAll('tr.dc-table-row')[0].length).toEqual(1); + expect(chart.selectAll('tr.dc-table-row').nodes().length).toEqual(1); }); }); - describe('external filter', function () { - beforeEach(function () { + describe('external filter', () => { + beforeEach(() => { countryDimension.filter('CA'); chart.redraw(); }); - it('renders only filtered data set', function () { - expect(chart.selectAll('td._0')[0].length).toEqual(2); + it('renders only filtered data set', () => { + expect(chart.selectAll('td._0').nodes().length).toEqual(2); }); - it('renders the correctly filtered records', function () { - expect(chart.selectAll('td._0')[0][0].innerHTML).toEqual('7'); - expect(chart.selectAll('td._0')[0][1].innerHTML).toEqual('5'); + it('renders the correctly filtered records', () => { + expect(chart.selectAll('td._0').nodes()[0].innerHTML).toEqual('7'); + expect(chart.selectAll('td._0').nodes()[1].innerHTML).toEqual('5'); }); }); - describe('ascending order', function () { - beforeEach(function () { + describe('ascending order', () => { + beforeEach(() => { chart.order(d3.ascending); chart.redraw(); }); - it('uses dimension.bottom() instead of top()', function () { - expect(chart.selectAll('td._0')[0][0].innerHTML).toEqual('1'); + it('uses dimension.bottom() instead of top()', () => { + expect(chart.selectAll('td._0').nodes()[0].innerHTML).toEqual('1'); }); }); }); - describe('renderlet', function () { - var derlet; - beforeEach(function () { - derlet = jasmine.createSpy('renderlet', function (chart) { - chart.selectAll('td.dc-table-label').text('changed'); + describe('renderlet', () => { + let derlet; + beforeEach(() => { + derlet = jasmine.createSpy('renderlet', _chart => { + _chart.selectAll('td.dc-table-label').text('changed'); }); derlet.and.callThrough(); chart.on('renderlet', derlet); }); - it('custom renderlet should be invoked with render', function () { + it('custom renderlet should be invoked with render', () => { chart.render(); expect(chart.selectAll('td.dc-table-label').text()).toEqual('changed'); expect(derlet).toHaveBeenCalled(); }); - it('custom renderlet should be invoked with redraw', function () { + it('custom renderlet should be invoked with redraw', () => { chart.redraw(); expect(chart.selectAll('td.dc-table-label').text()).toEqual('changed'); expect(derlet).toHaveBeenCalled(); }); }); - describe('specifying chart columns with label', function () { - beforeEach(function () { + describe('specifying chart columns with label', () => { + beforeEach(() => { chart.columns(['state']); chart.render(); }); - it('should render value and capitalized header', function () { - var cols = chart.selectAll('td.dc-table-column')[0].map(function (d) {return d.textContent;}); - var expected = ['Mississippi', 'Mississippi', 'Delaware']; + it('should render value and capitalized header', () => { + const cols = chart.selectAll('td.dc-table-column').nodes().map(d => d.textContent); + const expected = ['Mississippi', 'Mississippi', 'Delaware']; expect(cols.length).toEqual(expected.length); - expected.forEach(function (d) { + expected.forEach(d => { expect(cols).toContain(d); }); - var colheader = chart.selectAll('th.dc-table-head')[0].map(function (d) {return d.textContent;}); + const colheader = chart.selectAll('th.dc-table-head').nodes().map(d => d.textContent); expect(colheader.length).toEqual(1); expect(colheader[0]).toEqual('State'); }); }); - describe('specifying chart columns with function', function () { - beforeEach(function () { - chart.columns([function (d) {return '' + d.id + 'test';}]); + describe('specifying chart columns with function', () => { + beforeEach(() => { + chart.columns([function (d) {return `${d.id}test`;}]); chart.render(); }); - it('should render function result and no header', function () { - var cols = chart.selectAll('td.dc-table-column')[0].map(function (d) {return d.textContent;}); - var expected = ['9test', '8test', '3test']; + it('should render function result and no header', () => { + const cols = chart.selectAll('td.dc-table-column').nodes().map(d => d.textContent); + const expected = ['9test', '8test', '3test']; expect(cols.length).toEqual(expected.length); - expected.forEach(function (d) { + expected.forEach(d => { expect(cols).toContain(d); }); - var colheader = chart.selectAll('th.dc-table-head')[0].map(function (d) {return d.textContent;}); + const colheader = chart.selectAll('th.dc-table-head').nodes().map(d => d.textContent); expect(colheader.length).toEqual(0); }); }); - describe('specifying chart columns with object', function () { - beforeEach(function () { + describe('specifying chart columns with object', () => { + beforeEach(() => { chart.columns([{ label: 'Test ID', format: function (d) { - return 'test' + d.id; + return `test${d.id}`; } }]); chart.render(); }); - it('should produce correct table header with single column', function () { - var thead = chart.selectAll('thead'); - expect(thead.length).toBe(1); - var tr = thead.selectAll('tr'); - expect(tr.length).toBe(1); - var colheader = tr.selectAll('th.dc-table-head')[0].map(function (d) {return d.textContent;}); + it('should produce correct table header with single column', () => { + const thead = chart.selectAll('thead'); + expect(thead.nodes().length).toBe(1); + const tr = thead.selectAll('tr'); + expect(tr.nodes().length).toBe(1); + const colheader = tr.selectAll('th.dc-table-head').nodes().map(d => d.textContent); expect(colheader.length).toEqual(1); expect(colheader[0]).toEqual('Test ID'); }); - it('should render correct values in rows', function () { - var cols = chart.selectAll('td.dc-table-column')[0].map(function (d) {return d.textContent;}); - var expected = ['test9', 'test8', 'test3']; + it('should render correct values in rows', () => { + const cols = chart.selectAll('td.dc-table-column').nodes().map(d => d.textContent); + const expected = ['test9', 'test8', 'test3']; expect(cols.length).toEqual(expected.length); - expected.forEach(function (d, i) { + expected.forEach((d, i) => { expect(cols[i]).toEqual(d); }); }); }); - describe('with existing table header', function () { - beforeEach(function () { + describe('with existing table header', () => { + beforeEach(() => { // add some garbage for table to replace d3.select('#data-table') .selectAll('thead').data([0]).enter().append('thead') @@ -217,33 +225,33 @@ describe('dc.dataTable', function () { chart.columns([{ label: 'Test ID', format: function (d) { - return 'test' + d.id; + return `test${d.id}`; } }]); chart.render(); }); - it('should produce correct table header with single column', function () { - var thead = chart.selectAll('thead'); - expect(thead.length).toBe(1); - var tr = thead.selectAll('tr'); - expect(tr.length).toBe(1); - var colheader = tr.selectAll('th.dc-table-head')[0].map(function (d) {return d.textContent;}); + it('should produce correct table header with single column', () => { + const thead = chart.selectAll('thead'); + expect(thead.nodes().length).toBe(1); + const tr = thead.selectAll('tr'); + expect(tr.nodes().length).toBe(1); + const colheader = tr.selectAll('th.dc-table-head').nodes().map(d => d.textContent); expect(colheader.length).toEqual(1); expect(colheader[0]).toEqual('Test ID'); }); }); - describe('specifying showGroups as false', function () { - beforeEach(function () { + describe('specifying showGroups as false', () => { + beforeEach(() => { chart.showGroups(false); chart.render(); }); - it('group tr should be undefined', function () { - expect(typeof(chart.selectAll('tr.dc-table-group')[0][0])).toBe('undefined'); + it('group tr should be undefined', () => { + expect(typeof(chart.selectAll('tr.dc-table-group').nodes()[0])).toBe('undefined'); }); }); - afterEach(function () { + afterEach(() => { dimension.filterAll(); countryDimension.filterAll(); }); diff --git a/spec/event-spec.js b/spec/event-spec.js index 1e5dc45b06..665ad37829 100644 --- a/spec/event-spec.js +++ b/spec/event-spec.js @@ -1,27 +1,27 @@ -describe('dc event engine', function () { - describe('event execution', function () { - var engine, trigger; - beforeEach(function () { +describe('dc event engine', () => { + describe('event execution', () => { + let engine, trigger; + beforeEach(() => { engine = dc.events; trigger = jasmine.createSpy('trigger'); }); - it('event can be dispatched immediately', function () { + it('event can be dispatched immediately', () => { engine.trigger(trigger); expect(trigger).toHaveBeenCalled(); }); - it('event can be dispatched with delay', function () { + it('event can be dispatched with delay', () => { engine.trigger(trigger, 100); expect(trigger).not.toHaveBeenCalled(); jasmine.clock().tick(101); expect(trigger).toHaveBeenCalled(); }); - it('multiple events dispatched with delay should be throttled', function () { - var times = 0; - var i = 0; - var increment = function () { + it('multiple events dispatched with delay should be throttled', () => { + let times = 0; + let i = 0; + const increment = function () { times++; }; @@ -34,7 +34,7 @@ describe('dc event engine', function () { jasmine.clock().tick(5); expect(times).toEqual(1); }); - afterEach(function () { + afterEach(() => { }); }); }); diff --git a/spec/filter-dates-spec.js b/spec/filter-dates-spec.js index bf8830cfc4..70c002d624 100644 --- a/spec/filter-dates-spec.js +++ b/spec/filter-dates-spec.js @@ -1,25 +1,24 @@ /* global appendChartID, makeDate */ -describe('dc.filter-dates', function () { +describe('dc.filter-dates', () => { // do date filters work correctly? // adapted from a fiddle demonstrating the problem by Matt Traynham // see it fail with 1.7.1: http://jsfiddle.net/gordonwoodhull/Q2H9C/4/ // see it win with 2.0: http://jsfiddle.net/gordonwoodhull/Q2H9C/3/ // (Thanks!!) - var dateDim1, dateDim2, group1, group2, - row1, row2; - var width = 400; - var height = 200; - var margins = {top: 15, right: 10, bottom: 20, left: 40}; - beforeEach(function () { + let dateDim1, dateDim2, group1, group2, row1, row2; + const width = 400; + const height = 200; + const margins = {top: 15, right: 10, bottom: 20, left: 40}; + beforeEach(() => { // Months are 0 indexed... - var start = makeDate(2013, 10, 1); - var end = makeDate(2013, 11, 1); - var stringLength = 2; + const start = makeDate(2013, 10, 1); + const end = makeDate(2013, 11, 1); + const stringLength = 2; // Generate Random Data [Date, VowelString, Random Number, Random Measure] - var data = []; - for (var i = 0; i < 2000; i++) { + const data = []; + for (let i = 0; i < 2000; i++) { data[i] = [ randomDate(start, end), randomVowelString(stringLength), @@ -28,17 +27,17 @@ describe('dc.filter-dates', function () { ]; } - var ndx = crossfilter(data); - dateDim1 = ndx.dimension(function (d) { return d[0]; }); - dateDim2 = ndx.dimension(function (d) { return d[0]; }); + const ndx = crossfilter(data); + dateDim1 = ndx.dimension(d => d[0]); + dateDim2 = ndx.dimension(d => d[0]); - group1 = dateDim1.group().reduceSum(function (d) { return d[3]; }); - group2 = dateDim2.group().reduceSum(function (d) { return d[3]; }); + group1 = dateDim1.group().reduceSum(d => d[3]); + group2 = dateDim2.group().reduceSum(d => d[3]); appendChartID(row1); appendChartID(row2); - row1 = dc.rowChart('row1') + row1 = new dc.RowChart('row1') .width(width) .height(height) .margins(margins) @@ -47,7 +46,7 @@ describe('dc.filter-dates', function () { .gap(1) .render(); - row2 = dc.rowChart('row2') + row2 = new dc.RowChart('row2') .width(width) .height(height) .margins(margins) @@ -57,7 +56,7 @@ describe('dc.filter-dates', function () { .render(); }); - it('filtering on 11/8 should keep only that row', function () { + it('filtering on 11/8 should keep only that row', () => { row1.filter(makeDate(2013, 10, 8)); expect(group1.all()[6].value).not.toEqual(0); expect(group2.all()[6].value).toEqual(0); @@ -65,7 +64,7 @@ describe('dc.filter-dates', function () { expect(group2.all()[8].value).toEqual(0); }); - it('filtering on 11/17 should keep only that row', function () { + it('filtering on 11/17 should keep only that row', () => { row1.filter(makeDate(2013, 10, 17)); expect(group1.all()[15].value).not.toEqual(0); expect(group2.all()[15].value).toEqual(0); @@ -75,16 +74,17 @@ describe('dc.filter-dates', function () { // Create a Random Date function randomDate (start, end) { - var d = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); - d.setUTCHours(0,0,0,0); + const d = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); + d.setUTCHours(0, 0, 0, 0); return d; } // Create a Random String of vowels - var vowels = ['a','e','i','o','u','y']; + const vowels = ['a', 'e', 'i', 'o', 'u', 'y']; + function randomVowelString (length) { - var val = ''; - for (var i = 0; i < length; i++) { + let val = ''; + for (let i = 0; i < length; i++) { val = val + vowels[Math.floor(Math.random() * (vowels.length - 1))]; } return val; diff --git a/spec/filters-spec.js b/spec/filters-spec.js index 36014662d2..3047f6642a 100644 --- a/spec/filters-spec.js +++ b/spec/filters-spec.js @@ -1,104 +1,131 @@ -describe('dc.filters', function () { - describe('RangedFilter', function () { - var filter; - beforeEach(function () { +/* global makeDate */ + +describe('dc.filters', () => { + describe('RangedFilter', () => { + let filter; + beforeEach(() => { filter = dc.filters.RangedFilter(0, 10); }); - it('should act like an array', function () { + it('should act like an array', () => { expect([filter[0], filter[1]]).toEqual([0, 10]); }); - describe('isFiltered', function () { - it('should return false when the number is out of range', function () { + describe('isFiltered', () => { + it('should return false when the number is out of range', () => { expect(filter.isFiltered(1234)).toBeFalsy(); }); - it('should return true when the number is in range', function () { + it('should return true when the number is in range', () => { expect(filter.isFiltered(8.1)).toBeTruthy(); }); - it('should include the left bounds', function () { + it('should include the left bounds', () => { expect(filter.isFiltered(0)).toBeTruthy(); }); - it('should exclude the right bounds', function () { + it('should exclude the right bounds', () => { expect(filter.isFiltered(10)).toBeFalsy(); }); }); }); - describe('TwoDimensionalFilter', function () { - var filter; - beforeEach(function () { + describe('RangedFilter with Dates', () => { + let filter; + beforeEach(() => { + filter = dc.filters.RangedFilter(makeDate(2015, 7, 1), makeDate(2015, 8, 20)); + }); + + describe('isFiltered', () => { + it('should return false when the date is out of range', () => { + expect(filter.isFiltered(makeDate(2015, 10, 1))).toBeFalsy(); + }); + + it('should return true when the date is in range', () => { + expect(filter.isFiltered(makeDate(2015, 8, 1))).toBeTruthy(); + }); + + it('should include the left bounds', () => { + expect(filter.isFiltered(makeDate(2015, 7, 1))).toBeTruthy(); + }); + + it('should exclude the right bounds', () => { + expect(filter.isFiltered(makeDate(2015, 8, 20))).toBeFalsy(); + }); + }); + }); + + describe('TwoDimensionalFilter', () => { + let filter; + beforeEach(() => { filter = dc.filters.TwoDimensionalFilter([1,2]); }); - describe('isFiltered', function () { - it('should return true if both dimensions are equal', function () { + describe('isFiltered', () => { + it('should return true if both dimensions are equal', () => { expect(filter.isFiltered([1,2])).toBeTruthy(); }); - it('should return false if either dimension is not equal to the filter', function () { + it('should return false if either dimension is not equal to the filter', () => { expect(filter.isFiltered([1,5])).toBeFalsy(); }); - it('should return false if the dimensionality is less', function () { + it('should return false if the dimensionality is less', () => { expect(filter.isFiltered([1])).toBeFalsy(); }); - it('should return false if the dimensionality is more', function () { + it('should return false if the dimensionality is more', () => { expect(filter.isFiltered([1,2,3])).toBeFalsy(); }); - it('should return false if the value is not an array', function () { + it('should return false if the value is not an array', () => { expect(filter.isFiltered(1)).toBeFalsy(); }); }); }); - describe('RangedTwoDimensionalFilter', function () { - var filter; + describe('RangedTwoDimensionalFilter', () => { + let filter; - it('should return null if filtered with null', function () { + it('should return null if filtered with null', () => { expect(dc.filters.RangedTwoDimensionalFilter(null)).toBe(null); }); - describe('two-dimensional filtering', function () { - beforeEach(function () { + describe('two-dimensional filtering', () => { + beforeEach(() => { filter = dc.filters.RangedTwoDimensionalFilter([[0, 1],[10, 20]]); }); - it('should return true if on bottom left of filter rectangle', function () { + it('should return true if on bottom left of filter rectangle', () => { expect(filter.isFiltered([0,1])).toBeTruthy(); }); - it('should return false if on bottom right of filter rectangle', function () { + it('should return false if on bottom right of filter rectangle', () => { expect(filter.isFiltered([10,1])).toBeFalsy(); }); - it('should return false for the top left of filter rectangle', function () { + it('should return false for the top left of filter rectangle', () => { expect(filter.isFiltered([0,20])).toBeFalsy(); }); - it('should return false for the top right of filter rectangle', function () { + it('should return false for the top right of filter rectangle', () => { expect(filter.isFiltered([10,20])).toBeFalsy(); }); - it('should return true for a point inside the filter rectangle', function () { + it('should return true for a point inside the filter rectangle', () => { expect(filter.isFiltered([5,5])).toBeTruthy(); }); - it('should return false for a point to the right and above the filter rectangle', function () { + it('should return false for a point to the right and above the filter rectangle', () => { expect(filter.isFiltered([11,21])).toBeFalsy(); }); - it('should return false for a point to the left and below the filter rectangle', function () { + it('should return false for a point to the left and below the filter rectangle', () => { expect(filter.isFiltered([-1,-1])).toBeFalsy(); }); - describe('when a single value is considered', function () { - it('should filter that value using only x coordinates', function () { + describe('when a single value is considered', () => { + it('should filter that value using only x coordinates', () => { expect(filter.isFiltered(5)).toBeTruthy(); expect(filter.isFiltered(0)).toBeTruthy(); expect(filter.isFiltered(10)).toBeFalsy(); @@ -106,29 +133,29 @@ describe('dc.filters', function () { }); }); - describe('one-dimensional filtering', function () { - beforeEach(function () { + describe('one-dimensional filtering', () => { + beforeEach(() => { filter = dc.filters.RangedTwoDimensionalFilter([10, 20]); }); - it('should return true while inside the range', function () { + it('should return true while inside the range', () => { expect(filter.isFiltered([15,10])).toBeTruthy(); }); - it('should return false while to the left of the range', function () { + it('should return false while to the left of the range', () => { expect(filter.isFiltered([5,10])).toBeFalsy(); }); - it('should return true while on the left edge of the range', function () { + it('should return true while on the left edge of the range', () => { expect(filter.isFiltered([10,10])).toBeTruthy(); }); - it('should return false while on the right edge of the range', function () { + it('should return false while on the right edge of the range', () => { expect(filter.isFiltered([20,10])).toBeFalsy(); }); - describe('when a single value is considered', function () { - it('should filter that value using only x coordinates', function () { + describe('when a single value is considered', () => { + it('should filter that value using only x coordinates', () => { expect(filter.isFiltered(10)).toBeTruthy(); expect(filter.isFiltered(15)).toBeTruthy(); expect(filter.isFiltered(20)).toBeFalsy(); @@ -137,4 +164,81 @@ describe('dc.filters', function () { }); }); + + describe('RangedTwoDimensionalFilter with Dates', () => { + let filter; + + describe('two-dimensional filtering', () => { + beforeEach(() => { + filter = dc.filters.RangedTwoDimensionalFilter([[makeDate(2014, 5, 1), 1],[makeDate(2014, 5, 20), 20]]); + }); + + it('should return true if on bottom left of filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 1), 1])).toBeTruthy(); + }); + + it('should return false if on bottom right of filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 20), 1])).toBeFalsy(); + }); + + it('should return false for the top left of filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 1), 20])).toBeFalsy(); + }); + + it('should return false for the top right of filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 20), 20])).toBeFalsy(); + }); + + it('should return true for a point inside the filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 12), 5])).toBeTruthy(); + }); + + it('should return false for a point to the right and above the filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 5, 21), 21])).toBeFalsy(); + }); + + it('should return false for a point to the left and below the filter rectangle', () => { + expect(filter.isFiltered([makeDate(2014, 4, 30), -1])).toBeFalsy(); + }); + + describe('when a single value is considered', () => { + it('should filter that value using only x coordinates', () => { + expect(filter.isFiltered(makeDate(2014, 5, 10))).toBeTruthy(); + expect(filter.isFiltered(makeDate(2014, 5, 1))).toBeTruthy(); + expect(filter.isFiltered(makeDate(2014, 5, 20))).toBeFalsy(); + }); + }); + }); + + describe('one-dimensional filtering', () => { + beforeEach(() => { + filter = dc.filters.RangedTwoDimensionalFilter([makeDate(2014, 5, 1), makeDate(2014, 5, 20), 20]); + }); + + it('should return true while inside the range', () => { + expect(filter.isFiltered([makeDate(2014, 5, 15),10])).toBeTruthy(); + }); + + it('should return false while to the left of the range', () => { + expect(filter.isFiltered([makeDate(2014, 4, 30),10])).toBeFalsy(); + }); + + it('should return true while on the left edge of the range', () => { + expect(filter.isFiltered([makeDate(2014, 5, 1),10])).toBeTruthy(); + }); + + it('should return false while on the right edge of the range', () => { + expect(filter.isFiltered([makeDate(2014, 5, 20),10])).toBeFalsy(); + }); + + describe('when a single value is considered', () => { + it('should filter that value using only x coordinates', () => { + expect(filter.isFiltered(makeDate(2014, 5, 10))).toBeTruthy(); + expect(filter.isFiltered(makeDate(2014, 5, 1))).toBeTruthy(); + expect(filter.isFiltered(makeDate(2014, 5, 20))).toBeFalsy(); + }); + }); + }); + + }); }); diff --git a/spec/geo-choropleth-chart-spec.js b/spec/geo-choropleth-chart-spec.js index f5dc40809b..c5361dfa4a 100644 --- a/spec/geo-choropleth-chart-spec.js +++ b/spec/geo-choropleth-chart-spec.js @@ -1,15 +1,15 @@ /* global appendChartID, loadDateFixture, loadGeoFixture, loadGeoFixture2, loadGeoFixture3 */ -describe('dc.geoChoropleth', function () { - var data; - var stateDimension, stateValueSumGroup, districtDimension, districtValueEnrollGroup; - var geoJson, geoJson2, geoJson3; +describe('dc.geoChoropleth', () => { + let data; + let stateDimension, stateValueSumGroup, districtDimension, districtValueEnrollGroup; + let geoJson, geoJson2, geoJson3; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - stateDimension = data.dimension(function (d) {return d.state;}); - stateValueSumGroup = stateDimension.group().reduceSum(function (d) {return d.value;}); - districtDimension = data.dimension(function (d) {return d.district;}); - districtValueEnrollGroup = districtDimension.group().reduceSum(function (d) {return d.value;}); + stateDimension = data.dimension(d => d.state); + stateValueSumGroup = stateDimension.group().reduceSum(d => d.value); + districtDimension = data.dimension(d => d.district); + districtValueEnrollGroup = districtDimension.group().reduceSum(d => d.value); if (!geoJson) { geoJson = loadGeoFixture(); @@ -23,203 +23,298 @@ describe('dc.geoChoropleth', function () { }); function buildChart (id) { - var div = appendChartID(id); + const div = appendChartID(id); div.append('a').attr('class', 'reset').style('display', 'none'); div.append('span').attr('class', 'filter').style('display', 'none'); - var chart = dc.geoChoroplethChart('#' + id); + const chart = new dc.GeoChoroplethChart(`#${id}`); chart.dimension(stateDimension) .group(stateValueSumGroup) .width(990) .height(600) - .colors(['#ccc', '#E2F2FF', '#C4E4FF', '#9ED2FF', '#81C5FF', '#6BBAFF', '#51AEFF', '#36A2FF', '#1E96FF', '#0089FF']) + .colors(['#ccc', '#e2f2ff', '#c4e4ff', '#9ed2ff', '#81c5ff', '#6bbaff', '#51aeff', '#36a2ff', '#1e96ff', '#0089ff']) .colorDomain([0, 155]) - .overlayGeoJson(geoJson.features, 'state', function (d) { - return d.properties.name; - }) + .overlayGeoJson(geoJson.features, 'state', d => d.properties.name) .overlayGeoJson(geoJson2.features, 'county') .transitionDuration(0) - .title(function (d) { - return d.key + ' : ' + (d.value ? d.value : 0); - }); + .title(d => `${d.key} : ${d.value ? d.value : 0}`); chart.render(); return chart; } function buildChartWithCustomProjection (id) { - var div = appendChartID(id); + const div = appendChartID(id); div.append('a').attr('class', 'reset').style('display', 'none'); div.append('span').attr('class', 'filter').style('display', 'none'); - var chart = dc.geoChoroplethChart('#' + id); + const chart = new dc.GeoChoroplethChart(`#${id}`); chart.dimension(districtDimension) .group(districtValueEnrollGroup) - .projection(d3.geo.mercator() + .projection(d3.geoMercator() .scale(26778) .translate([8227, 3207])) .width(990) .height(600) - .colors(['#ccc', '#E2F2FF', '#C4E4FF', '#9ED2FF', '#81C5FF', '#6BBAFF', '#51AEFF', '#36A2FF', '#1E96FF', '#0089FF']) + .colors(['#ccc', '#e2f2ff', '#c4e4ff', '#9ed2ff', '#81c5ff', '#6bbaff', '#51aeff', '#36a2ff', '#1e96ff', '#0089ff']) .colorDomain([0, 155]) - .overlayGeoJson(geoJson3.features, 'district', function (d) { - return d.properties.NAME; - }) + .overlayGeoJson(geoJson3.features, 'district', d => d.properties.NAME) .transitionDuration(0) - .title(function (d) { - return d.key + ' : ' + (d.value ? d.value : 0); - }); + .title(d => `${d.key} : ${d.value ? d.value : 0}`); chart.render(); return chart; } - describe('creation', function () { - var chart; - beforeEach(function () { + describe('creation', () => { + let chart; + beforeEach(() => { chart = buildChart('choropleth-chart'); }); - it('should return not null', function () { + it('should return not null', () => { expect(chart).not.toBeNull(); }); - it('should have a d3.geo.path', function () { + it('should have a d3.geoPath', () => { expect(chart.geoPath()).not.toBeNull(); }); - it('svg is created', function () { + it('svg is created', () => { expect(chart.selectAll('svg').length).not.toEqual(0); }); - it('geo layer0 g is created', function () { + it('geo layer0 g is created', () => { expect(chart.selectAll('g.layer0').length).not.toEqual(0); }); - it('correct number of states should be generated', function () { - expect(chart.selectAll('g.layer0 g.state')[0].length).toEqual(52); + it('correct number of states should be generated', () => { + expect(chart.selectAll('g.layer0 g.state').nodes().length).toEqual(52); }); - it('correct css class should be set [Alaska]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][1].getAttribute('class')).toEqual('state alaska'); + it('correct css class should be set [Alaska]', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[1].getAttribute('class')).toEqual('state alaska'); }); - it('correct title should be set [Alaska]', function () { - expect(chart.selectAll('g.layer0 g.state title')[0][1].textContent).toEqual('Alaska : 0'); + it('correct title should be set [Alaska]', () => { + expect(chart.selectAll('g.layer0 g.state title').nodes()[1].textContent).toEqual('Alaska : 0'); }); - it('correct color filling should be set [Alaska]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][1].getAttribute('fill')).toEqual('#ccc'); + it('correct color filling should be set [Alaska]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[1].getAttribute('fill')).toMatch(/#ccc/i); }); - it('correct state boundary should be rendered [Alaska]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][1].getAttribute('d').length).not.toEqual(0); + it('correct state boundary should be rendered [Alaska]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[1].getAttribute('d').length).not.toEqual(0); }); - it('correct css class should be set [California]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][4].getAttribute('class')).toEqual('state california'); + it('correct css class should be set [California]', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[4].getAttribute('class')).toEqual('state california'); }); - it('correct css class should be set [District of Columbia]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][8].getAttribute('class')).toEqual('state district_of_columbia'); + it('correct css class should be set [District of Columbia]', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[8].getAttribute('class')).toEqual('state district_of_columbia'); }); - it('correct title should be set [California]', function () { - expect(chart.selectAll('g.layer0 g.state title')[0][4].textContent).toEqual('California : 154'); + it('correct title should be set [California]', () => { + expect(chart.selectAll('g.layer0 g.state title').nodes()[4].textContent).toEqual('California : 154'); }); - it('correct color should be set [California]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][4].getAttribute('fill')).toMatch(/#0089FF/i); + it('correct color should be set [California]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[4].getAttribute('fill')).toMatch(/#0089ff/i); }); - it('correct state boundary should be rendered [California]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][4].getAttribute('d').length).not.toEqual(0); + it('correct state boundary should be rendered [California]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[4].getAttribute('d').length).not.toEqual(0); }); - it('correct css class should be set [Colorado]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][5].getAttribute('class')).toEqual('state colorado'); + it('correct css class should be set [Colorado]', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[5].getAttribute('class')).toEqual('state colorado'); }); - it('correct title should be set [Colorado]', function () { - expect(chart.selectAll('g.layer0 g.state title')[0][5].textContent).toEqual('Colorado : 22'); + it('correct title should be set [Colorado]', () => { + expect(chart.selectAll('g.layer0 g.state title').nodes()[5].textContent).toEqual('Colorado : 22'); }); - it('correct color should be set [Colorado]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][5].getAttribute('fill')).toMatch(/#E2F2FF/i); + it('correct color should be set [Colorado]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[5].getAttribute('fill')).toMatch(/#e2f2ff/i); }); - it('correct state boundary should be rendered [Colorado]', function () { - expect(chart.selectAll('g.layer0 g.state path')[0][5].getAttribute('d').length).not.toEqual(0); + it('correct state boundary should be rendered [Colorado]', () => { + expect(chart.selectAll('g.layer0 g.state path').nodes()[5].getAttribute('d').length).not.toEqual(0); }); - it('geo layer1 g is created', function () { + it('geo layer1 g is created', () => { expect(chart.selectAll('g.layer1').length).not.toEqual(0); }); - it('correct number of counties should be generated', function () { - expect(chart.selectAll('g.layer1 g.county')[0].length).toEqual(5); + it('correct number of counties should be generated', () => { + expect(chart.selectAll('g.layer1 g.county').nodes().length).toEqual(5); }); - it('correct css class should be set [county]', function () { - expect(chart.selectAll('g.layer1 g.county')[0][1].getAttribute('class')).toEqual('county'); + it('correct css class should be set [county]', () => { + expect(chart.selectAll('g.layer1 g.county').nodes()[1].getAttribute('class')).toEqual('county'); }); - it('correct title should be set [county]', function () { - expect(chart.selectAll('g.layer1 g.county title')[0][1].textContent).toEqual(''); + it('correct title should be set [county]', () => { + expect(chart.selectAll('g.layer1 g.county title').nodes()[1].textContent).toEqual(''); }); - it('correct color filling should be set [county]', function () { - expect(chart.selectAll('g.layer1 g.county path')[0][1].getAttribute('fill')).toEqual('white'); + it('correct color filling should be set [county]', () => { + expect(chart.selectAll('g.layer1 g.county path').nodes()[1].getAttribute('fill')).toEqual('white'); }); - it('correct state boundary should be rendered [county]', function () { - expect(chart.selectAll('g.layer1 g.county path')[0][1].getAttribute('d').length).not.toEqual(0); - }); - - afterEach(function () { - stateDimension.filterAll(); - districtDimension.filterAll(); + it('correct state boundary should be rendered [county]', () => { + expect(chart.selectAll('g.layer1 g.county path').nodes()[1].getAttribute('d').length).not.toEqual(0); }); }); - describe('filter and highlight', function () { - var chart; - beforeEach(function () { + describe('filter and highlight', () => { + let chart; + beforeEach(() => { chart = buildChart('choropleth-chart-with-filter'); chart.filter('Colorado'); chart.filter('California'); chart.redraw(); }); - it('correct color should be set [California]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][0].getAttribute('class')).toEqual('state alabama deselected'); - expect(chart.selectAll('g.layer0 g.state')[0][1].getAttribute('class')).toEqual('state alaska deselected'); + it('sets deselected classes for some states', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[0].getAttribute('class')).toEqual('state alabama deselected'); + expect(chart.selectAll('g.layer0 g.state').nodes()[1].getAttribute('class')).toEqual('state alaska deselected'); }); - it('correct color should be set [California, Colorado]', function () { - expect(chart.selectAll('g.layer0 g.state')[0][4].getAttribute('class')).toEqual('state california selected'); - expect(chart.selectAll('g.layer0 g.state')[0][5].getAttribute('class')).toEqual('state colorado selected'); + it('sets selected classes for selected states', () => { + expect(chart.selectAll('g.layer0 g.state').nodes()[4].getAttribute('class')).toEqual('state california selected'); + expect(chart.selectAll('g.layer0 g.state').nodes()[5].getAttribute('class')).toEqual('state colorado selected'); }); + }); - afterEach(function () { - stateDimension.filterAll(); - districtDimension.filterAll(); + describe('respond to external filter', () => { + let chart, nvalueDim; + beforeEach(() => { + chart = buildChart('choropleth-chart-being-filtered'); + nvalueDim = data.dimension(d => +d.nvalue); + }); + it('gets right colors when not filtered', () => { + expect(chart.selectAll('g.layer0 g.state.california path').attr('fill')).toMatch(/#0089ff/i); + expect(chart.selectAll('g.layer0 g.state.colorado path').attr('fill')).toMatch(/#e2f2ff/i); + expect(chart.selectAll('g.layer0 g.state.delaware path').attr('fill')).toMatch(/#c4e4ff/i); + expect(chart.selectAll('g.layer0 g.state.mississippi path').attr('fill')).toMatch(/#81c5ff/i); + expect(chart.selectAll('g.layer0 g.state.oklahoma path').attr('fill')).toMatch(/#9ed2ff/i); + expect(chart.selectAll('g.layer0 g.state.maryland path').attr('fill')).toMatch(/#ccc/i); + expect(chart.selectAll('g.layer0 g.state.washington path').attr('fill')).toMatch(/#ccc/i); + }); + it('has right titles when not filtered', () => { + expect(chart.selectAll('g.layer0 g.state.california title').text()).toEqual('California : 154'); + expect(chart.selectAll('g.layer0 g.state.colorado title').text()).toEqual('Colorado : 22'); + expect(chart.selectAll('g.layer0 g.state.delaware title').text()).toEqual('Delaware : 33'); + expect(chart.selectAll('g.layer0 g.state.mississippi title').text()).toEqual('Mississippi : 77'); + expect(chart.selectAll('g.layer0 g.state.oklahoma title').text()).toEqual('Oklahoma : 55'); + expect(chart.selectAll('g.layer0 g.state.maryland title').text()).toEqual('Maryland : 0'); + expect(chart.selectAll('g.layer0 g.state.washington title').text()).toEqual('Washington : 0'); + }); + + function checkEvenNValueColors () { + expect(chart.selectAll('g.layer0 g.state.california path').attr('fill')).toMatch(/#36a2ff/i); + expect(chart.selectAll('g.layer0 g.state.colorado path').attr('fill')).toMatch(/#e2f2ff/i); + expect(chart.selectAll('g.layer0 g.state.delaware path').attr('fill')).toMatch(/#ccc/i); + expect(chart.selectAll('g.layer0 g.state.mississippi path').attr('fill')).toMatch(/#c4e4ff/i); + expect(chart.selectAll('g.layer0 g.state.oklahoma path').attr('fill')).toMatch(/#ccc/i); + expect(chart.selectAll('g.layer0 g.state.maryland path').attr('fill')).toMatch(/#ccc/i); + expect(chart.selectAll('g.layer0 g.state.washington path').attr('fill')).toMatch(/#ccc/i); + } + + function checkEvenNValueTitles () { + expect(chart.selectAll('g.layer0 g.state.california title').text()).toEqual('California : 110'); + expect(chart.selectAll('g.layer0 g.state.colorado title').text()).toEqual('Colorado : 22'); + expect(chart.selectAll('g.layer0 g.state.delaware title').text()).toEqual('Delaware : 0'); + expect(chart.selectAll('g.layer0 g.state.mississippi title').text()).toEqual('Mississippi : 44'); + expect(chart.selectAll('g.layer0 g.state.oklahoma title').text()).toEqual('Oklahoma : 0'); + expect(chart.selectAll('g.layer0 g.state.maryland title').text()).toEqual('Maryland : 0'); + expect(chart.selectAll('g.layer0 g.state.washington title').text()).toEqual('Washington : 0'); + } + + describe('column filtering with straight crossfilter', () => { + beforeEach(() => { + nvalueDim.filterFunction(k => k % 2 === 0); + chart.redraw(); + }); + it('gets right filtered colors', () => { + checkEvenNValueColors(); + }); + it('gets the titles right', () => { + checkEvenNValueTitles(); + }); + }); + describe('column filtering with cloned results', () => { + function dupeGroup (group) { + return { + all: function () { + return group.all().map(kv => Object.assign({}, kv)); + } + }; + } + beforeEach(() => { + chart.group(dupeGroup(stateValueSumGroup)).render(); + nvalueDim.filterFunction(k => k % 2 === 0); + chart.redraw(); + }); + it('gets right filtered colors', () => { + checkEvenNValueColors(); + }); + it('gets the titles right', () => { + checkEvenNValueTitles(); + }); }); }); - describe('custom projection', function () { - var chart; - beforeEach(function () { + describe('custom projection', () => { + let chart; + beforeEach(() => { chart = buildChartWithCustomProjection('choropleth-chart-with-projection'); }); - it('should return not null', function () { + it('should return not null', () => { expect(chart).not.toBeNull(); }); - it('svg is created', function () { + it('svg is created', () => { expect(chart.selectAll('svg').length).not.toEqual(0); }); - - afterEach(function () { - stateDimension.filterAll(); - districtDimension.filterAll(); - }); }); - describe('replace and remove layer', function () { - var chart; - beforeEach(function () { + describe('replace and remove layer', () => { + let chart; + beforeEach(() => { chart = buildChart('choropleth-chart-replace-layer'); - chart.overlayGeoJson(geoJson3.features, 'state', function (d) { - return d.properties.name; - }); + chart.overlayGeoJson(geoJson3.features, 'state', d => d.properties.name); }); - it('geo json layer with the same name should be replaced', function () { - expect(chart.geoJsons().filter(function (e) { - return e.name === 'state'; - })[0].data).toBe(geoJson3.features); + it('geo json layer with the same name should be replaced', () => { + expect(chart.geoJsons().filter(e => e.name === 'state')[0].data).toBe(geoJson3.features); }); - it('geo json layer can be removed by name', function () { + it('geo json layer can be removed by name', () => { chart.removeGeoJson('state'); - expect(chart.geoJsons().filter(function (e) { - return e.name === 'state'; - }).length).toEqual(0); + expect(chart.geoJsons().filter(e => e.name === 'state').length).toEqual(0); + }); + }); + + describe('accessibility choropleth', () => { + // create chart without rendering it + let chart; + beforeEach(() => { + const id = 'accessible-choropleth-chart' + chart = new dc.GeoChoroplethChart(`#${id}`); + appendChartID(id); + + chart.dimension(stateDimension) + .group(stateValueSumGroup) + .width(990) + .height(600) + .keyboardAccessible(true) + .colors(['#ccc', '#e2f2ff', '#c4e4ff', '#9ed2ff', '#81c5ff', '#6bbaff', '#51aeff', '#36a2ff', '#1e96ff', '#0089ff']) + .colorDomain([0, 155]) + .overlayGeoJson(geoJson.features, 'state', d => d.properties.name) + .overlayGeoJson(geoJson2.features, 'county') + .transitionDuration(0) + .title(d => `${d.key} : ${d.value ? d.value : 0}`); }); - afterEach(function () { - stateDimension.filterAll(); - districtDimension.filterAll(); + + it('internal elements are focusable by keyboard', () => { + + chart.render(); + chart.selectAll('path.dc-tabbable').each(function () { + const state = d3.select(this); + expect(state.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('path.dc-tabbable').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); }); + }); + }); diff --git a/spec/heatmap-spec.js b/spec/heatmap-spec.js index 015aef8621..18e2bde0e1 100644 --- a/spec/heatmap-spec.js +++ b/spec/heatmap-spec.js @@ -1,27 +1,27 @@ -/* global appendChartID, loadColorFixture, loadColorFixture2 */ -describe('dc.heatmap', function () { - var id, data, dimension, group, chart, chartHeight, chartWidth; +/* global appendChartID, loadColorFixture, loadColorFixture2, loadIrisFixture */ +describe('dc.heatmap', () => { + let id, data, dimension, group, chart, chartHeight, chartWidth; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadColorFixture()); - dimension = data.dimension(function (d) { return [+d.colData, +d.rowData]; }); - group = dimension.group().reduceSum(function (d) { return +d.colorData; }); + dimension = data.dimension(d => [+d.colData, +d.rowData]); + group = dimension.group().reduceSum(d => +d.colorData); chartHeight = 210; chartWidth = 210; id = 'heatmap-chart'; appendChartID(id); - chart = dc.heatMap('#' + id); + chart = new dc.HeatMap(`#${id}`); chart .dimension(dimension) .group(group) - .keyAccessor(function (d) { return d.key[0]; }) - .valueAccessor(function (d) { return d.key[1]; }) - .colorAccessor(function (d) { return d.value; }) + .keyAccessor(d => d.key[0]) + .valueAccessor(d => d.key[1]) + .colorAccessor(d => d.value) .colors(['#000001', '#000002', '#000003', '#000004']) - .title(function (d) {return d.key + ': ' + d.value; }) + .title(d => `${d.key}: ${d.value}`) .height(chartHeight) .width(chartWidth) .transitionDuration(0) @@ -30,111 +30,118 @@ describe('dc.heatmap', function () { }); - describe('rendering the heatmap', function () { - beforeEach(function () { + describe('rendering the heatmap', () => { + beforeEach(() => { chart.render(); }); - it('should create svg', function () { + it('should create svg', () => { expect(chart.svg()).not.toBeNull(); }); - it('should transform the graph position using the graph margins', function () { - expect(chart.select('g.heatmap').attr('transform')).toMatchTranslate(5,5); + it('should transform the graph position using the graph margins', () => { + expect(chart.select('g.heatmap').attr('transform')).toMatchTranslate(5, 5); }); - it('should position the heatboxes in a matrix', function () { - var heatBoxes = chart.selectAll('rect.heat-box'); + it('should position the heatboxes in a matrix', () => { + const heatBoxes = chart.selectAll('rect.heat-box'); - expect(+heatBoxes[0][0].getAttribute('x')).toEqual(0); - expect(+heatBoxes[0][0].getAttribute('y')).toEqual(100); + expect(+heatBoxes.nodes()[0].getAttribute('x')).toEqual(0); + expect(+heatBoxes.nodes()[0].getAttribute('y')).toEqual(100); - expect(+heatBoxes[0][1].getAttribute('x')).toEqual(0); - expect(+heatBoxes[0][1].getAttribute('y')).toEqual(0); + expect(+heatBoxes.nodes()[1].getAttribute('x')).toEqual(0); + expect(+heatBoxes.nodes()[1].getAttribute('y')).toEqual(0); - expect(+heatBoxes[0][2].getAttribute('x')).toEqual(100); - expect(+heatBoxes[0][2].getAttribute('y')).toEqual(100); + expect(+heatBoxes.nodes()[2].getAttribute('x')).toEqual(100); + expect(+heatBoxes.nodes()[2].getAttribute('y')).toEqual(100); - expect(+heatBoxes[0][3].getAttribute('x')).toEqual(100); - expect(+heatBoxes[0][3].getAttribute('y')).toEqual(0); + expect(+heatBoxes.nodes()[3].getAttribute('x')).toEqual(100); + expect(+heatBoxes.nodes()[3].getAttribute('y')).toEqual(0); }); - it('should color heatboxes using the provided color option', function () { - var heatBoxes = chart.selectAll('rect.heat-box'); + it('should color heatboxes using the provided color option', () => { + const heatBoxes = chart.selectAll('rect.heat-box'); - expect(heatBoxes[0][0].getAttribute('fill')).toEqual('#000001'); - expect(heatBoxes[0][1].getAttribute('fill')).toEqual('#000002'); - expect(heatBoxes[0][2].getAttribute('fill')).toEqual('#000003'); - expect(heatBoxes[0][3].getAttribute('fill')).toEqual('#000004'); + expect(heatBoxes.nodes()[0].getAttribute('fill')).toMatch(/#000001/i); + expect(heatBoxes.nodes()[1].getAttribute('fill')).toMatch(/#000002/i); + expect(heatBoxes.nodes()[2].getAttribute('fill')).toMatch(/#000003/i); + expect(heatBoxes.nodes()[3].getAttribute('fill')).toMatch(/#000004/i); }); - it('should size heatboxes based on the size of the matrix', function () { + it('should size heatboxes based on the size of the matrix', () => { chart.selectAll('rect.heat-box').each(function () { expect(+this.getAttribute('height')).toEqual(100); expect(+this.getAttribute('width')).toEqual(100); }); }); - it('should position the y-axis labels with their associated rows', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(+yaxisTexts[0][0].getAttribute('y')).toEqual(150); - expect(+yaxisTexts[0][0].getAttribute('x')).toEqual(0); - expect(+yaxisTexts[0][1].getAttribute('y')).toEqual(50); - expect(+yaxisTexts[0][1].getAttribute('x')).toEqual(0); + it('should position the y-axis labels with their associated rows', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(+yaxisTexts.nodes()[0].getAttribute('y')).toEqual(150); + expect(+yaxisTexts.nodes()[0].getAttribute('x')).toEqual(0); + expect(+yaxisTexts.nodes()[1].getAttribute('y')).toEqual(50); + expect(+yaxisTexts.nodes()[1].getAttribute('x')).toEqual(0); }); - it('should have labels on the y-axis corresponding to the row values', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0][0].textContent).toEqual('1'); - expect(yaxisTexts[0][1].textContent).toEqual('2'); + it('should have labels on the y-axis corresponding to the row values', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes()[0].textContent).toEqual('1'); + expect(yaxisTexts.nodes()[1].textContent).toEqual('2'); }); - it('should position the x-axis labels with their associated columns', function () { - var xaxisTexts = chart.selectAll('.cols.axis text'); - expect(+xaxisTexts[0][0].getAttribute('y')).toEqual(200); - expect(+xaxisTexts[0][0].getAttribute('x')).toEqual(50); - expect(+xaxisTexts[0][1].getAttribute('y')).toEqual(200); - expect(+xaxisTexts[0][1].getAttribute('x')).toEqual(150); + it('should position the x-axis labels with their associated columns', () => { + const xaxisTexts = chart.selectAll('.cols.axis text'); + expect(+xaxisTexts.nodes()[0].getAttribute('y')).toEqual(200); + expect(+xaxisTexts.nodes()[0].getAttribute('x')).toEqual(50); + expect(+xaxisTexts.nodes()[1].getAttribute('y')).toEqual(200); + expect(+xaxisTexts.nodes()[1].getAttribute('x')).toEqual(150); }); - it('should have labels on the x-axis corresponding to the row values', function () { - var xaxisTexts = chart.selectAll('.cols.axis text'); - expect(xaxisTexts[0][0].textContent).toEqual('1'); - expect(xaxisTexts[0][1].textContent).toEqual('2'); + it('should have labels on the x-axis corresponding to the row values', () => { + const xaxisTexts = chart.selectAll('.cols.axis text'); + expect(xaxisTexts.nodes()[0].textContent).toEqual('1'); + expect(xaxisTexts.nodes()[1].textContent).toEqual('2'); }); - describe('with custom labels', function () { - beforeEach(function () { - chart.colsLabel(function (x) { return 'col ' + x;}) - .rowsLabel(function (x) { return 'row ' + x;}) + it('should have tooltips (titles)', () => { + const titles = chart.selectAll('title'); + expect(titles.nodes().length).toEqual(4); + expect(titles.nodes()[0].textContent).toEqual('1,1: 2'); + expect(titles.nodes()[2].textContent).toEqual('2,1: 6'); + }); + + describe('with custom labels', () => { + beforeEach(() => { + chart.colsLabel(x => `col ${x}`) + .rowsLabel(x => `row ${x}`) .redraw(); }); - it('should display the custom labels on the x axis', function () { - var xaxisTexts = chart.selectAll('.cols.axis text'); - expect(xaxisTexts[0][0].textContent).toEqual('col 1'); - expect(xaxisTexts[0][1].textContent).toEqual('col 2'); + it('should display the custom labels on the x axis', () => { + const xaxisTexts = chart.selectAll('.cols.axis text'); + expect(xaxisTexts.nodes()[0].textContent).toEqual('col 1'); + expect(xaxisTexts.nodes()[1].textContent).toEqual('col 2'); }); - it('should display the custom labels on the y axis', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0][0].textContent).toEqual('row 1'); - expect(yaxisTexts[0][1].textContent).toEqual('row 2'); + it('should display the custom labels on the y axis', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes()[0].textContent).toEqual('row 1'); + expect(yaxisTexts.nodes()[1].textContent).toEqual('row 2'); }); }); - describe('box radius', function () { - it('should default the x', function () { + describe('box radius', () => { + it('should default the x', () => { chart.select('rect.heat-box').each(function () { expect(this.getAttribute('rx')).toBe('6.75'); }); }); - it('should default the y', function () { + it('should default the y', () => { chart.select('rect.heat-box').each(function () { expect(this.getAttribute('ry')).toBe('6.75'); }); }); - it('should set the radius to an overridden x', function () { + it('should set the radius to an overridden x', () => { chart.xBorderRadius(7); chart.render(); @@ -143,7 +150,7 @@ describe('dc.heatmap', function () { }); }); - it('should set the radius to an overridden y', function () { + it('should set the radius to an overridden y', () => { chart.yBorderRadius(7); chart.render(); @@ -155,81 +162,80 @@ describe('dc.heatmap', function () { }); - describe('override scale domains', function () { - beforeEach(function () { + describe('override scale domains', () => { + beforeEach(() => { chart.rows([1]); chart.cols([1]); chart.render(); }); - it('should only have 1 row on the y axis', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0].length).toEqual(1); - expect(yaxisTexts[0][0].textContent).toEqual('1'); + it('should only have 1 row on the y axis', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes().length).toEqual(1); + expect(yaxisTexts.nodes()[0].textContent).toEqual('1'); }); - it('should only have 1 col on the x axis', function () { - var xaxisTexts = chart.selectAll('.cols.axis text'); - expect(xaxisTexts[0].length).toEqual(1); - expect(xaxisTexts[0][0].textContent).toEqual('1'); + it('should only have 1 col on the x axis', () => { + const xaxisTexts = chart.selectAll('.cols.axis text'); + expect(xaxisTexts.nodes().length).toEqual(1); + expect(xaxisTexts.nodes()[0].textContent).toEqual('1'); }); - it('should reset the rows to using the chart data on the y axis', function () { + it('should reset the rows to using the chart data on the y axis', () => { chart.rows(null); chart.redraw(); - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0].length).toEqual(2); - expect(yaxisTexts[0][0].textContent).toEqual('1'); - expect(yaxisTexts[0][1].textContent).toEqual('2'); + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes().length).toEqual(2); + expect(yaxisTexts.nodes()[0].textContent).toEqual('1'); + expect(yaxisTexts.nodes()[1].textContent).toEqual('2'); }); - it('should reset the cols to using the chart data on the y axis', function () { + it('should reset the cols to using the chart data on the y axis', () => { chart.cols(null); chart.redraw(); - var xaxisTexts = chart.selectAll('.cols.axis text'); - expect(xaxisTexts[0].length).toEqual(2); - expect(xaxisTexts[0][0].textContent).toEqual('1'); - expect(xaxisTexts[0][1].textContent).toEqual('2'); + const xaxisTexts = chart.selectAll('.cols.axis text'); + expect(xaxisTexts.nodes().length).toEqual(2); + expect(xaxisTexts.nodes()[0].textContent).toEqual('1'); + expect(xaxisTexts.nodes()[1].textContent).toEqual('2'); }); }); - describe('use a custom ordering on x and y axes', function () { - beforeEach(function () { + describe('use a custom ordering on x and y axes', () => { + beforeEach(() => { chart.rowOrdering(d3.descending); chart.colOrdering(d3.descending); chart.render(); }); - it('should have descending rows', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0][0].textContent).toEqual('2'); - expect(yaxisTexts[0][1].textContent).toEqual('1'); + it('should have descending rows', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes()[0].textContent).toEqual('2'); + expect(yaxisTexts.nodes()[1].textContent).toEqual('1'); }); - it('should have descending cols', function () { - var yaxisTexts = chart.selectAll('.rows.axis text'); - expect(yaxisTexts[0][0].textContent).toEqual('2'); - expect(yaxisTexts[0][1].textContent).toEqual('1'); + it('should have descending cols', () => { + const yaxisTexts = chart.selectAll('.rows.axis text'); + expect(yaxisTexts.nodes()[0].textContent).toEqual('2'); + expect(yaxisTexts.nodes()[1].textContent).toEqual('1'); }); }); - describe('change crossfilter', function () { - var data2, dimension2, group2, originalDomain, newDomain; + describe('change crossfilter', () => { + let data2, dimension2, group2, originalDomain; - var reduceDimensionValues = function (dimension) { - return dimension.top(Infinity).reduce(function (p, d) { - p.cols.add(d.colData); - p.rows.add(d.rowData); + const reduceDimensionValues = function (dmsn) { + return dmsn.top(Infinity).reduce((p, d) => { + p.cols.add(+d.colData); + p.rows.add(+d.rowData); return p; - }, {cols: d3.set(), rows: d3.set()}); + }, {cols: new Set(), rows: new Set()}); }; - beforeEach(function () { + beforeEach(() => { data2 = crossfilter(loadColorFixture2()); - dimension2 = data2.dimension(function (d) { return [+d.colData, +d.rowData]; }); - group2 = dimension2.group().reduceSum(function (d) { return +d.colorData; }); + dimension2 = data2.dimension(d => [+d.colData, +d.rowData]); + group2 = dimension2.group().reduceSum(d => +d.colorData); originalDomain = reduceDimensionValues(dimension); - newDomain = reduceDimensionValues(dimension2); chart.dimension(dimension2).group(group2); chart.render(); @@ -237,32 +243,31 @@ describe('dc.heatmap', function () { chart.redraw(); }); - it('should have the correct number of columns', function () { - chart.selectAll('.box-group').each(function (d) { + it('should have the correct number of columns', () => { + chart.selectAll('.box-group').each(d => { expect(originalDomain.cols.has(d.key[0])).toBeTruthy(); }); - chart.selectAll('.cols.axis text').each(function (d) { + chart.selectAll('.cols.axis text').each(d => { expect(originalDomain.cols.has(d)).toBeTruthy(); }); }); - it('should have the correct number of rows', function () { - chart.selectAll('.box-group').each(function (d) { + it('should have the correct number of rows', () => { + chart.selectAll('.box-group').each(d => { expect(originalDomain.rows.has(d.key[1])).toBeTruthy(); }); - chart.selectAll('.rows.axis text').each(function (d) { + chart.selectAll('.rows.axis text').each(d => { expect(originalDomain.rows.has(d)).toBeTruthy(); }); }); }); - describe('indirect filtering', function () { - var dimension2, group2; - beforeEach(function () { - dimension2 = data.dimension(function (d) { return +d.colorData; }); - group2 = dimension2.group().reduceSum(function (d) { return +d.colorData; }); + describe('indirect filtering', () => { + let dimension2; + beforeEach(() => { + dimension2 = data.dimension(d => +d.colorData); chart.dimension(dimension).group(group); chart.render(); @@ -270,38 +275,36 @@ describe('dc.heatmap', function () { chart.redraw(); }); - it('should update the title of the boxes', function () { - var titles = chart.selectAll('.box-group title'); - var expected = ['1,1: 0', '1,2: 0', '2,1: 6', '2,2: 0']; + it('should update the title of the boxes', () => { + const titles = chart.selectAll('.box-group title'); + const expected = ['1,1: 0', '1,2: 0', '2,1: 6', '2,2: 0']; titles.each(function (d) { expect(this.textContent).toBe(expected.shift()); }); }); }); - describe('filtering', function () { - var filterX, filterY; - var otherDimension; + describe('filtering', () => { + let filterX, filterY; + let otherDimension; - beforeEach(function () { + beforeEach(() => { filterX = Math.ceil(Math.random() * 2); filterY = Math.ceil(Math.random() * 2); - otherDimension = data.dimension(function (d) { return +d.colData; }); + otherDimension = data.dimension(d => +d.colData); chart.render(); }); - function clickCellOnChart (chart, x, y) { - var oneCell = chart.selectAll('.box-group').filter(function (d) { - return d.key[0] === x && d.key[1] === y; - }); - oneCell.select('rect').on('click')(oneCell.datum()); + function clickCellOnChart (_chart, x, y) { + const oneCell = _chart.selectAll('.box-group').filter(d => d.key[0] === x && d.key[1] === y); + dc.d3compat.callHandler(oneCell.select('rect').on('click'), null, {}, oneCell.datum()); return oneCell; } - it('cells should have the appropriate class', function () { + it('cells should have the appropriate class', () => { clickCellOnChart(chart, filterX, filterY); chart.selectAll('.box-group').each(function (d) { - var cell = d3.select(this); + const cell = d3.select(this); if (d.key[0] === filterX && d.key[1] === filterY) { expect(cell.classed('selected')).toBeTruthy(); expect(chart.hasFilter(d.key)).toBeTruthy(); @@ -312,16 +315,16 @@ describe('dc.heatmap', function () { }); }); - it('should keep all data points for that cell', function () { - var otherGroup = otherDimension.group().reduceSum(function (d) { return +d.colorData; }); - var otherChart = dc.baseChart({}).dimension(otherDimension).group(otherGroup); + it('should keep all data points for that cell', () => { + const otherGroup = otherDimension.group().reduceSum(d => +d.colorData); + const otherChart = dc.baseMixin().dimension(otherDimension).group(otherGroup); otherChart.render(); - var clickedCell = clickCellOnChart(chart, filterX, filterY); + const clickedCell = clickCellOnChart(chart, filterX, filterY); expect(otherChart.data()[filterX - 1].value).toEqual(clickedCell.datum().value); }); - it('should be able to clear filters by filtering with null', function () { + it('should be able to clear filters by filtering with null', () => { clickCellOnChart(chart, filterX, filterY); expect(otherDimension.top(Infinity).length).toBe(2); chart.filter(null); @@ -329,93 +332,309 @@ describe('dc.heatmap', function () { }); }); - describe('click events', function () { - beforeEach(function () { + describe('click events', () => { + beforeEach(() => { chart.render(); }); - it('should toggle a filter for the clicked box', function () { + it('should toggle a filter for the clicked box', () => { chart.selectAll('.box-group').each(function (d) { - var cell = d3.select(this).select('rect'); - cell.on('click')(d); + const cell = d3.select(this).select('rect'); + dc.d3compat.callHandler(cell.on('click'), null, {}, d); expect(chart.hasFilter(d.key)).toBeTruthy(); - cell.on('click')(d); + dc.d3compat.callHandler(cell.on('click'), null, {}, d); expect(chart.hasFilter(d.key)).toBeFalsy(); }); }); - describe('on axis labels', function () { - function assertOnlyThisAxisIsFiltered (chart, axis, value) { - chart.selectAll('.box-group').each(function (d) { + describe('on axis labels', () => { + function assertOnlyThisAxisIsFiltered (_chart, axis, value) { + _chart.selectAll('.box-group').each(d => { if (d.key[axis] === value) { - expect(chart.hasFilter(d.key)).toBeTruthy(); + expect(_chart.hasFilter(d.key)).toBeTruthy(); } else { - expect(chart.hasFilter(d.key)).toBeFalsy(); + expect(_chart.hasFilter(d.key)).toBeFalsy(); } }); } - describe('with nothing previously filtered', function () { - it('should filter all cells on that axis', function () { + describe('with nothing previously filtered', () => { + it('should filter all cells on that axis', () => { chart.selectAll('.cols.axis text').each(function (d) { - var axisLabel = d3.select(this); - axisLabel.on('click')(d); + const axisLabel = d3.select(this); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, d); assertOnlyThisAxisIsFiltered(chart, 0, d); - axisLabel.on('click')(d); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, d); }); chart.selectAll('.rows.axis text').each(function (d) { - var axisLabel = d3.select(this); - axisLabel.on('click')(d); + const axisLabel = d3.select(this); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, d); assertOnlyThisAxisIsFiltered(chart, 1, d); - axisLabel.on('click')(d); + dc.d3compat.callHandler(axisLabel.on('click'), null, {}, d); }); }); }); - describe('with one cell on that axis already filtered', function () { - it('should filter all cells on that axis (and the original cell should remain filtered)', function () { - var boxes = chart.selectAll('.box-group'); - var box = d3.select(boxes[0][Math.floor(Math.random() * boxes.length)]); + describe('with one cell on that axis already filtered', () => { + it('should filter all cells on that axis (and the original cell should remain filtered)', () => { + const boxNodes = chart.selectAll('.box-group').nodes(); + const box = d3.select(boxNodes[Math.floor(Math.random() * boxNodes.length)]); - box.select('rect').on('click')(box.datum()); + dc.d3compat.callHandler(box.select('rect').on('click'), null, {}, box.datum()); expect(chart.hasFilter(box.datum().key)).toBeTruthy(); - var xVal = box.datum().key[0]; + const xVal = box.datum().key[0]; - var columns = chart.selectAll('.cols.axis text'); - var column = columns.filter(function (columnData) { - return columnData === xVal; - }); + const columns = chart.selectAll('.cols.axis text'); + const column = columns.filter(columnData => columnData === xVal); - column.on('click')(column.datum()); + dc.d3compat.callHandler(column.on('click'), null, {}, column.datum()); assertOnlyThisAxisIsFiltered(chart, 0, xVal); - column.on('click')(column.datum()); + dc.d3compat.callHandler(column.on('click'), null, {}, column.datum()); }); }); - describe('with all cells on that axis already filtered', function () { - it('should remove all filters on that axis', function () { - var xVal = 1; + describe('with all cells on that axis already filtered', () => { + it('should remove all filters on that axis', () => { + const xVal = 1; chart.selectAll('.box-group').each(function (d) { - var box = d3.select(this); + const box = d3.select(this); if (d.key[0] === xVal) { - box.select('rect').on('click')(box.datum()); + dc.d3compat.callHandler(box.select('rect').on('click'), null, {}, box.datum()); } }); assertOnlyThisAxisIsFiltered(chart, 0, xVal); - var columns = chart.selectAll('.cols.axis text'); - var column = columns.filter(function (columnData) { - return columnData === xVal; - }); + const columns = chart.selectAll('.cols.axis text'); + const column = columns.filter(columnData => columnData === xVal); - column.on('click')(column.datum()); + dc.d3compat.callHandler(column.on('click'), null, {}, column.datum()); - chart.select('.box-group').each(function (d) { + chart.select('.box-group').each(d => { expect(chart.hasFilter(d.key)).toBeFalsy(); }); }); }); }); }); + describe('iris filtering', () => { + /* eslint camelcase: 0 */ + // 2-chart version of from http://bl.ocks.org/gordonwoodhull/14c623b95993808d69620563508edba6 + let irisData, bubbleChart, petalDim, petalGroup; + const fields = { + sl: 'sepal_length', + sw: 'sepal_width', + pl: 'petal_length', + pw: 'petal_width' + }; + const keyfuncs = {}; + + function duo_key (ab1, ab2) { + return function (d) { + return [keyfuncs[ab1](d[fields[ab1]]), keyfuncs[ab2](d[fields[ab2]])]; + }; + } + beforeEach(() => { + irisData = loadIrisFixture(); + + const species = ['setosa', 'versicolor', 'virginica']; + + irisData.forEach(d => { + Object.keys(fields).forEach(ab => { + d[fields[ab]] = +d[fields[ab]]; + }); + }); + // autogenerate a key function for an extent + function key_function (extent) { + const div = extent[1] - extent[0] < 5 ? 2 : 1; + return function (k) { + return Math.floor(k * div) / div; + }; + } + + const extents = {}; + Object.keys(fields).forEach(ab => { + extents[ab] = d3.extent(irisData, d => d[fields[ab]]); + keyfuncs[ab] = key_function(extents[ab]); + }); + data = crossfilter(irisData); + function key_part (i) { + return function (kv) { + return kv.key[i]; + }; + } + function reduce_species (grp) { + grp.reduce( + (p, v) => { + p[v.species]++; + p.total++; + return p; + }, (p, v) => { + p[v.species]--; + p.total--; + return p; + }, () => { + const init = {total: 0}; + species.forEach(s => { init[s] = 0; }); + return init; + } + ); + } + function max_species (d) { + let max = 0, i = -1; + species.forEach((s, j) => { + if (d.value[s] > max) { + max = d.value[s]; + i = j; + } + }); + return i >= 0 ? species[i] : null; + } + function initialize_bubble (bblChart) { + bblChart + .width(400) + .height(400) + .transitionDuration(0) + .x(d3.scaleLinear()).xAxisPadding(0.5) + .y(d3.scaleLinear()).yAxisPadding(0.5) + .elasticX(true) + .elasticY(true) + .label(dc.utils.constant('')) + .keyAccessor(key_part(0)) + .valueAccessor(key_part(1)) + .r(d3.scaleLinear().domain([0,20]).range([4,25])) + .radiusValueAccessor(kv => kv.value.total) + .colors(d3.scaleOrdinal() + .domain(species.concat('none')) + .range(['#e41a1c','#377eb8','#4daf4a', '#f8f8f8'])) + .colorAccessor(d => max_species(d) || 'none'); + } + function initialize_heatmap (heatMap) { + heatMap + .width(400) + .height(400) + .xBorderRadius(15).yBorderRadius(15) + .keyAccessor(key_part(0)) + .valueAccessor(key_part(1)) + .colors(d3.scaleOrdinal() + .domain(species.concat('none')) + .range(['#e41a1c','#377eb8','#4daf4a', '#f8f8f8'])) + .colorAccessor(d => max_species(d) || 'none') + .renderTitle(true) + .title(d => JSON.stringify(d.value, null, 2)); + } + + const bubbleId = 'bubble-chart'; + appendChartID(bubbleId); + + bubbleChart = new dc.BubbleChart(`#${bubbleId}`); + const sepalDim = data.dimension(duo_key('sl', 'sw')), sepalGroup = sepalDim.group(); + petalDim = data.dimension(duo_key('pl', 'pw')); petalGroup = petalDim.group(); + + reduce_species(sepalGroup); + reduce_species(petalGroup); + initialize_bubble(bubbleChart.dimension(sepalDim).group(sepalGroup)); + initialize_heatmap(chart.dimension(petalDim).group(petalGroup)); + bubbleChart.render(); + chart.render(); + }); + // return brand-new objects and keys every time + function clone_group (grp) { + function clone_kvs (all) { + return all.map(kv => ({ + key: kv.key.slice(0), + value: Object.assign({}, kv.value) + })); + } + return { + all: function () { + return clone_kvs(grp.all()); + }, + top: function (N) { + return clone_kvs(grp.top(N)); + } + }; + } + + function testRectFillsBubble12 (bblChart) { + const rects = bblChart.selectAll('rect').nodes(); + expect(d3.select(rects[0]).attr('fill')).toMatch(/#f8f8f8/i); + expect(d3.select(rects[3]).attr('fill')).toMatch(/#377eb8/i); + expect(d3.select(rects[4]).attr('fill')).toMatch(/#377eb8/i); + expect(d3.select(rects[7]).attr('fill')).toMatch(/#4daf4a/i); + expect(d3.select(rects[8]).attr('fill')).toMatch(/#f8f8f8/i); + expect(d3.select(rects[10]).attr('fill')).toMatch(/#f8f8f8/i); + expect(d3.select(rects[11]).attr('fill')).toMatch(/#f8f8f8/i); + expect(d3.select(rects[12]).attr('fill')).toMatch(/#f8f8f8/i); + } + function testRectTitlesBubble12 (bblChart) { + const titles = bblChart.selectAll('g.box-group title').nodes(); + expect(JSON.parse(d3.select(titles[0]).text()).total).toBe(0); + expect(JSON.parse(d3.select(titles[2]).text()).total).toBe(0); + expect(JSON.parse(d3.select(titles[3]).text()).total).toBe(2); + expect(JSON.parse(d3.select(titles[4]).text()).total).toBe(3); + expect(JSON.parse(d3.select(titles[5]).text()).total).toBe(0); + expect(JSON.parse(d3.select(titles[7]).text()).total).toBe(1); + expect(JSON.parse(d3.select(titles[9]).text()).total).toBe(0); + expect(JSON.parse(d3.select(titles[10]).text()).total).toBe(0); + expect(JSON.parse(d3.select(titles[12]).text()).total).toBe(0); + } + + describe('bubble filtering with straight crossfilter', () => { + beforeEach(() => { + bubbleChart.filter(duo_key('sl', 'sw')({sepal_length: 5.5, sepal_width: 3})).redrawGroup(); + }); + it('updates rect fills correctly', () => { + testRectFillsBubble12(chart); + }); + it('updates rect titles correctly', () => { + testRectTitlesBubble12(chart); + }); + }); + describe('column filtering with cloned results', () => { + beforeEach(() => { + chart.group(clone_group(petalGroup)); + chart.render(); + bubbleChart.filter(duo_key('sl', 'sw')({sepal_length: 5.5, sepal_width: 3})).redrawGroup(); + }); + it('updates rect fills correctly', () => { + testRectFillsBubble12(chart); + }); + it('updates rect titles correctly', () => { + testRectTitlesBubble12(chart); + }); + }); + }); + + describe('accessibility heatmap', () => { + + beforeEach(() => { + chart.keyboardAccessible(true); + }) + + it('internal elements are focusable by keyboard', () => { + + chart.render(); + chart.selectAll('rect.heat-box').each(function () { + const bar = d3.select(this); + expect(bar.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + const clickHandlerSpy = jasmine.createSpy(); + chart.boxOnClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('rect.heat-box').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + }); }); diff --git a/spec/helpers/custom_matchers.js b/spec/helpers/custom_matchers.js index 557d45710f..69823e8f1a 100644 --- a/spec/helpers/custom_matchers.js +++ b/spec/helpers/custom_matchers.js @@ -1,5 +1,5 @@ function parseTranslate (actual) { - var parts = /translate\((-?[\d\.]*)(?:[, ](.*))?\)/.exec(actual); + const parts = /translate\((-?[\d\.]*)(?:[, ](.*))?\)/.exec(actual); if (!parts) { return null; } @@ -11,7 +11,7 @@ function parseTranslate (actual) { } function parseTranslateRotate (actual) { - var parts = /translate\((-?[\d\.]*)(?:[, ](.*))?\)[, ]rotate\((-?[\d\.]*)\)/.exec(actual); + const parts = /translate\((-?[\d\.]*)(?:[, ](.*))?\)[, ]rotate\((-?[\d\.]*)\)/.exec(actual); if (!parts) { return null; } @@ -25,12 +25,14 @@ function parseTranslateRotate (actual) { function parsePath (path) { // an svg path is a string of any number of letters // each followed by zero or more numbers separated by spaces or commas - var instrexp = /([a-z])[^a-z]*/gi, + const instrexp = /([a-z])[^a-z]*/gi, argexp = /(-?\d+(?:\.\d*)?)[, ]*/gi; - var match, result = [], die = 99; + let match; + const result = []; + let die = 99; while ((match = instrexp.exec(path))) { - var instr = match[0]; - var cmd = {op: match[1], args: []}; + const instr = match[0]; + const cmd = {op: match[1], args: []}; argexp.lastIndex = 0; while ((match = argexp.exec(instr))) { cmd.args.push(match[1]); @@ -49,15 +51,15 @@ function compareWithinDelta (actual, expected, delta) { delta = 1e-6; } - var result = {}; + const result = {}; result.pass = actual >= (+expected - delta) && actual <= (+expected + delta); - var pre = 'Expected ' + actual + ' to ', - post = 'be within [' + (+expected - delta) + '/' + (+expected + delta) + ']'; + const pre = `Expected ${actual} to `, + post = `be within [${+expected - delta}/${+expected + delta}]`; if (result.pass) { - result.message = pre + 'not ' + post; + result.message = `${pre}not ${post}`; } else { result.message = pre + post; } @@ -69,26 +71,26 @@ function compareWithinDelta (actual, expected, delta) { // failure instead of using expect function compareSubPath (got, wanted, i, j, delta) { - for (var k = 0; k !== wanted.length; ++k) { - var commandNum = 'path command #' + i + k; + for (let k = 0; k !== wanted.length; ++k) { + const commandNum = `path command #${i}${k}`; if (got[i + k].op.toUpperCase() !== wanted[j + k].op.toUpperCase()) { return { pass: false, - message: commandNum + ' actual \'' + got[i + k].op.toUpperCase() + - '\' != expected \'' + wanted[j + k].op.toUpperCase() + '\'' + message: `${commandNum} actual '${got[i + k].op.toUpperCase() + }' != expected '${wanted[j + k].op.toUpperCase()}'` }; } if (got[i + k].args.length !== wanted[j + k].args.length) { return { pass: false, - message: commandNum + ' number of arguments ' + - got[i + k].args.length + ' != expected ' + wanted[j + k].args.length + message: `${commandNum} number of arguments ${ + got[i + k].args.length} != expected ${wanted[j + k].args.length}` }; } - for (var h = 0; h < got[i + k].args.length; ++h) { - var result = compareWithinDelta(got[i + k].args[h], wanted[j + k].args[h], delta); + for (let h = 0; h < got[i + k].args.length; ++h) { + const result = compareWithinDelta(got[i + k].args[h], wanted[j + k].args[h], delta); if (!result.pass) { - result.message = commandNum + ', element ' + h + ': ' + result.message; + result.message = `${commandNum}, element ${h}: ${result.message}`; return result; } } @@ -98,13 +100,13 @@ function compareSubPath (got, wanted, i, j, delta) { function comparePaths (actual, expected, delta) { delta = delta || 1; // default delta of 1px - var got = parsePath(actual), + const got = parsePath(actual), wanted = parsePath(expected); if (got.length !== wanted.length) { return { pass: false, - message: 'actual number of path cmds ' + actual.length + - ' did not match expected number ' + expected.length + message: `actual number of path cmds ${actual.length + } did not match expected number ${expected.length}` }; } return compareSubPath(got, wanted, 0, 0, delta); @@ -112,44 +114,59 @@ function comparePaths (actual, expected, delta) { function findSubPath (actual, expected, delta) { delta = delta || 1; // default delta of 1px - var got = parsePath(actual), + const got = parsePath(actual), wanted = parsePath(expected), end = got.length - wanted.length; - for (var i = 0; i < end; ++i) { - var result = compareSubPath(got, wanted, i, 0, delta); + for (let i = 0; i < end; ++i) { + const result = compareSubPath(got, wanted, i, 0, delta); if (result.pass) { return result; } } return { pass: false, - message: 'did not find expected subpath \'' + expected + '\' in actual path \'' + actual + '\'' + message: `did not find expected subpath '${expected}' in actual path '${actual}'` }; } -// actually number list, but presumably you'd want closeness if you need that -function compareIntList (actual, expected) { - var aparts = actual.split(/, */), +function compareIntListOptSuffix (actual, expected, suffix) { + const aparts = actual.split(/, */), eparts = expected.split(/, */); if (aparts.length !== eparts.length) { return { pass: false, - message: 'actual number of list items ' + aparts.length + - ' did not match expected number ' + eparts.length + message: `actual number of list items ${aparts.length + } did not match expected number ${eparts.length}` }; } - for (var i = 0; i < eparts.length; ++i) { - if (+aparts[i] !== +eparts[i]) { + const suffixRE = suffix ? new RegExp(`${suffix}$`) : ''; + for (let i = 0; i < eparts.length; ++i) { + const apart = aparts[i].replace(suffixRE, ''); + if (+apart !== +eparts[i]) { return { pass: false, - message: 'list item[' + i + '] value ' + aparts[i] + ' did not equal expected value ' + eparts[i] + message: `list item[${i}] value ${aparts[i]} did not equal expected value ${eparts[i]}` }; } } return {pass: true}; } +// actually number list, but presumably you'd want closeness if you need that +function compareIntList (actual, expected) { + return compareIntListOptSuffix(actual, expected); +} + +// Edge will tack 'px' onto dash array items; I'm sure this is technically more correct +function compareIntOrPixelList (actual, expected) { + return compareIntListOptSuffix(actual, expected, 'px'); +} + +function normalizeColor (c) { + // will convert to rgb(0, 0, 0) + return d3.color(c).toString(); +} -beforeEach(function () { +beforeEach(() => { jasmine.addMatchers({ toBeWithinDelta: function (_) { return { @@ -161,9 +178,9 @@ beforeEach(function () { toMatchTranslate: function () { return { compare: function (actual, x, y, prec) { - var parts = parseTranslate(actual); + const parts = parseTranslate(actual); if (!parts) { - return {pass: false, message: '\'' + actual + '\' did not match translate(x[,y]) regexp'}; + return {pass: false, message: `'${actual}' did not match translate(x[,y]) regexp`}; } expect(+parts[1]).toBeCloseTo(x, prec); expect(+parts[2]).toBeCloseTo(y, prec); @@ -174,9 +191,9 @@ beforeEach(function () { toMatchTransRot: function () { return { compare: function (actual, x, y, r, prec) { - var parts = parseTranslateRotate(actual); + const parts = parseTranslateRotate(actual); if (!parts) { - return {pass: false, message: '\'' + actual + '\' did not match translate(x[,y]),rotate(r) regexp'}; + return {pass: false, message: `'${actual}' did not match translate(x[,y]),rotate(r) regexp`}; } expect(+parts[1]).toBeCloseTo(x, prec); expect(+parts[2]).toBeCloseTo(y, prec); @@ -188,8 +205,21 @@ beforeEach(function () { toMatchUrl: function () { return { compare: function (actual, url) { - var regexp = new RegExp('url\\("?' + url + '"?\\)'); - expect(actual).toMatch(regexp); + /* + URL can be like: + url(http://localhost:8888/spec/?random=true#composite-chart-clip) + url("http://localhost:8888/spec/?random=true#composite-chart-clip") + http://localhost:8888/spec/?random=true#composite-chart-clip + http://localhost:8888/spec/##composite-chart-clip + */ + const cleanURL = function (u) { + const matches = u.match(/url\((.*)\)/); + if (matches) { + u = matches[1].replace(/"/g, ''); + } + return u.replace(/\#+/, '#'); + }; + expect(cleanURL(actual)).toEqual(cleanURL(url)); return {pass: true}; } }; @@ -208,6 +238,32 @@ beforeEach(function () { return { compare: compareIntList }; + }, + toEqualIntOrPixelList: function () { + return { + compare: compareIntOrPixelList + }; + }, + toMatchColor: function () { + return { + compare: function (actual, expected) { + // Colors can be rgb(0, 0, 0), #000000 or black + expect(normalizeColor(actual)).toEqual(normalizeColor(expected)); + return {pass: true}; + } + }; + }, + toMatchColors: function () { + return { + compare: function (actual, expected) { + // Colors can be rgb(0, 0, 0), #000000 or black + actual = actual.map(normalizeColor); + expected = expected.map(normalizeColor); + + expect(actual).toEqual(expected); + return {pass: true}; + } + }; } }); }); diff --git a/spec/helpers/fixtures.js b/spec/helpers/fixtures.js index 7f37a02508..4b448a6733 100644 --- a/spec/helpers/fixtures.js +++ b/spec/helpers/fixtures.js @@ -1,33 +1,32 @@ -/* jscs:disable validateQuoteMarks, maximumLineLength */ -/* jshint -W109, -W101, -W098 */ +/* eslint "max-len": 0, "quotes": 0, "no-unused-vars": 0 */ function dateCleaner (e) { - e.dd = d3.time.format.iso.parse(e.date); + e.dd = d3.isoParse(e.date); } function loadDateFixture () { - var fixture = JSON.parse("[" + - "{\"value\":\"44\",\"nvalue\":\"-4\",\"countrycode\":\"US\",\"state\":\"California\",\"status\":\"T\",\"id\":1,\"region\":\"South\",\"date\":\"2012-05-25T16:10:09Z\"}, " + - "{\"value\":\"22\",\"nvalue\":\"-2\",\"countrycode\":\"US\",\"state\":\"Colorado\",\"status\":\"F\",\"id\":2,\"region\":\"West\",\"date\":\"2012-06-10T16:10:19Z\"}, " + - "{\"value\":\"33\",\"nvalue\":\"1\",\"countrycode\":\"US\",\"state\":\"Delaware\",\"status\":\"T\",\"id\":3,\"region\":\"West\",\"date\":\"2012-08-10T16:20:29Z\"}, " + - "{\"value\":\"44\",\"nvalue\":\"-3\",\"countrycode\":\"US\",\"state\":\"California\",\"status\":\"F\",\"id\":4,\"region\":\"South\",\"date\":\"2012-07-01T16:10:39Z\"}, " + - "{\"value\":\"55\",\"nvalue\":\"-5\",\"countrycode\":\"CA\",\"state\":\"Ontario\",\"status\":\"T\",\"id\":5,\"region\":\"Central\",\"date\":\"2012-06-10T16:10:49Z\"}, " + - "{\"value\":\"66\",\"nvalue\":\"-4\",\"countrycode\":\"US\",\"state\":\"California\",\"status\":\"F\",\"id\":6,\"region\":\"West\",\"date\":\"2012-06-08T16:10:59Z\"}, " + - "{\"value\":\"22\",\"nvalue\":\"10\",\"countrycode\":\"CA\",\"state\":\"Ontario\",\"status\":\"T\",\"id\":7,\"region\":\"East\",\"date\":\"2012-07-10T16:10:09Z\"}, " + - "{\"value\":\"33\",\"nvalue\":\"1\",\"countrycode\":\"US\",\"state\":\"Mississippi\",\"status\":\"F\",\"id\":8,\"region\":\"Central\",\"date\":\"2012-07-10T16:10:19Z\"}, " + - "{\"value\":\"44\",\"nvalue\":\"2\",\"countrycode\":\"US\",\"state\":\"Mississippi\",\"status\":\"T\",\"id\":9,\"region\":\"Central\",\"date\":\"2012-08-10T16:30:29Z\"}, " + - "{\"value\":\"55\",\"nvalue\":\"-3\",\"countrycode\":\"US\",\"state\":\"Oklahoma\",\"status\":\"F\",\"id\":10,\"region\":\"\",\"date\":\"2012-06-10T16:10:39Z\"}" + - "]"); + const fixture = JSON.parse('[' + + '{"value":"44","nvalue":"-4","countrycode":"US","state":"California","status":"T","id":1,"region":"South","date":"2012-05-25T16:10:09Z"}, ' + + '{"value":"22","nvalue":"-2","countrycode":"US","state":"Colorado","status":"F","id":2,"region":"West","date":"2012-06-10T16:10:19Z"}, ' + + '{"value":"33","nvalue":"1","countrycode":"US","state":"Delaware","status":"T","id":3,"region":"West","date":"2012-08-10T16:20:29Z"}, ' + + '{"value":"44","nvalue":"-3","countrycode":"US","state":"California","status":"F","id":4,"region":"South","date":"2012-07-01T16:10:39Z"}, ' + + '{"value":"55","nvalue":"-5","countrycode":"CA","state":"Ontario","status":"T","id":5,"region":"Central","date":"2012-06-10T16:10:49Z"}, ' + + '{"value":"66","nvalue":"-4","countrycode":"US","state":"California","status":"F","id":6,"region":"West","date":"2012-06-08T16:10:59Z"}, ' + + '{"value":"22","nvalue":"10","countrycode":"CA","state":"Ontario","status":"T","id":7,"region":"East","date":"2012-07-10T16:10:09Z"}, ' + + '{"value":"33","nvalue":"1","countrycode":"US","state":"Mississippi","status":"F","id":8,"region":"Central","date":"2012-07-10T16:10:19Z"}, ' + + '{"value":"44","nvalue":"2","countrycode":"US","state":"Mississippi","status":"T","id":9,"region":"Central","date":"2012-08-10T16:30:29Z"}, ' + + '{"value":"55","nvalue":"-3","countrycode":"US","state":"Oklahoma","status":"F","id":10,"region":"","date":"2012-06-10T16:10:39Z"}' + + ']'); fixture.forEach(dateCleaner); return fixture; } function loadDateFixture2 () { - var fixture = JSON.parse( - "[" + - "{\"value\":\"11\",\"nvalue\":\"-4\",\"countrycode\":\"UK\",\"state\":\"Liverpool\",\"status\":\"T\",\"id\":11,\"region\":\"South\",\"date\":\"2012-05-25T16:20:09Z\"}, " + - "{\"value\":\"76\",\"nvalue\":\"-1\",\"countrycode\":\"UK\",\"state\":\"London\",\"status\":\"F\",\"id\":12,\"region\":\"\",\"date\":\"2012-06-10T16:20:39Z\"}" + - "]"); + const fixture = JSON.parse( + '[' + + '{"value":"11","nvalue":"-4","countrycode":"UK","state":"Liverpool","status":"T","id":11,"region":"South","date":"2012-05-25T16:20:09Z"}, ' + + '{"value":"76","nvalue":"-1","countrycode":"UK","state":"London","status":"F","id":12,"region":"","date":"2012-06-10T16:20:39Z"}' + + ']'); fixture.forEach(dateCleaner); return fixture; @@ -77,5 +76,184 @@ function loadColorFixture2 () { "{\"colData\":\"6\", \"rowData\": \"6\", \"colorData\": \"8\"}" + "]"); } -/* jscs:enable validateQuoteMarks, maximumLineLength */ -/* jshint +W109, +W101, +W098 */ + +function loadIrisFixture () { + return d3.csvParse( + "sepal_length,sepal_width,petal_length,petal_width,species\n" + + "5.1,3.5,1.4,0.2,setosa\n" + + "4.9,3,1.4,0.2,setosa\n" + + "4.7,3.2,1.3,0.2,setosa\n" + + "4.6,3.1,1.5,0.2,setosa\n" + + "5,3.6,1.4,0.2,setosa\n" + + "5.4,3.9,1.7,0.4,setosa\n" + + "4.6,3.4,1.4,0.3,setosa\n" + + "5,3.4,1.5,0.2,setosa\n" + + "4.4,2.9,1.4,0.2,setosa\n" + + "4.9,3.1,1.5,0.1,setosa\n" + + "5.4,3.7,1.5,0.2,setosa\n" + + "4.8,3.4,1.6,0.2,setosa\n" + + "4.8,3,1.4,0.1,setosa\n" + + "4.3,3,1.1,0.1,setosa\n" + + "5.8,4,1.2,0.2,setosa\n" + + "5.7,4.4,1.5,0.4,setosa\n" + + "5.4,3.9,1.3,0.4,setosa\n" + + "5.1,3.5,1.4,0.3,setosa\n" + + "5.7,3.8,1.7,0.3,setosa\n" + + "5.1,3.8,1.5,0.3,setosa\n" + + "5.4,3.4,1.7,0.2,setosa\n" + + "5.1,3.7,1.5,0.4,setosa\n" + + "4.6,3.6,1,0.2,setosa\n" + + "5.1,3.3,1.7,0.5,setosa\n" + + "4.8,3.4,1.9,0.2,setosa\n" + + "5,3,1.6,0.2,setosa\n" + + "5,3.4,1.6,0.4,setosa\n" + + "5.2,3.5,1.5,0.2,setosa\n" + + "5.2,3.4,1.4,0.2,setosa\n" + + "4.7,3.2,1.6,0.2,setosa\n" + + "4.8,3.1,1.6,0.2,setosa\n" + + "5.4,3.4,1.5,0.4,setosa\n" + + "5.2,4.1,1.5,0.1,setosa\n" + + "5.5,4.2,1.4,0.2,setosa\n" + + "4.9,3.1,1.5,0.1,setosa\n" + + "5,3.2,1.2,0.2,setosa\n" + + "5.5,3.5,1.3,0.2,setosa\n" + + "4.9,3.1,1.5,0.1,setosa\n" + + "4.4,3,1.3,0.2,setosa\n" + + "5.1,3.4,1.5,0.2,setosa\n" + + "5,3.5,1.3,0.3,setosa\n" + + "4.5,2.3,1.3,0.3,setosa\n" + + "4.4,3.2,1.3,0.2,setosa\n" + + "5,3.5,1.6,0.6,setosa\n" + + "5.1,3.8,1.9,0.4,setosa\n" + + "4.8,3,1.4,0.3,setosa\n" + + "5.1,3.8,1.6,0.2,setosa\n" + + "4.6,3.2,1.4,0.2,setosa\n" + + "5.3,3.7,1.5,0.2,setosa\n" + + "5,3.3,1.4,0.2,setosa\n" + + "7,3.2,4.7,1.4,versicolor\n" + + "6.4,3.2,4.5,1.5,versicolor\n" + + "6.9,3.1,4.9,1.5,versicolor\n" + + "5.5,2.3,4,1.3,versicolor\n" + + "6.5,2.8,4.6,1.5,versicolor\n" + + "5.7,2.8,4.5,1.3,versicolor\n" + + "6.3,3.3,4.7,1.6,versicolor\n" + + "4.9,2.4,3.3,1,versicolor\n" + + "6.6,2.9,4.6,1.3,versicolor\n" + + "5.2,2.7,3.9,1.4,versicolor\n" + + "5,2,3.5,1,versicolor\n" + + "5.9,3,4.2,1.5,versicolor\n" + + "6,2.2,4,1,versicolor\n" + + "6.1,2.9,4.7,1.4,versicolor\n" + + "5.6,2.9,3.6,1.3,versicolor\n" + + "6.7,3.1,4.4,1.4,versicolor\n" + + "5.6,3,4.5,1.5,versicolor\n" + + "5.8,2.7,4.1,1,versicolor\n" + + "6.2,2.2,4.5,1.5,versicolor\n" + + "5.6,2.5,3.9,1.1,versicolor\n" + + "5.9,3.2,4.8,1.8,versicolor\n" + + "6.1,2.8,4,1.3,versicolor\n" + + "6.3,2.5,4.9,1.5,versicolor\n" + + "6.1,2.8,4.7,1.2,versicolor\n" + + "6.4,2.9,4.3,1.3,versicolor\n" + + "6.6,3,4.4,1.4,versicolor\n" + + "6.8,2.8,4.8,1.4,versicolor\n" + + "6.7,3,5,1.7,versicolor\n" + + "6,2.9,4.5,1.5,versicolor\n" + + "5.7,2.6,3.5,1,versicolor\n" + + "5.5,2.4,3.8,1.1,versicolor\n" + + "5.5,2.4,3.7,1,versicolor\n" + + "5.8,2.7,3.9,1.2,versicolor\n" + + "6,2.7,5.1,1.6,versicolor\n" + + "5.4,3,4.5,1.5,versicolor\n" + + "6,3.4,4.5,1.6,versicolor\n" + + "6.7,3.1,4.7,1.5,versicolor\n" + + "6.3,2.3,4.4,1.3,versicolor\n" + + "5.6,3,4.1,1.3,versicolor\n" + + "5.5,2.5,4,1.3,versicolor\n" + + "5.5,2.6,4.4,1.2,versicolor\n" + + "6.1,3,4.6,1.4,versicolor\n" + + "5.8,2.6,4,1.2,versicolor\n" + + "5,2.3,3.3,1,versicolor\n" + + "5.6,2.7,4.2,1.3,versicolor\n" + + "5.7,3,4.2,1.2,versicolor\n" + + "5.7,2.9,4.2,1.3,versicolor\n" + + "6.2,2.9,4.3,1.3,versicolor\n" + + "5.1,2.5,3,1.1,versicolor\n" + + "5.7,2.8,4.1,1.3,versicolor\n" + + "6.3,3.3,6,2.5,virginica\n" + + "5.8,2.7,5.1,1.9,virginica\n" + + "7.1,3,5.9,2.1,virginica\n" + + "6.3,2.9,5.6,1.8,virginica\n" + + "6.5,3,5.8,2.2,virginica\n" + + "7.6,3,6.6,2.1,virginica\n" + + "4.9,2.5,4.5,1.7,virginica\n" + + "7.3,2.9,6.3,1.8,virginica\n" + + "6.7,2.5,5.8,1.8,virginica\n" + + "7.2,3.6,6.1,2.5,virginica\n" + + "6.5,3.2,5.1,2,virginica\n" + + "6.4,2.7,5.3,1.9,virginica\n" + + "6.8,3,5.5,2.1,virginica\n" + + "5.7,2.5,5,2,virginica\n" + + "5.8,2.8,5.1,2.4,virginica\n" + + "6.4,3.2,5.3,2.3,virginica\n" + + "6.5,3,5.5,1.8,virginica\n" + + "7.7,3.8,6.7,2.2,virginica\n" + + "7.7,2.6,6.9,2.3,virginica\n" + + "6,2.2,5,1.5,virginica\n" + + "6.9,3.2,5.7,2.3,virginica\n" + + "5.6,2.8,4.9,2,virginica\n" + + "7.7,2.8,6.7,2,virginica\n" + + "6.3,2.7,4.9,1.8,virginica\n" + + "6.7,3.3,5.7,2.1,virginica\n" + + "7.2,3.2,6,1.8,virginica\n" + + "6.2,2.8,4.8,1.8,virginica\n" + + "6.1,3,4.9,1.8,virginica\n" + + "6.4,2.8,5.6,2.1,virginica\n" + + "7.2,3,5.8,1.6,virginica\n" + + "7.4,2.8,6.1,1.9,virginica\n" + + "7.9,3.8,6.4,2,virginica\n" + + "6.4,2.8,5.6,2.2,virginica\n" + + "6.3,2.8,5.1,1.5,virginica\n" + + "6.1,2.6,5.6,1.4,virginica\n" + + "7.7,3,6.1,2.3,virginica\n" + + "6.3,3.4,5.6,2.4,virginica\n" + + "6.4,3.1,5.5,1.8,virginica\n" + + "6,3,4.8,1.8,virginica\n" + + "6.9,3.1,5.4,2.1,virginica\n" + + "6.7,3.1,5.6,2.4,virginica\n" + + "6.9,3.1,5.1,2.3,virginica\n" + + "5.8,2.7,5.1,1.9,virginica\n" + + "6.8,3.2,5.9,2.3,virginica\n" + + "6.7,3.3,5.7,2.5,virginica\n" + + "6.7,3,5.2,2.3,virginica\n" + + "6.3,2.5,5,1.9,virginica\n" + + "6.5,3,5.2,2,virginica\n" + + "6.2,3.4,5.4,2.3,virginica\n" + + "5.9,3,5.1,1.8,virginica" + ); +} + +function getSunburstDataOneRing3Segments () { + return [ + {"x":"a","y":1}, + {"x":"b","y":2}, + {"x":"c","y":3} + ]; +} + +function loadSunburstData3CompleteRings () { + return [ + {"x1":"a","x2":"aa","x3":"aaa","y":1}, + {"x1":"a","x2":"aa","x3":"aaa","y":2}, + {"x1":"a","x2":"aa","x3":"aaa","y":3} + ]; +} + +function loadSunburstData10CompleteRings () { + return [ + {"x0": "a", "x1": "a", "x2": "a", "x3": "a", "x4": "a", "x5": "a", "x6": "a", "x7": "a", "x8": "a", "x9": "a", "y": 1}, + {"x0": "a", "x1": "a", "x2": "a", "x3": "a", "x4": "a", "x5": "a", "x6": "a", "x7": "a", "x8": "a", "x9": "a", "y": 1}, + {"x0": "a", "x1": "a", "x2": "a", "x3": "a", "x4": "a", "x5": "a", "x6": "a", "x7": "a", "x8": "a", "x9": "a", "y": 1}, + {"x0": "a", "x1": "a", "x2": "a", "x3": "a", "x4": "a", "x5": "a", "x6": "a", "x7": "a", "x8": "a", "x9": "a", "y": 1}, + ]; +} diff --git a/spec/helpers/geoFixtures.js b/spec/helpers/geoFixtures.js index eee053459e..1f14b93f57 100644 --- a/spec/helpers/geoFixtures.js +++ b/spec/helpers/geoFixtures.js @@ -1,5 +1,4 @@ -/* jscs:disable validateQuoteMarks, maximumLineLength */ -/* jshint -W109, -W101, -W098 */ +/* eslint "max-len": 0, "quotes": 0, "no-unused-vars": 0 */ function loadGeoFixture () { return JSON.parse('{"type":"FeatureCollection","features":[{"type":"Feature","id":"01","properties":{"name":"Alabama"},"geometry":{"type":"Polygon","coordinates":[[[-87.359296,35.00118],[-85.606675,34.984749],[-85.431413,34.124869],[-85.184951,32.859696],[-85.069935,32.580372],[-84.960397,32.421541],[-85.004212,32.322956],[-84.889196,32.262709],[-85.058981,32.13674],[-85.053504,32.01077],[-85.141136,31.840985],[-85.042551,31.539753],[-85.113751,31.27686],[-85.004212,31.003013],[-85.497137,30.997536],[-87.600282,30.997536],[-87.633143,30.86609],[-87.408589,30.674397],[-87.446927,30.510088],[-87.37025,30.427934],[-87.518128,30.280057],[-87.655051,30.247195],[-87.90699,30.411504],[-87.934375,30.657966],[-88.011052,30.685351],[-88.10416,30.499135],[-88.137022,30.318396],[-88.394438,30.367688],[-88.471115,31.895754],[-88.241084,33.796253],[-88.098683,34.891641],[-88.202745,34.995703],[-87.359296,35.00118]]]}},' + '{"type":"Feature","id":"02","properties":{"name":"Alaska"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-131.602021,55.117982],[-131.569159,55.28229],[-131.355558,55.183705],[-131.38842,55.01392],[-131.645836,55.035827],[-131.602021,55.117982]]],[[[-131.832052,55.42469],[-131.645836,55.304197],[-131.749898,55.128935],[-131.832052,55.189182],[-131.832052,55.42469]]],[[[-132.976733,56.437924],[-132.735747,56.459832],[-132.631685,56.421493],[-132.664547,56.273616],[-132.878148,56.240754],[-133.069841,56.333862],[-132.976733,56.437924]]],[[[-133.595627,56.350293],[-133.162949,56.317431],[-133.05341,56.125739],[-132.620732,55.912138],[-132.472854,55.780691],[-132.4619,55.671152],[-132.357838,55.649245],[-132.341408,55.506844],[-132.166146,55.364444],[-132.144238,55.238474],[-132.029222,55.276813],[-131.97993,55.178228],[-131.958022,54.789365],[-132.029222,54.701734],[-132.308546,54.718165],[-132.385223,54.915335],[-132.483808,54.898904],[-132.686455,55.046781],[-132.746701,54.997489],[-132.916486,55.046781],[-132.889102,54.898904],[-132.73027,54.937242],[-132.626209,54.882473],[-132.675501,54.679826],[-132.867194,54.701734],[-133.157472,54.95915],[-133.239626,55.090597],[-133.223195,55.22752],[-133.453227,55.216566],[-133.453227,55.320628],[-133.277964,55.331582],[-133.102702,55.42469],[-133.17938,55.588998],[-133.387503,55.62186],[-133.420365,55.884753],[-133.497042,56.0162],[-133.639442,55.923092],[-133.694212,56.070969],[-133.546335,56.142169],[-133.666827,56.311955],[-133.595627,56.350293]]],[[[-133.738027,55.556137],[-133.546335,55.490413],[-133.414888,55.572568],[-133.283441,55.534229],[-133.420365,55.386352],[-133.633966,55.430167],[-133.738027,55.556137]]],[[[-133.907813,56.930849],[-134.050213,57.029434],[-133.885905,57.095157],[-133.343688,57.002049],[-133.102702,57.007526],[-132.932917,56.82131],[-132.620732,56.667956],[-132.653593,56.55294],[-132.817901,56.492694],[-133.042456,56.520078],[-133.201287,56.448878],[-133.420365,56.492694],[-133.66135,56.448878],[-133.710643,56.684386],[-133.688735,56.837741],[-133.869474,56.843218],[-133.907813,56.930849]]],[[[-134.115936,56.48174],[-134.25286,56.558417],[-134.400737,56.722725],[-134.417168,56.848695],[-134.296675,56.908941],[-134.170706,56.848695],[-134.143321,56.952757],[-133.748981,56.772017],[-133.710643,56.596755],[-133.847566,56.574848],[-133.935197,56.377678],[-133.836612,56.322908],[-133.957105,56.092877],[-134.110459,56.142169],[-134.132367,55.999769],[-134.230952,56.070969],[-134.291198,56.350293],[-134.115936,56.48174]]],[[[-134.636246,56.28457],[-134.669107,56.169554],[-134.806031,56.235277],[-135.178463,56.67891],[-135.413971,56.810356],[-135.331817,56.914418],[-135.424925,57.166357],[-135.687818,57.369004],[-135.419448,57.566174],[-135.298955,57.48402],[-135.063447,57.418296],[-134.849846,57.407343],[-134.844369,57.248511],[-134.636246,56.728202],[-134.636246,56.28457]]],[[[-134.712923,58.223407],[-134.373353,58.14673],[-134.176183,58.157683],[-134.187137,58.081006],[-133.902336,57.807159],[-134.099505,57.850975],[-134.148798,57.757867],[-133.935197,57.615466],[-133.869474,57.363527],[-134.083075,57.297804],[-134.154275,57.210173],[-134.499322,57.029434],[-134.603384,57.034911],[-134.6472,57.226604],[-134.575999,57.341619],[-134.608861,57.511404],[-134.729354,57.719528],[-134.707446,57.829067],[-134.784123,58.097437],[-134.91557,58.212453],[-134.953908,58.409623],[-134.712923,58.223407]]],[[[-135.857603,57.330665],[-135.715203,57.330665],[-135.567326,57.149926],[-135.633049,57.023957],[-135.857603,56.996572],[-135.824742,57.193742],[-135.857603,57.330665]]],[[[-136.279328,58.206976],[-135.978096,58.201499],[-135.780926,58.28913],[-135.496125,58.168637],[-135.64948,58.037191],[-135.59471,57.987898],[-135.45231,58.135776],[-135.107263,58.086483],[-134.91557,57.976944],[-135.025108,57.779775],[-134.937477,57.763344],[-134.822462,57.500451],[-135.085355,57.462112],[-135.572802,57.675713],[-135.556372,57.456635],[-135.709726,57.369004],[-135.890465,57.407343],[-136.000004,57.544266],[-136.208128,57.637374],[-136.366959,57.829067],[-136.569606,57.916698],[-136.558652,58.075529],[-136.421728,58.130299],[-136.377913,58.267222],[-136.279328,58.206976]]],[[[-147.079854,60.200582],[-147.501579,59.948643],[-147.53444,59.850058],[-147.874011,59.784335],[-147.80281,59.937689],[-147.435855,60.09652],[-147.205824,60.271782],[-147.079854,60.200582]]],[[[-147.561825,60.578491],[-147.616594,60.370367],[-147.758995,60.156767],[-147.956165,60.227967],[-147.791856,60.474429],[-147.561825,60.578491]]],[[[-147.786379,70.245291],[-147.682318,70.201475],[-147.162008,70.15766],[-146.888161,70.185044],[-146.510252,70.185044],[-146.099482,70.146706],[-145.858496,70.168614],[-145.622988,70.08646],[-145.195787,69.993352],[-144.620708,69.971444],[-144.461877,70.026213],[-144.078491,70.059075],[-143.914183,70.130275],[-143.497935,70.141229],[-143.503412,70.091936],[-143.25695,70.119321],[-142.747594,70.042644],[-142.402547,69.916674],[-142.079408,69.856428],[-142.008207,69.801659],[-141.712453,69.790705],[-141.433129,69.697597],[-141.378359,69.63735],[-141.208574,69.686643],[-141.00045,69.648304],[-141.00045,60.304644],[-140.53491,60.22249],[-140.474664,60.310121],[-139.987216,60.184151],[-139.696939,60.342983],[-139.088998,60.359413],[-139.198537,60.091043],[-139.045183,59.997935],[-138.700135,59.910304],[-138.623458,59.767904],[-137.604747,59.242118],[-137.445916,58.908024],[-137.265177,59.001132],[-136.827022,59.159963],[-136.580559,59.16544],[-136.465544,59.285933],[-136.476498,59.466672],[-136.301236,59.466672],[-136.25742,59.625503],[-135.945234,59.663842],[-135.479694,59.800766],[-135.025108,59.565257],[-135.068924,59.422857],[-134.959385,59.280456],[-134.701969,59.247595],[-134.378829,59.033994],[-134.400737,58.973748],[-134.25286,58.858732],[-133.842089,58.727285],[-133.173903,58.152206],[-133.075318,57.998852],[-132.867194,57.845498],[-132.560485,57.505928],[-132.253777,57.21565],[-132.368792,57.095157],[-132.05113,57.051341],[-132.127807,56.876079],[-131.870391,56.804879],[-131.837529,56.602232],[-131.580113,56.613186],[-131.087188,56.405062],[-130.78048,56.366724],[-130.621648,56.268139],[-130.468294,56.240754],[-130.424478,56.142169],[-130.101339,56.114785],[-130.002754,55.994292],[-130.150631,55.769737],[-130.128724,55.583521],[-129.986323,55.276813],[-130.095862,55.200136],[-130.336847,54.920812],[-130.687372,54.718165],[-130.785957,54.822227],[-130.917403,54.789365],[-131.010511,54.997489],[-130.983126,55.08512],[-131.092665,55.189182],[-130.862634,55.298721],[-130.928357,55.337059],[-131.158389,55.200136],[-131.284358,55.287767],[-131.426759,55.238474],[-131.843006,55.457552],[-131.700606,55.698537],[-131.963499,55.616383],[-131.974453,55.49589],[-132.182576,55.588998],[-132.226392,55.704014],[-132.083991,55.829984],[-132.127807,55.955953],[-132.324977,55.851892],[-132.522147,56.076446],[-132.642639,56.032631],[-132.719317,56.218847],[-132.527624,56.339339],[-132.341408,56.339339],[-132.396177,56.487217],[-132.297592,56.67891],[-132.450946,56.673433],[-132.768609,56.837741],[-132.993164,57.034911],[-133.51895,57.177311],[-133.507996,57.577128],[-133.677781,57.62642],[-133.639442,57.790728],[-133.814705,57.834544],[-134.072121,58.053622],[-134.143321,58.168637],[-134.586953,58.206976],[-135.074401,58.502731],[-135.282525,59.192825],[-135.38111,59.033994],[-135.337294,58.891593],[-135.140124,58.617746],[-135.189417,58.573931],[-135.05797,58.349376],[-135.085355,58.201499],[-135.277048,58.234361],[-135.430402,58.398669],[-135.633049,58.426053],[-135.91785,58.382238],[-135.912373,58.617746],[-136.087635,58.814916],[-136.246466,58.75467],[-136.876314,58.962794],[-136.931084,58.902547],[-136.586036,58.836824],[-136.317666,58.672516],[-136.213604,58.667039],[-136.180743,58.535592],[-136.043819,58.382238],[-136.388867,58.294607],[-136.591513,58.349376],[-136.59699,58.212453],[-136.859883,58.316515],[-136.947514,58.393192],[-137.111823,58.393192],[-137.566409,58.590362],[-137.900502,58.765624],[-137.933364,58.869686],[-138.11958,59.02304],[-138.634412,59.132579],[-138.919213,59.247595],[-139.417615,59.379041],[-139.746231,59.505011],[-139.718846,59.641934],[-139.625738,59.598119],[-139.5162,59.68575],[-139.625738,59.88292],[-139.488815,59.992458],[-139.554538,60.041751],[-139.801,59.833627],[-140.315833,59.696704],[-140.92925,59.745996],[-141.444083,59.871966],[-141.46599,59.970551],[-141.706976,59.948643],[-141.964392,60.019843],[-142.539471,60.085566],[-142.873564,60.091043],[-143.623905,60.036274],[-143.892275,59.997935],[-144.231845,60.140336],[-144.65357,60.206059],[-144.785016,60.29369],[-144.834309,60.441568],[-145.124586,60.430614],[-145.223171,60.299167],[-145.738004,60.474429],[-145.820158,60.551106],[-146.351421,60.408706],[-146.608837,60.238921],[-146.718376,60.397752],[-146.608837,60.485383],[-146.455483,60.463475],[-145.951604,60.578491],[-146.017328,60.666122],[-146.252836,60.622307],[-146.345944,60.737322],[-146.565022,60.753753],[-146.784099,61.044031],[-146.866253,60.972831],[-147.172962,60.934492],[-147.271547,60.972831],[-147.375609,60.879723],[-147.758995,60.912584],[-147.775426,60.808523],[-148.032842,60.781138],[-148.153334,60.819476],[-148.065703,61.005692],[-148.175242,61.000215],[-148.350504,60.803046],[-148.109519,60.737322],[-148.087611,60.594922],[-147.939734,60.441568],[-148.027365,60.277259],[-148.219058,60.332029],[-148.273827,60.249875],[-148.087611,60.217013],[-147.983549,59.997935],[-148.251919,59.95412],[-148.399797,59.997935],[-148.635305,59.937689],[-148.755798,59.986981],[-149.067984,59.981505],[-149.05703,60.063659],[-149.204907,60.008889],[-149.287061,59.904827],[-149.418508,59.997935],[-149.582816,59.866489],[-149.511616,59.806242],[-149.741647,59.729565],[-149.949771,59.718611],[-150.031925,59.61455],[-150.25648,59.521442],[-150.409834,59.554303],[-150.579619,59.444764],[-150.716543,59.450241],[-151.001343,59.225687],[-151.308052,59.209256],[-151.406637,59.280456],[-151.592853,59.159963],[-151.976239,59.253071],[-151.888608,59.422857],[-151.636669,59.483103],[-151.47236,59.472149],[-151.423068,59.537872],[-151.127313,59.669319],[-151.116359,59.778858],[-151.505222,59.63098],[-151.828361,59.718611],[-151.8667,59.778858],[-151.702392,60.030797],[-151.423068,60.211536],[-151.379252,60.359413],[-151.297098,60.386798],[-151.264237,60.545629],[-151.406637,60.720892],[-151.06159,60.786615],[-150.404357,61.038554],[-150.245526,60.939969],[-150.042879,60.912584],[-149.741647,61.016646],[-150.075741,61.15357],[-150.207187,61.257632],[-150.47008,61.246678],[-150.656296,61.29597],[-150.711066,61.252155],[-151.023251,61.180954],[-151.165652,61.044031],[-151.477837,61.011169],[-151.800977,60.852338],[-151.833838,60.748276],[-152.080301,60.693507],[-152.13507,60.578491],[-152.310332,60.507291],[-152.392486,60.304644],[-152.732057,60.173197],[-152.567748,60.069136],[-152.704672,59.915781],[-153.022334,59.888397],[-153.049719,59.691227],[-153.345474,59.620026],[-153.438582,59.702181],[-153.586459,59.548826],[-153.761721,59.543349],[-153.72886,59.433811],[-154.117723,59.368087],[-154.1944,59.066856],[-153.750768,59.050425],[-153.400243,58.968271],[-153.301658,58.869686],[-153.444059,58.710854],[-153.679567,58.612269],[-153.898645,58.606793],[-153.920553,58.519161],[-154.062953,58.4863],[-153.99723,58.376761],[-154.145107,58.212453],[-154.46277,58.059098],[-154.643509,58.059098],[-154.818771,58.004329],[-154.988556,58.015283],[-155.120003,57.955037],[-155.081664,57.872883],[-155.328126,57.829067],[-155.377419,57.708574],[-155.547204,57.785251],[-155.73342,57.549743],[-156.045606,57.566174],[-156.023698,57.440204],[-156.209914,57.473066],[-156.34136,57.418296],[-156.34136,57.248511],[-156.549484,56.985618],[-156.883577,56.952757],[-157.157424,56.832264],[-157.20124,56.766541],[-157.376502,56.859649],[-157.672257,56.607709],[-157.754411,56.67891],[-157.918719,56.657002],[-157.957058,56.514601],[-158.126843,56.459832],[-158.32949,56.48174],[-158.488321,56.339339],[-158.208997,56.295524],[-158.510229,55.977861],[-159.375585,55.873799],[-159.616571,55.594475],[-159.676817,55.654722],[-159.643955,55.829984],[-159.813741,55.857368],[-160.027341,55.791645],[-160.060203,55.720445],[-160.394296,55.605429],[-160.536697,55.473983],[-160.580512,55.567091],[-160.668143,55.457552],[-160.865313,55.528752],[-161.232268,55.358967],[-161.506115,55.364444],[-161.467776,55.49589],[-161.588269,55.62186],[-161.697808,55.517798],[-161.686854,55.408259],[-162.053809,55.074166],[-162.179779,55.15632],[-162.218117,55.03035],[-162.470057,55.052258],[-162.508395,55.249428],[-162.661749,55.293244],[-162.716519,55.222043],[-162.579595,55.134412],[-162.645319,54.997489],[-162.847965,54.926289],[-163.00132,55.079643],[-163.187536,55.090597],[-163.220397,55.03035],[-163.034181,54.942719],[-163.373752,54.800319],[-163.14372,54.76198],[-163.138243,54.696257],[-163.329936,54.74555],[-163.587352,54.614103],[-164.085754,54.61958],[-164.332216,54.531949],[-164.354124,54.466226],[-164.638925,54.389548],[-164.847049,54.416933],[-164.918249,54.603149],[-164.710125,54.663395],[-164.551294,54.88795],[-164.34317,54.893427],[-163.894061,55.041304],[-163.532583,55.046781],[-163.39566,54.904381],[-163.291598,55.008443],[-163.313505,55.128935],[-163.105382,55.183705],[-162.880827,55.183705],[-162.579595,55.446598],[-162.245502,55.682106],[-161.807347,55.89023],[-161.292514,55.983338],[-161.078914,55.939523],[-160.87079,55.999769],[-160.816021,55.912138],[-160.931036,55.813553],[-160.805067,55.736876],[-160.766728,55.857368],[-160.509312,55.868322],[-160.438112,55.791645],[-160.27928,55.76426],[-160.273803,55.857368],[-160.536697,55.939523],[-160.558604,55.994292],[-160.383342,56.251708],[-160.147834,56.399586],[-159.830171,56.541986],[-159.326293,56.667956],[-158.959338,56.848695],[-158.784076,56.782971],[-158.641675,56.810356],[-158.701922,56.925372],[-158.658106,57.034911],[-158.378782,57.264942],[-157.995396,57.41282],[-157.688688,57.609989],[-157.705118,57.719528],[-157.458656,58.497254],[-157.07527,58.705377],[-157.119086,58.869686],[-158.039212,58.634177],[-158.32949,58.661562],[-158.40069,58.760147],[-158.564998,58.803962],[-158.619768,58.913501],[-158.767645,58.864209],[-158.860753,58.694424],[-158.701922,58.480823],[-158.893615,58.387715],[-159.0634,58.420577],[-159.392016,58.760147],[-159.616571,58.929932],[-159.731586,58.929932],[-159.808264,58.803962],[-159.906848,58.782055],[-160.054726,58.886116],[-160.235465,58.902547],[-160.317619,59.072332],[-160.854359,58.88064],[-161.33633,58.743716],[-161.374669,58.667039],[-161.752577,58.552023],[-161.938793,58.656085],[-161.769008,58.776578],[-161.829255,59.061379],[-161.955224,59.36261],[-161.703285,59.48858],[-161.911409,59.740519],[-162.092148,59.88292],[-162.234548,60.091043],[-162.448149,60.178674],[-162.502918,59.997935],[-162.760334,59.959597],[-163.171105,59.844581],[-163.66403,59.795289],[-163.9324,59.806242],[-164.162431,59.866489],[-164.189816,60.02532],[-164.386986,60.074613],[-164.699171,60.29369],[-164.962064,60.337506],[-165.268773,60.578491],[-165.060649,60.68803],[-165.016834,60.890677],[-165.175665,60.846861],[-165.197573,60.972831],[-165.120896,61.076893],[-165.323543,61.170001],[-165.34545,61.071416],[-165.591913,61.109754],[-165.624774,61.279539],[-165.816467,61.301447],[-165.920529,61.416463],[-165.915052,61.558863],[-166.106745,61.49314],[-166.139607,61.630064],[-165.904098,61.662925],[-166.095791,61.81628],[-165.756221,61.827233],[-165.756221,62.013449],[-165.674067,62.139419],[-165.044219,62.539236],[-164.912772,62.659728],[-164.819664,62.637821],[-164.874433,62.807606],[-164.633448,63.097884],[-164.425324,63.212899],[-164.036462,63.262192],[-163.73523,63.212899],[-163.313505,63.037637],[-163.039658,63.059545],[-162.661749,63.22933],[-162.272887,63.486746],[-162.075717,63.514131],[-162.026424,63.448408],[-161.555408,63.448408],[-161.13916,63.503177],[-160.766728,63.771547],[-160.766728,63.837271],[-160.952944,64.08921],[-160.974852,64.237087],[-161.26513,64.395918],[-161.374669,64.532842],[-161.078914,64.494503],[-160.79959,64.609519],[-160.783159,64.719058],[-161.144637,64.921705],[-161.413007,64.762873],[-161.664946,64.790258],[-161.900455,64.702627],[-162.168825,64.680719],[-162.234548,64.620473],[-162.541257,64.532842],[-162.634365,64.384965],[-162.787719,64.324718],[-162.858919,64.49998],[-163.045135,64.538319],[-163.176582,64.401395],[-163.253259,64.467119],[-163.598306,64.565704],[-164.304832,64.560227],[-164.80871,64.450688],[-165.000403,64.434257],[-165.411174,64.49998],[-166.188899,64.576658],[-166.391546,64.636904],[-166.484654,64.735489],[-166.413454,64.872412],[-166.692778,64.987428],[-166.638008,65.113398],[-166.462746,65.179121],[-166.517516,65.337952],[-166.796839,65.337952],[-167.026871,65.381768],[-167.47598,65.414629],[-167.711489,65.496784],[-168.072967,65.578938],[-168.105828,65.682999],[-167.541703,65.819923],[-166.829701,66.049954],[-166.3313,66.186878],[-166.046499,66.110201],[-165.756221,66.09377],[-165.690498,66.203309],[-165.86576,66.21974],[-165.88219,66.312848],[-165.186619,66.466202],[-164.403417,66.581218],[-163.981692,66.592172],[-163.751661,66.553833],[-163.872153,66.389525],[-163.828338,66.274509],[-163.915969,66.192355],[-163.768091,66.060908],[-163.494244,66.082816],[-163.149197,66.060908],[-162.749381,66.088293],[-162.634365,66.039001],[-162.371472,66.028047],[-162.14144,66.077339],[-161.840208,66.02257],[-161.549931,66.241647],[-161.341807,66.252601],[-161.199406,66.208786],[-161.128206,66.334755],[-161.528023,66.395002],[-161.911409,66.345709],[-161.87307,66.510017],[-162.174302,66.68528],[-162.502918,66.740049],[-162.601503,66.89888],[-162.344087,66.937219],[-162.015471,66.778388],[-162.075717,66.652418],[-161.916886,66.553833],[-161.571838,66.438817],[-161.489684,66.55931],[-161.884024,66.718141],[-161.714239,67.002942],[-161.851162,67.052235],[-162.240025,66.991988],[-162.639842,67.008419],[-162.700088,67.057712],[-162.902735,67.008419],[-163.740707,67.128912],[-163.757138,67.254881],[-164.009077,67.534205],[-164.211724,67.638267],[-164.534863,67.725898],[-165.192096,67.966884],[-165.493328,68.059992],[-165.794559,68.081899],[-166.243668,68.246208],[-166.681824,68.339316],[-166.703731,68.372177],[-166.375115,68.42147],[-166.227238,68.574824],[-166.216284,68.881533],[-165.329019,68.859625],[-164.255539,68.930825],[-163.976215,68.985595],[-163.532583,69.138949],[-163.110859,69.374457],[-163.023228,69.609966],[-162.842489,69.812613],[-162.470057,69.982398],[-162.311225,70.108367],[-161.851162,70.311014],[-161.779962,70.256245],[-161.396576,70.239814],[-160.837928,70.343876],[-160.487404,70.453415],[-159.649432,70.792985],[-159.33177,70.809416],[-159.298908,70.760123],[-158.975769,70.798462],[-158.658106,70.787508],[-158.033735,70.831323],[-157.420318,70.979201],[-156.812377,71.285909],[-156.565915,71.351633],[-156.522099,71.296863],[-155.585543,71.170894],[-155.508865,71.083263],[-155.832005,70.968247],[-155.979882,70.96277],[-155.974405,70.809416],[-155.503388,70.858708],[-155.476004,70.940862],[-155.262403,71.017539],[-155.191203,70.973724],[-155.032372,71.148986],[-154.566832,70.990155],[-154.643509,70.869662],[-154.353231,70.8368],[-154.183446,70.7656],[-153.931507,70.880616],[-153.487874,70.886093],[-153.235935,70.924431],[-152.589656,70.886093],[-152.26104,70.842277],[-152.419871,70.606769],[-151.817408,70.546523],[-151.773592,70.486276],[-151.187559,70.382214],[-151.182082,70.431507],[-150.760358,70.49723],[-150.355064,70.491753],[-150.349588,70.436984],[-150.114079,70.431507],[-149.867617,70.508184],[-149.462323,70.519138],[-149.177522,70.486276],[-148.78866,70.404122],[-148.607921,70.420553],[-148.350504,70.305537],[-148.202627,70.349353],[-147.961642,70.316491],[-147.786379,70.245291]]],[[[-152.94018,58.026237],[-152.945657,57.982421],[-153.290705,58.048145],[-153.044242,58.305561],[-152.819688,58.327469],[-152.666333,58.562977],[-152.496548,58.354853],[-152.354148,58.426053],[-152.080301,58.311038],[-152.080301,58.152206],[-152.480117,58.130299],[-152.655379,58.059098],[-152.94018,58.026237]]],[[[-153.958891,57.538789],[-153.67409,57.670236],[-153.931507,57.69762],[-153.936983,57.812636],[-153.723383,57.889313],[-153.570028,57.834544],[-153.548121,57.719528],[-153.46049,57.796205],[-153.455013,57.96599],[-153.268797,57.889313],[-153.235935,57.998852],[-153.071627,57.933129],[-152.874457,57.933129],[-152.721103,57.993375],[-152.469163,57.889313],[-152.469163,57.599035],[-152.151501,57.620943],[-152.359625,57.42925],[-152.74301,57.505928],[-152.60061,57.379958],[-152.710149,57.275896],[-152.907319,57.325188],[-152.912796,57.128019],[-153.214027,57.073249],[-153.312612,56.991095],[-153.498828,57.067772],[-153.695998,56.859649],[-153.849352,56.837741],[-154.013661,56.744633],[-154.073907,56.969187],[-154.303938,56.848695],[-154.314892,56.919895],[-154.523016,56.991095],[-154.539447,57.193742],[-154.742094,57.275896],[-154.627078,57.511404],[-154.227261,57.659282],[-153.980799,57.648328],[-153.958891,57.538789]]],[[[-154.53397,56.602232],[-154.742094,56.399586],[-154.807817,56.432447],[-154.53397,56.602232]]],[[[-155.634835,55.923092],[-155.476004,55.912138],[-155.530773,55.704014],[-155.793666,55.731399],[-155.837482,55.802599],[-155.634835,55.923092]]],[[[-159.890418,55.28229],[-159.950664,55.068689],[-160.257373,54.893427],[-160.109495,55.161797],[-160.005433,55.134412],[-159.890418,55.28229]]],[[[-160.520266,55.358967],[-160.33405,55.358967],[-160.339527,55.249428],[-160.525743,55.128935],[-160.690051,55.211089],[-160.794113,55.134412],[-160.854359,55.320628],[-160.79959,55.380875],[-160.520266,55.358967]]],[[[-162.256456,54.981058],[-162.234548,54.893427],[-162.349564,54.838658],[-162.437195,54.931766],[-162.256456,54.981058]]],[[[-162.415287,63.634624],[-162.563165,63.536039],[-162.612457,63.62367],[-162.415287,63.634624]]],[[[-162.80415,54.488133],[-162.590549,54.449795],[-162.612457,54.367641],[-162.782242,54.373118],[-162.80415,54.488133]]],[[[-165.548097,54.29644],[-165.476897,54.181425],[-165.630251,54.132132],[-165.685021,54.252625],[-165.548097,54.29644]]],[[[-165.73979,54.15404],[-166.046499,54.044501],[-166.112222,54.121178],[-165.980775,54.219763],[-165.73979,54.15404]]],[[[-166.364161,60.359413],[-166.13413,60.397752],[-166.084837,60.326552],[-165.88219,60.342983],[-165.685021,60.277259],[-165.646682,59.992458],[-165.750744,59.89935],[-166.00816,59.844581],[-166.062929,59.745996],[-166.440838,59.855535],[-166.6161,59.850058],[-166.994009,59.992458],[-167.125456,59.992458],[-167.344534,60.074613],[-167.421211,60.206059],[-167.311672,60.238921],[-166.93924,60.206059],[-166.763978,60.310121],[-166.577762,60.321075],[-166.495608,60.392275],[-166.364161,60.359413]]],[[[-166.375115,54.01164],[-166.210807,53.934962],[-166.5449,53.748746],[-166.539423,53.715885],[-166.117699,53.852808],[-166.112222,53.776131],[-166.282007,53.683023],[-166.555854,53.622777],[-166.583239,53.529669],[-166.878994,53.431084],[-167.13641,53.425607],[-167.306195,53.332499],[-167.623857,53.250345],[-167.793643,53.337976],[-167.459549,53.442038],[-167.355487,53.425607],[-167.103548,53.513238],[-167.163794,53.611823],[-167.021394,53.715885],[-166.807793,53.666592],[-166.785886,53.732316],[-167.015917,53.754223],[-167.141887,53.825424],[-167.032348,53.945916],[-166.643485,54.017116],[-166.561331,53.880193],[-166.375115,54.01164]]],[[[-168.790446,53.157237],[-168.40706,53.34893],[-168.385152,53.431084],[-168.237275,53.524192],[-168.007243,53.568007],[-167.886751,53.518715],[-167.842935,53.387268],[-168.270136,53.244868],[-168.500168,53.036744],[-168.686384,52.965544],[-168.790446,53.157237]]],[[[-169.74891,52.894344],[-169.705095,52.795759],[-169.962511,52.790282],[-169.989896,52.856005],[-169.74891,52.894344]]],[[[-170.148727,57.221127],[-170.28565,57.128019],[-170.313035,57.221127],[-170.148727,57.221127]]],[[[-170.669036,52.697174],[-170.603313,52.604066],[-170.789529,52.538343],[-170.816914,52.636928],[-170.669036,52.697174]]],[[[-171.742517,63.716778],[-170.94836,63.5689],[-170.488297,63.69487],[-170.280174,63.683916],[-170.093958,63.612716],[-170.044665,63.492223],[-169.644848,63.4265],[-169.518879,63.366254],[-168.99857,63.338869],[-168.686384,63.295053],[-168.856169,63.147176],[-169.108108,63.180038],[-169.376478,63.152653],[-169.513402,63.08693],[-169.639372,62.939052],[-169.831064,63.075976],[-170.055619,63.169084],[-170.263743,63.180038],[-170.362328,63.2841],[-170.866206,63.415546],[-171.101715,63.421023],[-171.463193,63.306007],[-171.73704,63.366254],[-171.852055,63.486746],[-171.742517,63.716778]]],[[[-172.432611,52.390465],[-172.41618,52.275449],[-172.607873,52.253542],[-172.569535,52.352127],[-172.432611,52.390465]]],[[[-173.626584,52.14948],[-173.495138,52.105664],[-173.122706,52.111141],[-173.106275,52.07828],[-173.549907,52.028987],[-173.626584,52.14948]]],[[[-174.322156,52.280926],[-174.327632,52.379511],[-174.185232,52.41785],[-173.982585,52.319265],[-174.059262,52.226157],[-174.179755,52.231634],[-174.141417,52.127572],[-174.333109,52.116618],[-174.738403,52.007079],[-174.968435,52.039941],[-174.902711,52.116618],[-174.656249,52.105664],[-174.322156,52.280926]]],[[[-176.469116,51.853725],[-176.288377,51.870156],[-176.288377,51.744186],[-176.518409,51.760617],[-176.80321,51.61274],[-176.912748,51.80991],[-176.792256,51.815386],[-176.775825,51.963264],[-176.627947,51.968741],[-176.627947,51.859202],[-176.469116,51.853725]]],[[[-177.153734,51.946833],[-177.044195,51.897541],[-177.120872,51.727755],[-177.274226,51.678463],[-177.279703,51.782525],[-177.153734,51.946833]]],[[[-178.123152,51.919448],[-177.953367,51.913971],[-177.800013,51.793479],[-177.964321,51.651078],[-178.123152,51.919448]]],[[[173.107557,52.992929],[173.293773,52.927205],[173.304726,52.823143],[172.90491,52.762897],[172.642017,52.927205],[172.642017,53.003883],[173.107557,52.992929]]]]}},' + @@ -109,5 +108,3 @@ function loadGeoFixture3 () { '{ "type": "Feature", "id": 39, "properties": { "NAME": "DAGGETT COUNTY SCHOOL DISTRICT", "TOTENROLL": 168, "Color4": "1", "Shape_Leng": 273628.633657, "Shape_Area": 1870465385.27 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -109.04994430932786, 40.999653282383015 ], [ -109.04988792193215, 40.992694027987596 ], [ -109.04985126684744, 40.98970291264316 ], [ -109.04979954554481, 40.985004615445575 ], [ -109.04970417096163, 40.978157279815299 ], [ -109.04967501102045, 40.975113140183822 ], [ -109.04953951575851, 40.963777553865569 ], [ -109.04952513678701, 40.960634574550454 ], [ -109.04952278928261, 40.949415612566533 ], [ -109.04950870471791, 40.946060052481577 ], [ -109.04955893968447, 40.932243264004285 ], [ -109.0493968939732, 40.92039101789441 ], [ -109.04932046785048, 40.917498280254385 ], [ -109.0491188009876, 40.906023657461773 ], [ -109.04911731993587, 40.902641265458364 ], [ -109.04903013563742, 40.895510241255941 ], [ -109.04902386951267, 40.894915630478586 ], [ -109.04890378201067, 40.874966131398381 ], [ -109.04889061802459, 40.873394069071594 ], [ -109.04880426042889, 40.863403986317401 ], [ -109.0488051512126, 40.86256538526127 ], [ -109.04875590559372, 40.848075662253549 ], [ -109.04874369297362, 40.844247176598344 ], [ -109.0486803970071, 40.836499463552187 ], [ -109.04874769615986, 40.823286250845307 ], [ -109.04862471985138, 40.818987473468418 ], [ -109.04866632146236, 40.81493919115546 ], [ -109.04884729284714, 40.804515763854809 ], [ -109.04899413735917, 40.775620346448001 ], [ -109.04888858075705, 40.771493882214919 ], [ -109.04891495198069, 40.760509283843234 ], [ -109.0489234584204, 40.756978355781754 ], [ -109.0489392618036, 40.749957008756574 ], [ -109.04889153758913, 40.74247427827045 ], [ -109.04885959119356, 40.739718233374383 ], [ -109.04888409630244, 40.736448792734137 ], [ -109.04886523945866, 40.727976569087588 ], [ -109.04888445349845, 40.725495222820776 ], [ -109.04883924769956, 40.718126006349358 ], [ -109.04897571587335, 40.713453215758797 ], [ -109.04889179006646, 40.703597147542723 ], [ -109.04893262599143, 40.69891372156588 ], [ -109.04892486228094, 40.688878760381023 ], [ -109.04894738403539, 40.684415708649567 ], [ -109.04905398378411, 40.670009295418325 ], [ -109.04906746564524, 40.667517921223833 ], [ -109.04909446050991, 40.666186099643554 ], [ -109.0486182417954, 40.653711014754109 ], [ -109.04947584890805, 40.653707493700317 ], [ -109.06637794405938, 40.653694600805373 ], [ -109.06913928026587, 40.653709295778228 ], [ -109.08526019724584, 40.65371659773583 ], [ -109.08812872629096, 40.653705592037156 ], [ -109.10437196818857, 40.65377980862003 ], [ -109.10708580777349, 40.653801823111806 ], [ -109.12335410254553, 40.65382873707167 ], [ -109.1233729681547, 40.668345486390905 ], [ -109.12333974342546, 40.669741189344677 ], [ -109.12336561529642, 40.673880793530785 ], [ -109.1234386432277, 40.684142100163001 ], [ -109.12565105893994, 40.684155531058394 ], [ -109.16103557850289, 40.683814938390015 ], [ -109.16113804814729, 40.698378033154896 ], [ -109.16127869427831, 40.713013767205965 ], [ -109.16074971070292, 40.727755900131527 ], [ -109.16112497656802, 40.742291715512266 ], [ -109.16133966804648, 40.749975307804085 ], [ -109.16149250664913, 40.756894933810351 ], [ -109.16168066767705, 40.762361237207998 ], [ -109.16199702304428, 40.77147327740046 ], [ -109.16334162704561, 40.771481179956339 ], [ -109.16355966137274, 40.785933318322172 ], [ -109.20161146179689, 40.785807672536336 ], [ -109.20236590389135, 40.858400302227679 ], [ -109.25067457572007, 40.85849017705975 ], [ -109.25913582086658, 40.858185842235883 ], [ -109.37568353803847, 40.858215358723733 ], [ -109.39449248209064, 40.858294982895465 ], [ -109.39432453126918, 40.791029060012299 ], [ -109.41495293143289, 40.786819308789198 ], [ -109.41549764055769, 40.786340356047425 ], [ -109.41596308538546, 40.785954897016929 ], [ -109.41634991116744, 40.785635917357403 ], [ -109.4165480697678, 40.785526036516444 ], [ -109.41675225842441, 40.785411734051486 ], [ -109.41739155225531, 40.785190799987099 ], [ -109.4180545367941, 40.784970187203889 ], [ -109.41863890661885, 40.784816053523592 ], [ -109.41910848106863, 40.784754928578444 ], [ -109.41965388842702, 40.784744384892399 ], [ -109.42021502830887, 40.784770086328628 ], [ -109.42056010793063, 40.784761299038962 ], [ -109.42097915192578, 40.784631914158375 ], [ -109.42112280222256, 40.784521279329411 ], [ -109.42128583437635, 40.78439289340551 ], [ -109.42178394237264, 40.783877240483633 ], [ -109.42205353560432, 40.783502589197127 ], [ -109.42232723763975, 40.783204562035472 ], [ -109.42252591213379, 40.783072157672642 ], [ -109.42269961312925, 40.782993459961368 ], [ -109.42289690137167, 40.782919588462754 ], [ -109.42357199107137, 40.78268649785371 ], [ -109.4242688969122, 40.782532972275469 ], [ -109.42484752110656, 40.78236972034847 ], [ -109.42558334366534, 40.782073489727694 ], [ -109.42621899258003, 40.781753367734773 ], [ -109.42678799010972, 40.781495389873889 ], [ -109.4269572621196, 40.781403113175365 ], [ -109.42714246573071, 40.781288533231184 ], [ -109.42759330659116, 40.781015428321425 ], [ -109.42805134123054, 40.780688371166377 ], [ -109.42870326936102, 40.780179287426741 ], [ -109.42906441933566, 40.779940086582968 ], [ -109.42923216013278, 40.779862198566818 ], [ -109.42957952955122, 40.779704781994027 ], [ -109.43007054021228, 40.779486262497549 ], [ -109.4305390207282, 40.779217889948633 ], [ -109.43105182105309, 40.778828509064304 ], [ -109.43129277531304, 40.77866063198109 ], [ -109.43182828521515, 40.778312993533078 ], [ -109.43211674791779, 40.778140355583133 ], [ -109.43244664989376, 40.777969180746808 ], [ -109.43276406888498, 40.777824859640553 ], [ -109.43306329389486, 40.777698306721703 ], [ -109.43388216412615, 40.777394142295634 ], [ -109.4341872024751, 40.777272169388198 ], [ -109.43429045367382, 40.777164572785018 ], [ -109.43436341255041, 40.777085390897042 ], [ -109.43444561416626, 40.776864907401098 ], [ -109.43447880288524, 40.776713121061185 ], [ -109.43447634763353, 40.776565355096835 ], [ -109.434468857466, 40.776379686836613 ], [ -109.4344042097775, 40.776104963696419 ], [ -109.43436467283706, 40.77597200827131 ], [ -109.43432712459142, 40.775855294378928 ], [ -109.43429063344043, 40.775643109068753 ], [ -109.43433050599118, 40.775458984321098 ], [ -109.43436371574838, 40.775356742759222 ], [ -109.43454139953869, 40.775056481969315 ], [ -109.43477325561848, 40.774820913272229 ], [ -109.43500105000395, 40.774657353730085 ], [ -109.43522431633967, 40.774484724224479 ], [ -109.43563456926624, 40.774170500298865 ], [ -109.43593873639834, 40.773832316560529 ], [ -109.43606723335786, 40.773658400612369 ], [ -109.43619604642782, 40.773470976656554 ], [ -109.4363045466867, 40.773139147736124 ], [ -109.43634367288585, 40.772986540401284 ], [ -109.4364177968807, 40.772604700918961 ], [ -109.43641239184744, 40.772329880753176 ], [ -109.43640648210736, 40.772127118504557 ], [ -109.43630691591706, 40.771522226660906 ], [ -109.43622463711284, 40.771039178307717 ], [ -109.43617002517648, 40.770538488670248 ], [ -109.43620967788981, 40.770363368201366 ], [ -109.43623547941507, 40.770273636919605 ], [ -109.43629850482657, 40.770112345339122 ], [ -109.43635372828643, 40.770031120065717 ], [ -109.43641493738328, 40.769947273451479 ], [ -109.43662602248911, 40.76978798807869 ], [ -109.43687116349878, 40.769692220403357 ], [ -109.437021017737, 40.769617681674767 ], [ -109.43747692282949, 40.769376133997106 ], [ -109.43763375291473, 40.769256648428254 ], [ -109.43786947159259, 40.76905715784892 ], [ -109.43803403641074, 40.768860306769199 ], [ -109.43820585115461, 40.768606802536738 ], [ -109.43866731252618, 40.767874383638677 ], [ -109.4391892713189, 40.767340959474623 ], [ -109.43981836833773, 40.766785560581937 ], [ -109.44021097475019, 40.766462973741241 ], [ -109.44050081703048, 40.766228176852543 ], [ -109.44074306999474, 40.766001744206044 ], [ -109.44081613501247, 40.765917154568577 ], [ -109.4409442877741, 40.765756740342731 ], [ -109.44109136369728, 40.765547037044101 ], [ -109.44114992383152, 40.76532262551914 ], [ -109.44111244745334, 40.765151865924324 ], [ -109.44099273673895, 40.764951169250828 ], [ -109.44073964202191, 40.764627961296142 ], [ -109.44014515687461, 40.76416051225624 ], [ -109.43945808795719, 40.763700816096865 ], [ -109.43882134927551, 40.763318365803066 ], [ -109.43797735443505, 40.762933106376501 ], [ -109.437451036051, 40.762642224452975 ], [ -109.43731768294435, 40.762518808956308 ], [ -109.43704198314494, 40.762150246176581 ], [ -109.43691190244593, 40.761887248813849 ], [ -109.43674966906742, 40.76147968589688 ], [ -109.43657643851064, 40.761035941274905 ], [ -109.4365751599607, 40.760837745477154 ], [ -109.43662970833284, 40.760532208753993 ], [ -109.43672486305758, 40.760263254607231 ], [ -109.43683175457906, 40.7599989634301 ], [ -109.43687774195541, 40.759805911987478 ], [ -109.43688175093941, 40.759634812124567 ], [ -109.43683288837013, 40.759444979757276 ], [ -109.4367550516793, 40.759227730474805 ], [ -109.43643546683406, 40.758457710410099 ], [ -109.43634726712968, 40.758177263586639 ], [ -109.43632072060466, 40.758046286145465 ], [ -109.43635820933004, 40.757912573247005 ], [ -109.4365373832961, 40.75769790558298 ], [ -109.4366273404071, 40.757600035179863 ], [ -109.43674958892611, 40.757489090021664 ], [ -109.43718054118479, 40.75724720458846 ], [ -109.43738979061121, 40.757164461436652 ], [ -109.43756869495614, 40.757112835416685 ], [ -109.43801997849982, 40.7570648966717 ], [ -109.43841807522308, 40.757011732296647 ], [ -109.43943525006215, 40.756827315283026 ], [ -109.44004735241798, 40.75674100697946 ], [ -109.44049305299211, 40.756729015537907 ], [ -109.44097096566475, 40.756757994157766 ], [ -109.44158031016556, 40.756789646835607 ], [ -109.44192323967249, 40.756815897506357 ], [ -109.44230125567775, 40.756861537887502 ], [ -109.44327742795751, 40.756910744566305 ], [ -109.4437626591104, 40.756930802241762 ], [ -109.44477436169835, 40.756980475461525 ], [ -109.44516537773281, 40.756976737007172 ], [ -109.44539662341531, 40.756966340663773 ], [ -109.44599056758072, 40.756947317067201 ], [ -109.44620234060709, 40.756959177158286 ], [ -109.4465099340845, 40.756976831042287 ], [ -109.44668736372283, 40.756988227855828 ], [ -109.44697685817657, 40.757020049845153 ], [ -109.44745514360113, 40.757084138318326 ], [ -109.44802306689483, 40.75711429882292 ], [ -109.44841450272422, 40.757092538749546 ], [ -109.44874122253243, 40.75705189105966 ], [ -109.44898493882499, 40.75701463079745 ], [ -109.44915749439612, 40.756980917664343 ], [ -109.44984834269545, 40.756819046569476 ], [ -109.45040393922217, 40.756614818427686 ], [ -109.45068008255024, 40.75645638032379 ], [ -109.45087768003818, 40.756364448012746 ], [ -109.45098541274338, 40.756316349632392 ], [ -109.45148492427774, 40.755976241359491 ], [ -109.45175451431803, 40.75584473708323 ], [ -109.45187408800514, 40.755796796742835 ], [ -109.45229160235475, 40.755671779857018 ], [ -109.45294223440088, 40.755455301869866 ], [ -109.45311433057933, 40.755390048161161 ], [ -109.45343932923592, 40.755218746117471 ], [ -109.45369254190139, 40.755078009618096 ], [ -109.45407733828212, 40.754830937967284 ], [ -109.45487994675162, 40.754445330457024 ], [ -109.45536887971494, 40.754253697657731 ], [ -109.455733505247, 40.754109943925734 ], [ -109.45589577094219, 40.754008521918713 ], [ -109.45602843082753, 40.753906703534803 ], [ -109.45633207175663, 40.753838701001051 ], [ -109.45666365107053, 40.753843136434973 ], [ -109.45705807156777, 40.753947500727286 ], [ -109.45722217502775, 40.754022660874753 ], [ -109.45742683125791, 40.754137097915695 ], [ -109.45772568459937, 40.754276214831023 ], [ -109.45790757377547, 40.754350710916832 ], [ -109.45808956741313, 40.754420704044904 ], [ -109.45835372892626, 40.754523323206392 ], [ -109.45875189326283, 40.754722317169424 ], [ -109.45899714967936, 40.75487422708688 ], [ -109.45930400515084, 40.755180097299537 ], [ -109.45977004952913, 40.755569164941036 ], [ -109.45997211780089, 40.755693471882161 ], [ -109.46008435061511, 40.755758026709074 ], [ -109.46047868416318, 40.755866882254928 ], [ -109.46071511867385, 40.755888052865863 ], [ -109.46095843012426, 40.755867877296353 ], [ -109.46136219667765, 40.755824618157312 ], [ -109.46229307826263, 40.755782978562294 ], [ -109.46284520665569, 40.75572727826431 ], [ -109.46361070625372, 40.755665408446013 ], [ -109.46433361597309, 40.755652511481493 ], [ -109.46477158071849, 40.755667347604941 ], [ -109.46529130392184, 40.755732814289502 ], [ -109.46585366127957, 40.755798845494731 ], [ -109.4666277942268, 40.755876696580096 ], [ -109.46747854885589, 40.755919527604796 ], [ -109.46767436454597, 40.755904111909587 ], [ -109.46815023737182, 40.755815845014141 ], [ -109.46837607240711, 40.755782810371478 ], [ -109.46877527717042, 40.755680010972029 ], [ -109.46929579803214, 40.755452705632386 ], [ -109.46955412932516, 40.755293985777364 ], [ -109.46978362453194, 40.755152899209158 ], [ -109.46991611433934, 40.755006021813358 ], [ -109.47003171449934, 40.754872432527293 ], [ -109.47010473031941, 40.754787823296773 ], [ -109.47023320436008, 40.7546093637769 ], [ -109.47034931929333, 40.754453260624295 ], [ -109.47042908111649, 40.754332708033878 ], [ -109.47048443563811, 40.754243360360441 ], [ -109.4706056552733, 40.75391616986218 ], [ -109.47063145790027, 40.75377238154767 ], [ -109.47070849632159, 40.753512166404455 ], [ -109.47072987127606, 40.753354807157159 ], [ -109.4707498014516, 40.753260485770767 ], [ -109.47083981582909, 40.752950897682361 ], [ -109.47094208401624, 40.752623455592172 ], [ -109.47099832466714, 40.752236850539575 ], [ -109.47107663959176, 40.751662267636121 ], [ -109.47113572526015, 40.751409921555314 ], [ -109.47116425711674, 40.751198608101276 ], [ -109.47117261261059, 40.750833888780114 ], [ -109.4712057239077, 40.750681188939133 ], [ -109.47124537473256, 40.750501551275235 ], [ -109.47127735108558, 40.750398381191339 ], [ -109.47131906434856, 40.750128689315027 ], [ -109.47134002398008, 40.749989340655539 ], [ -109.47198245080249, 40.746245953636674 ], [ -109.4742276658162, 40.743883996432146 ], [ -109.48421280456228, 40.740466371800345 ], [ -109.48433202138671, 40.740431905020507 ], [ -109.48460546327804, 40.740385951256862 ], [ -109.48474733753221, 40.740396822446407 ], [ -109.48492983396071, 40.74044425949949 ], [ -109.4851356017775, 40.740510018107564 ], [ -109.49342153855694, 40.743856933160437 ], [ -109.49622036396758, 40.745798668998773 ], [ -109.50025296675146, 40.747134815066872 ], [ -109.50066703674287, 40.747420350103596 ], [ -109.5011806892781, 40.747754920476403 ], [ -109.50162909827074, 40.748094046301098 ], [ -109.50224420100396, 40.748394797364469 ], [ -109.50237896259829, 40.748459603652741 ], [ -109.50274251099673, 40.748621964411235 ], [ -109.50312946890678, 40.748744090925285 ], [ -109.50328378433947, 40.748782125295307 ], [ -109.50342509451367, 40.748819089971548 ], [ -109.50377258113403, 40.748905570534546 ], [ -109.5040377028816, 40.748967561042463 ], [ -109.50432660910398, 40.749025355145456 ], [ -109.50449760496043, 40.749059100014527 ], [ -109.50482755391215, 40.749135441124821 ], [ -109.5054155979781, 40.749323222564669 ], [ -109.5055860910596, 40.749379479743517 ], [ -109.50579782843585, 40.749445278921186 ], [ -109.50616169314262, 40.749594120774759 ], [ -109.50650761561987, 40.749750836617913 ], [ -109.50693578690297, 40.749937441834824 ], [ -109.5072769805963, 40.750040945973318 ], [ -109.50758325431285, 40.750116972954793 ], [ -109.50820824959173, 40.750242160893436 ], [ -109.50863223878108, 40.750351235479187 ], [ -109.50958228484772, 40.750507641147209 ], [ -109.51097971384118, 40.750786919206909 ], [ -109.51177512446445, 40.750972839924074 ], [ -109.51193348422761, 40.751042443521932 ], [ -109.51206193829046, 40.751125173541503 ], [ -109.51227760123879, 40.751281093216477 ], [ -109.51252377348706, 40.751396868998818 ], [ -109.51285354310508, 40.751482193074303 ], [ -109.51322235301468, 40.751676117326369 ], [ -109.51353125258326, 40.751900797257882 ], [ -109.51375216061751, 40.75208740954038 ], [ -109.5139207428241, 40.752230108290021 ], [ -109.51400785436066, 40.752307799615281 ], [ -109.51413521058596, 40.752440058146689 ], [ -109.51436523760981, 40.752749297831777 ], [ -109.51472734401182, 40.753244904761154 ], [ -109.51537819252444, 40.753807283108145 ], [ -109.51609458647981, 40.754352484369612 ], [ -109.51625085621372, 40.754516640981862 ], [ -109.51629111773836, 40.754836948766531 ], [ -109.51613948013275, 40.754997145937942 ], [ -109.51595281449994, 40.755134371976546 ], [ -109.51546366909498, 40.755555967974693 ], [ -109.51531744827209, 40.755738754143046 ], [ -109.51520645446263, 40.755935505669719 ], [ -109.51507077218467, 40.756176980209609 ], [ -109.51501537483441, 40.756270853055568 ], [ -109.51475856340555, 40.756898119474826 ], [ -109.51465170312228, 40.757175096304266 ], [ -109.51437941188499, 40.757965210283139 ], [ -109.51427824920557, 40.758252169042365 ], [ -109.51413876797024, 40.758663847749013 ], [ -109.51408656100966, 40.75888027220882 ], [ -109.51406468418716, 40.759064657839723 ], [ -109.51407430207423, 40.759217920476601 ], [ -109.51427326284146, 40.75980601308634 ], [ -109.51491262691454, 40.7603547336143 ], [ -109.51501139310264, 40.760441582296622 ], [ -109.51516215300289, 40.760587653039693 ], [ -109.51522488781788, 40.760696558268599 ], [ -109.51529836417801, 40.760855146567422 ], [ -109.51531765163112, 40.761319315055196 ], [ -109.5152722900342, 40.761494390507544 ], [ -109.51526085619284, 40.761741967796866 ], [ -109.51528153738275, 40.761877356319168 ], [ -109.51532068598692, 40.761981453900468 ], [ -109.5154231724354, 40.762167439849186 ], [ -109.51550347459032, 40.762285579092946 ], [ -109.5156166036124, 40.762525750745191 ], [ -109.51562494073188, 40.762683500787965 ], [ -109.51557679129118, 40.762930605727455 ], [ -109.51544157828559, 40.763203614963139 ], [ -109.51526644012152, 40.763620240806453 ], [ -109.51508789161782, 40.764189961122995 ], [ -109.51507394232068, 40.764284367248216 ], [ -109.51510626760493, 40.76442891375747 ], [ -109.51524750605726, 40.764737008612251 ], [ -109.51530442274144, 40.764841334796849 ], [ -109.51552074781337, 40.765235972938356 ], [ -109.51558890856417, 40.765367468106021 ], [ -109.51564010445333, 40.765462712365121 ], [ -109.51580945591313, 40.765838729323384 ], [ -109.51599918096038, 40.766097902050141 ], [ -109.51604777327793, 40.766310218641735 ], [ -109.51601997646689, 40.766494528296505 ], [ -109.5159562445665, 40.766696392054023 ], [ -109.51587484531599, 40.766893524442523 ], [ -109.51555615841893, 40.767371360991383 ], [ -109.51549384550164, 40.767456136733166 ], [ -109.51520755383379, 40.767862323835146 ], [ -109.51485089715845, 40.768501816400402 ], [ -109.5147869778727, 40.768658636259623 ], [ -109.51471862107618, 40.768801886730039 ], [ -109.51466100597474, 40.768994820259785 ], [ -109.51469694842622, 40.769243007060197 ], [ -109.51472445546246, 40.769337946722324 ], [ -109.51480205716352, 40.769577661596031 ], [ -109.51487925831003, 40.769835387551645 ], [ -109.51485647670142, 40.770060298018919 ], [ -109.5147497605338, 40.770595809938406 ], [ -109.51462782172247, 40.771016722273508 ], [ -109.51458987816426, 40.7711243315457 ], [ -109.51452573590696, 40.77134420533055 ], [ -109.51451027947392, 40.77150615295669 ], [ -109.51453558044389, 40.771700153829478 ], [ -109.51461388603805, 40.771908349301704 ], [ -109.51476545948644, 40.772338187439907 ], [ -109.51489308625081, 40.772938871862451 ], [ -109.51497702949858, 40.7736921322848 ], [ -109.51506064673508, 40.774194061207744 ], [ -109.51511045278566, 40.774671232912873 ], [ -109.5152268619205, 40.775243847166493 ], [ -109.51531170433387, 40.775637693884384 ], [ -109.51537255725987, 40.776151040088152 ], [ -109.51536460877217, 40.776241920016595 ], [ -109.51535607873437, 40.776358916063209 ], [ -109.51535929485645, 40.776480567324334 ], [ -109.51536281177363, 40.776588710245441 ], [ -109.51537817519541, 40.776697005602102 ], [ -109.51541602857131, 40.776859639173878 ], [ -109.51548902076554, 40.777040741133106 ], [ -109.51568861685085, 40.777390122423711 ], [ -109.51606431176921, 40.777813833537891 ], [ -109.51632525119211, 40.778069417237148 ], [ -109.51665064869616, 40.778357357562491 ], [ -109.51681179582815, 40.778571120494064 ], [ -109.51702937392837, 40.778911722456677 ], [ -109.51717217229756, 40.779151372624213 ], [ -109.51747599893088, 40.779876828761061 ], [ -109.51762272197986, 40.780206610129575 ], [ -109.51779229987328, 40.780574519082968 ], [ -109.51790476552037, 40.780846207901099 ], [ -109.518057796722, 40.781158954263809 ], [ -109.518426202727, 40.781645620894629 ], [ -109.51850564816007, 40.781750234602256 ], [ -109.51873125388434, 40.782050399747156 ], [ -109.51880003752805, 40.782154876362739 ], [ -109.51886199720735, 40.782299801928417 ], [ -109.51879333407055, 40.782456562739462 ], [ -109.51864353876309, 40.782531208628953 ], [ -109.51848209570623, 40.782596696619819 ], [ -109.51819495159775, 40.782719122848377 ], [ -109.51803913114199, 40.782798194624554 ], [ -109.51769646827844, 40.783018995887986 ], [ -109.5175333207591, 40.783161029746452 ], [ -109.51739901058325, 40.783338565655335 ], [ -109.51724398337271, 40.783648254653748 ], [ -109.51714771286407, 40.783980318134311 ], [ -109.5171560547697, 40.784138067607152 ], [ -109.51732857863939, 40.784640236016386 ], [ -109.51746928164771, 40.785241084643971 ], [ -109.51749419466108, 40.785453095766243 ], [ -109.51737995001086, 40.785793936496425 ], [ -109.51722390374982, 40.785936061077187 ], [ -109.51690533645397, 40.78608510446724 ], [ -109.51634536519029, 40.786217530600844 ], [ -109.51566650851171, 40.786366440757412 ], [ -109.51545735946056, 40.786444822818943 ], [ -109.51516949104747, 40.786598760452044 ], [ -109.51500713184242, 40.786704768241215 ], [ -109.51479667658874, 40.786841685081619 ], [ -109.5145153312627, 40.786968680661971 ], [ -109.51414462041626, 40.787117044947493 ], [ -109.51378987316434, 40.787346686775763 ], [ -109.51363202830387, 40.787515807604748 ], [ -109.51347900212834, 40.787734534965125 ], [ -109.51339837152906, 40.787895642204454 ], [ -109.51334605607362, 40.788115667039527 ], [ -109.51335240047393, 40.788362571295849 ], [ -109.51339234219145, 40.788697287234193 ], [ -109.51331773298435, 40.789119707438203 ], [ -109.51305665381589, 40.789665838025194 ], [ -109.51278233886833, 40.790008213876789 ], [ -109.51267266434698, 40.790142822578723 ], [ -109.51262878138738, 40.790250354237799 ], [ -109.51246620264901, 40.790631103057244 ], [ -109.51230512358187, 40.791210049499547 ], [ -109.51214996615242, 40.791789072019327 ], [ -109.51208498963197, 40.792044965281903 ], [ -109.51206078117784, 40.792332912704587 ], [ -109.51209923017183, 40.792734269642594 ], [ -109.51213537428278, 40.79297345078848 ], [ -109.51215093650093, 40.793072740731859 ], [ -109.51215767996101, 40.793248485896072 ], [ -109.51214972293157, 40.793392513074551 ], [ -109.51208454357102, 40.793657411759185 ], [ -109.51188811367496, 40.793961153961163 ], [ -109.51180867805799, 40.794068226623146 ], [ -109.51165081181311, 40.79423734418593 ], [ -109.51155962644576, 40.794339761027338 ], [ -109.51147988807166, 40.794460341711151 ], [ -109.51140617482591, 40.794576496025179 ], [ -109.51136579720028, 40.794792169652212 ], [ -109.51138446675398, 40.795017613295741 ], [ -109.51141629392974, 40.795184673995621 ], [ -109.51146146983262, 40.795550085314794 ], [ -109.51145221509803, 40.795964338887828 ], [ -109.51147390300925, 40.796054699804529 ], [ -109.51156266700748, 40.796326088307808 ], [ -109.51165876488437, 40.796534514598896 ], [ -109.51192889301321, 40.796911835714447 ], [ -109.51224178521336, 40.797285203636591 ], [ -109.51230908693034, 40.797403176939369 ], [ -109.51243461304246, 40.797620990163352 ], [ -109.51247759040706, 40.797819722664457 ], [ -109.5124916397355, 40.798252292891469 ], [ -109.51253170219381, 40.798581605292128 ], [ -109.51262820240044, 40.799037758788117 ], [ -109.51274599240141, 40.799602283888575 ], [ -109.51277206962168, 40.800292640767566 ], [ -109.51275329731638, 40.800868016483321 ], [ -109.51280360472259, 40.801269525549912 ], [ -109.51283784515968, 40.801594258592303 ], [ -109.5129705072812, 40.802023853477422 ], [ -109.51304351829708, 40.802204956581711 ], [ -109.5132715908429, 40.802874495482484 ], [ -109.51330854387278, 40.803343392849889 ], [ -109.51327740061704, 40.80394203000688 ], [ -109.51326210411534, 40.804627349053384 ], [ -109.51329455906584, 40.805032230844347 ], [ -109.51336124251939, 40.805497007139394 ], [ -109.51346920673419, 40.805971323416053 ], [ -109.51367861327701, 40.806681157066592 ], [ -109.51385568339164, 40.807246444206449 ], [ -109.51393171450221, 40.807558202883286 ], [ -109.5139610414311, 40.807837831541605 ], [ -109.51396234588833, 40.808045034463966 ], [ -109.51393251300333, 40.808319396951298 ], [ -109.51374026400202, 40.808699764063135 ], [ -109.51339885053234, 40.809388987745351 ], [ -109.51329679475226, 40.809711963728475 ], [ -109.51326455027981, 40.809828653318789 ], [ -109.51322868676608, 40.810107441848594 ], [ -109.5132174326198, 40.810346011139572 ], [ -109.51327729343906, 40.810585496977744 ], [ -109.51331636470665, 40.81069409757832 ], [ -109.51356536483456, 40.81095854090421 ], [ -109.51369965956647, 40.81105035217076 ], [ -109.51390446745279, 40.81117009596359 ], [ -109.51447449821296, 40.811393632182977 ], [ -109.51508087462494, 40.811635649633324 ], [ -109.51557218341999, 40.811880687284585 ], [ -109.516114607254, 40.812279517864148 ], [ -109.51646407293032, 40.812558759373324 ], [ -109.51681442594801, 40.812851523362603 ], [ -109.51703355082074, 40.813020990168177 ], [ -109.51747864441724, 40.813585212640334 ], [ -109.517942745223, 40.814041580553393 ], [ -109.51825606694305, 40.814347376503584 ], [ -109.5185460857264, 40.814634856160481 ], [ -109.518979466014, 40.815140369814841 ], [ -109.51937306796982, 40.815568802542721 ], [ -109.51976094840491, 40.815988152416075 ], [ -109.52004435334601, 40.816307071709822 ], [ -109.52034544134753, 40.816630721169147 ], [ -109.52079752897095, 40.817095931532421 ], [ -109.52094269948883, 40.817232914246368 ], [ -109.52117317328494, 40.817533135886187 ], [ -109.52141972990857, 40.817910131907148 ], [ -109.52175269427075, 40.818400835764123 ], [ -109.52200791247427, 40.818922070797299 ], [ -109.52236692350877, 40.81957525201728 ], [ -109.52277315871609, 40.820238044939657 ], [ -109.52299542595007, 40.820641750684764 ], [ -109.52320514216173, 40.821076823575638 ], [ -109.52333337770916, 40.821443292429677 ], [ -109.52343560830522, 40.821913021137064 ], [ -109.52351492990471, 40.822346424183138 ], [ -109.52359768307923, 40.822892472021998 ], [ -109.52365801312177, 40.823433728732503 ], [ -109.52373375545247, 40.823975182619712 ], [ -109.52374894142227, 40.824092481940461 ], [ -109.52379186755246, 40.824295712977211 ], [ -109.52384275445887, 40.824674703306449 ], [ -109.52389011089565, 40.824945551535841 ], [ -109.52391775159461, 40.825035985981081 ], [ -109.52398478852956, 40.825221509311518 ], [ -109.52404789518727, 40.825316901581964 ], [ -109.5241453695488, 40.825466781985398 ], [ -109.52426725367577, 40.82558544634589 ], [ -109.52467689741587, 40.825829400415451 ], [ -109.52513949406551, 40.826092046256406 ], [ -109.52579531465338, 40.826465256779287 ], [ -109.52656870058109, 40.826885005763863 ], [ -109.52745029079364, 40.827238570447911 ], [ -109.52794996903441, 40.827434117890164 ], [ -109.52848789604366, 40.827562590588904 ], [ -109.52865239047976, 40.827578201077806 ], [ -109.52900746198344, 40.827609753980731 ], [ -109.52953503747783, 40.827616480814633 ], [ -109.53029045551487, 40.827509003593605 ], [ -109.53105931695266, 40.827329628020514 ], [ -109.53206806634198, 40.827027187354375 ], [ -109.53315949751219, 40.826739301388734 ], [ -109.53393990074414, 40.826573565397162 ], [ -109.53489537595217, 40.826265918687362 ], [ -109.53569198379336, 40.825902198872441 ], [ -109.53629039608063, 40.825653063704962 ], [ -109.53645785568031, 40.825587627958377 ], [ -109.5371465623182, 40.825276577364164 ], [ -109.53755913028697, 40.825119663362088 ], [ -109.53795480369448, 40.82492199736712 ], [ -109.53848187026881, 40.824680954465087 ], [ -109.53899381891766, 40.824318108525439 ], [ -109.53916838597925, 40.824198710323785 ], [ -109.53936636609924, 40.82409312045278 ], [ -109.5396476272299, 40.823975072498961 ], [ -109.53977437719686, 40.823927132651846 ], [ -109.54049535761025, 40.823711055270635 ], [ -109.54149245225527, 40.823394871942291 ], [ -109.54285812356977, 40.823033792027424 ], [ -109.54419355255422, 40.82269933843893 ], [ -109.54527775490058, 40.822465294312664 ], [ -109.54637352934122, 40.822243997104756 ], [ -109.54761579113324, 40.82210200354529 ], [ -109.54777027610643, 40.82208683319022 ], [ -109.54861995212431, 40.8220029422355 ], [ -109.54997869272768, 40.821956973658089 ], [ -109.55085633518503, 40.821949986544681 ], [ -109.55158618532998, 40.821923120892116 ], [ -109.55210938030426, 40.821856723673612 ], [ -109.55303240868849, 40.821671028572894 ], [ -109.55339057417474, 40.821559316415566 ], [ -109.55360049653555, 40.821448446831965 ], [ -109.55377000302445, 40.82128752562177 ], [ -109.55383850979128, 40.821136147682878 ], [ -109.55393784598587, 40.820930206793193 ], [ -109.55395752533285, 40.820570129610644 ], [ -109.5539400761451, 40.820281651746249 ], [ -109.55395975518582, 40.819921574520578 ], [ -109.5540758926373, 40.819760884571622 ], [ -109.55434040425945, 40.819593045999795 ], [ -109.55458052160392, 40.819456429490089 ], [ -109.5549387898931, 40.819339308848427 ], [ -109.55512370412744, 40.819287576582106 ], [ -109.55525488297988, 40.819253187217086 ], [ -109.55584508850986, 40.819102936024898 ], [ -109.55652032129527, 40.818859160759992 ], [ -109.55748131776049, 40.818560402739493 ], [ -109.55847016666442, 40.818343958462307 ], [ -109.5595303677774, 40.818117586971411 ], [ -109.55988210909469, 40.818027393682918 ], [ -109.56022803930269, 40.81793172192252 ], [ -109.56071742423063, 40.81778198885582 ], [ -109.56132735159957, 40.817540973652676 ], [ -109.56221835158095, 40.817187254263864 ], [ -109.56313936565924, 40.816815885572865 ], [ -109.56401470238272, 40.816362867871533 ], [ -109.56436236591941, 40.81618613220698 ], [ -109.56473319156454, 40.816034906379237 ], [ -109.56549679906618, 40.815813797152153 ], [ -109.56656410527647, 40.815529797051241 ], [ -109.56756504522845, 40.815299011607799 ], [ -109.56855487992942, 40.815032947987724 ], [ -109.5695458097108, 40.814715543148459 ], [ -109.57067415530588, 40.814071937039614 ], [ -109.57078247926017, 40.813996710187972 ], [ -109.57130125816032, 40.813579754960692 ], [ -109.57158844320908, 40.813457197756648 ], [ -109.57176624318242, 40.8134593992392 ], [ -109.57184174463892, 40.813532398944766 ], [ -109.57179008177437, 40.813729937921529 ], [ -109.57169090833921, 40.813931392674093 ], [ -109.57147622843598, 40.814266538759767 ], [ -109.57113962907403, 40.814757816353584 ], [ -109.57085916885585, 40.815119170757001 ], [ -109.5707536769864, 40.815338562587208 ], [ -109.57070890278774, 40.815491145778864 ], [ -109.57058807603445, 40.81587249348685 ], [ -109.57046707381765, 40.816261946166101 ], [ -109.57039015975278, 40.816806884622977 ], [ -109.57037884354824, 40.817113020193446 ], [ -109.57044230427164, 40.817415578407349 ], [ -109.57046330523448, 40.817541952225866 ], [ -109.5705168714376, 40.817808355317744 ], [ -109.57070579406388, 40.818121476142601 ], [ -109.57101599828947, 40.818584732949844 ], [ -109.5712970541075, 40.819025107619559 ], [ -109.57136049426393, 40.819107867134164 ], [ -109.57158052891027, 40.81935291017659 ], [ -109.57222656906315, 40.819914907005362 ], [ -109.57286630667984, 40.820494838451729 ], [ -109.57339098230061, 40.820911197435983 ], [ -109.57368941730671, 40.821095050076558 ], [ -109.57393634040142, 40.821192688106272 ], [ -109.57411290738715, 40.821253423515202 ], [ -109.57428957113771, 40.821309655796455 ], [ -109.57496794170068, 40.821471176049187 ], [ -109.5755517662614, 40.821618012676346 ], [ -109.57604591167356, 40.821799771785706 ], [ -109.5766912849073, 40.822118516483378 ], [ -109.57731228081343, 40.82246848530184 ], [ -109.57777304798348, 40.822825483460903 ], [ -109.57823343539019, 40.823200491313031 ], [ -109.57851859671963, 40.823451728684496 ], [ -109.57888189483243, 40.823986782575872 ], [ -109.57903496838281, 40.824259812345041 ], [ -109.57942901504592, 40.824688046794726 ], [ -109.57981859935965, 40.825047763345978 ], [ -109.58038034236625, 40.825397886935434 ], [ -109.5805454551576, 40.825440455344655 ], [ -109.58069364904441, 40.825442278867897 ], [ -109.5811402657106, 40.825352287403064 ], [ -109.58162977632767, 40.825197062465179 ], [ -109.58183849431853, 40.825141076022106 ], [ -109.58203506873683, 40.825098452083132 ], [ -109.58239938017726, 40.825030865015975 ], [ -109.5827008920791, 40.825016553843938 ], [ -109.58291457771769, 40.825005667019887 ], [ -109.58357441134814, 40.824982242844492 ], [ -109.58432088513246, 40.824955374190878 ], [ -109.58526253787109, 40.82472821221829 ], [ -109.58612186630452, 40.824468505097137 ], [ -109.58653999768997, 40.82437904429991 ], [ -109.58675345135609, 40.8243231069522 ], [ -109.58687955758082, 40.824248082958242 ], [ -109.58704285439597, 40.824096945439763 ], [ -109.58730538867906, 40.823739836506462 ], [ -109.58739707418086, 40.823610341707209 ], [ -109.58764899144744, 40.823194549195932 ], [ -109.58775128412289, 40.822844485192569 ], [ -109.58777126393433, 40.822741136496603 ], [ -109.58794133119176, 40.821991040922498 ], [ -109.58800480834604, 40.821793639414608 ], [ -109.58825088273348, 40.821373269840841 ], [ -109.58884627792933, 40.820695938199627 ], [ -109.58918167461617, 40.82031269167021 ], [ -109.589608292948, 40.819989112271884 ], [ -109.59002395195414, 40.819678909483599 ], [ -109.59038559453911, 40.819399573521899 ], [ -109.59073863799995, 40.819246245035146 ], [ -109.59107437467297, 40.819070183771828 ], [ -109.59154727151788, 40.818576007977846 ], [ -109.59186979261698, 40.818183588054154 ], [ -109.59215284336396, 40.817975352006691 ], [ -109.59231468453746, 40.817891749911986 ], [ -109.59242844207246, 40.817839089308428 ], [ -109.59290010972047, 40.817682697449762 ], [ -109.59340629125742, 40.817576269187008 ], [ -109.59391754244831, 40.817510437050437 ], [ -109.59439830172407, 40.81748476766569 ], [ -109.59456464024889, 40.817468778129538 ], [ -109.59497503428416, 40.817406216514975 ], [ -109.5952498649746, 40.817305970175198 ], [ -109.59554731266638, 40.817201494476606 ], [ -109.59591299255025, 40.817066320093019 ], [ -109.59667464929579, 40.816652206350227 ], [ -109.59749518702701, 40.81625681965955 ], [ -109.59844093929908, 40.815826915947817 ], [ -109.59915759177132, 40.815577988398637 ], [ -109.5996466112078, 40.815440696537145 ], [ -109.60032426729653, 40.815354335473252 ], [ -109.60087669985634, 40.815302484218464 ], [ -109.60141182383506, 40.815227900133003 ], [ -109.60172651689273, 40.815204690655442 ], [ -109.6022543455593, 40.815251624018295 ], [ -109.60249531266328, 40.815295080098743 ], [ -109.60303794306775, 40.815427766461134 ], [ -109.60362860996352, 40.815588056159292 ], [ -109.60443453009924, 40.815774368289297 ], [ -109.60467789029384, 40.815816947956399 ], [ -109.60483023975223, 40.815845815036973 ], [ -109.6052683226423, 40.815932185770194 ], [ -109.60587202532648, 40.81598001994103 ], [ -109.60651147934591, 40.816019274696593 ], [ -109.60726777857889, 40.81614100988611 ], [ -109.6077872828663, 40.816246370332138 ], [ -109.60852431932246, 40.816439029079746 ], [ -109.60980699060967, 40.816905801644893 ], [ -109.61083832806985, 40.817201081466671 ], [ -109.61181638708526, 40.817493008509132 ], [ -109.61251749262358, 40.817704126484749 ], [ -109.61318341487983, 40.817896800965919 ], [ -109.61392639449419, 40.818090397533211 ], [ -109.61407975144839, 40.818128272660822 ], [ -109.61429821398758, 40.818171433749264 ], [ -109.61454696873736, 40.818183429773015 ], [ -109.61468404379258, 40.818149043461986 ], [ -109.61492384817672, 40.818021305080045 ], [ -109.61539082319284, 40.817517951396376 ], [ -109.61563137297527, 40.817354187912265 ], [ -109.61593203514127, 40.817150608554847 ], [ -109.61623222754517, 40.816969543109678 ], [ -109.61657340736009, 40.81652773239675 ], [ -109.61695220242748, 40.815987282070331 ], [ -109.61719813645685, 40.81562089662615 ], [ -109.61756266654255, 40.81513882609606 ], [ -109.61818715767004, 40.814470697594693 ], [ -109.61889036590044, 40.813722434743028 ], [ -109.61955792306516, 40.812977344089823 ], [ -109.61975157361474, 40.812786886922964 ], [ -109.61993187648881, 40.812668334913248 ], [ -109.62026575066731, 40.812576842300324 ], [ -109.62066321342455, 40.812563579123442 ], [ -109.62088194219113, 40.812593218681457 ], [ -109.62117132558204, 40.812646222716381 ], [ -109.62144904244106, 40.812690078463135 ], [ -109.62217182339536, 40.812712225737343 ], [ -109.6234750524043, 40.812759312466675 ], [ -109.62365257525482, 40.81277494285365 ], [ -109.62407225712452, 40.81283399821293 ], [ -109.62459713316647, 40.81296637149859 ], [ -109.62503875765339, 40.813111262377795 ], [ -109.62568631182415, 40.813389223237358 ], [ -109.6261140664372, 40.813574481440533 ], [ -109.62623695027185, 40.813652514151471 ], [ -109.6264823472798, 40.813826591065038 ], [ -109.62674996715114, 40.814072997192582 ], [ -109.62708852590333, 40.81432925513279 ], [ -109.62732855769671, 40.814476241947844 ], [ -109.62763462184006, 40.814583477176292 ], [ -109.62784067172912, 40.814653489394829 ], [ -109.62828898374231, 40.814762414814091 ], [ -109.6287656337079, 40.81493473238357 ], [ -109.62953307330017, 40.815380747428115 ], [ -109.6302560713056, 40.815682099320384 ], [ -109.63080996967108, 40.815846317529093 ], [ -109.63137690966653, 40.815953035664968 ], [ -109.63156622324891, 40.815972397048967 ], [ -109.6319604611232, 40.815828438600398 ], [ -109.6322184684268, 40.815678359526629 ], [ -109.63241740800699, 40.815517670659972 ], [ -109.63261130737544, 40.815313682578903 ], [ -109.6327750344372, 40.815135460196181 ], [ -109.63346224834173, 40.814292332751187 ], [ -109.63368300834581, 40.813934621582547 ], [ -109.63392163881593, 40.813572617507582 ], [ -109.63408637404451, 40.813344860274363 ], [ -109.6344401022175, 40.812862607751725 ], [ -109.63469809277579, 40.812423361011305 ], [ -109.63492447105513, 40.812080126846297 ], [ -109.6350540081459, 40.811833935320784 ], [ -109.63510010956047, 40.811609276874378 ], [ -109.63508755187272, 40.811065035607349 ], [ -109.63510968778806, 40.810852704991149 ], [ -109.63516561112718, 40.810727252425956 ], [ -109.63526894682806, 40.810602360735203 ], [ -109.63564229849452, 40.810318515858583 ], [ -109.63600659840253, 40.810129148395959 ], [ -109.63661069626356, 40.809924597743155 ], [ -109.63765919800005, 40.809671243923241 ], [ -109.63869381411024, 40.809516806451548 ], [ -109.64002631252832, 40.809289302355175 ], [ -109.64201700562106, 40.809051516329539 ], [ -109.642830948355, 40.808962005003146 ], [ -109.64359866975875, 40.808813391393073 ], [ -109.64435416839304, 40.808682645354075 ], [ -109.6445925999836, 40.808617885729653 ], [ -109.64487370709975, 40.808495073832582 ], [ -109.64516183880949, 40.808318294739806 ], [ -109.64538422931876, 40.808167767484868 ], [ -109.6459458192324, 40.807660894884684 ], [ -109.64621689775366, 40.807447880268406 ], [ -109.64645861319404, 40.807279561336465 ], [ -109.64664332102588, 40.8071745311331 ], [ -109.64685906050825, 40.807117607917725 ], [ -109.647089823814, 40.807079777645512 ], [ -109.64742233608956, 40.807052148085937 ], [ -109.64793009255405, 40.806859920429375 ], [ -109.64806165872054, 40.806802909216586 ], [ -109.64846930485757, 40.806577977328239 ], [ -109.64887166144246, 40.806321453426293 ], [ -109.64932277599588, 40.805998838487682 ], [ -109.64972651334074, 40.805673865598571 ], [ -109.6500757980981, 40.805403203964133 ], [ -109.65033536699877, 40.80517202846741 ], [ -109.65051807716797, 40.804930945159811 ], [ -109.65064863708655, 40.804630698446836 ], [ -109.650772722486, 40.804357400373164 ], [ -109.65084821294747, 40.804142087005111 ], [ -109.65108452716925, 40.803595351586999 ], [ -109.65125957221072, 40.803146989295591 ], [ -109.65141820450093, 40.802630873496192 ], [ -109.65147454563819, 40.80242434396996 ], [ -109.65150226012337, 40.80228504114433 ], [ -109.65149797484108, 40.802145364270217 ], [ -109.65148402573543, 40.801956029442785 ], [ -109.65147627614917, 40.80181180797608 ], [ -109.65152796573999, 40.801307954055531 ], [ -109.65167784020554, 40.80093136216648 ], [ -109.65187284060238, 40.800667899660951 ], [ -109.65206711056243, 40.800440461003959 ], [ -109.65226019493934, 40.800271561344715 ], [ -109.6523926552334, 40.800169514590962 ], [ -109.65277754494242, 40.799894756172492 ], [ -109.65330592115384, 40.799558614173115 ], [ -109.65372408239911, 40.799396843227946 ], [ -109.65396247192074, 40.799332063468015 ], [ -109.65421872878238, 40.799262987546641 ], [ -109.65455721609605, 40.799230902814401 ], [ -109.65480618257777, 40.799229301954284 ], [ -109.65497182689974, 40.799244745536868 ], [ -109.65521423158606, 40.799274595945278 ], [ -109.65539747121588, 40.799299252202033 ], [ -109.65631421642937, 40.799395510937408 ], [ -109.65667586130888, 40.799390714259175 ], [ -109.65709138141882, 40.799359519019887 ], [ -109.6576606044993, 40.799348127140874 ], [ -109.65815746836212, 40.799398047356895 ], [ -109.65864692053779, 40.799521746398831 ], [ -109.65917131225621, 40.799676477286702 ], [ -109.65960727434687, 40.799807657944328 ], [ -109.66033223851464, 40.800009754673333 ], [ -109.66089336906188, 40.800106351140997 ], [ -109.66124809679152, 40.800151004882679 ], [ -109.6614254879883, 40.800171980433845 ], [ -109.66172216256848, 40.800215058311693 ], [ -109.66216988486211, 40.800292316594103 ], [ -109.66282026818236, 40.800371922289472 ], [ -109.66306860665283, 40.80040182498859 ], [ -109.66335349359095, 40.800382605572445 ], [ -109.66365697050961, 40.800323063937533 ], [ -109.66386518378563, 40.800284938711229 ], [ -109.66451908975198, 40.80018891593425 ], [ -109.66529295157633, 40.800022211770752 ], [ -109.66615202323135, 40.799743885207647 ], [ -109.6671839229063, 40.799418003913352 ], [ -109.66789429815371, 40.799164970914781 ], [ -109.66812154275182, 40.7990640003637 ], [ -109.66830847743765, 40.79890401081304 ], [ -109.66846057760121, 40.798707586133524 ], [ -109.66852845889186, 40.798573246661817 ], [ -109.66878453129301, 40.798215873931142 ], [ -109.6690234540342, 40.797826774065939 ], [ -109.66916863467534, 40.79767981364872 ], [ -109.66931992003362, 40.797523915259006 ], [ -109.66968685955355, 40.797253396998521 ], [ -109.66979477661557, 40.797191583951609 ], [ -109.67030966867019, 40.796931777668838 ], [ -109.67088264320608, 40.796731191503468 ], [ -109.67194975695013, 40.796419185099317 ], [ -109.67239083859329, 40.796293642759181 ], [ -109.67267175395308, 40.796175264326045 ], [ -109.67287510037717, 40.796083017538521 ], [ -109.67337147881153, 40.795859017292003 ], [ -109.67370607726514, 40.795723237196754 ], [ -109.67383158494724, 40.795670630753129 ], [ -109.67425568860945, 40.795504349161305 ], [ -109.67513693450806, 40.795298275502944 ], [ -109.67585074569949, 40.795166843226177 ], [ -109.6764558596704, 40.795136853106158 ], [ -109.67695381715943, 40.795130853982748 ], [ -109.67748065035573, 40.795163018178286 ], [ -109.6782672865162, 40.795244098509471 ], [ -109.67889977713941, 40.795327912578898 ], [ -109.679430914146, 40.795442091820291 ], [ -109.67996187461522, 40.79556527480549 ], [ -109.68040988212898, 40.795687506578176 ], [ -109.68086929631951, 40.795832387549957 ], [ -109.68122842665731, 40.795953599906156 ], [ -109.68155198814948, 40.796075305493211 ], [ -109.68193987514714, 40.796240984470188 ], [ -109.68250878105982, 40.796543852540495 ], [ -109.68312328031332, 40.796939121925575 ], [ -109.68361334045451, 40.797273514087841 ], [ -109.68423629758259, 40.797601312521884 ], [ -109.6848880058056, 40.797914121391869 ], [ -109.68543446331894, 40.798154562552824 ], [ -109.68568704280936, 40.798270042823098 ], [ -109.6859872944855, 40.798372553214328 ], [ -109.68635136619743, 40.798484797733373 ], [ -109.68655277953552, 40.798550148376215 ], [ -109.68674743755942, 40.798597405364134 ], [ -109.68811509065435, 40.798973293510613 ], [ -109.68898075852272, 40.799257884199157 ], [ -109.68975737100079, 40.79955046524038 ], [ -109.69018083585676, 40.799717421437478 ], [ -109.69073758637386, 40.800039028227431 ], [ -109.69091880764256, 40.80016719953872 ], [ -109.69157851561575, 40.800679142762441 ], [ -109.69209185504403, 40.801099340910092 ], [ -109.69243485229937, 40.801441036528047 ], [ -109.69275096270657, 40.801642799323439 ], [ -109.69306088407215, 40.801858003444543 ], [ -109.69323088119849, 40.801954515259034 ], [ -109.69347853441106, 40.802020377587517 ], [ -109.6936322558865, 40.802040134769122 ], [ -109.69384523699806, 40.80206056268193 ], [ -109.6941611662549, 40.80196955297928 ], [ -109.69436973937262, 40.801912459482686 ], [ -109.69460790653386, 40.8018575021106 ], [ -109.69488138189833, 40.80181555516662 ], [ -109.6953441340017, 40.801793764609322 ], [ -109.69648893668759, 40.80181120926121 ], [ -109.69694812503934, 40.801910982761413 ], [ -109.69737179957001, 40.802068906780775 ], [ -109.69748926229782, 40.802124282235653 ], [ -109.69782440185013, 40.802263188582771 ], [ -109.69825861284433, 40.802488789811818 ], [ -109.69876244375321, 40.802791744416908 ], [ -109.69903644018964, 40.802965990409056 ], [ -109.69932536400833, 40.803104371230944 ], [ -109.69961819630106, 40.803224778977842 ], [ -109.69991419106326, 40.803304684703342 ], [ -109.70020900133572, 40.803384576325627 ], [ -109.70058702361091, 40.803452792984821 ], [ -109.70107741431103, 40.803533984293153 ], [ -109.7015271836971, 40.8035705761244 ], [ -109.70184719347566, 40.803574177450905 ], [ -109.70227997483089, 40.803570038269086 ], [ -109.70262342603201, 40.80358741343148 ], [ -109.7034301660819, 40.803555946029192 ], [ -109.70393563774701, 40.803471543701178 ], [ -109.7042223681739, 40.803357657880603 ], [ -109.70439632687041, 40.803251513143302 ], [ -109.70451128697867, 40.803131193332383 ], [ -109.70463304838194, 40.802965908734656 ], [ -109.70472447848076, 40.802836316292272 ], [ -109.70486401690555, 40.802671231027091 ], [ -109.7051470045174, 40.802444698255563 ], [ -109.70530151849962, 40.802423911856089 ], [ -109.70556217560542, 40.802431340863137 ], [ -109.70582840887103, 40.8024568482506 ], [ -109.70608981407516, 40.802486804979019 ], [ -109.70688337656964, 40.802522727127332 ], [ -109.70739836732214, 40.802496969615277 ], [ -109.70777920525839, 40.802420162093505 ], [ -109.70827995966965, 40.802272630345527 ], [ -109.70855979147204, 40.802208201584151 ], [ -109.7088631521834, 40.802153043677563 ], [ -109.70933862796069, 40.802086298298178 ], [ -109.71043307277122, 40.801949901577984 ], [ -109.71104940972336, 40.801893731784958 ], [ -109.71272393032883, 40.801736768103993 ], [ -109.71420820457679, 40.801609188661033 ], [ -109.7154018414199, 40.801491866598866 ], [ -109.71608942578978, 40.801490512424905 ], [ -109.71666459055334, 40.801478895455439 ], [ -109.71721570452711, 40.801485024629059 ], [ -109.71784359614259, 40.801505516794535 ], [ -109.71811593041738, 40.801522055410004 ], [ -109.7186415223143, 40.80162248045923 ], [ -109.71880675674798, 40.801660348412796 ], [ -109.71901922604371, 40.801707748824278 ], [ -109.71934376999337, 40.801783417644984 ], [ -109.71968525366862, 40.801841257113466 ], [ -109.71985210713787, 40.801856620998187 ], [ -109.72002971400849, 40.801867599839248 ], [ -109.72025053305951, 40.801788975588167 ], [ -109.72042515462685, 40.801646781013673 ], [ -109.72099737337972, 40.801171186540799 ], [ -109.72138705361496, 40.800941292283447 ], [ -109.72180224911799, 40.800617093078735 ], [ -109.72198949351169, 40.80043449894454 ], [ -109.72207970142432, 40.80030487900536 ], [ -109.72234870607078, 40.799938521361142 ], [ -109.72262348442472, 40.799518177653766 ], [ -109.72302983428523, 40.799036232065333 ], [ -109.72338043084775, 40.798679783189762 ], [ -109.72353133469433, 40.798537321332866 ], [ -109.72399606617401, 40.798101059259977 ], [ -109.72458600567478, 40.797625642477861 ], [ -109.72502538425655, 40.797274674012868 ], [ -109.72596260799375, 40.79661391462745 ], [ -109.72673088775393, 40.796108927106964 ], [ -109.72730644487424, 40.795763956711696 ], [ -109.7278403460159, 40.795427532316531 ], [ -109.72804540306146, 40.795303677984109 ], [ -109.72834856354817, 40.795194416981289 ], [ -109.72898026621178, 40.795012205118262 ], [ -109.73000991104438, 40.79478482562584 ], [ -109.73051588572781, 40.7946687830066 ], [ -109.73082503486243, 40.794618134866049 ], [ -109.73121104193288, 40.794577339383579 ], [ -109.73153118369076, 40.794571851402111 ], [ -109.73184471444003, 40.794602322799619 ], [ -109.73205742830696, 40.794636189532206 ], [ -109.73221088853721, 40.794669404771412 ], [ -109.7324115807168, 40.794712146983059 ], [ -109.7327884935424, 40.794837898628828 ], [ -109.73323445820762, 40.795072506045145 ], [ -109.73379876382387, 40.795317418815152 ], [ -109.73401637982946, 40.795405385145038 ], [ -109.73425795489359, 40.795480101570668 ], [ -109.73449386161298, 40.79554124296569 ], [ -109.73474196175653, 40.795584501134719 ], [ -109.73575239847413, 40.795744213773105 ], [ -109.73656197074672, 40.795870189265003 ], [ -109.73700484711601, 40.795956112454476 ], [ -109.73735206302138, 40.796086028235941 ], [ -109.73775785321841, 40.796252616765962 ], [ -109.73855690661283, 40.796621685522204 ], [ -109.73888550002822, 40.796796434252492 ], [ -109.73924947840655, 40.796980576965034 ], [ -109.73950232018275, 40.797086934367584 ], [ -109.74016149378042, 40.797331951698823 ], [ -109.74094947118715, 40.797661246734137 ], [ -109.74150282699657, 40.797860961228309 ], [ -109.74203806895741, 40.798078492035593 ], [ -109.74254825171708, 40.798367813109913 ], [ -109.74329377078894, 40.79874977796775 ], [ -109.74401618947748, 40.79909995771763 ], [ -109.74460892617614, 40.799412688968943 ], [ -109.74505470937437, 40.799660761147372 ], [ -109.74570019554177, 40.800005589386565 ], [ -109.74604075982141, 40.800239001423677 ], [ -109.74640164304421, 40.800526682634654 ], [ -109.74654191691711, 40.800631801425283 ], [ -109.7471207948002, 40.801052467993081 ], [ -109.74772473847226, 40.801401337880101 ], [ -109.74798192852168, 40.801530244505571 ], [ -109.74820652603822, 40.801627268112838 ], [ -109.74834773576023, 40.801682849588325 ], [ -109.74875942965555, 40.801853967651368 ], [ -109.74915268794162, 40.802060016470094 ], [ -109.74960517588195, 40.802268507556619 ], [ -109.74975807134776, 40.802333222192431 ], [ -109.74999918284671, 40.802434925390649 ], [ -109.75033485969828, 40.802551164796625 ], [ -109.75070711090598, 40.802676807517777 ], [ -109.75087092878712, 40.802728126609637 ], [ -109.75120719960475, 40.802812841103659 ], [ -109.75157911266291, 40.802893436199398 ], [ -109.75206963440316, 40.80297080902281 ], [ -109.75228744755549, 40.802987578053113 ], [ -109.75259181198628, 40.802940423261958 ], [ -109.75278872450133, 40.802870486331436 ], [ -109.75340959593322, 40.802633974419294 ], [ -109.75421594129008, 40.802304875633574 ], [ -109.75483823339523, 40.801991801318415 ], [ -109.75515568200782, 40.801815062364462 ], [ -109.75537822787767, 40.80164180285675 ], [ -109.75553499726699, 40.801499362236619 ], [ -109.75595663196644, 40.801139075993362 ], [ -109.75609562091933, 40.800996442860608 ], [ -109.75624867210614, 40.80079901090982 ], [ -109.75630290562019, 40.80068789342625 ], [ -109.75635317154712, 40.800535295253951 ], [ -109.75638082621376, 40.800323899777332 ], [ -109.75637767423524, 40.800175229878221 ], [ -109.75636267042763, 40.800026432218878 ], [ -109.75626789986674, 40.799070537292629 ], [ -109.75614299853406, 40.798141342023818 ], [ -109.75603709490144, 40.797464582101739 ], [ -109.75593535321558, 40.796882453440581 ], [ -109.75579763923835, 40.796322457320841 ], [ -109.75562656075999, 40.795644993965524 ], [ -109.75555792988348, 40.795257800026512 ], [ -109.75554659263753, 40.795166694466779 ], [ -109.75553428276216, 40.794873793721301 ], [ -109.75557504955405, 40.794594977829725 ], [ -109.75564468619262, 40.794357010395146 ], [ -109.75576105277511, 40.794155579858398 ], [ -109.7559128027556, 40.793963538989843 ], [ -109.75604559889214, 40.793834351284993 ], [ -109.75641784580272, 40.793577125050021 ], [ -109.75661006156244, 40.793439568882881 ], [ -109.75676757362092, 40.793319654936099 ], [ -109.75703096649335, 40.79311530314844 ], [ -109.75773312554969, 40.792645428402693 ], [ -109.75817171179889, 40.792325852925771 ], [ -109.75855612808235, 40.792050734143771 ], [ -109.75894529233135, 40.791838722889985 ], [ -109.75936516982283, 40.791568486932022 ], [ -109.75957632264495, 40.791368071592203 ], [ -109.75992769060731, 40.790957469039839 ], [ -109.76031493976224, 40.790529234404303 ], [ -109.76071962409335, 40.790119202205908 ], [ -109.76107656848791, 40.789726672426553 ], [ -109.7612045092354, 40.789538872819321 ], [ -109.76133268359091, 40.789338464010484 ], [ -109.76138769890649, 40.789248071241964 ], [ -109.76175517771532, 40.788607024452602 ], [ -109.76192031999673, 40.788330441490658 ], [ -109.76201252235511, 40.788152166505903 ], [ -109.76207571883917, 40.787940249671898 ], [ -109.76212095639872, 40.78773804920084 ], [ -109.76226652238965, 40.786919859216908 ], [ -109.76238354804876, 40.78604280908602 ], [ -109.76246240294331, 40.785625671529075 ], [ -109.76248837555669, 40.785503437731386 ], [ -109.76254011984403, 40.78526977787071 ], [ -109.76263809025657, 40.785099671573732 ], [ -109.76277210919115, 40.784902926954175 ], [ -109.76292406817686, 40.784697366256431 ], [ -109.76345362317348, 40.783941844427382 ], [ -109.76389129339422, 40.783347484475243 ], [ -109.7642185433089, 40.782955527022388 ], [ -109.76439938078983, 40.7827899099589 ], [ -109.76462100379688, 40.78266166320072 ], [ -109.76485981506069, 40.782565128950317 ], [ -109.76511581485357, 40.782500307106375 ], [ -109.7652765237475, 40.782461489801932 ], [ -109.76570967025471, 40.78243009113951 ], [ -109.76601148115367, 40.7825152946263 ], [ -109.76622217390704, 40.782593217237185 ], [ -109.76674619569592, 40.782774480713535 ], [ -109.76716433026428, 40.782914073252364 ], [ -109.76767659159282, 40.783090702715668 ], [ -109.76784141044153, 40.783150115870725 ], [ -109.7679813136149, 40.783211064400611 ], [ -109.76811751258506, 40.783280080654613 ], [ -109.76825959966321, 40.78328700255036 ], [ -109.76845845108465, 40.783108058999346 ], [ -109.76876793716102, 40.782778055974568 ], [ -109.76908297034839, 40.782340012018551 ], [ -109.76930707703235, 40.782076658634416 ], [ -109.76956589675575, 40.781858716343621 ], [ -109.76976904770302, 40.781703237819812 ], [ -109.76994428119561, 40.781583494402248 ], [ -109.77015464448182, 40.781486645847444 ], [ -109.77032025371965, 40.78143886544818 ], [ -109.77086021162573, 40.781398676597476 ], [ -109.77158896630691, 40.781402834282432 ], [ -109.77238932688812, 40.781379823592033 ], [ -109.77310090549925, 40.781351359188612 ], [ -109.77430577311912, 40.7812425530187 ], [ -109.77530221187573, 40.781190075899893 ], [ -109.77650977474306, 40.781256936676286 ], [ -109.77675225767281, 40.781282028362085 ], [ -109.77705365336479, 40.781325760530315 ], [ -109.77732551053114, 40.78136467476461 ], [ -109.77813935080695, 40.781575982199875 ], [ -109.77901227488067, 40.781796917430896 ], [ -109.77991466189921, 40.782027165900899 ], [ -109.78017434541098, 40.782083961256951 ], [ -109.78041666814656, 40.782118051834892 ], [ -109.7807597880084, 40.782148702937349 ], [ -109.78163075474204, 40.782153399051502 ], [ -109.78255438334206, 40.78219467737334 ], [ -109.78396381382412, 40.782241069322026 ], [ -109.78497614744649, 40.782292271390709 ], [ -109.78622637760289, 40.78229552104996 ], [ -109.7875410887583, 40.782337269535155 ], [ -109.78839412275117, 40.782350734424455 ], [ -109.7887615184766, 40.782350087672135 ], [ -109.78934211153096, 40.782356181091302 ], [ -109.78989933404632, 40.782344009922248 ], [ -109.79039138780398, 40.782331152878925 ], [ -109.79058595387468, 40.782319680035378 ], [ -109.79078897743702, 40.782299287217299 ], [ -109.79132331817142, 40.78224182794996 ], [ -109.79244676865042, 40.782047301469511 ], [ -109.79336346253677, 40.781817271341311 ], [ -109.79437655252191, 40.781499059156857 ], [ -109.79518665959397, 40.781264297382563 ], [ -109.79588444307177, 40.781014845320769 ], [ -109.79655901195875, 40.78073812202171 ], [ -109.79711460244462, 40.780487179299193 ], [ -109.7975382308916, 40.780324941591608 ], [ -109.79790613633148, 40.780229683954502 ], [ -109.79867013702683, 40.780052971083407 ], [ -109.79917364779868, 40.779995154340924 ], [ -109.79942254663024, 40.779993240289656 ], [ -109.79978984904125, 40.779997061534516 ], [ -109.79998526768584, 40.780003598248179 ], [ -109.8004530391609, 40.780021974676295 ], [ -109.80122781878832, 40.780102093159137 ], [ -109.80212116640129, 40.780178933301613 ], [ -109.80285464200674, 40.780249603762293 ], [ -109.80335788104021, 40.780272840547944 ], [ -109.80368379646161, 40.780271716020195 ], [ -109.80387929724448, 40.780273742846397 ], [ -109.80430544065837, 40.780300680407102 ], [ -109.80506285950015, 40.780358072516648 ], [ -109.80563664312827, 40.780412658113924 ], [ -109.80610960195983, 40.780472503455535 ], [ -109.80670074130552, 40.780550684906146 ], [ -109.80738707377895, 40.780607326566688 ], [ -109.8075763293312, 40.780627299163797 ], [ -109.80789085824868, 40.780666582397075 ], [ -109.80830973598376, 40.780702438401946 ], [ -109.80864734144581, 40.780710428884817 ], [ -109.80893211087431, 40.780690848100846 ], [ -109.80918741945595, 40.780661954272674 ], [ -109.80963909844854, 40.780586441134417 ], [ -109.810215379658, 40.780501401184495 ], [ -109.81075009301159, 40.78042133489506 ], [ -109.81092870533399, 40.780373630085776 ], [ -109.81104174871048, 40.78034777010393 ], [ -109.81117270940079, 40.780313987154187 ], [ -109.8113693509094, 40.780252054146104 ], [ -109.81182272626378, 40.780081061977825 ], [ -109.81226881125166, 40.779986563483369 ], [ -109.81261496658261, 40.779913555689234 ], [ -109.81275044052292, 40.77989242899897 ], [ -109.81339778703212, 40.779809005143036 ], [ -109.81422852714977, 40.779741875760116 ], [ -109.81511934043753, 40.779628514148712 ], [ -109.81640233293302, 40.779452507838919 ], [ -109.81659254744737, 40.779418425689045 ], [ -109.81679484995738, 40.779370954733253 ], [ -109.81692590184818, 40.779331761184352 ], [ -109.81717639644189, 40.779239742181325 ], [ -109.81735706472668, 40.779142502809542 ], [ -109.81745162547864, 40.779089422184143 ], [ -109.81765528400194, 40.778965393060005 ], [ -109.81820013157022, 40.778646676020394 ], [ -109.81898361409091, 40.778235811991934 ], [ -109.82010178421945, 40.777661711891511 ], [ -109.82123154443833, 40.777101231688327 ], [ -109.82225258620765, 40.77665673863126 ], [ -109.822925565623, 40.77639425744416 ], [ -109.82306997473182, 40.776336275676641 ], [ -109.82342179265572, 40.776209243213742 ], [ -109.82379217542626, 40.776037357379685 ], [ -109.82394794503647, 40.775939853756029 ], [ -109.82417038605155, 40.775757450420819 ], [ -109.82429029345104, 40.775677597487523 ], [ -109.82445198538942, 40.775580153516096 ], [ -109.82471430353823, 40.775488238454983 ], [ -109.82494020478505, 40.775445497638991 ], [ -109.82508861924374, 40.775428992331001 ], [ -109.82528924311438, 40.775408514214874 ], [ -109.82564019063999, 40.77539767326035 ], [ -109.82603075448488, 40.775425069208382 ], [ -109.82653941602187, 40.775475284869557 ], [ -109.82745026973211, 40.775565619275312 ], [ -109.82856333010604, 40.775612957981039 ], [ -109.82926756337596, 40.775660642799828 ], [ -109.83009533090879, 40.775759121611216 ], [ -109.83106551222862, 40.775845524847675 ], [ -109.83140309741574, 40.77585344844907 ], [ -109.83169431695386, 40.775802347589519 ], [ -109.83187937875101, 40.775723146415061 ], [ -109.83204706275255, 40.775621248263548 ], [ -109.83234941117991, 40.775340546428964 ], [ -109.83259123683352, 40.774997074107375 ], [ -109.83270680148914, 40.774826184473447 ], [ -109.83280647004453, 40.774547934988895 ], [ -109.83293827873452, 40.774125877451596 ], [ -109.83305184163743, 40.773730660150378 ], [ -109.83319201334281, 40.773169057934723 ], [ -109.83353497229594, 40.771852806969619 ], [ -109.83365309538354, 40.771196393748077 ], [ -109.83367244105371, 40.77110650609832 ], [ -109.83375116190761, 40.770670398256684 ], [ -109.83380192162181, 40.770206982775441 ], [ -109.83383926612802, 40.769968639689615 ], [ -109.83396488413145, 40.769289780859793 ], [ -109.83399141176214, 40.769127899119596 ], [ -109.83400522661167, 40.769015434684299 ], [ -109.83402622432635, 40.768830976242093 ], [ -109.83402337127193, 40.768655285113461 ], [ -109.83406166632021, 40.768498026404529 ], [ -109.83413432006708, 40.768408677257618 ], [ -109.83434297271424, 40.768334214462563 ], [ -109.8345683717736, 40.768318474530879 ], [ -109.83471637485596, 40.768324473406309 ], [ -109.83485126810399, 40.768334843879543 ], [ -109.83517199489907, 40.768356098587155 ], [ -109.83579433186505, 40.768339858349698 ], [ -109.83607919915926, 40.768311202950429 ], [ -109.83636414479017, 40.76827804347419 ], [ -109.83650085134813, 40.768252397005156 ], [ -109.83669694755409, 40.768218340793972 ], [ -109.8374334734529, 40.768108655414991 ], [ -109.8382403700886, 40.768040211304402 ], [ -109.83918373504754, 40.767959621980346 ], [ -109.84016207354688, 40.767911806446413 ], [ -109.84030432540874, 40.767907831183585 ], [ -109.84165031037769, 40.767840275666956 ], [ -109.84226640586476, 40.767841954490024 ], [ -109.84290580382972, 40.76786638451329 ], [ -109.8431187283189, 40.767886536085037 ], [ -109.8435578296326, 40.767845895905005 ], [ -109.84381309131217, 40.767816023844013 ], [ -109.8441814874669, 40.767753052831161 ], [ -109.84576618829162, 40.767584244310129 ], [ -109.84688863718266, 40.767424308124646 ], [ -109.84790048463827, 40.767150652628331 ], [ -109.84860719193942, 40.766982043899063 ], [ -109.84940493775497, 40.766755784451917 ], [ -109.85035910649766, 40.766459011314758 ], [ -109.85144932193261, 40.766105030269628 ], [ -109.85327270993425, 40.765488077042704 ], [ -109.85434939983713, 40.765160959025465 ], [ -109.85511852012958, 40.764943383988303 ], [ -109.85535629069352, 40.764896196928667 ], [ -109.85565352275366, 40.764836086557345 ], [ -109.8558373676404, 40.764824397072125 ], [ -109.85606876639561, 40.764803269545553 ], [ -109.85624076512981, 40.764791461981844 ], [ -109.85651920801058, 40.764790618180335 ], [ -109.85666712871441, 40.764801092228737 ], [ -109.85679143462507, 40.76480682796771 ], [ -109.85734765717348, 40.764843866329272 ], [ -109.85799926538454, 40.764845812679432 ], [ -109.85834233760136, 40.764876232425394 ], [ -109.8586140257293, 40.764923961778166 ], [ -109.85904558810955, 40.765045338082949 ], [ -109.85995308703025, 40.765256995075532 ], [ -109.86080877645686, 40.765450116796018 ], [ -109.86132254617085, 40.765545271116636 ], [ -109.86149977740247, 40.765574044883202 ], [ -109.86168916235721, 40.765584921588598 ], [ -109.86205093145223, 40.765561464710125 ], [ -109.86219962303221, 40.765526897567987 ], [ -109.86231262238812, 40.765500986683385 ], [ -109.86243169832994, 40.765466127250463 ], [ -109.86272961798291, 40.76536546787996 ], [ -109.86301599766568, 40.765246677347427 ], [ -109.86374267625786, 40.765015114015156 ], [ -109.86467811179071, 40.764700020893535 ], [ -109.86518478544282, 40.764515829547136 ], [ -109.86591637650328, 40.764342854991348 ], [ -109.86648766111986, 40.764190822070503 ], [ -109.8669571055826, 40.764105348989219 ], [ -109.86731317159904, 40.764068307051474 ], [ -109.86786461845004, 40.764037685233788 ], [ -109.8689376669691, 40.763989653674727 ], [ -109.8693884223585, 40.76395803757616 ], [ -109.8697081093643, 40.763970177707044 ], [ -109.86997426102442, 40.763995305229088 ], [ -109.87030714148671, 40.764277823310962 ], [ -109.87055809381494, 40.76450098431836 ], [ -109.87089835055858, 40.764697993593117 ], [ -109.8712101371659, 40.764827160774132 ], [ -109.87184647409948, 40.76503156731961 ], [ -109.87227604031094, 40.765202420600353 ], [ -109.8724054344047, 40.765257735151643 ], [ -109.87255806436022, 40.765340301622537 ], [ -109.8727685558177, 40.765504508245705 ], [ -109.87285565214137, 40.76560895499928 ], [ -109.87310092313564, 40.765818542458469 ], [ -109.87333594670112, 40.76593344171242 ], [ -109.87354781082824, 40.766016585201768 ], [ -109.87433611690328, 40.766344074103003 ], [ -109.87478278395697, 40.766555622435085 ], [ -109.87495858099099, 40.766669940844743 ], [ -109.87508760046262, 40.766747769602162 ], [ -109.8753047092395, 40.766871498550977 ], [ -109.87545157513094, 40.766944996670347 ], [ -109.87560413684967, 40.767032062621311 ], [ -109.87587516395065, 40.767120282488037 ], [ -109.8760516473095, 40.767194068365789 ], [ -109.87626883521871, 40.76731329210012 ], [ -109.87667223177432, 40.767632511872129 ], [ -109.87696992220869, 40.767896651450805 ], [ -109.87735259946545, 40.768391329896389 ], [ -109.87743378333884, 40.768495715658062 ], [ -109.87765979359725, 40.768795189467639 ], [ -109.87804173806656, 40.769686225532837 ], [ -109.87825380281049, 40.770463004649628 ], [ -109.87832056830968, 40.77072039139464 ], [ -109.8783597612243, 40.770855897481717 ], [ -109.87849350467955, 40.771005835059462 ], [ -109.87883434808717, 40.771171297415627 ], [ -109.87916274046593, 40.771372671185361 ], [ -109.87943212531488, 40.771559958496731 ], [ -109.87955516013514, 40.77164222829596 ], [ -109.8803451766499, 40.772226430441151 ], [ -109.88119157372209, 40.772982332279049 ], [ -109.88218816021542, 40.773969395523103 ], [ -109.88265241153344, 40.774550425545193 ], [ -109.88283228089659, 40.774777375564689 ], [ -109.88289608633222, 40.774859068328645 ], [ -109.88311953709244, 40.774960323096813 ], [ -109.88345489827158, 40.774747368587171 ], [ -109.88386111827499, 40.774548611023391 ], [ -109.88462894066781, 40.774267768686336 ], [ -109.88572742274451, 40.773841477143698 ], [ -109.88705723871449, 40.773327323124789 ], [ -109.88789183109961, 40.773020077876446 ], [ -109.88854601580414, 40.772872338302165 ], [ -109.88913455608142, 40.77275278975717 ], [ -109.89036137758121, 40.772728560545076 ], [ -109.89138836218463, 40.772607810907665 ], [ -109.89201605721719, 40.772627352306344 ], [ -109.892523120253, 40.77270428680459 ], [ -109.89291325593788, 40.772829643193255 ], [ -109.8932367475736, 40.772972375755415 ], [ -109.89352965017663, 40.77317336833481 ], [ -109.89382661090185, 40.773487003370178 ], [ -109.89394142800828, 40.773708808416785 ], [ -109.89398725049526, 40.773803835241914 ], [ -109.89402016476818, 40.773962697562609 ], [ -109.89404036500534, 40.774173686400353 ], [ -109.89407200991582, 40.774409107442374 ], [ -109.89405543086957, 40.774980077425255 ], [ -109.8940356965078, 40.775241130179118 ], [ -109.89402957185403, 40.775610413452654 ], [ -109.89394524932897, 40.7759789471624 ], [ -109.89389322522729, 40.776257707006252 ], [ -109.89393337209268, 40.776694996300684 ], [ -109.89396060239817, 40.77683939073917 ], [ -109.89402025085937, 40.777101204297779 ], [ -109.89416408787835, 40.777431387217888 ], [ -109.89445178581217, 40.777947619313785 ], [ -109.89473859231275, 40.778517892143135 ], [ -109.89512462505574, 40.779179197757173 ], [ -109.89563358624484, 40.779931762002526 ], [ -109.89594291578496, 40.780574313950751 ], [ -109.89628682922171, 40.781275750002052 ], [ -109.89632666092447, 40.781375222667648 ], [ -109.89647384153871, 40.781791013680625 ], [ -109.89656654801755, 40.781918016929595 ], [ -109.89678382084719, 40.782037202841785 ], [ -109.89700228658585, 40.782084333091227 ], [ -109.89725230560573, 40.782086722829845 ], [ -109.89765014886484, 40.782036474393941 ], [ -109.89875228219225, 40.78196592357417 ], [ -109.89978450302428, 40.781894695607967 ], [ -109.90090484850073, 40.78186933953031 ], [ -109.90239874037601, 40.7818295098702 ], [ -109.90392121738003, 40.78185299074925 ], [ -109.90556226221936, 40.781873072057103 ], [ -109.90671060143939, 40.781874950112766 ], [ -109.90729728668842, 40.781871499209601 ], [ -109.907571092818, 40.781868686841577 ], [ -109.90770741817406, 40.781866374111196 ], [ -109.90827077364403, 40.781840176558667 ], [ -109.90896060934654, 40.781689055540639 ], [ -109.90956654008926, 40.781595691681694 ], [ -109.90979789416782, 40.781579861154199 ], [ -109.91028422681501, 40.781552925990994 ], [ -109.91076375159194, 40.781579974544833 ], [ -109.91156232331359, 40.781664081176203 ], [ -109.91175739447354, 40.781692946150002 ], [ -109.91217693998186, 40.781764464828051 ], [ -109.91234238859599, 40.78179304953612 ], [ -109.91261381959501, 40.781863170358164 ], [ -109.91312069495514, 40.78203009613437 ], [ -109.913391980971, 40.7821092221022 ], [ -109.91369149672093, 40.782274192433903 ], [ -109.91391384631001, 40.782447444009357 ], [ -109.91420626662418, 40.782684412928845 ], [ -109.91457928890279, 40.783066272772352 ], [ -109.91497440199795, 40.783547430852956 ], [ -109.91525674379828, 40.784040139106551 ], [ -109.91553986628568, 40.784485109794424 ], [ -109.91580120390829, 40.785176703476651 ], [ -109.91593673771368, 40.785587856212359 ], [ -109.91601017389443, 40.785809250359655 ], [ -109.91606063746102, 40.786277257011292 ], [ -109.91607197357689, 40.786381860183376 ], [ -109.91612009976123, 40.786702108137305 ], [ -109.91608936931885, 40.787134219461258 ], [ -109.91602412609673, 40.787575014845615 ], [ -109.91595278398142, 40.787880627879872 ], [ -109.91583061795032, 40.788104688319464 ], [ -109.91575563301606, 40.788342704487519 ], [ -109.91584084864346, 40.788568713505164 ], [ -109.91593916052608, 40.788718274689586 ], [ -109.91602628148502, 40.788827193165744 ], [ -109.91622362612486, 40.78900921360291 ], [ -109.91644740918358, 40.78916896116344 ], [ -109.91656459727989, 40.789251136598395 ], [ -109.91678171074118, 40.789383795891055 ], [ -109.91726253818422, 40.789699096374207 ], [ -109.91767160759814, 40.790054259228945 ], [ -109.91801425906326, 40.790485368602887 ], [ -109.91834191596548, 40.790745178131651 ], [ -109.91852532794948, 40.790836980710623 ], [ -109.91884294783654, 40.790912024000654 ], [ -109.91921207841648, 40.790807382364427 ], [ -109.91933168255292, 40.790740940189806 ], [ -109.91980417131464, 40.790475114739934 ], [ -109.92038484526753, 40.790115712200574 ], [ -109.92071980246038, 40.789925166795058 ], [ -109.92094657036304, 40.789828196135488 ], [ -109.92126272806046, 40.78970053163868 ], [ -109.92155394444988, 40.789649203969006 ], [ -109.92170851335018, 40.789619119434413 ], [ -109.92226051665676, 40.789565722699258 ], [ -109.92240257909515, 40.789576057907588 ], [ -109.92284019524271, 40.789633293343762 ], [ -109.92310594796402, 40.789690724848711 ], [ -109.92341232025851, 40.789801683920466 ], [ -109.92370026295667, 40.789953007760388 ], [ -109.92414702930346, 40.790177878579733 ], [ -109.92461084828609, 40.790447948267413 ], [ -109.92505133244754, 40.790695277862845 ], [ -109.92539123222917, 40.79093266068304 ], [ -109.92564859870453, 40.791143149867473 ], [ -109.92601084055829, 40.791465417203675 ], [ -109.92617985052104, 40.791642652724171 ], [ -109.92642486330557, 40.791884554350645 ], [ -109.92713902278682, 40.792435300343406 ], [ -109.92791098712563, 40.793077563158832 ], [ -109.92860738005264, 40.793629035777265 ], [ -109.92918093558367, 40.794080272586648 ], [ -109.92978427248789, 40.7945227744544 ], [ -109.93025810219505, 40.794910923356966 ], [ -109.93064423470405, 40.795224389252283 ], [ -109.93104141348762, 40.795588402823611 ], [ -109.9313912614478, 40.795947472494433 ], [ -109.93164678889488, 40.796275039449355 ], [ -109.93176286767374, 40.796428354949789 ], [ -109.93204377727049, 40.796651659435568 ], [ -109.9321677177639, 40.79668433573039 ], [ -109.93234621898269, 40.796640946019579 ], [ -109.93247738427723, 40.796592613904174 ], [ -109.93290115795112, 40.796407359224922 ], [ -109.93317013361479, 40.796265713382375 ], [ -109.93340207897153, 40.796141741241648 ], [ -109.93370136289549, 40.796031903471302 ], [ -109.9341418269, 40.795914360900149 ], [ -109.93543979398581, 40.795543490260066 ], [ -109.93707081638895, 40.795099102917227 ], [ -109.93796392967907, 40.794841581574168 ], [ -109.93845164172434, 40.7947334657037 ], [ -109.93868960720857, 40.794677100725558 ], [ -109.93885588879169, 40.794656109321281 ], [ -109.93927698049842, 40.794637460536741 ], [ -109.94018235617996, 40.794725954646061 ], [ -109.94067932407691, 40.794780965176216 ], [ -109.94092749342819, 40.794828285082509 ], [ -109.941422388112, 40.795013894203059 ], [ -109.9415985329852, 40.795118205158055 ], [ -109.94169821419786, 40.795185781180869 ], [ -109.9419150259515, 40.795341812153133 ], [ -109.9421724049504, 40.795555867982891 ], [ -109.94257478932971, 40.795969435576964 ], [ -109.9429754641491, 40.796491086061373 ], [ -109.94334151735511, 40.796953863912755 ], [ -109.94362825191469, 40.797560047652482 ], [ -109.94372992413416, 40.797876270021838 ], [ -109.94382218639768, 40.798038363729205 ], [ -109.94390385310891, 40.798121087082976 ], [ -109.94403916936736, 40.798184483085308 ], [ -109.94417384300938, 40.798213641399876 ], [ -109.94446555214031, 40.798207302173758 ], [ -109.94478035115966, 40.798165140073941 ], [ -109.94562307522189, 40.798096273650465 ], [ -109.94677409906924, 40.798021207488077 ], [ -109.94723697801969, 40.797984894505653 ], [ -109.94776504393595, 40.79794917418716 ], [ -109.94827433577032, 40.797976338629141 ], [ -109.94877177579362, 40.798003392839128 ], [ -109.94944707148773, 40.798027560326773 ], [ -109.94992052400764, 40.798072407828883 ], [ -109.95038141547954, 40.798162180774781 ], [ -109.95087658883769, 40.798333338594993 ], [ -109.95110643339635, 40.798416503333158 ], [ -109.95175484140472, 40.798643100338154 ], [ -109.9526448839153, 40.798957466595922 ], [ -109.95303288723431, 40.799160072252533 ], [ -109.95329146310104, 40.799301146675539 ], [ -109.95367228525116, 40.799583859175662 ], [ -109.95405084826611, 40.800010683217693 ], [ -109.95430552792129, 40.800400349944645 ], [ -109.95450531820596, 40.800888610334653 ], [ -109.95456069555632, 40.801136841175314 ], [ -109.95466058776502, 40.801570146036383 ], [ -109.95476613366577, 40.801643168897961 ], [ -109.95491450740624, 40.801631000498141 ], [ -109.95506880756692, 40.801618885582073 ], [ -109.95519940179732, 40.801606555787735 ], [ -109.95537754895992, 40.801585648079161 ], [ -109.95586415462041, 40.801549515383826 ], [ -109.95620224542597, 40.801534557935021 ], [ -109.95684787764409, 40.801562917995305 ], [ -109.95798413989161, 40.801676781609871 ], [ -109.9588583848851, 40.801792774059493 ], [ -109.95923634376082, 40.801881763271609 ], [ -109.95956222071138, 40.801965777424144 ], [ -109.95992783636567, 40.802086182216101 ], [ -109.96050484102325, 40.802334607216999 ], [ -109.9612818787741, 40.802679417867317 ], [ -109.96207084802343, 40.803019826462439 ], [ -109.96261830588308, 40.803263470924293 ], [ -109.96291846083957, 40.80340129430023 ], [ -109.96325863184471, 40.803634063933984 ], [ -109.96341034256736, 40.803788568680353 ], [ -109.96346806777132, 40.803888178916246 ], [ -109.96359800578921, 40.804299225143936 ], [ -109.96371331767091, 40.804507452468343 ], [ -109.9639928286402, 40.804829758323017 ], [ -109.9641386869941, 40.804979705378429 ], [ -109.96454217508661, 40.805334652078876 ], [ -109.96507055115744, 40.80566369273447 ], [ -109.96561636344148, 40.806015408109772 ], [ -109.96606686156818, 40.806397795899677 ], [ -109.966452238275, 40.806775094394155 ], [ -109.9667476666783, 40.807219148496635 ], [ -109.96697358103454, 40.807558983693596 ], [ -109.96720542641309, 40.80782230077822 ], [ -109.9673116927236, 40.807926847738777 ], [ -109.9675689928787, 40.808154358633779 ], [ -109.96799825035683, 40.808378903086762 ], [ -109.96817933985929, 40.808475110195623 ], [ -109.96855009721119, 40.808726154353472 ], [ -109.96878983241429, 40.808939992995647 ], [ -109.96895258569796, 40.809148639027342 ], [ -109.96910786536431, 40.809457210421293 ], [ -109.96930104085548, 40.809998534851488 ], [ -109.9693559925297, 40.810278283724323 ], [ -109.96945417779123, 40.810445814744575 ], [ -109.96974196741375, 40.810619543169395 ], [ -109.97004879408716, 40.810712365943651 ], [ -109.97038685950868, 40.810701871008312 ], [ -109.97063057516888, 40.810659004176237 ], [ -109.97082687212158, 40.810615713832533 ], [ -109.9714168047544, 40.810418287666565 ], [ -109.97203643978634, 40.810216618960979 ], [ -109.97291184573879, 40.809958670102553 ], [ -109.97355511161635, 40.809761707729052 ], [ -109.97379317225158, 40.809700767230716 ], [ -109.97450596479609, 40.809608013668196 ], [ -109.9751106103715, 40.809608882432343 ], [ -109.9758043028348, 40.809601530244969 ], [ -109.9765436829296, 40.809707183251845 ], [ -109.97689249020922, 40.809768831117985 ], [ -109.97718920758156, 40.809825511979788 ], [ -109.97740114010119, 40.809844506478377 ], [ -109.97802955243792, 40.809841967274011 ], [ -109.9786284114427, 40.809833758019515 ], [ -109.97887763194053, 40.809817947439839 ], [ -109.97905586347726, 40.809792499817647 ], [ -109.97925222170336, 40.809744691483139 ], [ -109.97980752489033, 40.809483857595445 ], [ -109.98007025340725, 40.809360063959197 ], [ -109.98021912309115, 40.809316338302921 ], [ -109.98045676268946, 40.809282405282644 ], [ -109.98087125324722, 40.809313092410541 ], [ -109.98130938416431, 40.809348490953354 ], [ -109.98154626586928, 40.809364094796223 ], [ -109.98181919287634, 40.809348487122179 ], [ -109.98220004824729, 40.809252756044103 ], [ -109.98261770393266, 40.809076273273377 ], [ -109.98279103666536, 40.808983214202854 ], [ -109.9829525145777, 40.808890050364106 ], [ -109.98314342158417, 40.808810658175076 ], [ -109.98342888769697, 40.808750115553316 ], [ -109.9842257368485, 40.808585975816598 ], [ -109.98514201684627, 40.808364327038234 ], [ -109.9857422477063, 40.80826510872982 ], [ -109.98588510195799, 40.808226727849053 ], [ -109.98617159142378, 40.808098624929336 ], [ -109.986369310458, 40.807960733077557 ], [ -109.98662057795482, 40.80780979874352 ], [ -109.98684159246845, 40.807699135681872 ], [ -109.98706094143456, 40.807619986732611 ], [ -109.98726927882132, 40.807563261536288 ], [ -109.98748390683217, 40.807560641165153 ], [ -109.98769108014361, 40.807580475816764 ], [ -109.98786241747483, 40.807618012385127 ], [ -109.98805126253149, 40.807673718929394 ], [ -109.98826285853349, 40.80779268300644 ], [ -109.98847963008174, 40.80796123790023 ], [ -109.98879793883668, 40.808157707372473 ], [ -109.98917723176064, 40.808476322773231 ], [ -109.98975091969031, 40.808954285105024 ], [ -109.99020648089346, 40.809404185724908 ], [ -109.99051557295853, 40.809740198900364 ], [ -109.99079496343847, 40.810080455592264 ], [ -109.99106781542902, 40.810461191900281 ], [ -109.99139817086153, 40.810959538553504 ], [ -109.99175939545732, 40.811377079052981 ], [ -109.99220054205986, 40.811998003961932 ], [ -109.99257036220146, 40.812631816817785 ], [ -109.99290612213048, 40.813166239534759 ], [ -109.99319739826379, 40.813898456208896 ], [ -109.99334308877359, 40.814457342849195 ], [ -109.9934284789362, 40.814769775919778 ], [ -109.99347131156235, 40.814995357719525 ], [ -109.99351675944835, 40.815126374914648 ], [ -109.99369289035697, 40.815240515412633 ], [ -109.99385273558705, 40.815255422053461 ], [ -109.99397122266743, 40.815260959505871 ], [ -109.99422073261907, 40.815227101715294 ], [ -109.99470782830778, 40.815163784769418 ], [ -109.99518872354614, 40.815118428408127 ], [ -109.99592539389151, 40.815016742284513 ], [ -109.99631771070625, 40.814948089443902 ], [ -109.99648443376996, 40.814899993998061 ], [ -109.99660366693939, 40.814855989446336 ], [ -109.99680165646357, 40.814700065565049 ], [ -109.99694036807912, 40.81454362596542 ], [ -109.99730670440444, 40.814231519045585 ], [ -109.9977158186403, 40.813834203475295 ], [ -109.99798401951239, 40.813660870816008 ], [ -109.9981592400957, 40.813599334237274 ], [ -109.99839570110815, 40.813565354065304 ], [ -109.99862701348722, 40.813558353703115 ], [ -109.99898253492789, 40.813570447320963 ], [ -109.99929603534775, 40.813617307842883 ], [ -109.99992319987655, 40.813700217758125 ], [ -110.00034971874673, 40.813721930913808 ], [ -110.00067627912307, 40.813688726724756 ], [ -110.00070506162228, 40.874945294748635 ], [ -110.00073546975561, 40.996677100598404 ], [ -110.00073192724334, 40.997226560950125 ], [ -110.00073083900278, 40.997298615913706 ], [ -109.99027322392067, 40.997342601663973 ], [ -109.97109470809445, 40.997452249859172 ], [ -109.95212497174998, 40.997438995788485 ], [ -109.93321395017178, 40.997472706470894 ], [ -109.91390333075258, 40.997585125025893 ], [ -109.88609885571844, 40.997617038877323 ], [ -109.87568836063777, 40.997682608661883 ], [ -109.86692577158824, 40.997677873356004 ], [ -109.85671298950327, 40.99765359219122 ], [ -109.84767657018556, 40.997670799719664 ], [ -109.83762313063465, 40.997713979336361 ], [ -109.81875295619393, 40.997788768788809 ], [ -109.79948981027623, 40.997896010264064 ], [ -109.78040615255108, 40.997938874645612 ], [ -109.75070947383949, 40.998062206108365 ], [ -109.74614953996165, 40.998075745914612 ], [ -109.74160158159567, 40.998084732023045 ], [ -109.73209530988457, 40.998111164097722 ], [ -109.72274883093149, 40.998174614368146 ], [ -109.71997913848067, 40.998143887993422 ], [ -109.71974130969852, 40.998145750430218 ], [ -109.71713804061267, 40.998116804252014 ], [ -109.71432578940558, 40.998135011849421 ], [ -109.70851738402557, 40.998175826408442 ], [ -109.70368905655249, 40.998209539723668 ], [ -109.67559754621288, 40.998322544040732 ], [ -109.66634080130011, 40.998355425201332 ], [ -109.64707783217534, 40.998441688290804 ], [ -109.63725018400646, 40.998483544632755 ], [ -109.62798383651518, 40.998405135529644 ], [ -109.62572443211052, 40.998423256144463 ], [ -109.61797209663193, 40.998437750904166 ], [ -109.60894287153374, 40.998393081767148 ], [ -109.59880001794379, 40.998441364845419 ], [ -109.58974136185408, 40.99838402349657 ], [ -109.57984267984226, 40.998412006003768 ], [ -109.57018224785595, 40.998418673466368 ], [ -109.5606932292559, 40.998470809993137 ], [ -109.5509457374982, 40.998381095436258 ], [ -109.54149537240724, 40.998297919814377 ], [ -109.53674138816963, 40.998215140403772 ], [ -109.535369132707, 40.998170686211971 ], [ -109.53283456489122, 40.998265458891538 ], [ -109.52966292032295, 40.998404295247077 ], [ -109.52867526613689, 40.998441233802176 ], [ -109.52283272751907, 40.998654748175447 ], [ -109.51563855160123, 40.998963163221582 ], [ -109.51216001772633, 40.9989993791934 ], [ -109.51003701541262, 40.999030503055018 ], [ -109.50366810537035, 40.999119137167845 ], [ -109.50070722775716, 40.999134703588766 ], [ -109.49640793259901, 40.999186786871306 ], [ -109.49073691851849, 40.999171211311364 ], [ -109.48407581006821, 40.999245927231414 ], [ -109.47772580229477, 40.999337879196752 ], [ -109.47184628219907, 40.999341138722983 ], [ -109.45270445980127, 40.999572153705977 ], [ -109.43955162759914, 40.999692070862487 ], [ -109.43354096396197, 40.999709614649049 ], [ -109.41439585789125, 40.999821620380921 ], [ -109.39529304442385, 40.999904009059364 ], [ -109.37615979855852, 41.000014327302104 ], [ -109.37569625996026, 41.000007794907809 ], [ -109.36301307889299, 41.000121084979604 ], [ -109.35624013576536, 41.00019132176574 ], [ -109.3387160761209, 41.000372406082448 ], [ -109.33688526551582, 41.000364014794656 ], [ -109.31778079747997, 41.000505583046333 ], [ -109.29869337274651, 41.000675760083226 ], [ -109.27941813819669, 41.000749892337147 ], [ -109.26957965424452, 41.000738594964929 ], [ -109.2506582458083, 41.001100569329282 ], [ -109.24061732157048, 41.001591754745554 ], [ -109.23593713612753, 41.001871503115716 ], [ -109.23229392994796, 41.002054377300851 ], [ -109.22141596211002, 41.001783411068992 ], [ -109.21687761104701, 41.001650222730319 ], [ -109.20239389566387, 41.001281075834441 ], [ -109.19521068673994, 41.001128264664004 ], [ -109.18333361099522, 41.000883088249893 ], [ -109.17863240880229, 41.000840405515767 ], [ -109.16413807559317, 41.000826584025063 ], [ -109.15959731868203, 41.000829817334832 ], [ -109.14512801246083, 41.000814903239032 ], [ -109.14046138609878, 41.000812653469289 ], [ -109.12570633122633, 41.000770870544891 ], [ -109.11631015830487, 41.000722144238424 ], [ -109.10643688685268, 41.00068552956666 ], [ -109.08732811460814, 41.000761766285983 ], [ -109.08312521064043, 41.000759484184506 ], [ -109.06858029838611, 41.000691357010254 ], [ -109.04995524225718, 41.000693833970828 ], [ -109.04994430932786, 40.999653282383015 ] ] ] } },' + '{ "type": "Feature", "id": 40, "properties": { "NAME": "SAN JUAN COUNTY SCHOOL DISTRICT", "TOTENROLL": 2912, "Color4": "3", "Shape_Leng": 849284.124266, "Shape_Area": 20527899235.5 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -109.06004803642122, 38.46795143689846 ], [ -109.05999189727831, 38.426193400156798 ], [ -109.06010830448324, 38.403816329120964 ], [ -109.06018019803786, 38.390246807019366 ], [ -109.06022094653441, 38.375009682861112 ], [ -109.06017808508777, 38.365470688319704 ], [ -109.06018211155143, 38.353959013205596 ], [ -109.06018284632883, 38.339779956174063 ], [ -109.06024979489607, 38.331693529073526 ], [ -109.06023186745801, 38.325930576204151 ], [ -109.06023080623841, 38.325326808600011 ], [ -109.06025313676962, 38.31719456941876 ], [ -109.06039489774329, 38.308870554596609 ], [ -109.06047197307005, 38.302757715340071 ], [ -109.0602722122408, 38.293084457477129 ], [ -109.06024052388439, 38.290624765722889 ], [ -109.06009812445186, 38.277722804361915 ], [ -109.06006844758915, 38.275401913689677 ], [ -109.05854752808767, 38.265766231406928 ], [ -109.05710973037654, 38.256884338423859 ], [ -109.05599623696533, 38.249994784097943 ], [ -109.05471447588917, 38.242566251860097 ], [ -109.05308207563684, 38.233086314556196 ], [ -109.05054681657452, 38.216147993021444 ], [ -109.04901040628, 38.205890086054893 ], [ -109.04659243250472, 38.190818930322578 ], [ -109.04292911351064, 38.167071511552301 ], [ -109.04281754399582, 38.166335223321163 ], [ -109.04270277870012, 38.163584835546125 ], [ -109.04257375333218, 38.160514304253304 ], [ -109.04253237803138, 38.149898179926204 ], [ -109.04250669600839, 38.136344574773489 ], [ -109.04263183226152, 38.125041811879363 ], [ -109.04260713055727, 38.105675775364446 ], [ -109.04229144877155, 38.077933146907135 ], [ -109.04261897217823, 38.044731108325578 ], [ -109.04273284175957, 38.02761553444796 ], [ -109.04272256959518, 38.018369477864056 ], [ -109.04272766113533, 38.017964041056338 ], [ -109.04272184590407, 38.017540399425926 ], [ -109.04271392981933, 38.01655349824415 ], [ -109.04271068014967, 38.01453484698083 ], [ -109.04277740791615, 38.011598177149153 ], [ -109.04283417805894, 38.008607270512776 ], [ -109.04290740626958, 38.005039893503223 ], [ -109.04296438920609, 38.001783144689668 ], [ -109.04298939820114, 37.999985743885098 ], [ -109.04298931478968, 37.988635602550872 ], [ -109.04298762789378, 37.978200097204613 ], [ -109.04299017375003, 37.975532691977264 ], [ -109.04292354317371, 37.974612394748213 ], [ -109.04269694839238, 37.964284868931522 ], [ -109.04238197912935, 37.950641360473355 ], [ -109.04209748105235, 37.93906561531653 ], [ -109.04200554719206, 37.931381608607111 ], [ -109.04196368223482, 37.925883767801821 ], [ -109.04195666433725, 37.917570338603717 ], [ -109.0419937464235, 37.905017609002954 ], [ -109.04198673878828, 37.898416387031503 ], [ -109.04198844324399, 37.897064652397027 ], [ -109.04198695570531, 37.894545841858481 ], [ -109.04197978930513, 37.887949112743534 ], [ -109.04197671288557, 37.886777531795843 ], [ -109.04196815275078, 37.884267611457709 ], [ -109.04198122451282, 37.8769052074976 ], [ -109.04195846577318, 37.875016860347259 ], [ -109.04191391481497, 37.855442495388516 ], [ -109.04190383076049, 37.843623327592262 ], [ -109.04186835150377, 37.834394620679497 ], [ -109.04203922293298, 37.821483484336937 ], [ -109.04207368729263, 37.816094964882588 ], [ -109.04219956283023, 37.788317928202829 ], [ -109.04197544314248, 37.779599687937768 ], [ -109.04197084022124, 37.773534590925024 ], [ -109.04227767745029, 37.771156037109996 ], [ -109.04209650838582, 37.768125018529084 ], [ -109.04227929255225, 37.758007651981814 ], [ -109.04214743222059, 37.753278694976345 ], [ -109.04234169999714, 37.740092921884354 ], [ -109.04204754762448, 37.725628317535339 ], [ -109.04201363163025, 37.713128116908962 ], [ -109.04204973077847, 37.698610363076881 ], [ -109.0420606524428, 37.684182279688308 ], [ -109.04197482336247, 37.681193361368024 ], [ -109.04192955988955, 37.678817934885025 ], [ -109.04177243812114, 37.625035701964258 ], [ -109.04181039666416, 37.620782608998695 ], [ -109.04181142697057, 37.613617980339178 ], [ -109.04178076039764, 37.604853161458216 ], [ -109.04192660341552, 37.591945664972819 ], [ -109.04150092718872, 37.563027506103786 ], [ -109.04244040633321, 37.519545533234378 ], [ -109.0431384252708, 37.499968913655238 ], [ -109.0431952383952, 37.4906421248591 ], [ -109.04320027167839, 37.490015852956454 ], [ -109.04355817322805, 37.476079728473543 ], [ -109.04447499214166, 37.447187808111629 ], [ -109.04507091540039, 37.417988523603569 ], [ -109.04521467620863, 37.4035485037124 ], [ -109.04552710771696, 37.374993228283728 ], [ -109.04553596119949, 37.374434601758189 ], [ -109.04563944271821, 37.36000283175003 ], [ -109.04572260174807, 37.269432612942694 ], [ -109.04557619524317, 37.250012502733036 ], [ -109.04557185754551, 37.240143589263361 ], [ -109.0455432822536, 37.233175436003563 ], [ -109.0455678405399, 37.225894511890552 ], [ -109.04537623205857, 37.213670161627235 ], [ -109.04570588419406, 37.2063527936646 ], [ -109.04597706425785, 37.199114664257522 ], [ -109.04587788330048, 37.184607967141119 ], [ -109.04553604445537, 37.170117964743426 ], [ -109.04540251590284, 37.156940021343878 ], [ -109.0453741358302, 37.15563720923835 ], [ -109.0452499691436, 37.142530593188724 ], [ -109.04519176852982, 37.141074069099972 ], [ -109.04522764572569, 37.127825860336159 ], [ -109.04518329727783, 37.124999615881585 ], [ -109.04519660052082, 37.100849988130925 ], [ -109.04520271783935, 37.085068596712283 ], [ -109.04512834481318, 37.065450860722585 ], [ -109.04503363734781, 37.041709325546073 ], [ -109.04507056747354, 37.012864040258052 ], [ -109.04522004227151, 37.000009513106988 ], [ -109.04521976240525, 36.998923445459475 ], [ -109.05313532808545, 36.998958950828211 ], [ -109.06637645217627, 36.999026755519942 ], [ -109.07392647787336, 36.999077447690148 ], [ -109.07996553376614, 36.99911223182675 ], [ -109.09572935250415, 36.99918600685222 ], [ -109.1082455826151, 36.999264538576035 ], [ -109.11971691144967, 36.999338715342013 ], [ -109.12562770708195, 36.999337595214129 ], [ -109.14442795804536, 36.999322131057831 ], [ -109.16306073887084, 36.999310105800532 ], [ -109.20009257364224, 36.999291750270551 ], [ -109.22887704668189, 36.99929224022916 ], [ -109.23799554936105, 36.999319831568094 ], [ -109.24692301236426, 36.999348406084209 ], [ -109.25067128354127, 36.999322603013894 ], [ -109.27094975428957, 36.999299843174946 ], [ -109.28581151680423, 36.999290130239743 ], [ -109.28876702694883, 36.999287721219872 ], [ -109.3104232175252, 36.999269056224989 ], [ -109.33229636898766, 36.99924948493252 ], [ -109.3556262009121, 36.99921903247612 ], [ -109.37206647439949, 36.999233890859607 ], [ -109.37510631892866, 36.999230486567718 ], [ -109.37565135670255, 36.999229836304949 ], [ -109.39682363703625, 36.999201384515445 ], [ -109.42189038523941, 36.999145292828409 ], [ -109.44318133030745, 36.999088509242263 ], [ -109.46820161095816, 36.999112153251431 ], [ -109.49581219501559, 36.999140845320582 ], [ -109.49826212881517, 36.999135818863493 ], [ -109.50066712408501, 36.999130174040999 ], [ -109.52751278095438, 36.999204914455547 ], [ -109.55960735897995, 36.998945309261991 ], [ -109.58812865795622, 36.998661601382615 ], [ -109.59363631669498, 36.998600805555085 ], [ -109.60880131601131, 36.9986263142928 ], [ -109.62565797497021, 36.998259362593998 ], [ -109.65782736720188, 36.998262479133203 ], [ -109.75068506163601, 36.998338854434543 ], [ -109.87566893856328, 36.998353771251388 ], [ -110.00068636633117, 36.998498712483659 ], [ -110.09594499389836, 36.998279982274035 ], [ -110.1256933923932, 36.998236925989296 ], [ -110.16240353655405, 36.998235743966589 ], [ -110.19827702341095, 36.998186007676253 ], [ -110.23431283810748, 36.998203094883571 ], [ -110.25069356255599, 36.998131857944671 ], [ -110.27031669475618, 36.998046787161229 ], [ -110.27722291251301, 36.998025942867351 ], [ -110.27807145099089, 36.998022092648824 ], [ -110.28846168738923, 36.997990183846049 ], [ -110.29643558913007, 36.997965602810403 ], [ -110.30642685168489, 36.997934262643568 ], [ -110.37566181754066, 36.997885942920199 ], [ -110.37716796676463, 36.997862305607612 ], [ -110.37870199031114, 36.997865837940047 ], [ -110.41479571609004, 36.997694112368713 ], [ -110.46894102496279, 36.997943301103561 ], [ -110.4694467748792, 36.997941055600684 ], [ -110.47740652196346, 36.99998656179045 ], [ -110.49060888576022, 37.003848001023385 ], [ -110.50067451116664, 37.003737529452565 ], [ -110.50523243547666, 37.003684502046234 ], [ -110.52294348575158, 37.004045467890528 ], [ -110.59475952484833, 37.003785050028014 ], [ -110.62565741348368, 37.003661160449923 ], [ -110.63072224728303, 37.003591389651064 ], [ -110.64883364936392, 37.00355621205842 ], [ -110.66686194471689, 37.003504515917719 ], [ -110.68490716950924, 37.003432097503563 ], [ -110.70288511891276, 37.003311695158501 ], [ -110.72100343877273, 37.003211435631641 ], [ -110.73871708197271, 37.003116534528303 ], [ -110.75064213938157, 37.003101621306214 ], [ -110.75115363160803, 37.003071144357698 ], [ -110.75341879215458, 37.002940655669896 ], [ -110.76464146764782, 37.002891324242832 ], [ -110.77588568739968, 37.002773364301603 ], [ -110.78712645572759, 37.002672361734732 ], [ -110.79834926416351, 37.002552235251216 ], [ -110.80960575091194, 37.002434707369893 ], [ -110.82079354861243, 37.002358375986944 ], [ -110.83207329386384, 37.002370362884527 ], [ -110.8433069748456, 37.002376709848512 ], [ -110.85457452520788, 37.002305412572717 ], [ -110.86578564609977, 37.002355577978854 ], [ -110.87565938390877, 37.002356416047242 ], [ -110.87708098822415, 37.002461562572428 ], [ -110.88830906574256, 37.002472659043818 ], [ -110.89952597503152, 37.002433104617978 ], [ -110.91078214414971, 37.002451113438717 ], [ -110.92204394029093, 37.002468058514502 ], [ -110.93326080949895, 37.002456866556763 ], [ -110.93774528826354, 37.002477332171431 ], [ -110.94448437789794, 37.002503211490733 ], [ -110.9557113590788, 37.002503424308884 ], [ -110.96695633395831, 37.002480044160727 ], [ -110.97822378257094, 37.002451095604236 ], [ -110.9894631284196, 37.002394031695907 ], [ -111.00066312029998, 37.002376468678584 ], [ -111.01193054913983, 37.002398407008059 ], [ -111.02319238350164, 37.002482377834468 ], [ -111.0344204689837, 37.002443595187835 ], [ -111.04565416980547, 37.002417269900782 ], [ -111.056859766648, 37.002394402110809 ], [ -111.06812712322204, 37.00231635447426 ], [ -111.07934386403427, 37.002223749492586 ], [ -111.09060538288719, 37.002003848447146 ], [ -111.10186675630621, 37.001724285352239 ], [ -111.11309990661081, 37.001416637501748 ], [ -111.12432742609644, 37.001158413290064 ], [ -111.12568732114609, 37.001133543609832 ], [ -111.13558296092678, 37.000897292240495 ], [ -111.14677694020322, 37.000811862708723 ], [ -111.15802162494199, 37.000801932599146 ], [ -111.16928329116668, 37.000849506733225 ], [ -111.18053941149125, 37.00092306405665 ], [ -111.19176749650826, 37.001013628050814 ], [ -111.20303474827411, 37.001030947601912 ], [ -111.21423470475087, 37.001096898338027 ], [ -111.22550206961033, 37.001148142579815 ], [ -111.2367356847553, 37.00118486293411 ], [ -111.24799185601407, 37.001243008981852 ], [ -111.25071741519302, 37.001264326435006 ], [ -111.25919743178848, 37.001291183641612 ], [ -111.25964142031188, 37.001303734880736 ], [ -111.26024275573923, 37.001315939580351 ], [ -111.27042410455977, 37.000946125929744 ], [ -111.27856571391499, 37.000643344381743 ], [ -111.28161723486765, 37.000676708481002 ], [ -111.2928850088624, 37.000843249680528 ], [ -111.30410196204261, 37.000936736191555 ], [ -111.31539753330738, 37.001010924953547 ], [ -111.32659204503889, 37.001102345598291 ], [ -111.33783707097669, 37.001174537844243 ], [ -111.3491045875893, 37.001245598534581 ], [ -111.3603328013203, 37.001320216054673 ], [ -111.36274928192874, 37.001335391550363 ], [ -111.37157220112344, 37.001380214756757 ], [ -111.37569147217981, 37.001407812775781 ], [ -111.38282885184029, 37.001515715627399 ], [ -111.39406926334729, 37.001546537496807 ], [ -111.40529637873581, 37.001612397694032 ], [ -111.41282755540864, 37.00178926601518 ], [ -111.41264342808176, 37.002033294044452 ], [ -111.41243665112007, 37.002245850221108 ], [ -111.41220192138404, 37.002485546193967 ], [ -111.41195011268778, 37.002684736350282 ], [ -111.41171518564767, 37.002888374593034 ], [ -111.41126165246436, 37.0031964351612 ], [ -111.41107688582547, 37.003323276259458 ], [ -111.41080818351899, 37.003517113871695 ], [ -111.41039926560451, 37.003762817623553 ], [ -111.41003486162423, 37.003926335522749 ], [ -111.40947965402438, 37.004140089690523 ], [ -111.40918246479472, 37.004262808450356 ], [ -111.40875066800486, 37.004435569078154 ], [ -111.40827252271086, 37.004558908597275 ], [ -111.40787520308373, 37.004663939749776 ], [ -111.40743192109892, 37.004791663254366 ], [ -111.40695035152578, 37.004905994846496 ], [ -111.40652260977414, 37.004997604238561 ], [ -111.40614075688622, 37.005052997639496 ], [ -111.40577564282695, 37.005085796690409 ], [ -111.4054328876659, 37.005095982348003 ], [ -111.40510699157498, 37.005106109475236 ], [ -111.40480928960483, 37.005134168270814 ], [ -111.40456776080632, 37.005157527683373 ], [ -111.40403960178294, 37.005177355495753 ], [ -111.40348329616617, 37.005188262284662 ], [ -111.4030549822448, 37.005172590254205 ], [ -111.40262888309921, 37.005150599112525 ], [ -111.40221285695321, 37.00512045938197 ], [ -111.40174517708887, 37.005099507400644 ], [ -111.40132467945513, 37.005073886870107 ], [ -111.40085231499327, 37.005016889765749 ], [ -111.40043715412423, 37.00493716189898 ], [ -111.40008713549332, 37.004848198651132 ], [ -111.39972154768715, 37.004790837066459 ], [ -111.39942346756153, 37.004746768737405 ], [ -111.39899611116215, 37.00469862712491 ], [ -111.39849017366193, 37.004668776546069 ], [ -111.39804036298422, 37.004625214054713 ], [ -111.39741074617649, 37.004586759210689 ], [ -111.39714659726292, 37.004583136172734 ], [ -111.39686003989222, 37.004593109018039 ], [ -111.3964104879548, 37.004599118475603 ], [ -111.39587661716455, 37.004600900310052 ], [ -111.39546646829358, 37.00461939487176 ], [ -111.39517996185464, 37.00463927929119 ], [ -111.39488218789062, 37.004653791888479 ], [ -111.394522480669, 37.004645973708278 ], [ -111.39405613885101, 37.004665551601484 ], [ -111.39351093512293, 37.004649331693727 ], [ -111.39299942194566, 37.004627589115081 ], [ -111.39257232498245, 37.004629002501602 ], [ -111.39169418600784, 37.004565197392537 ], [ -111.39143678095591, 37.004561539390401 ], [ -111.39111631991744, 37.004535552718941 ], [ -111.39067782254567, 37.004505446577149 ], [ -111.39019991858819, 37.004461946822566 ], [ -111.3896825393461, 37.004391531656026 ], [ -111.38930572190139, 37.004334174825608 ], [ -111.38881091481875, 37.004281710546948 ], [ -111.38831601670292, 37.004211215769629 ], [ -111.3878436210361, 37.004145152581003 ], [ -111.38743317966021, 37.004105928394708 ], [ -111.38703950627865, 37.004048619378224 ], [ -111.38633069951845, 37.003906698709486 ], [ -111.38592030572011, 37.003876483496803 ], [ -111.38548170023249, 37.003823822573295 ], [ -111.38517243798184, 37.003788769098641 ], [ -111.38471681560397, 37.0037046102793 ], [ -111.38444124926691, 37.003664938490381 ], [ -111.38404636570932, 37.003589594714327 ], [ -111.38369306811514, 37.003514115196374 ], [ -111.38329926472439, 37.003429751068779 ], [ -111.38304613331302, 37.003380989214413 ], [ -111.38241569835033, 37.003175691586499 ], [ -111.38210584909125, 37.003022543761197 ], [ -111.38181853346343, 37.002880139878933 ], [ -111.38144674078526, 37.002701047891151 ], [ -111.38101324725481, 37.002544688732783 ], [ -111.38064743713507, 37.002437689983964 ], [ -111.3803659659783, 37.002339434233889 ], [ -111.38010711277244, 37.002269049934057 ], [ -111.37978068224271, 37.002170035321576 ], [ -111.37940381574973, 37.002099125586554 ], [ -111.37896520239549, 37.002041933368993 ], [ -111.3784815442248, 37.001966854426612 ], [ -111.3781216723436, 37.001922929537699 ], [ -111.37786299655632, 37.001887695817146 ], [ -111.37745816491535, 37.001843010596303 ], [ -111.37707579837738, 37.001795548315563 ], [ -111.37653623756694, 37.001779232438722 ], [ -111.37628347121293, 37.001802569949525 ], [ -111.3759634260276, 37.001857670349892 ], [ -111.37571632309051, 37.001890003087752 ], [ -111.37544744915544, 37.001837669071278 ], [ -111.37520472649069, 37.001846549519001 ], [ -111.37469443571955, 37.001840048551827 ], [ -111.3743110927644, 37.001822327874997 ], [ -111.37390644442749, 37.001814588887186 ], [ -111.37353544702418, 37.001793221064119 ], [ -111.37311942774794, 37.00175847205486 ], [ -111.3725683693868, 37.001688989472335 ], [ -111.3722029221193, 37.00165317706125 ], [ -111.37187677209593, 37.001609127474126 ], [ -111.37142708146085, 37.001583492390822 ], [ -111.3710001318472, 37.001611870773338 ], [ -111.37051130188422, 37.001626919235513 ], [ -111.36994399535745, 37.001682774989234 ], [ -111.36941049219779, 37.001756551583014 ], [ -111.36872567485062, 37.001916432493907 ], [ -111.36814178874663, 37.002030924579259 ], [ -111.36758651928363, 37.002253497672214 ], [ -111.36714882377046, 37.002385560797627 ], [ -111.36654314581295, 37.002644342420787 ], [ -111.36620087096676, 37.002753571406267 ], [ -111.36571278817348, 37.00292634936779 ], [ -111.36510714411793, 37.003194137930656 ], [ -111.36486612553361, 37.003325587490487 ], [ -111.36444570826816, 37.003547731271347 ], [ -111.36403129501828, 37.0038509845063 ], [ -111.36367277471842, 37.004090964434006 ], [ -111.36322950644907, 37.004236551740178 ], [ -111.36283125832151, 37.004395521336903 ], [ -111.36240520949339, 37.00461767509276 ], [ -111.36208595446918, 37.004844008762127 ], [ -111.36182251055817, 37.004989042097023 ], [ -111.36142466095244, 37.005233642288694 ], [ -111.36107153255232, 37.00542852606025 ], [ -111.36047730465076, 37.005741328097365 ], [ -111.35993899384673, 37.005995364182084 ], [ -111.35935580560738, 37.006267562447285 ], [ -111.35899677172998, 37.006403864505288 ], [ -111.35850311391795, 37.006594658408801 ], [ -111.35795993529688, 37.006772078064429 ], [ -111.35726845230143, 37.006963463295122 ], [ -111.3568140415798, 37.007136103288339 ], [ -111.3562527872562, 37.007295540731874 ], [ -111.3557924372117, 37.007400586865266 ], [ -111.35505165523367, 37.007628164438863 ], [ -111.35433286747475, 37.007752006476458 ], [ -111.3535522160293, 37.007867014090742 ], [ -111.35293449962492, 37.007972517807943 ], [ -111.352058017277, 37.008025601372147 ], [ -111.35155791853647, 37.008044211034353 ], [ -111.35114189527278, 37.008013892280161 ], [ -111.35090577354278, 37.00799656187489 ], [ -111.35036596664369, 37.007935056007007 ], [ -111.34948910723824, 37.00790609094004 ], [ -111.34828680460413, 37.007990754481163 ], [ -111.34766897706562, 37.008073695207315 ], [ -111.34704565111595, 37.008183691910666 ], [ -111.34643366560883, 37.00831618816995 ], [ -111.34578264005559, 37.008515501366951 ], [ -111.34552447035482, 37.008593776824121 ], [ -111.3451317007405, 37.008734642359151 ], [ -111.34458822622642, 37.009105810688958 ], [ -111.34411180139334, 37.009391145621812 ], [ -111.34371370937484, 37.00959962966715 ], [ -111.34342765236093, 37.009726658917359 ], [ -111.34302385557726, 37.009917128412617 ], [ -111.34267045585719, 37.010066886373508 ], [ -111.34221611449554, 37.010266513409093 ], [ -111.34180133386614, 37.010515603810525 ], [ -111.34138099081699, 37.010778230310798 ], [ -111.34106732800288, 37.011018012874423 ], [ -111.34058578068976, 37.011420535123392 ], [ -111.34015473029139, 37.011804881951058 ], [ -111.33976311787946, 37.012211650220522 ], [ -111.33930445419971, 37.012707851120418 ], [ -111.33894663883815, 37.013133450194381 ], [ -111.33856637393103, 37.013567225140989 ], [ -111.33813579648628, 37.014063341320117 ], [ -111.3377671263125, 37.014579111336026 ], [ -111.33746523952018, 37.014945953297321 ], [ -111.33705734825445, 37.015491579966735 ], [ -111.33681707770936, 37.015812271979783 ], [ -111.33653213864923, 37.016200697880699 ], [ -111.3362360944803, 37.016620704806272 ], [ -111.33587283735348, 37.017094987374975 ], [ -111.33554848452188, 37.017470000850452 ], [ -111.33518486275575, 37.01786315305764 ], [ -111.33466955642935, 37.018274760700905 ], [ -111.33410908105392, 37.018641421469425 ], [ -111.33344762296987, 37.019053435149821 ], [ -111.33271308698313, 37.019465650031115 ], [ -111.3320457383635, 37.019819079062692 ], [ -111.33182147262515, 37.019950414518533 ], [ -111.33141208924751, 37.020167903049959 ], [ -111.33093552645333, 37.020448678020706 ], [ -111.33072804153296, 37.020561935894399 ], [ -111.33046446394471, 37.020702392685891 ], [ -111.33005472171371, 37.02083874831547 ], [ -111.32938655097327, 37.02100737034624 ], [ -111.32880792408012, 37.021085596987163 ], [ -111.32818438650155, 37.021177466549538 ], [ -111.32768412144573, 37.021178848951962 ], [ -111.32703201326392, 37.021162619068875 ], [ -111.32654268153611, 37.021091851673894 ], [ -111.32598586084707, 37.021012253306949 ], [ -111.32549633875287, 37.020896410326891 ], [ -111.32498406566695, 37.020717527121896 ], [ -111.324443537101, 37.020502661512829 ], [ -111.32384664960919, 37.020251889801571 ], [ -111.32332796167312, 37.019883715367044 ], [ -111.32283155232886, 37.019465899048029 ], [ -111.32253261946093, 37.01922332412002 ], [ -111.3221826065446, 37.018863700411231 ], [ -111.32184381944701, 37.018499538017146 ], [ -111.32153331018284, 37.018175862648604 ], [ -111.32122284150181, 37.017861200697872 ], [ -111.32072619544755, 37.017381176907527 ], [ -111.32032532606917, 37.01695317583016 ], [ -111.31989632410038, 37.016517136263786 ], [ -111.31959709124892, 37.016197932474562 ], [ -111.31926975805425, 37.015878803506986 ], [ -111.31894804814722, 37.015559658501495 ], [ -111.31884650169415, 37.015469787687302 ], [ -111.31822585544559, 37.014899041130107 ], [ -111.31770125406703, 37.014445220988208 ], [ -111.31741344813167, 37.014166545620583 ], [ -111.31691156285194, 37.013766747378732 ], [ -111.31658994651031, 37.013465624321078 ], [ -111.31617836941517, 37.013155725695313 ], [ -111.3158231483489, 37.012881733153975 ], [ -111.3154341147095, 37.012585293471268 ], [ -111.31507339029164, 37.01233835639448 ], [ -111.31475234853389, 37.012173343772218 ], [ -111.31440321786108, 37.012011108999289 ], [ -111.31393039068404, 37.011836580320953 ], [ -111.31336777098358, 37.011693837177276 ], [ -111.31285017083077, 37.011564494258835 ], [ -111.31248454050085, 37.011488835303275 ], [ -111.31170282867484, 37.011369196830444 ], [ -111.31093814153806, 37.011289171853363 ], [ -111.3105503672021, 37.011295595761098 ], [ -111.31016273564742, 37.01133717409445 ], [ -111.30971895608828, 37.011392419262734 ], [ -111.30911246243907, 37.011515694488793 ], [ -111.30861717513616, 37.011620648745897 ], [ -111.30808510194461, 37.011802318625463 ], [ -111.30754630001951, 37.01198851074318 ], [ -111.30704689197347, 37.012188120067691 ], [ -111.30666529071316, 37.012333336697708 ], [ -111.30622775597529, 37.012546304244921 ], [ -111.30584091389289, 37.012787084115857 ], [ -111.30548210986974, 37.013012466119726 ], [ -111.30529175656996, 37.013197750596028 ], [ -111.30495030001202, 37.013545681841471 ], [ -111.30467034123566, 37.013812324874898 ], [ -111.30440176520787, 37.01411499553695 ], [ -111.30421194550462, 37.014435492477411 ], [ -111.30391540658952, 37.014774291176437 ], [ -111.30364170578063, 37.015203174406686 ], [ -111.30358600250585, 37.015329518108437 ], [ -111.30346940498748, 37.01569039114996 ], [ -111.30340323043093, 37.016010570495745 ], [ -111.30340005993824, 37.016344110291442 ], [ -111.30344531651861, 37.016700062179765 ], [ -111.30359828065291, 37.017285604939516 ], [ -111.30363348754588, 37.017375658551117 ], [ -111.30386037896767, 37.017893403981759 ], [ -111.30395095688014, 37.018055430640814 ], [ -111.30412640328744, 37.018356962451051 ], [ -111.30439776398106, 37.018748391667501 ], [ -111.30465802979124, 37.019175906175661 ], [ -111.30494640279153, 37.019603347855899 ], [ -111.30533096528724, 37.020188292719901 ], [ -111.3056531436886, 37.020633674339173 ], [ -111.30595873407732, 37.021146705525005 ], [ -111.30614572691552, 37.021520319284548 ], [ -111.30645748832409, 37.022168548580545 ], [ -111.30667268205822, 37.022564624505335 ], [ -111.30692223922009, 37.02311836241757 ], [ -111.30695058049841, 37.023176882445249 ], [ -111.30700733573187, 37.023311951006995 ], [ -111.30717192342452, 37.023702748233603 ], [ -111.30725189377773, 37.024018945154054 ], [ -111.30729893276546, 37.024532641692716 ], [ -111.30721601207283, 37.024879909102694 ], [ -111.30711060557475, 37.025227234630634 ], [ -111.30693219387796, 37.025592777604885 ], [ -111.30670873744458, 37.025940408014186 ], [ -111.30643361693275, 37.026301692940258 ], [ -111.30619992915474, 37.026622305718057 ], [ -111.30574058459327, 37.027024628811695 ], [ -111.30556702533462, 37.027200855736567 ], [ -111.30519167100283, 37.027521831202435 ], [ -111.30507395972674, 37.027606868792489 ], [ -111.30478817020042, 37.027833863414394 ], [ -111.3045136543101, 37.028068941329813 ], [ -111.30418852531297, 37.028299641182045 ], [ -111.30382962938091, 37.028521412248942 ], [ -111.30359977532321, 37.028679751689751 ], [ -111.30326343371425, 37.028919492031413 ], [ -111.30294373986008, 37.02910510281172 ], [ -111.30261826195125, 37.029250162902265 ], [ -111.30231517978447, 37.029372629168712 ], [ -111.30189981126649, 37.029532339223962 ], [ -111.30150695589539, 37.02969920210365 ], [ -111.30115912862586, 37.029880372371181 ], [ -111.30086184099061, 37.030047891963484 ], [ -111.30044665746216, 37.030256273944318 ], [ -111.30016048593883, 37.030392213406842 ], [ -111.2997056635979, 37.030528578259265 ], [ -111.29915563891468, 37.030758930646826 ], [ -111.29883000896061, 37.030868824756936 ], [ -111.29839780921405, 37.031041185016527 ], [ -111.29800483973925, 37.031182796400195 ], [ -111.29753333350892, 37.031367872303832 ], [ -111.29707308951973, 37.031558326746421 ], [ -111.29674876685544, 37.031716889348743 ], [ -111.29634932139018, 37.031929724788455 ], [ -111.29606874051737, 37.032061133234315 ], [ -111.29559161980013, 37.032250722596451 ], [ -111.29503014175832, 37.032433308332081 ], [ -111.2947999265828, 37.032505995280708 ], [ -111.29435061678365, 37.032619790037693 ], [ -111.29396302063547, 37.032700978573551 ], [ -111.29347441109593, 37.032829290321743 ], [ -111.29309247287614, 37.032920377802888 ], [ -111.29265445362866, 37.033047659770347 ], [ -111.29223895488484, 37.033183899005373 ], [ -111.29198643710026, 37.033306214327588 ], [ -111.29172267474806, 37.03342855675664 ], [ -111.2913072755392, 37.033591835521769 ], [ -111.29076300037588, 37.033868108027086 ], [ -111.29029747976357, 37.034157706901944 ], [ -111.28987108658409, 37.034388615119511 ], [ -111.28940549098303, 37.034660181974708 ], [ -111.28886701105527, 37.034986010521912 ], [ -111.28826695690671, 37.035384100975868 ], [ -111.28773410604249, 37.035714417856902 ], [ -111.28711139920422, 37.036071992823622 ], [ -111.28653925155848, 37.036420428084817 ], [ -111.28631484134107, 37.036547170598766 ], [ -111.28583238725166, 37.036827778403186 ], [ -111.28532742413294, 37.037103931197265 ], [ -111.28476660591019, 37.037479373660581 ], [ -111.28429447525231, 37.037817642197858 ], [ -111.28390320654489, 37.038130475238667 ], [ -111.28369577099103, 37.038288722356207 ], [ -111.28346042437229, 37.038501121834351 ], [ -111.28311883899417, 37.038871525338621 ], [ -111.28284470131184, 37.039237259909285 ], [ -111.28269415216893, 37.039575656420077 ], [ -111.28259979189235, 37.039904904569177 ], [ -111.28247162971702, 37.040216204426756 ], [ -111.28233205480005, 37.040482459600049 ], [ -111.28210812590602, 37.040744408023436 ], [ -111.28191219103027, 37.040974739325243 ], [ -111.28174440056239, 37.041214017805615 ], [ -111.28165068352865, 37.041719043148511 ], [ -111.28165729170328, 37.041985851803247 ], [ -111.28178850519166, 37.042498455922484 ], [ -111.28228555921578, 37.043110249116658 ], [ -111.28237592139313, 37.043218206098167 ], [ -111.28270336944534, 37.043577999667008 ], [ -111.28313743346813, 37.043878944764835 ], [ -111.28393734404217, 37.044278170946143 ], [ -111.28430443030004, 37.044407999697114 ], [ -111.28498988057282, 37.044568613177738 ], [ -111.28560868174897, 37.044648254171094 ], [ -111.28639035325433, 37.044677018654248 ], [ -111.28714396947714, 37.044721170249751 ], [ -111.28795353790655, 37.044692165199535 ], [ -111.28888661737705, 37.04461327514278 ], [ -111.28994313708904, 37.044466468680397 ], [ -111.29071844986402, 37.044302313526181 ], [ -111.29144313803144, 37.04413377050696 ], [ -111.29233620879101, 37.043888186492445 ], [ -111.29279110671943, 37.043747342667068 ], [ -111.29311695978461, 37.043678930616977 ], [ -111.29362261482926, 37.043578522685671 ], [ -111.29431393669594, 37.043509202341468 ], [ -111.29514577028604, 37.043426007022774 ], [ -111.29591035815928, 37.043401566753879 ], [ -111.29660752680842, 37.043390811614834 ], [ -111.29747360210628, 37.043438222160951 ], [ -111.29824425265272, 37.043526430774087 ], [ -111.29886884037749, 37.043646552547628 ], [ -111.29939909366465, 37.043798459263698 ], [ -111.29983731486257, 37.043995667859029 ], [ -111.30022609434866, 37.044202014271924 ], [ -111.30069396680992, 37.044502809415441 ], [ -111.3010491573487, 37.044745295535421 ], [ -111.30156806884662, 37.045154129593108 ], [ -111.30203109751834, 37.04564873970844 ], [ -111.30240955762793, 37.046084970437875 ], [ -111.3026921296005, 37.046444822839511 ], [ -111.30299166239489, 37.04682716703671 ], [ -111.30322959743729, 37.047272768155935 ], [ -111.30341109074483, 37.047664427181438 ], [ -111.30366108475923, 37.048312818752052 ], [ -111.30387121884547, 37.04883511133248 ], [ -111.30412659196631, 37.049420387766425 ], [ -111.30431470784973, 37.050059922031778 ], [ -111.30455356129342, 37.050730875798543 ], [ -111.30465262141171, 37.051316552055646 ], [ -111.30474317981236, 37.051744499485409 ], [ -111.30494866345519, 37.052505681106609 ], [ -111.30508130050434, 37.053330149812048 ], [ -111.30523003446741, 37.05396076912578 ], [ -111.30541893449966, 37.054510155980729 ], [ -111.30557777780218, 37.055136241541305 ], [ -111.30570945005506, 37.055717325292214 ], [ -111.30582428985103, 37.056307466538534 ], [ -111.30582647854338, 37.056852826535838 ], [ -111.30576712919409, 37.057478572441532 ], [ -111.30561307313732, 37.058047772146075 ], [ -111.30550770053486, 37.058697073550206 ], [ -111.30540308962776, 37.059256229791707 ], [ -111.3052988384008, 37.059905527997941 ], [ -111.30524601809077, 37.060478072147532 ], [ -111.30520809000043, 37.061118185165959 ], [ -111.30505361603856, 37.061866769470214 ], [ -111.30492657372461, 37.062444011288648 ], [ -111.30479451853708, 37.06317450887218 ], [ -111.30454884337198, 37.06362134761077 ], [ -111.30439832535346, 37.063955262954387 ], [ -111.30412434466366, 37.064357101912734 ], [ -111.30383347056994, 37.064754476339715 ], [ -111.30357010385268, 37.064998536613643 ], [ -111.30331798747575, 37.065243468958869 ], [ -111.30295375398053, 37.065581534395953 ], [ -111.30261724827875, 37.06582127215534 ], [ -111.30224699477961, 37.066061094948942 ], [ -111.30175878938388, 37.066341781021833 ], [ -111.30134317950227, 37.066491573416961 ], [ -111.30094424507996, 37.0665917434333 ], [ -111.30060708826694, 37.066669219832811 ], [ -111.30005617066205, 37.066738221892486 ], [ -111.29974687148027, 37.066748919601736 ], [ -111.29939807078797, 37.06672636332501 ], [ -111.29881857026587, 37.066678245953398 ], [ -111.29832339647992, 37.066619997977867 ], [ -111.29774912006113, 37.066469099278152 ], [ -111.29703957795559, 37.06624552079515 ], [ -111.29649324935809, 37.066048573099252 ], [ -111.29591305541133, 37.065820157323628 ], [ -111.29552992344846, 37.065645333684778 ], [ -111.29485969532735, 37.065403615558004 ], [ -111.29443711120341, 37.065206350684718 ], [ -111.29394131023548, 37.06498222285235 ], [ -111.2935749379735, 37.064775801282387 ], [ -111.29330992429949, 37.064600678036875 ], [ -111.29287564978453, 37.064286250573474 ], [ -111.29242469676571, 37.064021441262234 ], [ -111.29183267784482, 37.063635284290633 ], [ -111.29129712972789, 37.063307578628013 ], [ -111.29078972370472, 37.062984308689067 ], [ -111.29022020006246, 37.062593581274989 ], [ -111.28968446053878, 37.062211782896867 ], [ -111.28940255850004, 37.062027677749505 ], [ -111.28914320503696, 37.061857038421174 ], [ -111.2887483480839, 37.061547006709155 ], [ -111.28828126928214, 37.061174049057804 ], [ -111.28778931370522, 37.060765092665996 ], [ -111.28731541076968, 37.060369611933794 ], [ -111.28702217168566, 37.060158485586292 ], [ -111.2861428060849, 37.059616145793775 ], [ -111.28569234004891, 37.059467593988551 ], [ -111.28528170129375, 37.059441539289764 ], [ -111.28475224254443, 37.059523940140629 ], [ -111.28427547831382, 37.059561140824812 ], [ -111.28390412218862, 37.059512451445173 ], [ -111.28345812993078, 37.059355767559374 ], [ -111.28285660519461, 37.059113817001112 ], [ -111.28240044451339, 37.058943631900412 ], [ -111.28195566678795, 37.0588094752231 ], [ -111.2815333522931, 37.058666249254081 ], [ -111.28104929467472, 37.058554718155904 ], [ -111.28061029467951, 37.058461107127734 ], [ -111.27989591544629, 37.058417723232353 ], [ -111.27915326977296, 37.058333837150521 ], [ -111.27828087204738, 37.058138473390969 ], [ -111.27762210682793, 37.057922771958765 ], [ -111.27732364110504, 37.057810791154211 ], [ -111.27689001152449, 37.057645039273851 ], [ -111.27625891848943, 37.057303966691123 ], [ -111.27593188200944, 37.057065848501082 ], [ -111.27568939741526, 37.056881618821734 ], [ -111.27518785395128, 37.056594325234705 ], [ -111.27465822888531, 37.056316108839937 ], [ -111.27424151669288, 37.056159322358717 ], [ -111.27384156348752, 37.055970945616664 ], [ -111.27327284154538, 37.055764927764677 ], [ -111.27278871745729, 37.055626320053676 ], [ -111.27235511331831, 37.055461452869622 ], [ -111.27183156398479, 37.055304903108791 ], [ -111.27133611497972, 37.055142878171864 ], [ -111.27092526378298, 37.055049166809013 ], [ -111.27048060874738, 37.054937502459524 ], [ -111.27013164978797, 37.054852661532102 ], [ -111.26954623518404, 37.054691735346502 ], [ -111.26894941708551, 37.054485760519697 ], [ -111.26852692842394, 37.054279388215761 ], [ -111.26817187540345, 37.054059340498434 ], [ -111.26790686211766, 37.053857117050924 ], [ -111.2674273235353, 37.053416497268451 ], [ -111.26702564513469, 37.053047814859617 ], [ -111.26683492937394, 37.052863450365109 ], [ -111.2663666498311, 37.052422800875995 ], [ -111.26605080154498, 37.052153079907733 ], [ -111.2657110550049, 37.051802282693494 ], [ -111.26541859372564, 37.051464900189544 ], [ -111.26515181358491, 37.051073373596211 ], [ -111.26493958569594, 37.05084488385814 ], [ -111.26459300533375, 37.050466154195291 ], [ -111.26435141235775, 37.050200770123425 ], [ -111.26404651437113, 37.04984087601742 ], [ -111.26382632419742, 37.04958445753342 ], [ -111.26338599502479, 37.049085140678017 ], [ -111.2630650660801, 37.048639643426021 ], [ -111.26275872957312, 37.048185098618667 ], [ -111.26260029241391, 37.047896990833848 ], [ -111.26230087979108, 37.047492008274695 ], [ -111.26209690467293, 37.047041742472821 ], [ -111.26183118885626, 37.046623162716088 ], [ -111.26164452050305, 37.046299058533748 ], [ -111.26142929141736, 37.045844309132207 ], [ -111.26122541857119, 37.045421084469545 ], [ -111.2609878886787, 37.045020469301825 ], [ -111.26079535845099, 37.044624261890412 ], [ -111.26063677900822, 37.044290178482392 ], [ -111.2604838451909, 37.043962392482612 ], [ -111.26022360245919, 37.043494218001712 ], [ -111.25996892406349, 37.043008002038711 ], [ -111.25968029863431, 37.042458759410842 ], [ -111.25945377048446, 37.041981494971807 ], [ -111.25927280750572, 37.041675402973631 ], [ -111.25905216705273, 37.04127474673308 ], [ -111.25877951181619, 37.040788567257977 ], [ -111.25864476521016, 37.040513923622846 ], [ -111.25820470079833, 37.039735141398076 ], [ -111.25797150426749, 37.039275917081483 ], [ -111.25769963724974, 37.038686068250598 ], [ -111.25742219786954, 37.038109752340432 ], [ -111.25724771007677, 37.037718006679469 ], [ -111.25695806077618, 37.037186787789551 ], [ -111.25671916644734, 37.036700530081539 ], [ -111.25648259981433, 37.036236802690119 ], [ -111.2562954193788, 37.035745925072355 ], [ -111.25608576838844, 37.035259602788315 ], [ -111.25589875929747, 37.034818303021176 ], [ -111.25572301142604, 37.03438148583038 ], [ -111.25555302645763, 37.033986121957085 ], [ -111.2553380770624, 37.033593558882927 ], [ -111.25520082039272, 37.033233279997475 ], [ -111.25508307126259, 37.03299014560848 ], [ -111.25477201695206, 37.032436431027371 ], [ -111.25453420074481, 37.031927630277423 ], [ -111.25427854839593, 37.031463939010493 ], [ -111.25401954114932, 37.031004761512264 ], [ -111.25381021781256, 37.030608577659116 ], [ -111.25359523004718, 37.030198883973377 ], [ -111.25334669447695, 37.029843347654818 ], [ -111.25312082712868, 37.029541848601909 ], [ -111.25289472248365, 37.029168234719116 ], [ -111.25273066622198, 37.02885758877548 ], [ -111.25254416992338, 37.028560511888813 ], [ -111.25238002693607, 37.028222822521194 ], [ -111.25221033843071, 37.027907680599043 ], [ -111.25205193894249, 37.0276060359827 ], [ -111.25184145142848, 37.027191822142093 ], [ -111.25163888078211, 37.026791112654955 ], [ -111.25151440738217, 37.026547988684754 ], [ -111.25144064596607, 37.02634081459415 ], [ -111.25131059712648, 37.026111223751855 ], [ -111.25118065295183, 37.025913182817334 ], [ -111.2509772021838, 37.025584588900891 ], [ -111.25080221525894, 37.025364106867777 ], [ -111.25055372335703, 37.025013071454495 ], [ -111.25034378362916, 37.02476111222424 ], [ -111.25014619723999, 37.024504619386157 ], [ -111.24981425156199, 37.024072628924579 ], [ -111.24950387647499, 37.02370369273693 ], [ -111.24911463164793, 37.023280835075667 ], [ -111.24879873023936, 37.022938951698286 ], [ -111.24841542249547, 37.022610730133849 ], [ -111.24802680465801, 37.022377169315369 ], [ -111.24770132072881, 37.022197561686404 ], [ -111.24728352152056, 37.021977580875806 ], [ -111.2468613737109, 37.021802679495046 ], [ -111.24629312472207, 37.0216416014717 ], [ -111.24578121897011, 37.021520968724509 ], [ -111.24535374596188, 37.02143621672883 ], [ -111.24485325862891, 37.021369642608704 ], [ -111.24439778062801, 37.021315593815807 ], [ -111.24384113096862, 37.021263554070771 ], [ -111.24317213100892, 37.021233376480915 ], [ -111.24245290060794, 37.021315977438327 ], [ -111.24217195035607, 37.02134810140592 ], [ -111.24166635921097, 37.021443783003406 ], [ -111.24119913223339, 37.021584456353487 ], [ -111.24069474779687, 37.021707174483339 ], [ -111.24029613676349, 37.021861226650955 ], [ -111.23977401659172, 37.022065106146655 ], [ -111.23947668020033, 37.022250501202024 ], [ -111.23914606788027, 37.022580192549448 ], [ -111.23877059653387, 37.022946030720341 ], [ -111.23846815436046, 37.023298199398759 ], [ -111.23808147606661, 37.023677579433325 ], [ -111.23771153117694, 37.024016359999351 ], [ -111.23734733043368, 37.024395692579539 ], [ -111.23696662626664, 37.02489224379655 ], [ -111.23653599613567, 37.0256052381541 ], [ -111.23620044695284, 37.026164797395886 ], [ -111.23583710629762, 37.0268280761087 ], [ -111.23554678273342, 37.027473179998097 ], [ -111.23527301299525, 37.028019092269851 ], [ -111.23496557950324, 37.028587606440162 ], [ -111.23477551784107, 37.028935937111676 ], [ -111.23466374917022, 37.029151601503877 ], [ -111.23457439975637, 37.029345586993976 ], [ -111.234401307353, 37.029729039499145 ], [ -111.23418908301367, 37.03018468386901 ], [ -111.23393160610273, 37.030550273424325 ], [ -111.23367981749081, 37.030938387105088 ], [ -111.23341131279761, 37.031376112099217 ], [ -111.23299167771066, 37.032030477950542 ], [ -111.23294693731845, 37.032107187852382 ], [ -111.23284072840585, 37.032305712228357 ], [ -111.2326170927202, 37.032711797028654 ], [ -111.23234883661357, 37.033235155426169 ], [ -111.23202984235859, 37.033713540612958 ], [ -111.23181212160738, 37.034218770175897 ], [ -111.23156062493091, 37.034710543684291 ], [ -111.23128706062718, 37.035342082153129 ], [ -111.23097848467921, 37.03592410913916 ], [ -111.230705831143, 37.036488036725217 ], [ -111.23046553700529, 37.036970771610761 ], [ -111.23026462519421, 37.0374633453428 ], [ -111.23008072167158, 37.03800366178271 ], [ -111.22993611717514, 37.038525873040037 ], [ -111.22986975307245, 37.038891984265959 ], [ -111.22991599540804, 37.039311061950464 ], [ -111.23006350891747, 37.039752479140262 ], [ -111.23026757486058, 37.04030195855286 ], [ -111.23064041277084, 37.040882659825868 ], [ -111.23106968624174, 37.04153085756478 ], [ -111.23126167156666, 37.041800913899152 ], [ -111.23156635549662, 37.042151879116915 ], [ -111.231859618903, 37.042444272605309 ], [ -111.23223726460901, 37.042750021731294 ], [ -111.232710470269, 37.043046567903488 ], [ -111.2332339799798, 37.043243855518043 ], [ -111.23375745093246, 37.043427619374143 ], [ -111.23434380114956, 37.043579706534693 ], [ -111.23507402437822, 37.04370896996879 ], [ -111.235394738726, 37.043780448846434 ], [ -111.2359123029614, 37.04386956429579 ], [ -111.23643543516273, 37.04394063770556 ], [ -111.23699234925883, 37.044026064279535 ], [ -111.23748185689243, 37.044132356159714 ], [ -111.23810078931137, 37.044270837983724 ], [ -111.23864660049564, 37.044400449330887 ], [ -111.23924896604811, 37.044633609045071 ], [ -111.23976571362473, 37.044817359870095 ], [ -111.24033543124582, 37.045037058504803 ], [ -111.2408417214326, 37.045112653738038 ], [ -111.24137008984727, 37.045057493980806 ], [ -111.24184235862793, 37.045043010760757 ], [ -111.24224721143874, 37.045046692005656 ], [ -111.24277030006186, 37.04509970885951 ], [ -111.24331608185102, 37.045215777238163 ], [ -111.24372696186023, 37.045345641806492 ], [ -111.24409849817921, 37.045480093067226 ], [ -111.24454885618331, 37.045645930901379 ], [ -111.24501630186801, 37.045879339259841 ], [ -111.24547841784677, 37.046202900155954 ], [ -111.24605909799163, 37.046674949934626 ], [ -111.24645942961283, 37.047016663742539 ], [ -111.24685996916753, 37.047421476082633 ], [ -111.247176270886, 37.047858012732419 ], [ -111.24740237427058, 37.048222621960434 ], [ -111.24764015049706, 37.048717914186945 ], [ -111.24783864166939, 37.049235823791491 ], [ -111.24795278903035, 37.049753909319087 ], [ -111.24803296445326, 37.050199951077978 ], [ -111.2480239357415, 37.050881453258015 ], [ -111.24792996605304, 37.051381043473086 ], [ -111.24776881201771, 37.051971818609985 ], [ -111.24748952210757, 37.052549318486243 ], [ -111.24717076220757, 37.053095349755196 ], [ -111.24680722958679, 37.053709080713908 ], [ -111.2466842443626, 37.053934694623273 ], [ -111.24648843082926, 37.054246095814889 ], [ -111.24614149566986, 37.054778661236419 ], [ -111.24582238246533, 37.055221024729732 ], [ -111.24548664177416, 37.055740043483176 ], [ -111.24524055474497, 37.056159718413177 ], [ -111.2450337433054, 37.056552268728019 ], [ -111.24474840153778, 37.057008080942602 ], [ -111.24446844868309, 37.057391766779176 ], [ -111.24417188189487, 37.057856615003196 ], [ -111.24405450305942, 37.058081313079931 ], [ -111.24391542788584, 37.058555752258897 ], [ -111.24371468826892, 37.059092516729358 ], [ -111.2435028422169, 37.059674375196153 ], [ -111.24331347407431, 37.060251679973341 ], [ -111.24314667068641, 37.060851473935131 ], [ -111.24301908870544, 37.061406115694119 ], [ -111.24288015630171, 37.061929230411124 ], [ -111.24270796594573, 37.062605656279906 ], [ -111.24257973210527, 37.062957476738845 ], [ -111.24247938808777, 37.063237125545271 ], [ -111.24228415285894, 37.063743227299099 ], [ -111.2420330398873, 37.064364825878584 ], [ -111.24187119785829, 37.064761785589461 ], [ -111.24165916491117, 37.065294061940001 ], [ -111.24143602328627, 37.065871432015719 ], [ -111.24115093925482, 37.066426391796632 ], [ -111.24071434899631, 37.067094337214129 ], [ -111.24026077828844, 37.067730765289504 ], [ -111.23991900817754, 37.068150622202147 ], [ -111.23946613854594, 37.068656338328637 ], [ -111.23881405816815, 37.069131805302369 ], [ -111.238438015657, 37.069388567992981 ], [ -111.23786535542672, 37.069724148357473 ], [ -111.23730362480259, 37.069958743900621 ], [ -111.23695529235852, 37.070085640485203 ], [ -111.23668428433466, 37.070117731612456 ], [ -111.23617904064876, 37.070069160024907 ], [ -111.23571201699812, 37.070011496038155 ], [ -111.23499140043576, 37.069796582581716 ], [ -111.23447360546608, 37.06968943561909 ], [ -111.23388124929005, 37.069478768943888 ], [ -111.23328525936803, 37.06918247055944 ], [ -111.23271031676867, 37.06877795621611 ], [ -111.23259759254701, 37.068701555720907 ], [ -111.23189289633395, 37.068166584303292 ], [ -111.2313063366947, 37.06763588548371 ], [ -111.23075889653904, 37.067019471688312 ], [ -111.23022263220236, 37.066375990673734 ], [ -111.23003603554859, 37.066047330404913 ], [ -111.22985524159283, 37.065777251590525 ], [ -111.22966855288274, 37.065417040798934 ], [ -111.22944771325994, 37.064921681088599 ], [ -111.22918291290995, 37.064394855771617 ], [ -111.22894398733406, 37.063867979875894 ], [ -111.22849167608572, 37.063075592403194 ], [ -111.22806812858582, 37.062494984191751 ], [ -111.22778520121845, 37.061918611625266 ], [ -111.2275135799174, 37.061360245271793 ], [ -111.22724166688039, 37.060702721302697 ], [ -111.22701536724652, 37.060252438678333 ], [ -111.22680571377863, 37.059725502046177 ], [ -111.22657789549213, 37.059140908038884 ], [ -111.22637518144657, 37.058676156098912 ], [ -111.22621665882983, 37.058320392803537 ], [ -111.22599616987851, 37.057928690048641 ], [ -111.22565779937031, 37.057609325726908 ], [ -111.22525208092671, 37.057335159930958 ], [ -111.22482932157514, 37.057002431923223 ], [ -111.2245193039381, 37.056759632310204 ], [ -111.22418679383459, 37.056516874381671 ], [ -111.22369096351436, 37.05619329464669 ], [ -111.22334182558271, 37.056031694600989 ], [ -111.22295936972922, 37.056014385354707 ], [ -111.22256035924505, 37.05610527784058 ], [ -111.22227826583669, 37.05617792132778 ], [ -111.22181845327023, 37.05624638941179 ], [ -111.221413698733, 37.05629672431683 ], [ -111.22074480422052, 37.056406142746354 ], [ -111.22035695802951, 37.056469964071511 ], [ -111.21985091127576, 37.056497945936705 ], [ -111.21946853170144, 37.056507668274811 ], [ -111.21896805616134, 37.056517607416886 ], [ -111.21859705287974, 37.056572377575236 ], [ -111.21820368363514, 37.05667225934102 ], [ -111.21785557300119, 37.056866707112974 ], [ -111.2176255444319, 37.057056430139077 ], [ -111.21744652385208, 37.057384879828078 ], [ -111.21731809448058, 37.057706025105489 ], [ -111.21719493832127, 37.057904565772965 ], [ -111.21690341601706, 37.058225107630363 ], [ -111.21660550901417, 37.058278836454612 ], [ -111.21627932165975, 37.058275825856803 ], [ -111.21601499294584, 37.058271800307175 ], [ -111.21566132218872, 37.058493294699211 ], [ -111.21557043660208, 37.058570983065501 ], [ -111.21531356607697, 37.058818442007194 ], [ -111.21496589346525, 37.059174236825939 ], [ -111.214758348573, 37.059364814925978 ], [ -111.21424789858176, 37.059834482633477 ], [ -111.21373193219542, 37.060344722497454 ], [ -111.213514280727, 37.060543429488725 ], [ -111.21329439117081, 37.060746647259684 ], [ -111.21282892719148, 37.061220735042149 ], [ -111.21248697166777, 37.061617978091753 ], [ -111.21204965511795, 37.062105533816165 ], [ -111.21180308752865, 37.062425982596913 ], [ -111.21161257083595, 37.062678723496703 ], [ -111.21113614867592, 37.063265503017639 ], [ -111.21067636730886, 37.063771122182388 ], [ -111.21030645488045, 37.064236015818437 ], [ -111.2099087769966, 37.064831664965027 ], [ -111.20961305783305, 37.065282903586116 ], [ -111.20920868181268, 37.065901097912992 ], [ -111.20890042013961, 37.066293763778006 ], [ -111.20862575336876, 37.066632283869062 ], [ -111.20828900638227, 37.066894290685951 ], [ -111.20800811956218, 37.067016476773759 ], [ -111.20772144765992, 37.067080079302997 ], [ -111.20745182032489, 37.067206751509794 ], [ -111.20726684038732, 37.067436939801354 ], [ -111.20695832983306, 37.067743965026352 ], [ -111.20658793541755, 37.068046590074815 ], [ -111.20616708843301, 37.068412401822158 ], [ -111.20573497618881, 37.068773724443936 ], [ -111.20534659766612, 37.069085391076051 ], [ -111.20489310433894, 37.069446747612304 ], [ -111.20451185571471, 37.069902628089856 ], [ -111.20404613634189, 37.070322595423526 ], [ -111.20325001175955, 37.071288493028788 ], [ -111.20304254638189, 37.071532234588787 ], [ -111.2028463531763, 37.071784970806185 ], [ -111.20247628225988, 37.072222796868019 ], [ -111.20212873026064, 37.072669597679898 ], [ -111.20182606544452, 37.073075756712342 ], [ -111.20146743485439, 37.073590181650133 ], [ -111.20103577068869, 37.074140786478466 ], [ -111.20082846639026, 37.074451229623143 ], [ -111.20046964463927, 37.074898044512146 ], [ -111.20007176570951, 37.075467518651791 ], [ -111.19969054091369, 37.075954933251928 ], [ -111.19924189270822, 37.07647400991479 ], [ -111.19886605906198, 37.076875776911471 ], [ -111.19810322332752, 37.077715383106153 ], [ -111.19785633588614, 37.077954674063562 ], [ -111.19745802177015, 37.07836999545912 ], [ -111.19727841132537, 37.078523537363886 ], [ -111.19694725631237, 37.078808038010429 ], [ -111.19620093088911, 37.079521404214965 ], [ -111.19592031439232, 37.079774268315738 ], [ -111.19562292418394, 37.080067723731304 ], [ -111.19537607915861, 37.080329545112718 ], [ -111.19492150808821, 37.080753964806497 ], [ -111.19451742274971, 37.081124214194105 ], [ -111.19410214000546, 37.081517016240916 ], [ -111.19366450003814, 37.081968446211611 ], [ -111.19320988677583, 37.082383845030513 ], [ -111.19290699885474, 37.082735895371513 ], [ -111.19250301857673, 37.083155716216496 ], [ -111.19205410847904, 37.083607158435406 ], [ -111.19177257646885, 37.083954664090875 ], [ -111.19150435076182, 37.084225526131689 ], [ -111.19122939496539, 37.084505412694753 ], [ -111.19088142723608, 37.084834994719117 ], [ -111.19053914992169, 37.085191609424825 ], [ -111.19020815472217, 37.085561726460142 ], [ -111.18990521781795, 37.085904754771832 ], [ -111.18949552227643, 37.086302038628247 ], [ -111.1892261662457, 37.086577404377422 ], [ -111.18881088239146, 37.086992723316087 ], [ -111.18850793350815, 37.087335748009316 ], [ -111.18817129320286, 37.087705868221846 ], [ -111.18777852351504, 37.08813016203851 ], [ -111.18734654502462, 37.088626630726729 ], [ -111.18711549639441, 37.088928973915564 ], [ -111.18699885172309, 37.089082400672993 ], [ -111.18680819728031, 37.089339608140797 ], [ -111.18649420982473, 37.089777294902795 ], [ -111.18625879683468, 37.090138236051217 ], [ -111.18590538693435, 37.090562461693914 ], [ -111.1856293833935, 37.090891915199883 ], [ -111.18536686933875, 37.091216839825002 ], [ -111.18512015028939, 37.091559767753886 ], [ -111.18493526287708, 37.091880063054148 ], [ -111.18472777041258, 37.092159829020268 ], [ -111.1845430110501, 37.09253420913668 ], [ -111.18438071144712, 37.092890525475283 ], [ -111.18418481593029, 37.093314500816881 ], [ -111.18389352038149, 37.093842287932169 ], [ -111.18360198157151, 37.09427091765928 ], [ -111.1833720805845, 37.094595787210253 ], [ -111.1830863164169, 37.095088408025894 ], [ -111.18282416474413, 37.09557468172553 ], [ -111.18253175828319, 37.096115988434391 ], [ -111.18235268076486, 37.09652190611196 ], [ -111.18215122437454, 37.096981943487528 ], [ -111.18192631683067, 37.097518637752238 ], [ -111.18176538893437, 37.09798762648537 ], [ -111.18158667943632, 37.098551292001723 ], [ -111.18131231217735, 37.099115103496231 ], [ -111.18113304947404, 37.099448905298566 ], [ -111.18092011001185, 37.099818815259525 ], [ -111.18054431919701, 37.100327792551752 ], [ -111.1802582269956, 37.100698714056762 ], [ -111.17991594597254, 37.101104875744682 ], [ -111.17951729608329, 37.101470557586786 ], [ -111.17897804222874, 37.101868000292221 ], [ -111.17843863473803, 37.102202340922126 ], [ -111.1775057407811, 37.102713046862128 ], [ -111.17709538656572, 37.102893945653982 ], [ -111.17654441648565, 37.103102095242861 ], [ -111.17593706830338, 37.103265254626628 ], [ -111.17531841138315, 37.10340589196695 ], [ -111.17466487447871, 37.103551084592134 ], [ -111.17395171858256, 37.103709882480068 ], [ -111.17327684468506, 37.103877634403105 ], [ -111.17257385254838, 37.104054437669383 ], [ -111.17188215217125, 37.104249248918613 ], [ -111.17133113762658, 37.104448360067835 ], [ -111.17066739447998, 37.10456650262163 ], [ -111.17004863653347, 37.104671055566996 ], [ -111.16954236049347, 37.104748401731037 ], [ -111.16900237029199, 37.104848329437957 ], [ -111.16840615647655, 37.104970870197427 ], [ -111.1680182374111, 37.105133677161362 ], [ -111.16779348657258, 37.105287237812732 ], [ -111.16754061845837, 37.105449852024968 ], [ -111.16724269156782, 37.105594500738654 ], [ -111.16697840841692, 37.105685015779763 ], [ -111.1665169136802, 37.105658621983743 ], [ -111.1660720255138, 37.105506003514172 ], [ -111.1656214039437, 37.105303812953487 ], [ -111.1651142308132, 37.104971894094248 ], [ -111.16449445601108, 37.104611283668653 ], [ -111.16413385917514, 37.104399948234153 ], [ -111.16368311352056, 37.104134650602234 ], [ -111.1629157402411, 37.103689501450134 ], [ -111.16238175086777, 37.103437834564069 ], [ -111.16184651495156, 37.10312757425249 ], [ -111.16114227134908, 37.102722891530604 ], [ -111.16060135188245, 37.102381083350053 ], [ -111.16026890193915, 37.102165190803433 ], [ -111.1596658760279, 37.101719798191013 ], [ -111.15914174744984, 37.10132838220855 ], [ -111.15876413093865, 37.101035924739612 ], [ -111.15841449228904, 37.100666807409496 ], [ -111.15811559250173, 37.100342692715962 ], [ -111.15782802375249, 37.100054619240041 ], [ -111.15759108182527, 37.09975836493895 ], [ -111.15728087774966, 37.099406318873001 ], [ -111.15705499630023, 37.099014497536459 ], [ -111.15682359262638, 37.098672261530666 ], [ -111.1565074379247, 37.098158865789564 ], [ -111.15614049022953, 37.097568914735589 ], [ -111.15590891038217, 37.09713653435923 ], [ -111.15566043492916, 37.096695161402081 ], [ -111.15533859615702, 37.096145712721558 ], [ -111.15498878550476, 37.095672921011008 ], [ -111.15467842877017, 37.095231626736883 ], [ -111.15433987020965, 37.094754311215752 ], [ -111.15409156682281, 37.094389555908286 ], [ -111.15379811795584, 37.093957251531258 ], [ -111.15354981068184, 37.093587987901131 ], [ -111.15333546367656, 37.09331783688738 ], [ -111.15313808788575, 37.093092734954055 ], [ -111.15288983191864, 37.092746005515167 ], [ -111.15263046123822, 37.092466896940813 ], [ -111.15247262715869, 37.092318364349062 ], [ -111.15197097939205, 37.091863787077152 ], [ -111.15164410040403, 37.091584762787669 ], [ -111.15132176062163, 37.091323760353916 ], [ -111.15085541056501, 37.091071954587939 ], [ -111.15030906519225, 37.090766162692738 ], [ -111.14973462009955, 37.090473925167487 ], [ -111.14923346922005, 37.090258214046713 ], [ -111.14862545323501, 37.090057057627085 ], [ -111.1482708132596, 37.08995744298592 ], [ -111.14794544918961, 37.089867706476845 ], [ -111.14721816499834, 37.089665790120343 ], [ -111.14656542649037, 37.089608005753433 ], [ -111.1459239065471, 37.089532175418434 ], [ -111.14529364172812, 37.089457229251146 ], [ -111.14461830626314, 37.089348981844203 ], [ -111.14423566752002, 37.08931429211431 ], [ -111.1439091840077, 37.089223644447799 ], [ -111.14316618065422, 37.089030736564396 ], [ -111.14275540383913, 37.088990667447163 ], [ -111.14206324174241, 37.088905862873602 ], [ -111.14149487880205, 37.088834428049203 ], [ -111.14093775226485, 37.08875396285935 ], [ -111.14045940769513, 37.08868241605758 ], [ -111.14016117094273, 37.088651218895755 ], [ -111.1396603485292, 37.08859321686284 ], [ -111.13914840670324, 37.08860734006096 ], [ -111.13855216480449, 37.088671138146005 ], [ -111.13810788159606, 37.088766306376478 ], [ -111.13753992242867, 37.088915702161948 ], [ -111.13698327799963, 37.089101139304994 ], [ -111.13662906375666, 37.089227747927858 ], [ -111.136201830495, 37.089422046522785 ], [ -111.13573522693973, 37.089624501498925 ], [ -111.13531918686714, 37.089788135520898 ], [ -111.13492013358214, 37.090013947328558 ], [ -111.13445930198471, 37.09030292784405 ], [ -111.13416719591723, 37.090560165797456 ], [ -111.13390896385648, 37.090884971912544 ], [ -111.13366198991119, 37.091214271903311 ], [ -111.13339267482311, 37.091638246471767 ], [ -111.13315133034855, 37.091972046170426 ], [ -111.13291561791347, 37.092310346189976 ], [ -111.13278654370993, 37.092499790713795 ], [ -111.13250048147883, 37.093004910456493 ], [ -111.13223674864385, 37.09341084748359 ], [ -111.13209663719297, 37.093726503458214 ], [ -111.13200694336504, 37.093915903219681 ], [ -111.13180522039868, 37.094393884423049 ], [ -111.13156415635669, 37.094898951735139 ], [ -111.13139600029547, 37.095268723586294 ], [ -111.13119417668015, 37.095692618093963 ], [ -111.13104298213744, 37.096111949155045 ], [ -111.13090860523818, 37.096496105753587 ], [ -111.13076301712074, 37.09690551451105 ], [ -111.13065658338262, 37.097180567228932 ], [ -111.13046018408731, 37.097491775947162 ], [ -111.13027509212725, 37.097835423291301 ], [ -111.13015742349769, 37.098123107845915 ], [ -111.12977027956714, 37.098768052691462 ], [ -111.12950116164461, 37.099336246061696 ], [ -111.12941705093039, 37.099507609054633 ], [ -111.12913545688302, 37.100021729517209 ], [ -111.12887301948021, 37.10055295556559 ], [ -111.12865997651969, 37.101013816103233 ], [ -111.12858708547363, 37.101167137749336 ], [ -111.12830687874488, 37.101843511439164 ], [ -111.12815573967346, 37.102312416819096 ], [ -111.12796530790085, 37.102839957115521 ], [ -111.12760634775407, 37.103538949594693 ], [ -111.12733697809428, 37.103976431048345 ], [ -111.12692711388303, 37.104526740638015 ], [ -111.12659563489622, 37.104842594244509 ], [ -111.12626976542863, 37.105149426672803 ], [ -111.12591574213194, 37.105447273828439 ], [ -111.1257134305812, 37.105610646651272 ], [ -111.12521447707805, 37.106065493425149 ], [ -111.12475246730676, 37.106404015230332 ], [ -111.12422961177641, 37.106702034806233 ], [ -111.12393165604047, 37.106882631823247 ], [ -111.12372926895989, 37.107004535706032 ], [ -111.1231220819364, 37.107356723905745 ], [ -111.1225430264027, 37.10770887990973 ], [ -111.12217192051362, 37.10789856231667 ], [ -111.1217275837692, 37.108043247461346 ], [ -111.12122122116627, 37.108111373160469 ], [ -111.12066970212214, 37.108093907194878 ], [ -111.1201462636237, 37.108040353175113 ], [ -111.11985918562722, 37.107991065285233 ], [ -111.11947635654336, 37.107887787658605 ], [ -111.11891332391185, 37.107703561307567 ], [ -111.11848535886696, 37.107523704515643 ], [ -111.11811366281681, 37.107339283004379 ], [ -111.11765191649027, 37.107145935443569 ], [ -111.11725204577037, 37.106934496383815 ], [ -111.11672820953802, 37.106615006920528 ], [ -111.11620439835984, 37.106309036492092 ], [ -111.11576516549567, 37.106111152345079 ], [ -111.11534289880159, 37.105967335640564 ], [ -111.11490937913007, 37.105823528333183 ], [ -111.11448152906844, 37.105706756753897 ], [ -111.11407054184525, 37.105576446010602 ], [ -111.11367083748303, 37.105464151551871 ], [ -111.11316421653117, 37.105351957827658 ], [ -111.11256756785502, 37.105244354567773 ], [ -111.11220737111009, 37.105208638905516 ], [ -111.11183589371949, 37.10515490425886 ], [ -111.11090732080957, 37.105101690819978 ], [ -111.11033325807047, 37.105043633640669 ], [ -111.10977043764174, 37.104976549008818 ], [ -111.10938210735095, 37.104940850801675 ], [ -111.10899371930067, 37.104864587180586 ], [ -111.10875728602888, 37.104801704410733 ], [ -111.10810991974894, 37.10463553248168 ], [ -111.10774401137769, 37.104536708598616 ], [ -111.10731056502605, 37.104428930457757 ], [ -111.10684335684412, 37.104321181155328 ], [ -111.10656751157485, 37.104240300983008 ], [ -111.10630291995908, 37.104158508652645 ], [ -111.10566113028639, 37.103948148420422 ], [ -111.10523442408675, 37.103826835268201 ], [ -111.10488879964134, 37.103741505954098 ], [ -111.10423693673991, 37.103566302548593 ], [ -111.10360083273481, 37.103391081785041 ], [ -111.10288029475464, 37.103193395216572 ], [ -111.10229485282072, 37.103027137735232 ], [ -111.10189068352788, 37.10291931448419 ], [ -111.1014448582675, 37.102798905519947 ], [ -111.10102271951939, 37.102717236057764 ], [ -111.10057922986164, 37.102659020303804 ], [ -111.10015042460903, 37.102641354702335 ], [ -111.09961029245262, 37.102691388142553 ], [ -111.0990927030463, 37.10276844309503 ], [ -111.09844580666851, 37.102935745904318 ], [ -111.09776516808317, 37.103121101544097 ], [ -111.09742207151336, 37.103243076553369 ], [ -111.09720271836092, 37.103324384986692 ], [ -111.09680341766438, 37.103500489873603 ], [ -111.09624108230203, 37.103798418468251 ], [ -111.09586433661276, 37.104015066078773 ], [ -111.09545946423202, 37.104240749399594 ], [ -111.09506021663604, 37.104466426821773 ], [ -111.09466090497503, 37.104642524475416 ], [ -111.09413785966893, 37.104872804676823 ], [ -111.09374971487833, 37.104981283387957 ], [ -111.0932658673007, 37.105058286207893 ], [ -111.09284947408321, 37.10507664152157 ], [ -111.09234869401509, 37.105113089657351 ], [ -111.09191539132438, 37.105108919192979 ], [ -111.09140891294024, 37.105086775044725 ], [ -111.09060971132782, 37.104974710110042 ], [ -111.0903237946811, 37.104929856912641 ], [ -111.09005811501983, 37.104866959123292 ], [ -111.08974967960232, 37.104813107373907 ], [ -111.08928140537259, 37.104736839610268 ], [ -111.08888179976516, 37.104674039944861 ], [ -111.08843710909397, 37.104552679826774 ], [ -111.08789105235829, 37.104363786206108 ], [ -111.08763209294386, 37.104269328053455 ], [ -111.08727183066472, 37.104162323958882 ], [ -111.08684963256472, 37.104022011353678 ], [ -111.08628676348619, 37.103887208248999 ], [ -111.08565186904067, 37.103752454515806 ], [ -111.0851948293963, 37.10364911967136 ], [ -111.08488526685233, 37.103586241793806 ], [ -111.0842830096623, 37.103446950219016 ], [ -111.08384397051169, 37.103334583095176 ], [ -111.08337119476219, 37.10324477374224 ], [ -111.08285902065302, 37.103145975769131 ], [ -111.08255506960016, 37.103065059339229 ], [ -111.08213293686786, 37.102971604066802 ], [ -111.0816939704147, 37.10292142738664 ], [ -111.08092860171429, 37.102840823774592 ], [ -111.08023637695993, 37.102751151479666 ], [ -111.07957797746479, 37.102720045207676 ], [ -111.07920090332433, 37.102661704899084 ], [ -111.07852563315494, 37.102639618321021 ], [ -111.07795168267785, 37.102649011284107 ], [ -111.0773609012974, 37.102707990941838 ], [ -111.0766868565979, 37.102785050074765 ], [ -111.0759374797347, 37.10293426780887 ], [ -111.07530751468093, 37.103205097680451 ], [ -111.07488009477832, 37.103448753654469 ], [ -111.07422764393215, 37.103751141910493 ], [ -111.07369898980753, 37.104057956820149 ], [ -111.0732941598685, 37.104396242827086 ], [ -111.07296240658975, 37.104657861211138 ], [ -111.07263068115265, 37.10495102857724 ], [ -111.07222028292362, 37.105361428420672 ], [ -111.0717029108031, 37.105717805952182 ], [ -111.07142732621853, 37.105880229078231 ], [ -111.07099993353754, 37.10618246368221 ], [ -111.07023503430814, 37.106633632507979 ], [ -111.069936958675, 37.106823108263555 ], [ -111.06953197368547, 37.107026167401564 ], [ -111.06922262766484, 37.107202126561774 ], [ -111.06866571496039, 37.107423299855476 ], [ -111.06833379083537, 37.10752715564611 ], [ -111.06766430440905, 37.10772585338924 ], [ -111.06695535092571, 37.10784344126612 ], [ -111.066330775567, 37.107924920676346 ], [ -111.06584118364565, 37.107920686414715 ], [ -111.06539094128824, 37.107866849986607 ], [ -111.06492940236285, 37.107763439582584 ], [ -111.06445658691524, 37.107632990717512 ], [ -111.06392190179645, 37.107538630390678 ], [ -111.06357293017122, 37.10745318249127 ], [ -111.063235236626, 37.107394770343305 ], [ -111.06276802773142, 37.107232761817542 ], [ -111.06239648638197, 37.107070701141851 ], [ -111.06208121667346, 37.106904102715802 ], [ -111.06182224393571, 37.106764516904796 ], [ -111.06161280745586, 37.106642933327095 ], [ -111.06116342204434, 37.106242031134514 ], [ -111.06094373972246, 37.105971716245222 ], [ -111.06084330692468, 37.105638239935203 ], [ -111.06070679870879, 37.105227259290722 ], [ -111.06062768745046, 37.104813544846536 ], [ -111.06051477735444, 37.104353874800111 ], [ -111.06046961656531, 37.104173612447518 ], [ -111.06042444883076, 37.103984335805698 ], [ -111.060277757031, 37.103497639865466 ], [ -111.06019869485576, 37.103140714896973 ], [ -111.06009149238433, 37.102776592700224 ], [ -111.05990663351145, 37.102407101077823 ], [ -111.05975333373306, 37.102096186019004 ], [ -111.05952236857264, 37.101767281208502 ], [ -111.05921820218492, 37.101370805452859 ], [ -111.05889152425108, 37.100965325796707 ], [ -111.05868307737084, 37.10064091523806 ], [ -111.05846335425298, 37.100284959889578 ], [ -111.05827182271385, 37.100001104471431 ], [ -111.05790017534444, 37.099640715459572 ], [ -111.05762430332646, 37.09943352146928 ], [ -111.05730908251246, 37.099275924377814 ], [ -111.05694887560742, 37.09915440516663 ], [ -111.05657180288119, 37.099050921461028 ], [ -111.05623978210944, 37.098996993724334 ], [ -111.05567706427378, 37.098944075025614 ], [ -111.05521000119332, 37.098889306304144 ], [ -111.05492864585973, 37.098866901268046 ], [ -111.05423656159678, 37.098880741242262 ], [ -111.05356246691443, 37.098872033357971 ], [ -111.05315622598113, 37.098890244710816 ], [ -111.05262844634051, 37.098908508674093 ], [ -111.05224474616543, 37.098976285427604 ], [ -111.05180595490414, 37.099120706381129 ], [ -111.05109141804779, 37.099220173444934 ], [ -111.05049506932346, 37.099360150182996 ], [ -111.04997182570818, 37.099436993193777 ], [ -111.04940921723836, 37.099550808840185 ], [ -111.04906039674557, 37.099617659318803 ], [ -111.04840780997669, 37.099816241606241 ], [ -111.04807591978354, 37.099965112191953 ], [ -111.04764279538796, 37.100195151048553 ], [ -111.04722657703618, 37.100470252962808 ], [ -111.04684975521053, 37.100763366396805 ], [ -111.04646841241022, 37.101029437566304 ], [ -111.04614672638768, 37.101318019984028 ], [ -111.04579245025509, 37.101687742572814 ], [ -111.04552818406182, 37.102025879599012 ], [ -111.04526955650574, 37.102387450975066 ], [ -111.04511218537898, 37.102701207642674 ], [ -111.04493799718836, 37.103125846005149 ], [ -111.04470752201242, 37.103527068211626 ], [ -111.04458950560793, 37.103788526510918 ], [ -111.04442215095459, 37.104360995499981 ], [ -111.04423005756355, 37.104974037639671 ], [ -111.04414582171277, 37.105271539904088 ], [ -111.04409529660785, 37.105478886879638 ], [ -111.04386601070435, 37.106010813732937 ], [ -111.0435443814813, 37.106452631374921 ], [ -111.04329137427412, 37.106844844614137 ], [ -111.04291456166432, 37.107237102160703 ], [ -111.0424589636812, 37.107633893855088 ], [ -111.04200328627583, 37.107895469832087 ], [ -111.04139005625422, 37.108193156205722 ], [ -111.04084432955976, 37.108450251973203 ], [ -111.04035484317427, 37.108648733377919 ], [ -111.0399441181971, 37.108806622064087 ], [ -111.03942084749806, 37.108977166762884 ], [ -111.03880753470777, 37.109149541504813 ], [ -111.03803663363793, 37.109294019513072 ], [ -111.03732196766688, 37.109361853587032 ], [ -111.03665793110062, 37.109393610660732 ], [ -111.03598264311704, 37.109434381693163 ], [ -111.03539738497209, 37.109452586380641 ], [ -111.03493030128182, 37.109461739162413 ], [ -111.03447448486659, 37.109497929616452 ], [ -111.03385546647061, 37.109529657897831 ], [ -111.03343342051367, 37.109579356096006 ], [ -111.03293821354595, 37.109624566006566 ], [ -111.03237546159257, 37.109638242392656 ], [ -111.03195903975003, 37.109683426675375 ], [ -111.03140755723649, 37.109733152478704 ], [ -111.03082795249743, 37.109823447211426 ], [ -111.03029898758555, 37.109895697656384 ], [ -111.02980378904918, 37.109972444389179 ], [ -111.02932548276524, 37.110076227661722 ], [ -111.02880778184603, 37.110180018581026 ], [ -111.02840825797681, 37.110279271852626 ], [ -111.02809876520271, 37.110351459691202 ], [ -111.0276767174711, 37.110419165916497 ], [ -111.02717589167371, 37.110513931504151 ], [ -111.02653437651664, 37.110617740803868 ], [ -111.02608980601089, 37.110658403633423 ], [ -111.02554957848787, 37.110739649620577 ], [ -111.0249361812847, 37.1107938657739 ], [ -111.02428225967832, 37.110834565668569 ], [ -111.02375440984925, 37.110915800939189 ], [ -111.0231860313574, 37.110969999009662 ], [ -111.02250510643378, 37.111051258551697 ], [ -111.02177916757469, 37.111164072370173 ], [ -111.0211263916664, 37.111294897249032 ], [ -111.02047924728998, 37.111448253208572 ], [ -111.01983772802616, 37.111601604691423 ], [ -111.01917932410444, 37.111759462561764 ], [ -111.01862221910774, 37.111926315164759 ], [ -111.01820018222936, 37.112111173007584 ], [ -111.01762622992491, 37.112453801546707 ], [ -111.0172830045645, 37.112760336849462 ], [ -111.01698480312363, 37.113084893216758 ], [ -111.01666973433589, 37.113495086629143 ], [ -111.01633214960353, 37.113900775151748 ], [ -111.01575821086705, 37.114414665399885 ], [ -111.01528553884725, 37.114784311738319 ], [ -111.01473406342753, 37.115117908971655 ], [ -111.01433451392337, 37.115316271542206 ], [ -111.01390682309012, 37.115519143190859 ], [ -111.0133609374041, 37.115699491034569 ], [ -111.01272947951817, 37.115740124651929 ], [ -111.01240417332998, 37.115703200692586 ], [ -111.01217342073041, 37.11568159040096 ], [ -111.01156556785942, 37.115510380434245 ], [ -111.01111530635892, 37.11537070256577 ], [ -111.01078323806786, 37.115257153630559 ], [ -111.01034423130277, 37.115086823338629 ], [ -111.00988833603122, 37.114866012999492 ], [ -111.00947746700275, 37.114645197308398 ], [ -111.00872891506026, 37.114343277227 ], [ -111.00836871294291, 37.114208990788825 ], [ -111.00771021089496, 37.11385657802802 ], [ -111.00718678975953, 37.11356815470112 ], [ -111.00647201922639, 37.113203118461939 ], [ -111.00584730649854, 37.112914694675297 ], [ -111.00522259727094, 37.112608239066333 ], [ -111.00469357000031, 37.11237839759923 ], [ -111.00444594206955, 37.112283757427321 ], [ -111.00370306482804, 37.112058426483415 ], [ -111.00310088975057, 37.111936751262448 ], [ -111.00243118328655, 37.111801552995409 ], [ -111.00181212908738, 37.111679871568754 ], [ -111.00120996089282, 37.111612272295076 ], [ -111.00083290301615, 37.111585232763993 ], [ -111.00051775012467, 37.111526641870071 ], [ -111.0002532471635, 37.111472557170515 ], [ -110.99968484845994, 37.111355371641508 ], [ -110.9993359311557, 37.111301284639644 ], [ -110.9987393962305, 37.111211137195156 ], [ -110.99810909479426, 37.111193100297896 ], [ -110.99752381431848, 37.111202103779931 ], [ -110.99682597998464, 37.111206594283139 ], [ -110.99616753857332, 37.111228209053763 ], [ -110.99548658669056, 37.111238100774713 ], [ -110.99472684504515, 37.111274126461844 ], [ -110.99402338147853, 37.111287614480219 ], [ -110.99350450590428, 37.111305615710876 ], [ -110.99322424552402, 37.11131461428657 ], [ -110.99254329257579, 37.111323587677767 ], [ -110.99195800996453, 37.111337070815679 ], [ -110.9912657991861, 37.111364064626216 ], [ -110.99067488556732, 37.111400076665461 ], [ -110.98996465616447, 37.111494668410614 ], [ -110.98966750417149, 37.111557742707099 ], [ -110.98947052769789, 37.111602796677111 ], [ -110.98905969020956, 37.111697409207416 ], [ -110.98869950134382, 37.111792025150621 ], [ -110.98837870373276, 37.111900165254347 ], [ -110.98805790167084, 37.112030840135318 ], [ -110.98768644350788, 37.11219305880136 ], [ -110.98738252384969, 37.112314719341818 ], [ -110.98710111206957, 37.112449902939048 ], [ -110.98675214609719, 37.112697756562881 ], [ -110.98666208935565, 37.112765353401244 ], [ -110.98632437697268, 37.113008699889242 ], [ -110.98597540673593, 37.113252044074066 ], [ -110.98557015647853, 37.113490873257149 ], [ -110.98519866921092, 37.113738719521287 ], [ -110.98481029041845, 37.114013605216165 ], [ -110.98448944848992, 37.114265962841074 ], [ -110.98412356115136, 37.114612963242692 ], [ -110.983746418189, 37.114942833868405 ], [ -110.98345370895534, 37.115194291078026 ], [ -110.98317224761878, 37.115473693337755 ], [ -110.98287390925591, 37.115712528339188 ], [ -110.98257556798612, 37.11595586970617 ], [ -110.9822490729115, 37.11624878448977 ], [ -110.98205202670198, 37.116519182395628 ], [ -110.98187748722573, 37.11680761190722 ], [ -110.98174231087209, 37.117231260983196 ], [ -110.98169155993244, 37.11763689444075 ], [ -110.98169145335729, 37.118079494104251 ], [ -110.9817926781288, 37.118425656873249 ], [ -110.98193891465567, 37.118835827566613 ], [ -110.98219208287614, 37.119277564028728 ], [ -110.9824891539334, 37.119723813533625 ], [ -110.98277162130077, 37.120052874932789 ], [ -110.98296855800355, 37.120300795168006 ], [ -110.98312048290983, 37.120485608943476 ], [ -110.98346935338974, 37.120895806283919 ], [ -110.98377320201904, 37.121296982171351 ], [ -110.98404888029022, 37.121846888495114 ], [ -110.98412763763923, 37.12204521243109 ], [ -110.98431891636106, 37.122482428690944 ], [ -110.98447643235382, 37.122888090345498 ], [ -110.98456640219413, 37.123317180017928 ], [ -110.98463385983256, 37.123739956706565 ], [ -110.98462250958966, 37.124199681516892 ], [ -110.98457739346557, 37.124627852063327 ], [ -110.98431277163354, 37.12498387980564 ], [ -110.98407627762015, 37.12540391181161 ], [ -110.98353578935819, 37.125997876278333 ], [ -110.9828264253966, 37.126601729537633 ], [ -110.98226345255669, 37.126984751698835 ], [ -110.98183561051528, 37.127187507228015 ], [ -110.98125579075452, 37.127371307379271 ], [ -110.98034387981446, 37.127489246173894 ], [ -110.97950406129237, 37.127439525659767 ], [ -110.97867775953614, 37.127367266039059 ], [ -110.97809802662296, 37.127218425464008 ], [ -110.97728753929221, 37.126979395705803 ], [ -110.97652095091077, 37.126776426045794 ], [ -110.975559626426, 37.126519326015519 ], [ -110.97464782663432, 37.126308201390316 ], [ -110.97359531575096, 37.126086221404286 ], [ -110.97236831558111, 37.125873205763774 ], [ -110.97147228788425, 37.125675581726952 ], [ -110.97072484338739, 37.12553117170161 ], [ -110.96982991969756, 37.125409255117262 ], [ -110.96908133870009, 37.125305398508907 ], [ -110.96850158617086, 37.125287217415178 ], [ -110.96799503973845, 37.125192432243672 ], [ -110.96775189774721, 37.125147295161767 ], [ -110.96755495389459, 37.125003013605607 ], [ -110.96724099977224, 37.124705457376614 ], [ -110.9670215511249, 37.124543140224112 ], [ -110.96670080711122, 37.124335723053399 ], [ -110.96615493086583, 37.124101198230129 ], [ -110.96544579695559, 37.123934230218246 ], [ -110.96473778352552, 37.123785286775401 ], [ -110.96419523926505, 37.123667939032998 ], [ -110.96356038103488, 37.12356408182935 ], [ -110.96299191350815, 37.12351883453497 ], [ -110.96242904853138, 37.123527671736831 ], [ -110.96180426422562, 37.123545500574593 ], [ -110.96118506221133, 37.123653470356345 ], [ -110.9605546011948, 37.123761433156147 ], [ -110.96006484706207, 37.123882961441964 ], [ -110.95932852120148, 37.124071108746513 ], [ -110.95862367196101, 37.124333179226781 ], [ -110.95804375774563, 37.124625938197319 ], [ -110.95771153232914, 37.124864697492505 ], [ -110.9575256843427, 37.125044915829037 ], [ -110.95713713507322, 37.125342245852231 ], [ -110.95683868134215, 37.125572000638442 ], [ -110.95661342044764, 37.125765724522985 ], [ -110.95638811185728, 37.126040576089224 ], [ -110.95602753806459, 37.126612846920324 ], [ -110.95561617262348, 37.127401439235634 ], [ -110.95521601139383, 37.128266655235215 ], [ -110.95484404773657, 37.129028216826775 ], [ -110.95448331856052, 37.129816824158802 ], [ -110.9540267640005, 37.130808213334575 ], [ -110.95384643430272, 37.131132655524368 ], [ -110.95365488041074, 37.131398500547292 ], [ -110.95323810417342, 37.131749891789497 ], [ -110.95252850224033, 37.132263420740024 ], [ -110.95158807259745, 37.132803894033323 ], [ -110.9513515269182, 37.13298408172394 ], [ -110.95097976307873, 37.133339990502925 ], [ -110.95076454447468, 37.133614835188624 ], [ -110.95064164602053, 37.13388971794592 ], [ -110.95061330582843, 37.134187175555809 ], [ -110.95064118053148, 37.134606348586289 ], [ -110.95078161255758, 37.135075146594644 ], [ -110.95097282227525, 37.135372695184415 ], [ -110.95122032274627, 37.13567928085039 ], [ -110.95159160878198, 37.136089580147832 ], [ -110.95199097546097, 37.136612567391914 ], [ -110.95236773311571, 37.137288785901077 ], [ -110.95278949285895, 37.138032627709208 ], [ -110.95305934155733, 37.13864119460235 ], [ -110.95335719953728, 37.139484141476665 ], [ -110.9534808092386, 37.139885322669478 ], [ -110.95371689636056, 37.140484860409224 ], [ -110.95396995120063, 37.14096181089721 ], [ -110.95430063070023, 37.141557778376864 ], [ -110.95464488170482, 37.142062706523014 ], [ -110.95520739586399, 37.142883213712857 ], [ -110.95538171529614, 37.143243847900784 ], [ -110.95568530501943, 37.143987634133516 ], [ -110.95587060937528, 37.144830531810911 ], [ -110.95596593841248, 37.145493111543026 ], [ -110.95606129517958, 37.146110620102952 ], [ -110.9561341400042, 37.146714598884628 ], [ -110.95612817645089, 37.147291505802478 ], [ -110.95606581225016, 37.148035154538441 ], [ -110.95581750004257, 37.149021216017175 ], [ -110.95578814433469, 37.149153713838494 ], [ -110.95574975816845, 37.149323166504885 ], [ -110.95569898834714, 37.149486304585061 ], [ -110.95561440661443, 37.149698106667145 ], [ -110.95554111191436, 37.149864841912176 ], [ -110.95541708356153, 37.150130714238557 ], [ -110.95509021694909, 37.150626371831876 ], [ -110.95448173793324, 37.151248119445171 ], [ -110.9539352687289, 37.151734675017842 ], [ -110.95368740819197, 37.151914862378945 ], [ -110.95273551268437, 37.152405760346639 ], [ -110.95229618717492, 37.15260840375992 ], [ -110.9517330309761, 37.15273437450567 ], [ -110.95092209244312, 37.152900804110388 ], [ -110.9501630631092, 37.152900487377984 ], [ -110.94982411687505, 37.15285978048891 ], [ -110.94956513699462, 37.152805585391647 ], [ -110.94925552271786, 37.152688268687236 ], [ -110.94900223512779, 37.152543932832621 ], [ -110.94834378326399, 37.152034345568453 ], [ -110.94774718777286, 37.151655487759562 ], [ -110.94727439454006, 37.151389359540872 ], [ -110.94687471414979, 37.151250362415787 ], [ -110.9464187618122, 37.151064464682371 ], [ -110.94618237374188, 37.150924637503493 ], [ -110.94554643522078, 37.150473637086876 ], [ -110.94471916666167, 37.149882824040702 ], [ -110.94420699456607, 37.149598636739377 ], [ -110.94358230305851, 37.149197209091987 ], [ -110.94312082433572, 37.148899519883663 ], [ -110.94277754139152, 37.148664985401176 ], [ -110.94215282736116, 37.148313128265187 ], [ -110.94154492364265, 37.148073953646524 ], [ -110.9404911204083, 37.147803003157144 ], [ -110.93987297357734, 37.147712549160396 ], [ -110.93890451289001, 37.147752617834939 ], [ -110.93798669168548, 37.147833269015074 ], [ -110.93698999119611, 37.147976069179414 ], [ -110.93613392556959, 37.148264065478969 ], [ -110.93581733813156, 37.148449587033916 ], [ -110.93561000383404, 37.148607223113856 ], [ -110.93532255474946, 37.148954113366031 ], [ -110.93510836902486, 37.149219915226219 ], [ -110.93461809974752, 37.149701905519088 ], [ -110.93367162931023, 37.150318852310406 ], [ -110.93287735784665, 37.150724044104756 ], [ -110.93232530021309, 37.151012184519516 ], [ -110.9319984850066, 37.15127791629763 ], [ -110.93139549063073, 37.151846364638473 ], [ -110.93056811330689, 37.1527103442317 ], [ -110.92996958153822, 37.153300421851426 ], [ -110.92940596432155, 37.153876995896596 ], [ -110.92916928272953, 37.154076068357888 ], [ -110.92902840659929, 37.154187760076731 ], [ -110.92857758900553, 37.15455707116184 ], [ -110.92827322227826, 37.154872384077343 ], [ -110.92783911333036, 37.155427394755591 ], [ -110.92737116197682, 37.156034665357275 ], [ -110.92716254649139, 37.15631397721701 ], [ -110.92712871271664, 37.156363534461605 ], [ -110.92685687997914, 37.156796048093135 ], [ -110.9265701984102, 37.15744038528775 ], [ -110.92615823274478, 37.15835957641665 ], [ -110.92587609711356, 37.158949829475795 ], [ -110.92556572119149, 37.159621191729926 ], [ -110.92533989743829, 37.160203365971334 ], [ -110.92522689458774, 37.160585496100161 ], [ -110.92509112404056, 37.161211896045444 ], [ -110.92500022020708, 37.162023114879254 ], [ -110.92488141106475, 37.162577411723667 ], [ -110.92483049105246, 37.162816255200298 ], [ -110.92481302062758, 37.163397658671627 ], [ -110.92483480153278, 37.164150356360814 ], [ -110.92483444448169, 37.164510923224967 ], [ -110.92488481256554, 37.164830958435552 ], [ -110.92495768554124, 37.165173543300497 ], [ -110.92523847535085, 37.165980489469185 ], [ -110.92559200300619, 37.167278752997369 ], [ -110.92597371561688, 37.168563511545003 ], [ -110.92636136179307, 37.169550804694836 ], [ -110.92649055322794, 37.169906944585826 ], [ -110.9265916509346, 37.17019546065238 ], [ -110.92663186626282, 37.170542531031913 ], [ -110.92664143762831, 37.171128457841647 ], [ -110.92654466615895, 37.17218756242243 ], [ -110.92652113440619, 37.173223275344775 ], [ -110.9264415212849, 37.174008359565818 ], [ -110.92626512202231, 37.174697833330796 ], [ -110.92584823110812, 37.175946034423937 ], [ -110.92551037728423, 37.176995972019952 ], [ -110.92543021764764, 37.177176204758588 ], [ -110.92527219466544, 37.177491600718383 ], [ -110.92506913161122, 37.177784432584907 ], [ -110.92462387661534, 37.178063589036981 ], [ -110.92416180144166, 37.178261605633722 ], [ -110.92347999953218, 37.178509056585064 ], [ -110.92258414610218, 37.178760871022689 ], [ -110.92207141788894, 37.178909268483388 ], [ -110.92173343680668, 37.178927074030696 ], [ -110.92132228174505, 37.178895252197869 ], [ -110.92042691299349, 37.178673807499365 ], [ -110.91983566624384, 37.178497632946396 ], [ -110.91916112124869, 37.178262806628524 ], [ -110.91836054504951, 37.177901691511764 ], [ -110.91732479385853, 37.177301531957951 ], [ -110.91676757210043, 37.176932462830301 ], [ -110.91577693289729, 37.176308884528531 ], [ -110.91520854258675, 37.175866785388251 ], [ -110.91447132364044, 37.175301969180396 ], [ -110.91419554716963, 37.175113373862942 ], [ -110.91378469765175, 37.174833636677995 ], [ -110.91293482003512, 37.174296672702503 ], [ -110.91242829737112, 37.173958268395467 ], [ -110.911735944322, 37.173592681147831 ], [ -110.91104926087729, 37.173200953019716 ], [ -110.91057192588796, 37.172960817009667 ], [ -110.90994033882531, 37.172662871289809 ], [ -110.90957439881167, 37.172531887234847 ], [ -110.90885932178097, 37.172351056129919 ], [ -110.90784564821269, 37.172246609266303 ], [ -110.90708537694414, 37.172182916432128 ], [ -110.90649962746836, 37.172182455702043 ], [ -110.90588014067008, 37.172136894464366 ], [ -110.90470867644166, 37.172108915729702 ], [ -110.90363846103777, 37.172184670677495 ], [ -110.90293423350012, 37.172341843785809 ], [ -110.90252279213027, 37.172566860135262 ], [ -110.90226346089493, 37.172759549616075 ], [ -110.9019644556102, 37.173143305950823 ], [ -110.90164274398006, 37.173661353667853 ], [ -110.90139426026469, 37.174170447260835 ], [ -110.90128116755351, 37.174512891196215 ], [ -110.90125136887421, 37.174904982323397 ], [ -110.9012632792397, 37.175274572780751 ], [ -110.90128535746886, 37.175621636288561 ], [ -110.90131306838305, 37.175968704463244 ], [ -110.90135199183173, 37.176356345654781 ], [ -110.90142471679462, 37.176739507854251 ], [ -110.90162083309677, 37.177528409511922 ], [ -110.90184539082765, 37.178105501672107 ], [ -110.90224952435038, 37.179205562534875 ], [ -110.90255229637049, 37.180292017277026 ], [ -110.90269787645079, 37.180972705313671 ], [ -110.90288859164025, 37.181599345198443 ], [ -110.90297765743151, 37.182428719860447 ], [ -110.90301647161495, 37.182911008549333 ], [ -110.90290877537159, 37.183433740882677 ], [ -110.90287486170362, 37.183523854554579 ], [ -110.90265459442035, 37.18397438110479 ], [ -110.9023666923305, 37.184451893932518 ], [ -110.9019208776825, 37.185068994644737 ], [ -110.90161502826908, 37.185478884618384 ], [ -110.90144122138321, 37.185713107894387 ], [ -110.90105204773387, 37.186082363384159 ], [ -110.90081511108359, 37.186342673990225 ], [ -110.90049364173258, 37.186627251329035 ], [ -110.89986784210355, 37.187009825113435 ], [ -110.89902793944994, 37.187414748646454 ], [ -110.89796245063725, 37.187999754920298 ], [ -110.89684055599515, 37.188625266068271 ], [ -110.89549322323921, 37.189309159770659 ], [ -110.89433744379656, 37.18996616663491 ], [ -110.89331704666273, 37.190483565024735 ], [ -110.89248242943805, 37.191082250519969 ], [ -110.89160253009803, 37.191820607709452 ], [ -110.89084655539132, 37.192559072498327 ], [ -110.89064904382046, 37.192788750722073 ], [ -110.89042893092029, 37.193063478361893 ], [ -110.89019723559349, 37.193554533976403 ], [ -110.88992597615255, 37.19413118657274 ], [ -110.8895868566559, 37.194879043704333 ], [ -110.88937149309574, 37.195753213170576 ], [ -110.88921230008283, 37.196740111221708 ], [ -110.88910364497976, 37.197839732756307 ], [ -110.88896135978003, 37.198817631820141 ], [ -110.88894396204799, 37.199155645084652 ], [ -110.88889779851117, 37.199899266791348 ], [ -110.8889585804442, 37.200715101631168 ], [ -110.88899690532993, 37.201476830579324 ], [ -110.88916494161347, 37.202157553792134 ], [ -110.8893724354193, 37.202829299428068 ], [ -110.88967563461392, 37.203559725543172 ], [ -110.88996761625965, 37.204258590978483 ], [ -110.89009680002157, 37.20454265548225 ], [ -110.89020358987364, 37.204727543833265 ], [ -110.89046794810903, 37.205052296628075 ], [ -110.89104177483679, 37.205683813675428 ], [ -110.89161568202016, 37.206265750345246 ], [ -110.89207717712407, 37.20665467986219 ], [ -110.89232481350064, 37.206861328339322 ], [ -110.89259605349611, 37.207113068244901 ], [ -110.89332100862096, 37.207687020684915 ], [ -110.89388389326605, 37.208115696422624 ], [ -110.89434557590234, 37.208386532349877 ], [ -110.89464510163015, 37.208567081280925 ], [ -110.89511132887245, 37.208815382979921 ], [ -110.89548861406978, 37.209000505647928 ], [ -110.89569695796209, 37.209108858565799 ], [ -110.89601784696315, 37.209329986296829 ], [ -110.89659764561439, 37.209772185043491 ], [ -110.89699731997619, 37.210074505798303 ], [ -110.89722803794318, 37.210309072935914 ], [ -110.89741366469616, 37.210552614678882 ], [ -110.89757673407095, 37.210809657776316 ], [ -110.89778455092302, 37.2113146271207 ], [ -110.89802610865219, 37.211873709728771 ], [ -110.89813273426341, 37.212202816222494 ], [ -110.89820562829384, 37.21247330195628 ], [ -110.89826680339988, 37.213078200732205 ], [ -110.89828820211063, 37.213929150198886 ], [ -110.8982425809404, 37.214330238447317 ], [ -110.89814064803264, 37.21469972889453 ], [ -110.89802197174301, 37.214947514490582 ], [ -110.89788075307207, 37.215195280524597 ], [ -110.89749662506976, 37.215875513086111 ], [ -110.89706758984585, 37.216420493864845 ], [ -110.89665004699772, 37.216798722301128 ], [ -110.89623254936552, 37.217140892899039 ], [ -110.89532435476735, 37.217771080384836 ], [ -110.89445557569712, 37.218414817097695 ], [ -110.8942186270952, 37.218594887574277 ], [ -110.89378990673526, 37.218887461915834 ], [ -110.89327670476412, 37.219139395186637 ], [ -110.89271849028017, 37.219337200912499 ], [ -110.89213206218433, 37.219557513535371 ], [ -110.89145555570441, 37.219710135051017 ], [ -110.89050848506312, 37.219894052209803 ], [ -110.88998986525098, 37.219983712558268 ], [ -110.88929089324027, 37.220077709242425 ], [ -110.88884560981079, 37.220116954198062 ], [ -110.88832132284298, 37.220225531504319 ], [ -110.88757707302337, 37.220445672616414 ], [ -110.88637044619203, 37.220823112910061 ], [ -110.88542326758116, 37.22106107377931 ], [ -110.88438008780261, 37.22142062356663 ], [ -110.88303921886798, 37.221847476196388 ], [ -110.88210752401693, 37.222261200457623 ], [ -110.88185937467222, 37.222369122229011 ], [ -110.88069751385753, 37.222913309778065 ], [ -110.88021805712529, 37.223165220231344 ], [ -110.87964830647846, 37.223489149684944 ], [ -110.87894754275665, 37.223970689000453 ], [ -110.87824887241582, 37.224546874137779 ], [ -110.87763935160771, 37.225055541615859 ], [ -110.87687834834257, 37.225825456856015 ], [ -110.87626188256175, 37.226433264769824 ], [ -110.87581574811212, 37.226964628460991 ], [ -110.87568585491344, 37.227122238557882 ], [ -110.87551641079517, 37.22733839844814 ], [ -110.87530146701033, 37.227802397307521 ], [ -110.87525048757182, 37.227955582924785 ], [ -110.87512591571202, 37.228302493583108 ], [ -110.87506918023081, 37.228527785645454 ], [ -110.87504039588505, 37.228892825331847 ], [ -110.87505694075868, 37.229113687623048 ], [ -110.87506196000611, 37.229487777009091 ], [ -110.87515149689017, 37.229879983644253 ], [ -110.87534253654248, 37.230245254848164 ], [ -110.87570252637578, 37.230700843884684 ], [ -110.87584852985572, 37.231034517698596 ], [ -110.87594401935526, 37.231237434375693 ], [ -110.87625873301832, 37.231810157137566 ], [ -110.87649480997865, 37.232216036735515 ], [ -110.87690512725054, 37.232929476833007 ], [ -110.87732683823498, 37.233573518906717 ], [ -110.8776977653708, 37.234254464655564 ], [ -110.87822064806593, 37.235088804645819 ], [ -110.8787717919171, 37.235882607860113 ], [ -110.87912033929334, 37.236473385355801 ], [ -110.87942959802059, 37.236960460051023 ], [ -110.8797558649444, 37.237388959765759 ], [ -110.88004847018182, 37.237718269780075 ], [ -110.88054925945694, 37.23829567591649 ], [ -110.88130895585421, 37.239134747407199 ], [ -110.88198420882459, 37.239910631381925 ], [ -110.88264945426576, 37.240605374977186 ], [ -110.88317744598523, 37.241115191271007 ], [ -110.88369549146245, 37.241498798611978 ], [ -110.8843092537322, 37.241963623719663 ], [ -110.88489371578316, 37.242423910110588 ], [ -110.8854690899885, 37.242933762097572 ], [ -110.88695529353129, 37.244332368500849 ], [ -110.887214299257, 37.244548952731748 ], [ -110.88746164256348, 37.245026932808237 ], [ -110.88760780569662, 37.245306507218956 ], [ -110.8878767106676, 37.245694366328223 ], [ -110.88806348131911, 37.245964964539567 ], [ -110.88816463338071, 37.246185904340393 ], [ -110.88840581859716, 37.247024438459995 ], [ -110.88852886696499, 37.247691593918766 ], [ -110.88855105980852, 37.247934994089064 ], [ -110.88842080477875, 37.248331489487946 ], [ -110.88832463515087, 37.248552242967158 ], [ -110.88816062366638, 37.248899128944643 ], [ -110.88792316400198, 37.249349606696263 ], [ -110.88742028752969, 37.25008828129738 ], [ -110.88720004958049, 37.250326943856919 ], [ -110.88683299897059, 37.250714197484363 ], [ -110.88616122427739, 37.251276931197111 ], [ -110.88540496325518, 37.251776481015305 ], [ -110.88460922513833, 37.252275987489462 ], [ -110.88345255561075, 37.252824711071568 ], [ -110.8821944090713, 37.253355294296455 ], [ -110.88112254886563, 37.253732812626225 ], [ -110.87990980646336, 37.254056094196073 ], [ -110.87841500763106, 37.254460200353648 ], [ -110.87692029552738, 37.254801189440677 ], [ -110.87569086963995, 37.254962157735513 ], [ -110.87539759341098, 37.255011426666663 ], [ -110.87499706128126, 37.255137200985239 ], [ -110.87472632995879, 37.255190999067963 ], [ -110.8743541808017, 37.255200520183301 ], [ -110.87377907560681, 37.255194500089921 ], [ -110.87352531109708, 37.255216764389033 ], [ -110.87269052054272, 37.255400657469288 ], [ -110.87166389027686, 37.255660956168327 ], [ -110.87140445453898, 37.255701237839197 ], [ -110.87070509126414, 37.255817658652852 ], [ -110.86963941438897, 37.255825504192423 ], [ -110.8687835022055, 37.25582455875594 ], [ -110.86830881000695, 37.2557879756123 ], [ -110.86797618272045, 37.255765070107365 ], [ -110.86740672646818, 37.255750912728601 ], [ -110.86660028225198, 37.25583564021256 ], [ -110.86610961206257, 37.255907198647854 ], [ -110.86550058358337, 37.255950677157678 ], [ -110.86482376116142, 37.256067990224473 ], [ -110.86411295378113, 37.25626999232415 ], [ -110.86328340086277, 37.256656640745362 ], [ -110.86298539521742, 37.256818548838247 ], [ -110.86274148686957, 37.256997645559309 ], [ -110.862426333673, 37.257285728783373 ], [ -110.86196165258771, 37.257939606530769 ], [ -110.86143614226229, 37.258551946671631 ], [ -110.86104560370848, 37.25935373746475 ], [ -110.86072957121603, 37.260110544386876 ], [ -110.86064863927892, 37.26057827709576 ], [ -110.86063118152281, 37.260872113766844 ], [ -110.86060247257444, 37.261151514735261 ], [ -110.86053409211141, 37.261539037246791 ], [ -110.86049917011508, 37.262129414640462 ], [ -110.86053776974781, 37.262602696302082 ], [ -110.86063812434806, 37.263224781974351 ], [ -110.86088526909636, 37.26375239285273 ], [ -110.86123377957682, 37.264356741189523 ], [ -110.86137991586433, 37.264618318945857 ], [ -110.86206090390229, 37.265353756844107 ], [ -110.86273636415602, 37.266035100233097 ], [ -110.86329933710523, 37.266558564583576 ], [ -110.86344571265028, 37.266693943751363 ], [ -110.86460533620723, 37.267844562578453 ], [ -110.86511749293281, 37.268417537095573 ], [ -110.86581011824295, 37.268990714040285 ], [ -110.86700394319345, 37.269974588533223 ], [ -110.86807938442303, 37.270949304981251 ], [ -110.86895106626039, 37.271711956929877 ], [ -110.87005575967456, 37.272758799618096 ], [ -110.87060746902937, 37.273331793377828 ], [ -110.87081573843557, 37.2735663850058 ], [ -110.87102951050382, 37.273882108309451 ], [ -110.8712318819513, 37.27426993085615 ], [ -110.87145119793529, 37.274644250426505 ], [ -110.8716987765365, 37.274982544184731 ], [ -110.87196871839619, 37.275438043646574 ], [ -110.87238502746033, 37.276055952389157 ], [ -110.87289676065734, 37.276948889157474 ], [ -110.87325642825193, 37.277719971870781 ], [ -110.87338522850811, 37.278269963704538 ], [ -110.87355879738408, 37.279031832143019 ], [ -110.87367603544109, 37.279753077144299 ], [ -110.87382747086953, 37.280262529480709 ], [ -110.87387138197812, 37.280988202960138 ], [ -110.87387026285222, 37.281658842996912 ], [ -110.87390338008885, 37.282093352798348 ], [ -110.87394769283344, 37.282579254242044 ], [ -110.87395789133187, 37.283228272569779 ], [ -110.87396253215448, 37.283827707956647 ], [ -110.87386567314581, 37.28440900718951 ], [ -110.87367821655026, 37.285197531389286 ], [ -110.87338346245538, 37.2860580523623 ], [ -110.8732360639801, 37.286499579985467 ], [ -110.87304362113086, 37.286891482161813 ], [ -110.87268190769825, 37.287310244007408 ], [ -110.87221860249457, 37.28776044403515 ], [ -110.87165937458543, 37.288224059221349 ], [ -110.871162389202, 37.288570557701462 ], [ -110.87060338807453, 37.288894451334691 ], [ -110.86980744059244, 37.289231602897246 ], [ -110.86902858069578, 37.289469614188519 ], [ -110.86814819458307, 37.28969849330948 ], [ -110.86721704240318, 37.289922801939682 ], [ -110.86628044313919, 37.290034422316715 ], [ -110.86545663664279, 37.29015968451224 ], [ -110.86467222556587, 37.290334562909187 ], [ -110.86391048042678, 37.290450871291256 ], [ -110.86304170898119, 37.290481418167204 ], [ -110.86202634476857, 37.290471224969203 ], [ -110.86084728389896, 37.290519421597097 ], [ -110.8598881791479, 37.290590401999907 ], [ -110.85887259511075, 37.290697363218378 ], [ -110.85798107692962, 37.290822492601102 ], [ -110.8573366843105, 37.290920871443355 ], [ -110.85689773494255, 37.290960904472449 ], [ -110.85627721217716, 37.290964659624315 ], [ -110.85544222642558, 37.291022233665224 ], [ -110.854346518814, 37.291133565137841 ], [ -110.85351264924256, 37.291195633924538 ], [ -110.85309514984472, 37.29122666541344 ], [ -110.85204011333309, 37.291306477075288 ], [ -110.85081546881096, 37.29157535920001 ], [ -110.84967542318046, 37.291848843094975 ], [ -110.84939888337983, 37.291911589393848 ], [ -110.84855772604175, 37.292226005307803 ], [ -110.84745123639026, 37.292634720289442 ], [ -110.84685842120251, 37.292877332087627 ], [ -110.84669469898535, 37.292940217965949 ], [ -110.84600023630162, 37.293232270605657 ], [ -110.84539039588232, 37.293519922732557 ], [ -110.84457142595538, 37.294001097675171 ], [ -110.84376372820098, 37.294482281781747 ], [ -110.84292074402134, 37.295107637036644 ], [ -110.84216369277523, 37.295638454151302 ], [ -110.84157161565452, 37.296047798723855 ], [ -110.84111388381413, 37.296416757865508 ], [ -110.84089330753167, 37.29668237361971 ], [ -110.84071224857429, 37.29693452118758 ], [ -110.84040680881871, 37.297312696357224 ], [ -110.84004477885088, 37.297771919942839 ], [ -110.83997687983909, 37.297866474805843 ], [ -110.83954114977207, 37.298492355492037 ], [ -110.83935994775943, 37.298807598464421 ], [ -110.8388957392533, 37.29955512651626 ], [ -110.83858404091005, 37.300212721118008 ], [ -110.83838534617644, 37.300789343530539 ], [ -110.83824304719245, 37.301375056602481 ], [ -110.83811779713119, 37.301902202025332 ], [ -110.8379815032395, 37.302316657660185 ], [ -110.83782899435036, 37.30292489099503 ], [ -110.83773097516705, 37.303379961515375 ], [ -110.83766087412347, 37.303970279567373 ], [ -110.83763746751525, 37.304885163983549 ], [ -110.83768099600631, 37.305633381928182 ], [ -110.83767995168233, 37.306119232600679 ], [ -110.83759399902735, 37.306732964870093 ], [ -110.83758688339384, 37.307418015447027 ], [ -110.83762539069861, 37.307877779787603 ], [ -110.83768097078152, 37.308269962873183 ], [ -110.83770319134968, 37.308432244447147 ], [ -110.83779201647221, 37.309108412425743 ], [ -110.83785244707154, 37.309870173863729 ], [ -110.83788554695467, 37.31022176315831 ], [ -110.83799097451507, 37.311051190610158 ], [ -110.83811887810673, 37.311925718324396 ], [ -110.83825215692349, 37.312926448324532 ], [ -110.8384536440693, 37.313697415627765 ], [ -110.83867195772541, 37.314517982105627 ], [ -110.83893675905388, 37.315239458018553 ], [ -110.83929651967593, 37.315888950742483 ], [ -110.83977888175585, 37.316736914993719 ], [ -110.84026179065593, 37.317331586294635 ], [ -110.840397806271, 37.317589568401701 ], [ -110.84052131480198, 37.317891701772098 ], [ -110.84077988529384, 37.318370689933346 ], [ -110.84104462799122, 37.318599999799517 ], [ -110.84144462531314, 37.3189160241417 ], [ -110.8419911685311, 37.319317875261738 ], [ -110.84239680738699, 37.319638410854054 ], [ -110.84280255294179, 37.319909368552821 ], [ -110.84306184014561, 37.320053935643074 ], [ -110.84340549610789, 37.320333822828843 ], [ -110.84380451443438, 37.320586740300506 ], [ -110.84424523981011, 37.320866753118182 ], [ -110.84455969984208, 37.321078092610215 ], [ -110.84497241617596, 37.321259814057186 ], [ -110.84525432238544, 37.321386378088434 ], [ -110.84558128387349, 37.321558069904938 ], [ -110.84589120641373, 37.321783822207244 ], [ -110.84651122204551, 37.322154199208782 ], [ -110.84726674907337, 37.322493199180322 ], [ -110.8484836882344, 37.322945460152013 ], [ -110.84941531675463, 37.323280164773834 ], [ -110.85049269811053, 37.323542934872918 ], [ -110.85189173945672, 37.323819619102551 ], [ -110.85325686868846, 37.324127793482511 ], [ -110.85398457700134, 37.324286437443874 ], [ -110.85525404226969, 37.32445926177656 ], [ -110.85678315965285, 37.32460985222729 ], [ -110.85801207951303, 37.324742035217767 ], [ -110.85889351975349, 37.324788159271293 ], [ -110.8594691467445, 37.324797858244857 ], [ -110.86021405589013, 37.324821275413385 ], [ -110.86065422932222, 37.324835315488833 ], [ -110.86139899023009, 37.324939850369354 ], [ -110.86210966934398, 37.325166028865397 ], [ -110.86270745588126, 37.325405593043271 ], [ -110.86304122242758, 37.325590765334169 ], [ -110.86336709767609, 37.325771420604077 ], [ -110.86411146582846, 37.326101286100474 ], [ -110.86492338729734, 37.326530377215427 ], [ -110.86572409470907, 37.326923394311727 ], [ -110.86628787649323, 37.327257547961523 ], [ -110.86672193598901, 37.327546483244681 ], [ -110.86723501988746, 37.327830998658591 ], [ -110.86766329230909, 37.328205556240448 ], [ -110.86814788936729, 37.328647779447792 ], [ -110.86828309017521, 37.328792152785944 ], [ -110.86848591592342, 37.328995191642349 ], [ -110.86878437552205, 37.329378614665927 ], [ -110.86913345382219, 37.329865752997428 ], [ -110.86946006205514, 37.330294274995055 ], [ -110.86987680874586, 37.330821146946938 ], [ -110.87028224678467, 37.331363328652152 ], [ -110.87060302293767, 37.331909021931146 ], [ -110.87094074231774, 37.332451127209659 ], [ -110.87126712741862, 37.333022965069233 ], [ -110.87158228884249, 37.333559635526903 ], [ -110.87178480688884, 37.333956467412449 ], [ -110.87212235442277, 37.334610341486766 ], [ -110.87236962102072, 37.335250596306487 ], [ -110.87259425330438, 37.335926881818189 ], [ -110.87285848433521, 37.336553632881014 ], [ -110.8729876919833, 37.336918835029039 ], [ -110.87326326422026, 37.337518555534949 ], [ -110.87339232416878, 37.337973896111798 ], [ -110.87357202078286, 37.338528443620767 ], [ -110.87375114669135, 37.339425518648198 ], [ -110.87382907125075, 37.340083616901843 ], [ -110.87389047734257, 37.340493815051019 ], [ -110.87400784246233, 37.341197024622808 ], [ -110.8741026378754, 37.34189570302928 ], [ -110.87414659931869, 37.342613256405834 ], [ -110.8741400382787, 37.343162196001792 ], [ -110.87409963581011, 37.343693973127401 ], [ -110.87401410268589, 37.344207674340524 ], [ -110.87389475831367, 37.344685283817093 ], [ -110.87370660265699, 37.345126764104542 ], [ -110.87356046809424, 37.345419559675349 ], [ -110.87324913838515, 37.345924004742322 ], [ -110.87294370029826, 37.346279725992751 ], [ -110.87253642471272, 37.346766038229724 ], [ -110.87197091615731, 37.347346823770394 ], [ -110.87146212848378, 37.347765418108089 ], [ -110.87084040560363, 37.348197407814261 ], [ -110.87020183264633, 37.348575292377149 ], [ -110.86949564138368, 37.348876480811363 ], [ -110.86857488024731, 37.34919996155422 ], [ -110.8680326067623, 37.349379635683704 ], [ -110.86724750613459, 37.3495995975791 ], [ -110.86641168779494, 37.349765413651276 ], [ -110.86552498440396, 37.349971728480632 ], [ -110.86490386351056, 37.350038624963304 ], [ -110.86392708554597, 37.350100602676903 ], [ -110.86287140882828, 37.350085862835741 ], [ -110.86217717375317, 37.349999424110699 ], [ -110.86160713184611, 37.349917633610445 ], [ -110.86131373438621, 37.349827151119747 ], [ -110.8608906589668, 37.349646376586868 ], [ -110.86012886914305, 37.349460693596484 ], [ -110.85944042285792, 37.349302134535009 ], [ -110.85887053264587, 37.349143712960732 ], [ -110.85822165193491, 37.348962659271798 ], [ -110.85778144019666, 37.348894526694629 ], [ -110.85739772552677, 37.348803925870321 ], [ -110.85666435955261, 37.348523608965792 ], [ -110.85605517889098, 37.348252452568524 ], [ -110.85570096321889, 37.348089770995358 ], [ -110.85518092450637, 37.347850267401896 ], [ -110.85426716263717, 37.347448027093286 ], [ -110.85300377526858, 37.346856054047102 ], [ -110.85178989924839, 37.346358775388651 ], [ -110.85077017147202, 37.345892376550005 ], [ -110.84987927785016, 37.345369344913152 ], [ -110.84910692672227, 37.344854570295176 ], [ -110.84828372650129, 37.344366767089255 ], [ -110.84771978064076, 37.3440902173 ], [ -110.84734760973363, 37.343892333324355 ], [ -110.8470486609569, 37.343775667934487 ], [ -110.84659757748273, 37.343521793380276 ], [ -110.84620859880476, 37.34326439228844 ], [ -110.84563914197339, 37.342930136432628 ], [ -110.84511477530616, 37.34263199245575 ], [ -110.84475421623075, 37.342284484766395 ], [ -110.84435965188601, 37.342004535475311 ], [ -110.84389744580243, 37.341679426127314 ], [ -110.84350270076307, 37.341489612718298 ], [ -110.8428656164141, 37.341114691407029 ], [ -110.84258386639139, 37.340879955438758 ], [ -110.84209343228218, 37.340563815333866 ], [ -110.84142853717664, 37.339999557176711 ], [ -110.84070694844337, 37.339556906606902 ], [ -110.84010384051368, 37.33914505906813 ], [ -110.83915684694566, 37.338531731363474 ], [ -110.83841272476133, 37.338080923567347 ], [ -110.83761782436936, 37.337623731649934 ], [ -110.83684560710411, 37.337122397509631 ], [ -110.83579723433888, 37.336431383310895 ], [ -110.8349912046104, 37.33591646919713 ], [ -110.83406110925365, 37.335356306076996 ], [ -110.83350860949834, 37.335062577867944 ], [ -110.8327361659932, 37.33468741115346 ], [ -110.83181709969706, 37.334257947591936 ], [ -110.83098814970059, 37.333918744735826 ], [ -110.83012540276982, 37.333552445808849 ], [ -110.82932470950155, 37.333204257929197 ], [ -110.82838848174319, 37.332891923757188 ], [ -110.82757065480281, 37.332638345204401 ], [ -110.82683170631141, 37.332447973848474 ], [ -110.82621700479301, 37.332226231739845 ], [ -110.8256531037718, 37.332004561300785 ], [ -110.82494262730646, 37.331710560093953 ], [ -110.82469453935192, 37.33160202582367 ], [ -110.82394354899772, 37.331258382049079 ], [ -110.82313831956523, 37.330941694173021 ], [ -110.82246169510439, 37.330661249504573 ], [ -110.82198802482731, 37.330480259534006 ], [ -110.82126057044572, 37.330217759328832 ], [ -110.82062327420709, 37.330018488764821 ], [ -110.81992371523278, 37.32989573829817 ], [ -110.81944987253993, 37.32979135617002 ], [ -110.81904944538262, 37.329669056612573 ], [ -110.81836166830988, 37.329343501832881 ], [ -110.81797834005458, 37.329153620526284 ], [ -110.81757832185176, 37.328864559167222 ], [ -110.8172911616477, 37.328584684686987 ], [ -110.81694788247671, 37.328174020896718 ], [ -110.81662708357021, 37.327803953556753 ], [ -110.81624440409023, 37.327352663979823 ], [ -110.81606461718961, 37.32701886965242 ], [ -110.81590704381175, 37.326833839262235 ], [ -110.8155747039695, 37.326571918073711 ], [ -110.81530994704804, 37.326368691928351 ], [ -110.81474053366033, 37.326124425941067 ], [ -110.81440675081313, 37.325993201031494 ], [ -110.81402453384453, 37.325821336422095 ], [ -110.81353972727318, 37.325599732393158 ], [ -110.81285794531262, 37.325156973940139 ], [ -110.81218154569565, 37.324822387137473 ], [ -110.81151070556093, 37.324523860999989 ], [ -110.81072165092867, 37.324107961020424 ], [ -110.80998915318641, 37.323647076977934 ], [ -110.80966227541708, 37.323470780123856 ], [ -110.80916079442997, 37.323158992038856 ], [ -110.80858050422813, 37.322770455998885 ], [ -110.80795503862511, 37.322395364671543 ], [ -110.80736905965067, 37.322029348234523 ], [ -110.80650107994475, 37.321600671986516 ], [ -110.80576825192526, 37.321287589526747 ], [ -110.80515351738144, 37.321137849100054 ], [ -110.80482087868342, 37.321015612894833 ], [ -110.80449493125563, 37.32092493555119 ], [ -110.80416083847417, 37.320928890056074 ], [ -110.80370357016646, 37.320991229868262 ], [ -110.80324049334709, 37.321116655735295 ], [ -110.80276603420285, 37.321278116516432 ], [ -110.80203776642234, 37.321385067494681 ], [ -110.80119691545899, 37.321383657790008 ], [ -110.80039559145466, 37.321373294867641 ], [ -110.79913704104381, 37.321407220893164 ], [ -110.79821718384569, 37.321405655875971 ], [ -110.79763579391502, 37.321453338221602 ], [ -110.79722370959547, 37.321498603784391 ], [ -110.79657435329295, 37.321637205056447 ], [ -110.79630326752132, 37.321713357064802 ], [ -110.79604900156204, 37.32183010009912 ], [ -110.79574925881143, 37.322068452060584 ], [ -110.79524070977953, 37.322306442111277 ], [ -110.79465318702452, 37.322530772054741 ], [ -110.79426347448249, 37.322647276098408 ], [ -110.7936433746513, 37.322812953869828 ], [ -110.79307191666625, 37.322938150809485 ], [ -110.79239999157005, 37.323067675723479 ], [ -110.79201033491375, 37.323161637623116 ], [ -110.79128215866135, 37.323223452884747 ], [ -110.7905033279597, 37.323235597427207 ], [ -110.79001798299444, 37.323238342707889 ], [ -110.78971888122928, 37.323237811550136 ], [ -110.78944789351074, 37.323274286740116 ], [ -110.78870814967146, 37.323435218695202 ], [ -110.78788373819636, 37.323600501230239 ], [ -110.78739246551071, 37.323703279620268 ], [ -110.7866304705493, 37.323746977629895 ], [ -110.78619589810741, 37.323755207123142 ], [ -110.7858347290243, 37.323750047019864 ], [ -110.78554128158605, 37.323745008573752 ], [ -110.78467821711867, 37.323608232401916 ], [ -110.78375895381333, 37.323390221972176 ], [ -110.78302577587966, 37.323225727891341 ], [ -110.78267608852811, 37.323153876197978 ], [ -110.78208935499205, 37.32308969969624 ], [ -110.78124298639408, 37.323038561453785 ], [ -110.78044733096991, 37.323014553024194 ], [ -110.77987176896309, 37.322990948894372 ], [ -110.77898032446468, 37.322916274415398 ], [ -110.77805481727457, 37.322910936515349 ], [ -110.77736070294701, 37.32290152001854 ], [ -110.7770331088097, 37.32299464794135 ], [ -110.77663075135396, 37.323178674425641 ], [ -110.77620243214541, 37.32336265043368 ], [ -110.7757843360106, 37.323524109459647 ], [ -110.77520812730897, 37.323716815444747 ], [ -110.7747051193805, 37.323963741513793 ], [ -110.77443358581974, 37.324179558207774 ], [ -110.77420154179205, 37.32439995659 ], [ -110.77387902171735, 37.324679673487523 ], [ -110.77345450129238, 37.325097107148714 ], [ -110.77328443616358, 37.325349171040614 ], [ -110.77294434317118, 37.325839777254664 ], [ -110.77252482699674, 37.326465438478102 ], [ -110.77224124263856, 37.326929109451584 ], [ -110.77200307701068, 37.327302728114915 ], [ -110.77191871885238, 37.327577489832244 ], [ -110.7717242301412, 37.328063865953958 ], [ -110.77145745706031, 37.328563622979161 ], [ -110.77130965223859, 37.328914879859362 ], [ -110.77107699649524, 37.329329069754969 ], [ -110.77088414664063, 37.329644183261884 ], [ -110.77068582931756, 37.329900695441161 ], [ -110.77035178173239, 37.330247082981863 ], [ -110.76993866049567, 37.330611343642218 ], [ -110.76959904490835, 37.330930676463197 ], [ -110.76903337586637, 37.33134421323404 ], [ -110.76845096210177, 37.331694617164572 ], [ -110.76791943670185, 37.332013569365273 ], [ -110.76756338771769, 37.332166106799598 ], [ -110.76720186008403, 37.332264548957859 ], [ -110.76655255198116, 37.332339887792742 ], [ -110.76593151906654, 37.332397251196319 ], [ -110.76517923326735, 37.332553503845169 ], [ -110.76469465879941, 37.33265169405707 ], [ -110.76430507344884, 37.33269598813115 ], [ -110.76394935242931, 37.332740348487945 ], [ -110.76345266897532, 37.332739356527441 ], [ -110.76287729354165, 37.332634544927913 ], [ -110.76238538163153, 37.332552432933603 ], [ -110.76208745760931, 37.332524792536532 ], [ -110.76120701875216, 37.332509498019732 ], [ -110.76052415276611, 37.33248558310526 ], [ -110.75998204580331, 37.33257011669609 ], [ -110.75974021928859, 37.332650750992897 ], [ -110.75946774153572, 37.332785405891983 ], [ -110.75905497142418, 37.333018927453374 ], [ -110.75851180586022, 37.333432459493061 ], [ -110.75802510536074, 37.333837090595864 ], [ -110.7576117747593, 37.334241869994116 ], [ -110.7574416650293, 37.334484896629057 ], [ -110.75728284275277, 37.334727946164023 ], [ -110.75706721365505, 37.335083552563191 ], [ -110.75686821045539, 37.335533838625253 ], [ -110.75673829872804, 37.335912155226225 ], [ -110.75660010542904, 37.336407635258347 ], [ -110.75647956509634, 37.337029345939605 ], [ -110.75642178167156, 37.337443866103797 ], [ -110.75642630551788, 37.337790910304975 ], [ -110.75644207479991, 37.338151498474929 ], [ -110.75640102018423, 37.338629150227831 ], [ -110.75633162553297, 37.339142799125483 ], [ -110.75623908326492, 37.339832171099211 ], [ -110.75619193005275, 37.340449525353343 ], [ -110.75617804012325, 37.340904698096409 ], [ -110.75614896357376, 37.341517582529306 ], [ -110.7561189324513, 37.342076381605288 ], [ -110.7560429663024, 37.342874855255616 ], [ -110.75593323676613, 37.34363990772632 ], [ -110.75591440263727, 37.344226672682915 ], [ -110.75577650000129, 37.344974540322269 ], [ -110.75577451777852, 37.345586578776256 ], [ -110.75570499538495, 37.346136281942591 ], [ -110.75561321262873, 37.346586786359914 ], [ -110.75544186977532, 37.347199376039349 ], [ -110.75538992247685, 37.347550809886336 ], [ -110.75534938219589, 37.347866211770388 ], [ -110.75526904957705, 37.348266261752023 ], [ -110.75517173038101, 37.348681600086451 ], [ -110.75499504127617, 37.349199532134911 ], [ -110.7548071322153, 37.349694905929546 ], [ -110.754659471991, 37.349965016013769 ], [ -110.75439275736767, 37.350388114629673 ], [ -110.7540468413065, 37.350860624265991 ], [ -110.75367288474172, 37.351274484294457 ], [ -110.75322528119986, 37.351764807399192 ], [ -110.75284590645235, 37.352106542470374 ], [ -110.75222905754029, 37.352555945580995 ], [ -110.75192358661793, 37.352740089695203 ], [ -110.75168048341902, 37.352843239127715 ], [ -110.75117757610576, 37.352977390407538 ], [ -110.7507200825801, 37.353035918756028 ], [ -110.75042670605156, 37.35297580863071 ], [ -110.7500544375481, 37.352871363155586 ], [ -110.74969919673505, 37.352739910932293 ], [ -110.7494061367929, 37.352585153320973 ], [ -110.74910738146164, 37.352445706479926 ], [ -110.748696139134, 37.352178924411135 ], [ -110.74840901176893, 37.351939446547824 ], [ -110.74802095938237, 37.351492434027634 ], [ -110.7477342439461, 37.35113126812616 ], [ -110.74756031998295, 37.350806397743348 ], [ -110.74732077810071, 37.350183929168686 ], [ -110.74709570649216, 37.349624588098393 ], [ -110.74678773793833, 37.348871270850772 ], [ -110.74658704384909, 37.348451695938898 ], [ -110.74634484991545, 37.347950906804911 ], [ -110.74604664714487, 37.347319295709973 ], [ -110.745547222873, 37.346763869127166 ], [ -110.74493926699937, 37.346253275838848 ], [ -110.74448318713904, 37.345905257336561 ], [ -110.74398288093667, 37.345615731572579 ], [ -110.74353078890117, 37.345425460887071 ], [ -110.74304711755279, 37.345226106006429 ], [ -110.74271888284935, 37.345135253836858 ], [ -110.74194499910283, 37.344953290707295 ], [ -110.74110546667137, 37.34482075520539 ], [ -110.74019119012038, 37.344755653719083 ], [ -110.73979602322518, 37.344759292163857 ], [ -110.73885294605286, 37.344860873749923 ], [ -110.73842367390618, 37.344932036410064 ], [ -110.73793774697607, 37.345061662233626 ], [ -110.73745169285201, 37.345227341285771 ], [ -110.73660334173664, 37.345681557712034 ], [ -110.73617893844508, 37.345972661641468 ], [ -110.73577102191214, 37.346390896505859 ], [ -110.73536816078229, 37.346975897925326 ], [ -110.73510103216745, 37.347489090923261 ], [ -110.73504987676706, 37.347588128979545 ], [ -110.73485611642322, 37.348105992597546 ], [ -110.7347124634278, 37.348822273414221 ], [ -110.73462990461432, 37.349502635545626 ], [ -110.73464084924099, 37.349921805083405 ], [ -110.7347120034665, 37.35055744249923 ], [ -110.73486232264314, 37.351157201791032 ], [ -110.73502969168894, 37.351725450489269 ], [ -110.73534382247419, 37.35262303346709 ], [ -110.73570640286714, 37.35355227227118 ], [ -110.73600308259861, 37.354278550841947 ], [ -110.73614878312748, 37.354589854216151 ], [ -110.73629390149264, 37.355067912563591 ], [ -110.73635441311399, 37.355523247502283 ], [ -110.73637007383651, 37.355888343811927 ], [ -110.73636302508103, 37.356289444930326 ], [ -110.73624269528982, 37.356793952880068 ], [ -110.73605954815991, 37.3575011323464 ], [ -110.7358481832263, 37.358203741499757 ], [ -110.73573398278569, 37.358568547657612 ], [ -110.73560325089184, 37.358817037976827 ], [ -110.73535398824848, 37.359054446380831 ], [ -110.7348613992683, 37.359445446023877 ], [ -110.73424462174928, 37.359827150776049 ], [ -110.73357131252574, 37.36022675266728 ], [ -110.73302221267305, 37.360626631100338 ], [ -110.73248985372955, 37.361080627927556 ], [ -110.73199757322519, 37.361376970712868 ], [ -110.73147700926803, 37.361686768001732 ], [ -110.73078074543417, 37.362180947154002 ], [ -110.73024858786584, 37.36257183724144 ], [ -110.72989160788728, 37.362922562737722 ], [ -110.72930410570984, 37.363313322113576 ], [ -110.72861805735825, 37.363784977109127 ], [ -110.72780854914345, 37.364355496348345 ], [ -110.72703881555734, 37.364853990999492 ], [ -110.72647835426358, 37.365253812408199 ], [ -110.72579331789782, 37.365747987757409 ], [ -110.72527200814876, 37.366247046406336 ], [ -110.72483427850388, 37.366741790254132 ], [ -110.72432496600786, 37.367353545556021 ], [ -110.72388822091362, 37.367884343446974 ], [ -110.72353062385045, 37.368388283180209 ], [ -110.72318419971741, 37.368923796368108 ], [ -110.7228490809445, 37.369454828057329 ], [ -110.72268399485002, 37.369814994620384 ], [ -110.72253021759659, 37.370170680540618 ], [ -110.72238084024325, 37.370864395424917 ], [ -110.72233476753274, 37.371107660838852 ], [ -110.72234395199048, 37.371680060935432 ], [ -110.72237162242605, 37.371833361079815 ], [ -110.72244910355533, 37.372261700055347 ], [ -110.72263922894189, 37.372771427665903 ], [ -110.72280726911913, 37.3731449943012 ], [ -110.72306009466013, 37.37349802742397 ], [ -110.7234705508904, 37.373985734741439 ], [ -110.72380244684118, 37.374338049703113 ], [ -110.72432088672491, 37.37464122261742 ], [ -110.72526854004539, 37.374940884144308 ], [ -110.72569146191987, 37.37511312857972 ], [ -110.72623829874081, 37.375375796695536 ], [ -110.7269204301418, 37.375706378468294 ], [ -110.72776126918654, 37.37619055682363 ], [ -110.72783904002875, 37.376235804961482 ], [ -110.72844202522604, 37.376593237260458 ], [ -110.72913516427835, 37.377009462866525 ], [ -110.72989015832405, 37.377502443213636 ], [ -110.73076914961621, 37.378067811672324 ], [ -110.73162018936496, 37.378556492616895 ], [ -110.73250475752401, 37.379148902248076 ], [ -110.73344000883395, 37.379786488596757 ], [ -110.73444285755964, 37.380478302255966 ], [ -110.73529361578504, 37.381061601159956 ], [ -110.73603182650453, 37.381531969968975 ], [ -110.73688808356668, 37.382164845630378 ], [ -110.73765431884762, 37.382702870261333 ], [ -110.73845984995174, 37.383313087369714 ], [ -110.7386964365195, 37.383493886760562 ], [ -110.73913578782376, 37.383837381870883 ], [ -110.74002610965582, 37.38443425451031 ], [ -110.74076394860008, 37.385030786247569 ], [ -110.74154135128238, 37.385622892905992 ], [ -110.74254981546862, 37.38636873254768 ], [ -110.74324263084634, 37.386929095396205 ], [ -110.74391266436545, 37.387547994612248 ], [ -110.74464465648488, 37.388221106674841 ], [ -110.74521307366081, 37.388830765138863 ], [ -110.74539314943709, 37.389029456871512 ], [ -110.74598965342311, 37.38968874797294 ], [ -110.7465018054699, 37.390239689480197 ], [ -110.74709854068701, 37.39083587870639 ], [ -110.74767240424656, 37.391517647263797 ], [ -110.7481618058146, 37.392122615752768 ], [ -110.74883718356618, 37.392858677536772 ], [ -110.74947865240509, 37.393603677364155 ], [ -110.74995104598078, 37.394235643659933 ], [ -110.75039533807468, 37.39482698657622 ], [ -110.75070443859057, 37.395305370281697 ], [ -110.75114285561651, 37.395968808340889 ], [ -110.75141242325104, 37.396447106911097 ], [ -110.75163131747769, 37.39687572249656 ], [ -110.7516930988788, 37.396984017871745 ], [ -110.75194040449963, 37.397363116602826 ], [ -110.75229446505429, 37.397918207592795 ], [ -110.75254152484344, 37.398373921799987 ], [ -110.75291789497571, 37.399019195519131 ], [ -110.75310817515695, 37.399564927788994 ], [ -110.75333177701843, 37.400286498269779 ], [ -110.75349911214697, 37.400940347487939 ], [ -110.75364370546822, 37.401639217995829 ], [ -110.75374779741065, 37.402630952202635 ], [ -110.75371837057766, 37.402991442643938 ], [ -110.75358037952958, 37.403725779221446 ], [ -110.75327270860626, 37.404518351229783 ], [ -110.75306239013806, 37.404910012043743 ], [ -110.75265389027265, 37.405436464869368 ], [ -110.75235351351417, 37.405724277350792 ], [ -110.75194021640797, 37.405989317726558 ], [ -110.75167422338878, 37.406128473083051 ], [ -110.75128359474598, 37.406371024277782 ], [ -110.75070221408461, 37.406550075612671 ], [ -110.75033803223286, 37.406652965724312 ], [ -110.74975649726868, 37.406877080999763 ], [ -110.74900543785748, 37.407109847431883 ], [ -110.74807141359379, 37.407315178007146 ], [ -110.74715555427643, 37.40749349868134 ], [ -110.74649985199346, 37.407591246266875 ], [ -110.74544306222307, 37.407674606673304 ], [ -110.74462388069925, 37.407663826351921 ], [ -110.74395275322038, 37.407644347290429 ], [ -110.74320048529677, 37.407561591724757 ], [ -110.74252279539917, 37.407478993805967 ], [ -110.7416758476279, 37.407328418939493 ], [ -110.74099305486745, 37.407088059880699 ], [ -110.7401519666452, 37.406878897336178 ], [ -110.73915286450192, 37.406619804490028 ], [ -110.73886502919626, 37.406533538166961 ], [ -110.73824424187339, 37.406338369081872 ], [ -110.73755558374107, 37.406165580566835 ], [ -110.73672032597833, 37.405910436245158 ], [ -110.73602083467273, 37.405606914775333 ], [ -110.73532139024708, 37.405291671343697 ], [ -110.7347956808777, 37.405055233523981 ], [ -110.73409202018445, 37.404657046511524 ], [ -110.7333984242338, 37.404290426246334 ], [ -110.73251889978893, 37.403783667723069 ], [ -110.73185934454058, 37.403381060250148 ], [ -110.73134106304057, 37.402969756376471 ], [ -110.73073239763474, 37.402558244413491 ], [ -110.7304112243803, 37.402323154038335 ], [ -110.72971239418375, 37.401851940169465 ], [ -110.72876533997632, 37.401287310954409 ], [ -110.72783494120364, 37.400807442101794 ], [ -110.72703966056798, 37.400458577888855 ], [ -110.72666732154771, 37.400318003983664 ], [ -110.72566311507042, 37.399946112874083 ], [ -110.72501412157894, 37.399764329495504 ], [ -110.72415038201977, 37.399604576245906 ], [ -110.72367621971441, 37.399504317395362 ], [ -110.72320077967881, 37.399444615719574 ], [ -110.72267081005234, 37.399465908382901 ], [ -110.72232039881229, 37.399510154961021 ], [ -110.72119545689719, 37.399714825018869 ], [ -110.72023425036714, 37.399942406353333 ], [ -110.71993456046752, 37.400018314118128 ], [ -110.71930108216785, 37.400224129163959 ], [ -110.71830509116077, 37.400685970730912 ], [ -110.7175240634367, 37.401067193492182 ], [ -110.71694668929675, 37.401372281553698 ], [ -110.71606985545682, 37.401987623726505 ], [ -110.71494618371965, 37.402737571271793 ], [ -110.71434107053611, 37.403200320846452 ], [ -110.71415975939408, 37.403339596333268 ], [ -110.71318471650089, 37.404215177706611 ], [ -110.71253287247289, 37.404777857488561 ], [ -110.71173342597763, 37.405524054969106 ], [ -110.71106419903106, 37.406193948089289 ], [ -110.71034383559038, 37.406935822287679 ], [ -110.70960021539818, 37.407844389735814 ], [ -110.70954349186162, 37.40790283995004 ], [ -110.70922013292245, 37.408244568639439 ], [ -110.70872031887821, 37.408923878410803 ], [ -110.7081691609709, 37.409728350711369 ], [ -110.7077372632057, 37.410372670028622 ], [ -110.70749224869647, 37.410903876669344 ], [ -110.70736130022466, 37.411160445114433 ], [ -110.70709859337997, 37.411880896245776 ], [ -110.70695535854945, 37.412389819305943 ], [ -110.70673752821328, 37.413191504610275 ], [ -110.70667437498956, 37.413448240330716 ], [ -110.70662840035564, 37.4136464291457 ], [ -110.70655259216684, 37.414250163400567 ], [ -110.70656137838672, 37.414894669484447 ], [ -110.70644476731654, 37.415818290894798 ], [ -110.70640859595295, 37.416399588834551 ], [ -110.70635596542327, 37.416854653149997 ], [ -110.70623475436311, 37.417507849771006 ], [ -110.70609769918993, 37.417877073340513 ], [ -110.70580165254567, 37.418444203900961 ], [ -110.70559657512105, 37.418867340084361 ], [ -110.70538573885014, 37.419317502802166 ], [ -110.70507795564957, 37.419992767234511 ], [ -110.70483900119689, 37.420406803703187 ], [ -110.70457581539259, 37.420946971689098 ], [ -110.70428716398129, 37.421351869007914 ], [ -110.70391707949787, 37.422058522433588 ], [ -110.70334892370499, 37.422836787754989 ], [ -110.70298988986059, 37.423602956562249 ], [ -110.70240372879873, 37.424641669237047 ], [ -110.70194175959097, 37.42542470153758 ], [ -110.70156029482159, 37.426140332075484 ], [ -110.70111795148085, 37.426815245517588 ], [ -110.70080988366064, 37.427544579608359 ], [ -110.70026283953989, 37.428678925542741 ], [ -110.70006310230002, 37.429165161026162 ], [ -110.69982905835386, 37.429750460173928 ], [ -110.69967427464972, 37.43029990523052 ], [ -110.69952963868265, 37.431137815489706 ], [ -110.69945409729564, 37.431655913435208 ], [ -110.69946934013409, 37.432084104754381 ], [ -110.69953528524732, 37.432552986748235 ], [ -110.69963586124783, 37.432841681940786 ], [ -110.69982149688731, 37.433342415872822 ], [ -110.70024175974484, 37.433965430133441 ], [ -110.70052794908827, 37.434479938431089 ], [ -110.70115312313671, 37.435026851590713 ], [ -110.70159269105751, 37.435347949654478 ], [ -110.70201550381736, 37.435619428303312 ], [ -110.70286194029673, 37.435959574099037 ], [ -110.70382138990472, 37.436308109418476 ], [ -110.70429015474814, 37.436395814907549 ], [ -110.70545878653292, 37.436732240843718 ], [ -110.70667287294764, 37.437010178776852 ], [ -110.7076908240649, 37.437147906520515 ], [ -110.70909053658205, 37.437367689277217 ], [ -110.71010750578391, 37.437469338871452 ], [ -110.7106727539923, 37.437457203222202 ], [ -110.7123404103335, 37.437375643036972 ], [ -110.71305291810195, 37.437282730695898 ], [ -110.71357348138946, 37.437130759821677 ], [ -110.71465435331358, 37.436777331590889 ], [ -110.71559342341388, 37.436554251482185 ], [ -110.71641418963954, 37.436227222169698 ], [ -110.71706060041173, 37.435971879788802 ], [ -110.71766531867885, 37.435680379331316 ], [ -110.71815768705453, 37.435505786501132 ], [ -110.71885370356787, 37.43528210061141 ], [ -110.71964561138675, 37.435108213638351 ], [ -110.7204428656225, 37.435015457633973 ], [ -110.72139146856512, 37.434954601161053 ], [ -110.72198590225254, 37.434992055717188 ], [ -110.72249557643072, 37.435024801456827 ], [ -110.72386171420789, 37.435154193168501 ], [ -110.72473724716833, 37.435291441365152 ], [ -110.72540360033324, 37.435446224795108 ], [ -110.72572529339973, 37.435573164015331 ], [ -110.72607514818581, 37.435727208838657 ], [ -110.72635713298645, 37.435894616129083 ], [ -110.72680344904354, 37.43625619802468 ], [ -110.72725894328251, 37.436581744451253 ], [ -110.72798634242186, 37.437052134933836 ], [ -110.72829079436752, 37.43726105247552 ], [ -110.72845988404833, 37.43739123883951 ], [ -110.72891644146776, 37.437739315620085 ], [ -110.72944528403916, 37.438105583573304 ], [ -110.72994278801373, 37.438386147071384 ], [ -110.73060294583091, 37.438703134234167 ], [ -110.7309018920014, 37.438875076156549 ], [ -110.73120660446902, 37.439015482364837 ], [ -110.73148859696542, 37.439187384243212 ], [ -110.73193371432842, 37.439580491980614 ], [ -110.73242925648036, 37.440099904438569 ], [ -110.73309392354886, 37.440745889057254 ], [ -110.73334188552714, 37.440953764555495 ], [ -110.73397303720115, 37.441491503777904 ], [ -110.73484108627815, 37.442173990964207 ], [ -110.73525261053109, 37.442485887129564 ], [ -110.73606379459056, 37.443271895746562 ], [ -110.73670594266993, 37.443908795784488 ], [ -110.73720142018932, 37.444464242715306 ], [ -110.73783311470466, 37.445186743683045 ], [ -110.73847904751328, 37.44604447858049 ], [ -110.7389791087946, 37.446915408366742 ], [ -110.73938428866654, 37.447439098436419 ], [ -110.73980096701331, 37.447908730063233 ], [ -110.74018376495604, 37.44836927199546 ], [ -110.74036401581525, 37.448554449391224 ], [ -110.74064000770049, 37.44884349443538 ], [ -110.74122075900334, 37.449277426029802 ], [ -110.7418355118417, 37.449688894726982 ], [ -110.74255721368007, 37.450235799005547 ], [ -110.74341985025991, 37.450900183229813 ], [ -110.74449160318545, 37.451583040821674 ], [ -110.74500463756438, 37.451994272977117 ], [ -110.74533161416049, 37.452260882647295 ], [ -110.74575422307217, 37.452667409770029 ], [ -110.74624860312049, 37.453249856926512 ], [ -110.74644564238807, 37.45349365012563 ], [ -110.74682956414574, 37.453976706899596 ], [ -110.74694775034585, 37.45413470001165 ], [ -110.74735291846078, 37.454689910238201 ], [ -110.74754898043938, 37.455226645113704 ], [ -110.74764998299248, 37.45545220362677 ], [ -110.74774504520005, 37.455763379625346 ], [ -110.74779994431927, 37.456250237190545 ], [ -110.74781480100087, 37.456876721752991 ], [ -110.74776213393606, 37.457408418202846 ], [ -110.74776078675283, 37.457809525359778 ], [ -110.74765218887217, 37.458160828130872 ], [ -110.74757196381903, 37.458480643412514 ], [ -110.74734465695177, 37.458826284010527 ], [ -110.74699291690352, 37.459186981112062 ], [ -110.7464377063552, 37.459528311961506 ], [ -110.74576387063492, 37.459837837065223 ], [ -110.74522053812665, 37.460007927313384 ], [ -110.74471691686313, 37.460137539177062 ], [ -110.74412861133025, 37.460230910746908 ], [ -110.74325789686601, 37.460242542840916 ], [ -110.74239311414982, 37.460173058116879 ], [ -110.74166962854487, 37.460117396579555 ], [ -110.74117111374346, 37.46007574411545 ], [ -110.74047732505487, 37.459934510134516 ], [ -110.73995767158152, 37.459793655388097 ], [ -110.73948879342886, 37.459684458261577 ], [ -110.73846072442902, 37.45942529692055 ], [ -110.73805961560723, 37.459338778346606 ], [ -110.73755116781309, 37.459229485819193 ], [ -110.73656835636423, 37.45896590166339 ], [ -110.73567578691885, 37.458765607142141 ], [ -110.73475484304376, 37.458596790164421 ], [ -110.73395239159825, 37.458494934242431 ], [ -110.73278817310251, 37.458376030765102 ], [ -110.73190650966804, 37.458292910601678 ], [ -110.7305328777543, 37.458240211072216 ], [ -110.72966228221759, 37.458224702188616 ], [ -110.72901212600223, 37.458223213133103 ], [ -110.7286003371425, 37.458280857237099 ], [ -110.72822119140412, 37.458379136647011 ], [ -110.72747286075996, 37.458634303849749 ], [ -110.72651555416067, 37.459141366535633 ], [ -110.72600539825238, 37.459505239756069 ], [ -110.72561968366735, 37.459851372334761 ], [ -110.72540909773532, 37.460233965486132 ], [ -110.72524293131897, 37.460837497156703 ], [ -110.72522341396342, 37.461536013437723 ], [ -110.72522514987813, 37.462297674932472 ], [ -110.72529160399287, 37.462987377224998 ], [ -110.72531158155893, 37.463708519309321 ], [ -110.72537608262081, 37.464623559198238 ], [ -110.72546410788935, 37.465290777025245 ], [ -110.7255456897701, 37.466174308344172 ], [ -110.72562725703564, 37.467062346288834 ], [ -110.72571990417099, 37.468013505585205 ], [ -110.72575696510134, 37.468703138735229 ], [ -110.72580535187794, 37.469388291232448 ], [ -110.72580847119191, 37.470082352286383 ], [ -110.72578341692569, 37.470749306828175 ], [ -110.72578701017132, 37.471313571781288 ], [ -110.72576825523772, 37.47180387261885 ], [ -110.72563073387734, 37.472299305908948 ], [ -110.72551080084904, 37.472623519908247 ], [ -110.72535249768359, 37.472925110384928 ], [ -110.72515790109833, 37.473254558628717 ], [ -110.72502012862977, 37.47381669172033 ], [ -110.72458119384198, 37.474775626211866 ], [ -110.72444979374441, 37.475140373803448 ], [ -110.72431252231618, 37.475563696424494 ], [ -110.72415874852125, 37.475860788863294 ], [ -110.72392018345359, 37.476148669322171 ], [ -110.72361911389247, 37.476517526172245 ], [ -110.72317076369366, 37.476953639814916 ], [ -110.72273950639936, 37.477353737131416 ], [ -110.72230213922855, 37.477875503063551 ], [ -110.72168326956262, 37.478541058676839 ], [ -110.72123441048707, 37.479107861811592 ], [ -110.72104106482165, 37.479395842942147 ], [ -110.72075097980097, 37.479844939828617 ], [ -110.72038723275584, 37.480331719071515 ], [ -110.72007513796588, 37.480614910633854 ], [ -110.71955913231244, 37.480983247380522 ], [ -110.71928160395656, 37.481095259170033 ], [ -110.71881716414491, 37.481283441803292 ], [ -110.71804720151979, 37.481506948575898 ], [ -110.71772466403284, 37.481555753611254 ], [ -110.71692136208002, 37.481620532851487 ], [ -110.71619155372206, 37.481691792752272 ], [ -110.7152234530168, 37.481666929180975 ], [ -110.71430835828784, 37.481682747352984 ], [ -110.71295682978781, 37.481656937458517 ], [ -110.71188227293997, 37.481667842495106 ], [ -110.71088709828256, 37.481624850041662 ], [ -110.71023691445184, 37.481578188955666 ], [ -110.70963754175978, 37.481554183335263 ], [ -110.70915715740128, 37.481471878816571 ], [ -110.70820208570046, 37.481297362960433 ], [ -110.70764245729869, 37.481233785247298 ], [ -110.70727495364349, 37.481210341158402 ], [ -110.70655111654375, 37.481199531953656 ], [ -110.70627966446185, 37.481198857450117 ], [ -110.70517660715261, 37.481268219472746 ], [ -110.70441291679684, 37.481324900195411 ], [ -110.70366610212089, 37.481404152464748 ], [ -110.7025798624436, 37.481509587063236 ], [ -110.70230826629779, 37.481544957723102 ], [ -110.70136929329176, 37.481592163331378 ], [ -110.70037387431415, 37.481612177356972 ], [ -110.6996498181439, 37.481655407285892 ], [ -110.69902786361948, 37.481622276778523 ], [ -110.69831557019383, 37.481552857715819 ], [ -110.69753537855922, 37.481492274225118 ], [ -110.69671009183473, 37.481395515187806 ], [ -110.69609406992311, 37.481294782004447 ], [ -110.6952632784743, 37.481161944057526 ], [ -110.69469257570277, 37.481043293123292 ], [ -110.69420082750138, 37.480978925781002 ], [ -110.69365798075448, 37.480963999058858 ], [ -110.69300160563573, 37.481052432025521 ], [ -110.69266240237569, 37.481024509192721 ], [ -110.69198985535242, 37.480919100742284 ], [ -110.69138513575135, 37.480822879311681 ], [ -110.69075212310885, 37.480731087568543 ], [ -110.68981386159778, 37.480606943644794 ], [ -110.68887013491749, 37.480437709573145 ], [ -110.6876385991085, 37.480123488846111 ], [ -110.68649751822271, 37.479818508989752 ], [ -110.68554261217974, 37.479622177699362 ], [ -110.68481943805607, 37.479458004893658 ], [ -110.68386454108169, 37.47926166007008 ], [ -110.68264968708063, 37.479024048119712 ], [ -110.68171741784077, 37.478828648089568 ], [ -110.6805702119302, 37.478644377585624 ], [ -110.6793660724553, 37.478550979454816 ], [ -110.67912298677022, 37.478531390858763 ], [ -110.67842758730019, 37.478489840181581 ], [ -110.67738737135748, 37.478414895239283 ], [ -110.6764093627818, 37.478340111525043 ], [ -110.6753806521387, 37.478221013486198 ], [ -110.6740635280285, 37.478103815345413 ], [ -110.67319295229963, 37.47803380815715 ], [ -110.6716325089841, 37.477952865690483 ], [ -110.67071108211404, 37.477873685227927 ], [ -110.66968788752179, 37.477789706297095 ], [ -110.66844978659144, 37.477709622498722 ], [ -110.66759725697543, 37.47765314522303 ], [ -110.66647495177747, 37.477731105508738 ], [ -110.66579153053154, 37.477796776854539 ], [ -110.66488053651086, 37.477915880969746 ], [ -110.66429773069184, 37.477990842655025 ], [ -110.66362973523569, 37.478146681906487 ], [ -110.66292190904504, 37.478356485701291 ], [ -110.66202695553501, 37.478678420853605 ], [ -110.66097890052707, 37.479090046572011 ], [ -110.65985147884309, 37.479541995936373 ], [ -110.65869556298479, 37.480038920450667 ], [ -110.65768697481556, 37.480468658106176 ], [ -110.65667827204152, 37.480920920897638 ], [ -110.65582233123838, 37.481355592808931 ], [ -110.65462675332336, 37.481856868533626 ], [ -110.65434912594904, 37.481968727304476 ], [ -110.65369758307142, 37.482223708472105 ], [ -110.6534143392938, 37.482326534921249 ], [ -110.65288752007605, 37.482514275019682 ], [ -110.65174353462048, 37.482857934092053 ], [ -110.65064524338524, 37.483102567032411 ], [ -110.64926989455293, 37.483332847137675 ], [ -110.64801918870489, 37.48351390753735 ], [ -110.64666083318581, 37.483735194198552 ], [ -110.64570449445772, 37.483854014506541 ], [ -110.6445090026529, 37.484075764658435 ], [ -110.643842236352, 37.484190933970638 ], [ -110.64311724650941, 37.484418594216137 ], [ -110.64265827430197, 37.484601986649558 ], [ -110.64219932135428, 37.484780870525803 ], [ -110.64124128157921, 37.485251181576764 ], [ -110.64066247583087, 37.485655036508682 ], [ -110.64018681156921, 37.486014134517085 ], [ -110.63984448519967, 37.486400678042671 ], [ -110.63953097992341, 37.486908992623341 ], [ -110.63943383758668, 37.487116009912775 ], [ -110.63937017380468, 37.487417772522129 ], [ -110.63928845889015, 37.487944820933421 ], [ -110.63925946510969, 37.488093457439113 ], [ -110.63942127182982, 37.488553646917389 ], [ -110.63960624501938, 37.488901236352142 ], [ -110.63979689737367, 37.489244335977489 ], [ -110.64011174224599, 37.489637388660213 ], [ -110.64039308723191, 37.48994020216535 ], [ -110.64071968165605, 37.490243152606197 ], [ -110.64103526881595, 37.490482973245598 ], [ -110.64146943871752, 37.490763714322135 ], [ -110.64230400285032, 37.491293541691959 ], [ -110.64292446541839, 37.491651457184346 ], [ -110.6436074714707, 37.491941955850095 ], [ -110.64464636552835, 37.492328164726935 ], [ -110.64582680017469, 37.492687747980291 ], [ -110.64748793100968, 37.493066782022829 ], [ -110.64886658813882, 37.493377351238948 ], [ -110.65013219242843, 37.493674950534775 ], [ -110.65091773181815, 37.493820591064406 ], [ -110.65177133264159, 37.49392676703124 ], [ -110.65248933355463, 37.49400099032092 ], [ -110.65352387454338, 37.494121206188737 ], [ -110.65416265073524, 37.494204200567772 ], [ -110.6545981991578, 37.494200967976958 ], [ -110.65501145442403, 37.494125559618141 ], [ -110.65541345860277, 37.494036596544404 ], [ -110.65575289215163, 37.494024065672285 ], [ -110.65610921150832, 37.494029610245946 ], [ -110.65662388366852, 37.49404012093143 ], [ -110.65770407252077, 37.494074803356284 ], [ -110.65881824064482, 37.494100560409017 ], [ -110.65984649668185, 37.494112539168889 ], [ -110.6614028551502, 37.494167486483036 ], [ -110.66238669403441, 37.494246016718179 ], [ -110.66352324887963, 37.494325875186959 ], [ -110.66450102873722, 37.494495408274041 ], [ -110.665139615473, 37.494624312322983 ], [ -110.66561424145381, 37.494737425767724 ], [ -110.66621734620051, 37.494959965355442 ], [ -110.66673195616134, 37.495240840870991 ], [ -110.66702512275299, 37.495457994757771 ], [ -110.66722235354273, 37.495625302725117 ], [ -110.66758248017875, 37.496049957385836 ], [ -110.66766682615838, 37.49616286510615 ], [ -110.66793649553225, 37.496578250521459 ], [ -110.66810422862569, 37.497021291213599 ], [ -110.66812536249174, 37.497358460403674 ], [ -110.66813444166448, 37.497863249236005 ], [ -110.66812193198696, 37.498133622999852 ], [ -110.66809197389452, 37.498512111282288 ], [ -110.66795961860818, 37.499021009381401 ], [ -110.66788394739339, 37.499503025776356 ], [ -110.66777443513587, 37.499962412846166 ], [ -110.6675860876162, 37.500340455326182 ], [ -110.66735734154717, 37.500898656242526 ], [ -110.66711227292332, 37.501564974156629 ], [ -110.66696742044613, 37.50208284926341 ], [ -110.66663589934387, 37.502852578938636 ], [ -110.66623053046857, 37.503689701094459 ], [ -110.6659900283516, 37.504342508800271 ], [ -110.66587375560078, 37.505045242295729 ], [ -110.66575053757037, 37.506036391700938 ], [ -110.66561620285044, 37.506982441256902 ], [ -110.66562877211074, 37.507969467700775 ], [ -110.66560607078225, 37.509253843355182 ], [ -110.66568713210924, 37.510105859126234 ], [ -110.66576342196318, 37.510759561799567 ], [ -110.6656526735714, 37.511489350749812 ], [ -110.6654744143152, 37.512133319045851 ], [ -110.66531213465316, 37.512999067005005 ], [ -110.66503656436767, 37.5138942382804 ], [ -110.66469288860364, 37.514835184824484 ], [ -110.66442241294226, 37.515852953813649 ], [ -110.66426148975846, 37.516411339803831 ], [ -110.66413435011991, 37.517005875990179 ], [ -110.66404166152833, 37.517740220762036 ], [ -110.66391326492935, 37.518361793788046 ], [ -110.66357553601242, 37.519230644448619 ], [ -110.66345649143932, 37.519532260786875 ], [ -110.66327797339767, 37.519973418181543 ], [ -110.66306558195438, 37.520648832103639 ], [ -110.66288196456199, 37.521216164570674 ], [ -110.66274470609665, 37.521540262071255 ], [ -110.66255019366263, 37.522012920098128 ], [ -110.66208238719231, 37.522859761544808 ], [ -110.66180189652509, 37.52357463776017 ], [ -110.66145966224342, 37.524177567745028 ], [ -110.66121455465203, 37.524573462794052 ], [ -110.66092903926155, 37.525145006252359 ], [ -110.66049468065331, 37.526094691784692 ], [ -110.65982254384124, 37.52706622485438 ], [ -110.65924234424506, 37.527727050609492 ], [ -110.65904344744919, 37.527911255007616 ], [ -110.65881623532712, 37.528099884056758 ], [ -110.65849280227968, 37.528292741251896 ], [ -110.65802773314705, 37.528521241839208 ], [ -110.65773287860056, 37.528651084613763 ], [ -110.65743121184731, 37.528785413677845 ], [ -110.6568085111786, 37.52908105394053 ], [ -110.65599697941198, 37.529583453337743 ], [ -110.65501504670505, 37.530220553118298 ], [ -110.65459468622836, 37.530566347164651 ], [ -110.65428783417116, 37.530840363404806 ], [ -110.65395247670585, 37.531159363189012 ], [ -110.6535651221309, 37.531708055651841 ], [ -110.65296762434366, 37.532418373786491 ], [ -110.65231932937803, 37.53309699174482 ], [ -110.65178479313289, 37.533649751521949 ], [ -110.65131296203265, 37.534103544691419 ], [ -110.65096598151807, 37.534481991008271 ], [ -110.65048758071471, 37.535128651764204 ], [ -110.65016834469692, 37.535623452798596 ], [ -110.64995173138524, 37.535956312938005 ], [ -110.6497015960681, 37.536437797084631 ], [ -110.64958001428212, 37.536779951910873 ], [ -110.64935146411364, 37.537243472155808 ], [ -110.64893027733802, 37.537751487210166 ], [ -110.64810486528766, 37.538767563190333 ], [ -110.64757545446929, 37.539418566335122 ], [ -110.64704698790294, 37.540107426793519 ], [ -110.64683500292399, 37.540413254059864 ], [ -110.6462314774769, 37.541173093335907 ], [ -110.64583284379896, 37.541690178035964 ], [ -110.64541690497543, 37.542274811050476 ], [ -110.64489891094298, 37.542895189899149 ], [ -110.64434692736971, 37.543519970802727 ], [ -110.64376635594475, 37.544203250900118 ], [ -110.64341858617357, 37.544729494103983 ], [ -110.64300792768705, 37.545386242617148 ], [ -110.64257451392901, 37.546065454613782 ], [ -110.64207342888814, 37.546690378521106 ], [ -110.64128163486431, 37.547738054182645 ], [ -110.64062093629322, 37.548592332130148 ], [ -110.64013666896902, 37.549244339301133 ], [ -110.63971485281603, 37.549855974019657 ], [ -110.63924241157757, 37.550399850916165 ], [ -110.63870168963524, 37.551015625283732 ], [ -110.63815501499816, 37.551689966866213 ], [ -110.63765363698462, 37.552359938064626 ], [ -110.63724199382496, 37.552967087994709 ], [ -110.63662906456968, 37.553524042666716 ], [ -110.63583938031861, 37.554107489676809 ], [ -110.63470900426164, 37.554901695858526 ], [ -110.63383597347121, 37.555390229271879 ], [ -110.6332328957234, 37.555775939405883 ], [ -110.6325518245413, 37.556134363123633 ], [ -110.63149053039115, 37.556681782288699 ], [ -110.63029289930392, 37.557321604361604 ], [ -110.62942445197932, 37.557787585358682 ], [ -110.62857288746197, 37.558271640076576 ], [ -110.62787474338325, 37.558638996381248 ], [ -110.62724405397326, 37.559101203535946 ], [ -110.6269080452977, 37.559502145502677 ], [ -110.6264752400274, 37.560013646643931 ], [ -110.62569684339299, 37.560574526752404 ], [ -110.62526537341179, 37.560816523215664 ], [ -110.62441377022607, 37.561296040666996 ], [ -110.62353858125748, 37.561960253901162 ], [ -110.62284021910826, 37.562359126701601 ], [ -110.62218709490823, 37.562767153621891 ], [ -110.62153480713339, 37.563008429461171 ], [ -110.62067829353676, 37.563330167366047 ], [ -110.61985619918023, 37.563561874673788 ], [ -110.61926149767737, 37.563609532665048 ], [ -110.61856486217052, 37.563662266483924 ], [ -110.61773809108486, 37.563699251927396 ], [ -110.61688871504323, 37.563728046062458 ], [ -110.61604506922301, 37.563743332445611 ], [ -110.61492415207546, 37.563730668214149 ], [ -110.61378694907785, 37.563582737322854 ], [ -110.61303945534698, 37.56361634376325 ], [ -110.61139156070217, 37.563692052750405 ], [ -110.61013378493428, 37.563868176296076 ], [ -110.60833738697862, 37.564191223780661 ], [ -110.60693732502433, 37.564506550559507 ], [ -110.60609835760062, 37.564706558419921 ], [ -110.60515131746523, 37.565000840779604 ], [ -110.60404488802685, 37.565456824246354 ], [ -110.60314780438144, 37.565936034945352 ], [ -110.60216537744017, 37.566491566026642 ], [ -110.60154648328005, 37.566822978656795 ], [ -110.60108071339914, 37.567105331228497 ], [ -110.60053476169077, 37.567558667288516 ], [ -110.60015265669357, 37.568075650359596 ], [ -110.59969641735765, 37.568690627987081 ], [ -110.59946665865823, 37.569303668328345 ], [ -110.59916288585082, 37.569992170291137 ], [ -110.59894478572453, 37.570541253185766 ], [ -110.59871472973119, 37.571207470486982 ], [ -110.59854726646398, 37.571815312379208 ], [ -110.59839639946036, 37.572495318413154 ], [ -110.59833515562408, 37.573355899087623 ], [ -110.59823650223734, 37.573801731470802 ], [ -110.59824567185491, 37.574202863254015 ], [ -110.59826592393624, 37.574649100200489 ], [ -110.59820673482072, 37.575126613981119 ], [ -110.59828770356174, 37.575865094684346 ], [ -110.59833442350498, 37.576654835619827 ], [ -110.59845396747464, 37.577380828387319 ], [ -110.59856314714841, 37.578350149928362 ], [ -110.59868438475684, 37.578972492907099 ], [ -110.59886171862, 37.579694174704521 ], [ -110.59905397030836, 37.580802585387204 ], [ -110.59933573579825, 37.582115905520411 ], [ -110.59947913008041, 37.582832964092496 ], [ -110.59961110466361, 37.583568010639112 ], [ -110.59982067473416, 37.58461879186568 ], [ -110.60006960280754, 37.585723786777663 ], [ -110.60016172910197, 37.586499258004871 ], [ -110.60036728996927, 37.587243566002712 ], [ -110.60066823940582, 37.588154945605105 ], [ -110.60098729279783, 37.588859075614366 ], [ -110.60122171406664, 37.589504331214997 ], [ -110.60158035505269, 37.590221212088778 ], [ -110.60195015701599, 37.590970577938428 ], [ -110.60225768656522, 37.591716127334657 ], [ -110.60255913198453, 37.592541875238624 ], [ -110.60273758841078, 37.593065257201232 ], [ -110.60290419310665, 37.59368774712302 ], [ -110.60311025522375, 37.594346423304948 ], [ -110.6033276006624, 37.5950141504497 ], [ -110.60361313120421, 37.595641545552098 ], [ -110.60392031875645, 37.596458295324496 ], [ -110.60403106058175, 37.596937281800251 ], [ -110.604068707038, 37.597315072175249 ], [ -110.60416756321121, 37.597685857046649 ], [ -110.60428894099958, 37.598510094405768 ], [ -110.60431600116246, 37.598748140481831 ], [ -110.60432611851972, 37.599190735276025 ], [ -110.60430565437464, 37.599632326164318 ], [ -110.60425781095105, 37.600109879045277 ], [ -110.60412361865355, 37.60084853251665 ], [ -110.60397283688361, 37.60151051569715 ], [ -110.60377707233198, 37.602109253411442 ], [ -110.60348548382684, 37.602618435635314 ], [ -110.60326820831597, 37.602999875882489 ], [ -110.60296036681774, 37.603368392218485 ], [ -110.60256210681244, 37.603696042729503 ], [ -110.60202213541822, 37.604041240982852 ], [ -110.60134661986102, 37.604309364624498 ], [ -110.60047272093145, 37.604599346577047 ], [ -110.59977468155363, 37.60484034456934 ], [ -110.59949094741398, 37.604934023235927 ], [ -110.59906559885749, 37.605027220201684 ], [ -110.59841935583441, 37.605115157467431 ], [ -110.5976031987767, 37.605198005239544 ], [ -110.59644103885255, 37.605365292465734 ], [ -110.59514829529193, 37.605586201022483 ], [ -110.59395765406228, 37.605780406385932 ], [ -110.5928122499747, 37.605988275973537 ], [ -110.59200701291, 37.606143230232838 ], [ -110.59103190740059, 37.606284070283444 ], [ -110.58985811494298, 37.606500826207004 ], [ -110.58864446950663, 37.606752583955164 ], [ -110.58816793639457, 37.606878011531023 ], [ -110.58791839208448, 37.606931221100965 ], [ -110.58677290419625, 37.607148045097134 ], [ -110.58579133664861, 37.607428527485084 ], [ -110.58494050162707, 37.607628340571729 ], [ -110.5837949946562, 37.607845135522282 ], [ -110.582717105854, 37.608125252516295 ], [ -110.5820870806691, 37.608343852398576 ], [ -110.58087833145039, 37.608722636879861 ], [ -110.57989032153098, 37.609133741966183 ], [ -110.5792713047681, 37.609406446545165 ], [ -110.57868688295356, 37.609571110131796 ], [ -110.57782414530227, 37.609864568966536 ], [ -110.57697305238958, 37.610101278565523 ], [ -110.57599748419698, 37.610309593195389 ], [ -110.57529972371665, 37.610478339394021 ], [ -110.57452265072087, 37.610646795526755 ], [ -110.57394953886876, 37.61081147634367 ], [ -110.57346232631853, 37.611012518602323 ], [ -110.57262697077256, 37.611266379143714 ], [ -110.57153714441706, 37.611636484707354 ], [ -110.57045834714197, 37.612057095508767 ], [ -110.56973114740246, 37.612414082171611 ], [ -110.5690554156775, 37.612686526048648 ], [ -110.56819166144027, 37.613143053450024 ], [ -110.56781084504739, 37.613357981630443 ], [ -110.56737807390641, 37.613739466502984 ], [ -110.56700168917665, 37.614166223790932 ], [ -110.56658981770144, 37.614849732111971 ], [ -110.56627983589759, 37.615547133564007 ], [ -110.56595731246442, 37.616451796682213 ], [ -110.56580718208541, 37.616937969138668 ], [ -110.56570748844032, 37.617518967906854 ], [ -110.56552291536102, 37.618081627202301 ], [ -110.56544073916132, 37.618572555935962 ], [ -110.56533982823944, 37.619361759680011 ], [ -110.56519782237885, 37.620396878062174 ], [ -110.56509822412357, 37.62095984947431 ], [ -110.56491830544091, 37.621693779478605 ], [ -110.56468581382229, 37.622697917535952 ], [ -110.56459730371715, 37.623301489544389 ], [ -110.56448444558926, 37.624193400672965 ], [ -110.56421910132957, 37.624999121109425 ], [ -110.56417298016426, 37.62532884150108 ], [ -110.56416389689699, 37.625719989837251 ], [ -110.56416176548277, 37.626085024945795 ], [ -110.56418622811745, 37.626747600655186 ], [ -110.56410021677941, 37.627891985343261 ], [ -110.56399744053759, 37.628995747482172 ], [ -110.5640554006107, 37.629744073978642 ], [ -110.56409243322128, 37.630194880835745 ], [ -110.56411773850368, 37.630713244822346 ], [ -110.56406415519869, 37.631155604763244 ], [ -110.56405013696819, 37.631615236295701 ], [ -110.56401295725642, 37.632159508142522 ], [ -110.56393017536934, 37.632749579715508 ], [ -110.56391025223249, 37.633249749561159 ], [ -110.56384415228057, 37.63389396298551 ], [ -110.56379560464549, 37.634443600559557 ], [ -110.56365683550767, 37.634916290588109 ], [ -110.56360873381061, 37.635389315800026 ], [ -110.56363445881937, 37.635835573850954 ], [ -110.56357373093302, 37.636529380347589 ], [ -110.56346305382893, 37.637042734133502 ], [ -110.56336990359475, 37.63746601874206 ], [ -110.56326541824797, 37.637889261285238 ], [ -110.56302953381996, 37.638492284859964 ], [ -110.56255986727849, 37.63933780274705 ], [ -110.56223380015119, 37.639854862987988 ], [ -110.56168588673923, 37.640510805730877 ], [ -110.56119543152062, 37.641031758810897 ], [ -110.56064323966439, 37.641448825998886 ], [ -110.55984761294987, 37.641819915688892 ], [ -110.55938156247264, 37.642043510543417 ], [ -110.55902890940479, 37.642258514069454 ], [ -110.55852948965718, 37.642373820235512 ], [ -110.55771293660757, 37.642447375584943 ], [ -110.55724249239005, 37.642454624360198 ], [ -110.55686251167644, 37.642498264605891 ], [ -110.55629598998765, 37.642460081788826 ], [ -110.55539549786329, 37.64235303778694 ], [ -110.55467104568599, 37.642188064583841 ], [ -110.55407133174377, 37.64201454510691 ], [ -110.55358518254262, 37.641805398838841 ], [ -110.55317821619101, 37.641623590625528 ], [ -110.55267013257607, 37.641292676882905 ], [ -110.55222427952297, 37.640980925250965 ], [ -110.55164296946704, 37.640576720741365 ], [ -110.55105073272209, 37.640105772756293 ], [ -110.55027769831572, 37.639543998924452 ], [ -110.54959551221732, 37.638955526716849 ], [ -110.54895276096613, 37.638407761526722 ], [ -110.54830405203219, 37.637909543610419 ], [ -110.54761086307533, 37.637271444105025 ], [ -110.54691180012577, 37.636669371472181 ], [ -110.54621236474496, 37.636130386933772 ], [ -110.5451163659164, 37.635572744518576 ], [ -110.54456831215525, 37.63530383400478 ], [ -110.54389052683273, 37.634936173576968 ], [ -110.54350612337865, 37.634781459331776 ], [ -110.54316746940201, 37.634559320580038 ], [ -110.54298165357196, 37.634364813136877 ], [ -110.54230955134763, 37.633997165625033 ], [ -110.54158626189103, 37.633660862269288 ], [ -110.54083862445711, 37.633414593608421 ], [ -110.54026369708166, 37.63328166066065 ], [ -110.53960581643787, 37.633184454803676 ], [ -110.53897599229279, 37.633132421853475 ], [ -110.53864837714593, 37.633144661345689 ], [ -110.53778649014203, 37.633231421911923 ], [ -110.53648692564346, 37.633532778835253 ], [ -110.53503390658304, 37.633904722500731 ], [ -110.53474428153901, 37.634003629346431 ], [ -110.53438054425402, 37.634173448763683 ], [ -110.53341903781531, 37.634782560454532 ], [ -110.53274700238792, 37.635316197202762 ], [ -110.53223957813641, 37.635805415877407 ], [ -110.53189091006996, 37.636280840889654 ], [ -110.53175354205338, 37.636497518261919 ], [ -110.53160535431419, 37.636632130750421 ], [ -110.53140576764916, 37.636829632576166 ], [ -110.531244516833, 37.637058833201621 ], [ -110.53106263742724, 37.637324005121435 ], [ -110.53039403942799, 37.638205558170569 ], [ -110.52955964233952, 37.639314484658826 ], [ -110.52935961661085, 37.639579581461149 ], [ -110.5292335466181, 37.63979990616091 ], [ -110.52909525976403, 37.640159889252715 ], [ -110.52892598918038, 37.64093887029604 ], [ -110.52873464370398, 37.641623122405221 ], [ -110.52845848418814, 37.642275488354535 ], [ -110.52806096708861, 37.643296916304465 ], [ -110.5276587131964, 37.644169603182775 ], [ -110.52716479801076, 37.645195148413563 ], [ -110.52659186566461, 37.646166294117592 ], [ -110.52628337020036, 37.646728390981131 ], [ -110.52595021859302, 37.647245321086309 ], [ -110.52550455445075, 37.647806864510265 ], [ -110.52501391441882, 37.648309638257935 ], [ -110.52472247414642, 37.648682518898916 ], [ -110.52425409196528, 37.649248472562945 ], [ -110.52375796752948, 37.649719672045165 ], [ -110.52343239276112, 37.650110438284138 ], [ -110.52285092097792, 37.650630862492164 ], [ -110.52226383081849, 37.651142247657731 ], [ -110.52195073356974, 37.65135279311513 ], [ -110.5214954135031, 37.651643881106587 ], [ -110.52083488181742, 37.652114401012405 ], [ -110.52000915473644, 37.65271043203672 ], [ -110.5192859932009, 37.65322124835761 ], [ -110.51851142981846, 37.653790437153638 ], [ -110.51786809810449, 37.654224956977956 ], [ -110.51730484378261, 37.654547134086457 ], [ -110.51654211406313, 37.65503523804027 ], [ -110.51575024255204, 37.655644897538721 ], [ -110.51501016491389, 37.656133084423814 ], [ -110.51421377529816, 37.656562447971545 ], [ -110.51355380104501, 37.656933781983049 ], [ -110.51315609918603, 37.657071848086787 ], [ -110.51265110782613, 37.657146376230159 ], [ -110.51212949349626, 37.657162246732589 ], [ -110.5115521688308, 37.657029164108096 ], [ -110.51097599900847, 37.656720323267898 ], [ -110.51013528536444, 37.656126461011681 ], [ -110.50937385255885, 37.655546442528141 ], [ -110.50865210949459, 37.654966584431996 ], [ -110.50798670307893, 37.654441036954204 ], [ -110.50720824008765, 37.653869946736712 ], [ -110.50662176041128, 37.653412321303229 ], [ -110.50615270720395, 37.653027291364857 ], [ -110.50569669468203, 37.652727940991447 ], [ -110.50518385556991, 37.652450883868148 ], [ -110.50466266592495, 37.652236882881461 ], [ -110.50425522477884, 37.652136024512572 ], [ -110.50396651389411, 37.652080730782529 ], [ -110.50364392117359, 37.652006365759874 ], [ -110.50319755103068, 37.651793574428282 ], [ -110.50283672032013, 37.651503627149445 ], [ -110.50232954747344, 37.651059834552711 ], [ -110.50199742453901, 37.650715925705164 ], [ -110.5017774887944, 37.650548250081059 ], [ -110.50152867226967, 37.650461572154036 ], [ -110.50126267175681, 37.65040186110113 ], [ -110.50072311627935, 37.650395072085786 ], [ -110.50009929896068, 37.650613257273484 ], [ -110.4996389870519, 37.650791572705593 ], [ -110.49921219650766, 37.651042135416333 ], [ -110.49889333702527, 37.65125710170355 ], [ -110.49862560886331, 37.651454257749656 ], [ -110.4982326372825, 37.651732000635945 ], [ -110.49798084793491, 37.652086956531107 ], [ -110.49766497703854, 37.652698519312615 ], [ -110.49734136706761, 37.653616501852419 ], [ -110.49697157626551, 37.654656867858073 ], [ -110.49682080215679, 37.655160070552569 ], [ -110.49675008192979, 37.655559961155959 ], [ -110.49673478498339, 37.656146664268363 ], [ -110.49692297828328, 37.656818960712535 ], [ -110.49718870972708, 37.657761987422759 ], [ -110.49726716373623, 37.658569015361429 ], [ -110.49733995266278, 37.658871272280841 ], [ -110.4973829921117, 37.659213962387483 ], [ -110.49732375996065, 37.659591368675152 ], [ -110.49719667370869, 37.659943248360221 ], [ -110.49702436461833, 37.660276007061483 ], [ -110.49654341873443, 37.660981501839416 ], [ -110.49592568202682, 37.661962217947703 ], [ -110.49560368690071, 37.662464686571688 ], [ -110.49532825754213, 37.662954734845435 ], [ -110.49517040199183, 37.663494858986134 ], [ -110.494978721781, 37.66434129111888 ], [ -110.49476423878215, 37.665205651783239 ], [ -110.49456985387096, 37.666115164654606 ], [ -110.49445969555494, 37.666475225459543 ], [ -110.49424700199421, 37.66690695309557 ], [ -110.4939892889158, 37.667288913917467 ], [ -110.49355417363174, 37.667913472187422 ], [ -110.49290303545096, 37.668622726734675 ], [ -110.49265143898933, 37.668937110899648 ], [ -110.49234293822884, 37.669281894875084 ], [ -110.49198915951158, 37.669614765695009 ], [ -110.49116858573646, 37.670224134003469 ], [ -110.49016096800875, 37.670823674806726 ], [ -110.4890792906792, 37.67147245931973 ], [ -110.48841887431382, 37.671870689026534 ], [ -110.48770510117632, 37.672606682391077 ], [ -110.48712236720417, 37.673248601456571 ], [ -110.48662448222031, 37.673917926825915 ], [ -110.4863265826142, 37.674362788485297 ], [ -110.48613064185994, 37.674821613585856 ], [ -110.48602575733928, 37.675231261985694 ], [ -110.48600052895365, 37.675600697565699 ], [ -110.48598103232425, 37.675961144792787 ], [ -110.48603536820339, 37.676303887160678 ], [ -110.48624170422615, 37.676805024527319 ], [ -110.48635875294329, 37.677098466705552 ], [ -110.48644735959843, 37.67740530486487 ], [ -110.48647858380163, 37.677811039428931 ], [ -110.48640203141203, 37.678387557382926 ], [ -110.48633573063459, 37.678792867171346 ], [ -110.48622995600401, 37.679166458388949 ], [ -110.48598391800741, 37.679652104480695 ], [ -110.48560576884024, 37.680218293543902 ], [ -110.48509521768618, 37.680906484167799 ], [ -110.48471107955893, 37.681516809204403 ], [ -110.48452313012753, 37.681799906656067 ], [ -110.48441277453358, 37.682177982638706 ], [ -110.48443806947189, 37.682619744643382 ], [ -110.48439652969836, 37.6837056648627 ], [ -110.48454918952324, 37.684589634786654 ], [ -110.48456444934794, 37.685662283019546 ], [ -110.48467147530228, 37.686585711516614 ], [ -110.48477783661896, 37.687605579043542 ], [ -110.48478553055349, 37.688132889896572 ], [ -110.48474125186361, 37.688795172901266 ], [ -110.48470959252222, 37.689272738636866 ], [ -110.4847391277298, 37.689921824101738 ], [ -110.48465976128999, 37.690737179344936 ], [ -110.48454577412156, 37.69163800925584 ], [ -110.48447372819378, 37.692214544225038 ], [ -110.4843331656904, 37.692857477752227 ], [ -110.48400989249731, 37.69367717324743 ], [ -110.48362865565642, 37.694675978096775 ], [ -110.48355342877188, 37.694891967259267 ], [ -110.48354027318169, 37.69515329461133 ], [ -110.48358968336166, 37.695388757468756 ], [ -110.48371152131905, 37.695812013526961 ], [ -110.48382790169832, 37.696204600415022 ], [ -110.48398332728374, 37.6966919973977 ], [ -110.48422131880051, 37.697378047294698 ], [ -110.48448090702897, 37.697730700046719 ], [ -110.48481798519492, 37.698196356677109 ], [ -110.48514986346464, 37.698594390091614 ], [ -110.48554422007049, 37.698980076582608 ], [ -110.48600708835349, 37.69930116486632 ], [ -110.48657145356987, 37.699709220692604 ], [ -110.48705645240766, 37.700112421946081 ], [ -110.48765402861103, 37.700641394827066 ], [ -110.48797452117559, 37.701049285325389 ], [ -110.48826654055976, 37.701474176573683 ], [ -110.48836712127624, 37.701694536747581 ], [ -110.48839333700137, 37.702006509506383 ], [ -110.48834015313957, 37.702317236402735 ], [ -110.48810491082924, 37.702708292404267 ], [ -110.48773501560237, 37.703049190029091 ], [ -110.48720883661437, 37.703515592580807 ], [ -110.48615626006361, 37.703984206536795 ], [ -110.48587185168672, 37.704100139170571 ], [ -110.48508734015564, 37.704353593776922 ], [ -110.4842011016046, 37.704552518609773 ], [ -110.48321846504736, 37.704746507670173 ], [ -110.48220708699431, 37.704994441861118 ], [ -110.4810537747975, 37.705259769261012 ], [ -110.48039452437972, 37.705441637683712 ], [ -110.47976438726793, 37.705515471773154 ], [ -110.4793039704801, 37.705653144914173 ], [ -110.47851355678952, 37.70609580791384 ], [ -110.47743088816692, 37.706636316439678 ], [ -110.47655356979654, 37.707173220129036 ], [ -110.47591501303887, 37.707634566074162 ], [ -110.47508742576889, 37.708355550068838 ], [ -110.47423071563365, 37.709181853279659 ], [ -110.47304743013845, 37.710302325501466 ], [ -110.47206063816904, 37.711227176783858 ], [ -110.47162119818194, 37.711599257947938 ], [ -110.47099779648532, 37.712313015460289 ], [ -110.47037486393479, 37.712959172341129 ], [ -110.46988229630979, 37.71361943192565 ], [ -110.46962426221113, 37.714005840805768 ], [ -110.46948009832282, 37.714334175471514 ], [ -110.4693082763947, 37.714563239808392 ], [ -110.46911344069434, 37.714837266453486 ], [ -110.46905462244561, 37.715129931858947 ], [ -110.46894771908187, 37.715800936641074 ], [ -110.46902270976129, 37.716580919430164 ], [ -110.46914319615537, 37.717027617212295 ], [ -110.4693368959658, 37.717708988525033 ], [ -110.46950777845514, 37.718408283251392 ], [ -110.46964907763531, 37.719278696006555 ], [ -110.46965290596303, 37.720333261380105 ], [ -110.46967638863113, 37.721018372552955 ], [ -110.46966260028977, 37.721360813265719 ], [ -110.46952735820435, 37.722027183757476 ], [ -110.46923841752913, 37.722764967955882 ], [ -110.46914574558561, 37.723030440896956 ], [ -110.46897368563086, 37.723448781028843 ], [ -110.46874822861602, 37.723875893485051 ], [ -110.46830073593011, 37.724567894383128 ], [ -110.46726685416337, 37.725536654951561 ], [ -110.46631957050018, 37.726293987590303 ], [ -110.46531562753064, 37.72703753566023 ], [ -110.46409642473598, 37.727729622632374 ], [ -110.46313468807574, 37.728122729551245 ], [ -110.4613715017497, 37.728709558781041 ], [ -110.45960861533825, 37.729251296797756 ], [ -110.45777676209121, 37.729909862875353 ], [ -110.45686098798093, 37.730216602847193 ], [ -110.45589318433366, 37.730653787076648 ], [ -110.45506167794369, 37.731073567022726 ], [ -110.45420799525286, 37.731421132700568 ], [ -110.45355293019945, 37.731765106425044 ], [ -110.45259457085926, 37.732455578218712 ], [ -110.45190969678818, 37.732992286866818 ], [ -110.45139576375611, 37.733431543206216 ], [ -110.45089190840285, 37.734042095064723 ], [ -110.45020563445748, 37.7347644590267 ], [ -110.44979812398165, 37.735388975141568 ], [ -110.44941283693885, 37.736076685964072 ], [ -110.44911326047765, 37.736683677234304 ], [ -110.44875606541152, 37.73740756979295 ], [ -110.44845711335685, 37.737928936778893 ], [ -110.44832929725891, 37.738329425877694 ], [ -110.44812607071142, 37.738950385042678 ], [ -110.44791582729556, 37.739751574790631 ], [ -110.44786413708985, 37.740598572808366 ], [ -110.44773048716667, 37.741783181343536 ], [ -110.44764792519838, 37.742201907815755 ], [ -110.44758828958868, 37.742590096804804 ], [ -110.44758107694938, 37.742949689236873 ], [ -110.44757752663681, 37.743427371573148 ], [ -110.44764437225344, 37.744207325545446 ], [ -110.44765573741756, 37.744968993032366 ], [ -110.4477668776012, 37.746051095974813 ], [ -110.44783687119755, 37.746560668766293 ], [ -110.44786186562303, 37.747015951589766 ], [ -110.44778497347377, 37.747434704333024 ], [ -110.44771634984286, 37.748268102058788 ], [ -110.44768093951851, 37.749214320009408 ], [ -110.44756751219691, 37.749966388822344 ], [ -110.44752694232095, 37.750232087401073 ], [ -110.44751167526006, 37.750606062690174 ], [ -110.44753526559138, 37.7510973913935 ], [ -110.44745191648836, 37.751772988842113 ], [ -110.44746468736091, 37.752345385307386 ], [ -110.44744891241578, 37.752940180823188 ], [ -110.44748421869193, 37.753535215755925 ], [ -110.44746807488367, 37.754179581868847 ], [ -110.44741807688374, 37.754796749672998 ], [ -110.44739662493298, 37.755391518315719 ], [ -110.44732465927632, 37.755909438088892 ], [ -110.44713316232813, 37.756471862937538 ], [ -110.44694730487534, 37.757038820460558 ], [ -110.44665296878664, 37.757689992106052 ], [ -110.44622692173161, 37.758495570541044 ], [ -110.4459785472898, 37.759071245691175 ], [ -110.44581578250222, 37.759584230714083 ], [ -110.44568841119468, 37.759918020016698 ], [ -110.44526850154394, 37.760658728720415 ], [ -110.44475778246949, 37.761396304051232 ], [ -110.4445803404812, 37.761592856095149 ], [ -110.44424273904453, 37.76195179085412 ], [ -110.44390016647716, 37.762216062999016 ], [ -110.44349528606959, 37.762462013599155 ], [ -110.44296031843265, 37.762644255871457 ], [ -110.44269829027725, 37.762764694650585 ], [ -110.44217252076946, 37.763082174161887 ], [ -110.44148970333771, 37.763448479460656 ], [ -110.44085595035578, 37.763932184568247 ], [ -110.44024064527422, 37.764226697609907 ], [ -110.43975012442745, 37.764534419123137 ], [ -110.43924279434756, 37.764812315179526 ], [ -110.43855874320916, 37.765187610571438 ], [ -110.43791982541616, 37.765599169827723 ], [ -110.43719031290784, 37.765978746911109 ], [ -110.4365516200976, 37.76635875370156 ], [ -110.43596421664363, 37.766711963038574 ], [ -110.43523981170118, 37.76716365753083 ], [ -110.43477215689693, 37.76744532949899 ], [ -110.43431647691796, 37.767645037442634 ], [ -110.43400328482191, 37.767770618956014 ], [ -110.43370699151689, 37.767913405815484 ], [ -110.43311385108215, 37.768271079770265 ], [ -110.43253123218108, 37.768736959090262 ], [ -110.43210893794539, 37.769023345346923 ], [ -110.4315501184924, 37.769345124133189 ], [ -110.43066071856519, 37.769836553204733 ], [ -110.43004501319534, 37.770171569623386 ], [ -110.42950833026519, 37.77056555078984 ], [ -110.42918290463022, 37.770802823062276 ], [ -110.42889631504983, 37.77115745344517 ], [ -110.42869550306739, 37.771431380757676 ], [ -110.42848302322048, 37.771745810240283 ], [ -110.4281617738484, 37.77217688231331 ], [ -110.42774933876994, 37.772652576358333 ], [ -110.42721738716328, 37.773312457278323 ], [ -110.42711855678084, 37.773465200124583 ], [ -110.42700306457357, 37.773717006336156 ], [ -110.42681369751418, 37.773977466230292 ], [ -110.42662478155469, 37.774179342635229 ], [ -110.42647006760598, 37.774363358935084 ], [ -110.42631977661358, 37.774709632935917 ], [ -110.42617505705726, 37.77506945354903 ], [ -110.42608185749776, 37.775374544801394 ], [ -110.4260446507183, 37.775780855769355 ], [ -110.42619470137652, 37.776200697100094 ], [ -110.42641675024743, 37.776855230061734 ], [ -110.42673058318721, 37.777388531894182 ], [ -110.42719560583608, 37.778048751702428 ], [ -110.42757252867705, 37.778501239756963 ], [ -110.42774755111552, 37.778776990253995 ], [ -110.42786009656483, 37.778908227116126 ], [ -110.428091491278, 37.779089612975369 ], [ -110.42815370252933, 37.779121460851961 ], [ -110.42841978929023, 37.779221896290643 ], [ -110.4287202549874, 37.779281938747118 ], [ -110.429424363035, 37.77927543594685 ], [ -110.43000998725519, 37.779171014079189 ], [ -110.43111356180113, 37.778901446925474 ], [ -110.43203530639506, 37.77864901934462 ], [ -110.4326731642043, 37.778395218024201 ], [ -110.43349916923509, 37.778038666941519 ], [ -110.43433132469187, 37.777619047631816 ], [ -110.43487288109729, 37.777334127312272 ], [ -110.43525461969395, 37.777159300138031 ], [ -110.43555665897176, 37.777012030677078 ], [ -110.43590445946818, 37.776819913850417 ], [ -110.43673186770675, 37.776274070814615 ], [ -110.43751921462186, 37.77576858976046 ], [ -110.43814659522513, 37.775393031201666 ], [ -110.43866644040067, 37.774971891355655 ], [ -110.43945389648191, 37.774448371420704 ], [ -110.43992715351571, 37.774180227622779 ], [ -110.44076849833618, 37.773886789944186 ], [ -110.44103731390794, 37.773775401153074 ], [ -110.44150376507218, 37.773655935481415 ], [ -110.4420326306315, 37.773541270080521 ], [ -110.44271481393109, 37.773422820913467 ], [ -110.4433804363878, 37.773241197574748 ], [ -110.44391504091568, 37.773117537665335 ], [ -110.44480865584762, 37.772815304510353 ], [ -110.44576467885544, 37.772517864656422 ], [ -110.4469297419183, 37.772356595473283 ], [ -110.44792538636223, 37.772226067145724 ], [ -110.44850946652252, 37.772165710118735 ], [ -110.44889524520039, 37.772203567536756 ], [ -110.44932704314959, 37.772160520452545 ], [ -110.44964432923994, 37.772094404156732 ], [ -110.45039491476891, 37.772088894181508 ], [ -110.45149784956649, 37.77203544773073 ], [ -110.45258118160294, 37.772022459045949 ], [ -110.45364861738069, 37.772009386698535 ], [ -110.45427316947291, 37.772003267599644 ], [ -110.45486956738395, 37.771965468934312 ], [ -110.45560198477698, 37.771959841735097 ], [ -110.45618673041392, 37.771962541731995 ], [ -110.4564598270677, 37.771882683399369 ], [ -110.45703456902811, 37.771700563502442 ], [ -110.45772888295289, 37.771470320089655 ], [ -110.4584749897509, 37.771143869883645 ], [ -110.45889660449691, 37.770938504185438 ], [ -110.45931234298259, 37.770760149454631 ], [ -110.459710589298, 37.770644805104197 ], [ -110.46023264816223, 37.770678743588952 ], [ -110.46088491979994, 37.770762847887809 ], [ -110.46120257330092, 37.77080035332542 ], [ -110.46155373396252, 37.770914622804113 ], [ -110.46198936615885, 37.771123915021462 ], [ -110.46261243686966, 37.771478270978655 ], [ -110.4631202538522, 37.771755486811529 ], [ -110.46358294634969, 37.772149666004744 ], [ -110.46396032316964, 37.772565988177867 ], [ -110.46443200663019, 37.773289184853432 ], [ -110.46493792544766, 37.773990002168887 ], [ -110.46553300454345, 37.774925563516582 ], [ -110.4660714212649, 37.775847345305117 ], [ -110.46642430694092, 37.776515916506561 ], [ -110.46679494366569, 37.777085422338828 ], [ -110.4671153578721, 37.777375292407058 ], [ -110.46749559732999, 37.777557274251542 ], [ -110.46782987034858, 37.777657027673641 ], [ -110.46843030076249, 37.777854421781356 ], [ -110.46875891813966, 37.777951443113444 ], [ -110.46903625730152, 37.778073469277651 ], [ -110.46926200896205, 37.778263762328386 ], [ -110.46957731617212, 37.778634720969471 ], [ -110.46989763756572, 37.779258069286463 ], [ -110.47014236480844, 37.77981347821958 ], [ -110.47037004026114, 37.780531046481642 ], [ -110.47056371070151, 37.781240349616489 ], [ -110.4707694025315, 37.781856871032254 ], [ -110.47108225318918, 37.782575721561194 ], [ -110.47146421528208, 37.783158782865563 ], [ -110.4717263346715, 37.783826930427061 ], [ -110.47192118709113, 37.784373098563748 ], [ -110.47203571472812, 37.785036077175583 ], [ -110.47209528945865, 37.785441935117412 ], [ -110.4720981467341, 37.785838525766174 ], [ -110.47207797044088, 37.786280078845948 ], [ -110.47202240962498, 37.786906242519379 ], [ -110.47206334766682, 37.787537345092773 ], [ -110.47211379577001, 37.788268535927507 ], [ -110.47226357561159, 37.788926263967717 ], [ -110.47232139189148, 37.78957997466258 ], [ -110.47243528977693, 37.790333080777373 ], [ -110.47251075306124, 37.790901245562559 ], [ -110.47269911149495, 37.79156545468598 ], [ -110.47298816633202, 37.792444626242201 ], [ -110.4732301913608, 37.793549816061415 ], [ -110.47327899712151, 37.793874506625137 ], [ -110.47335696533342, 37.794091170068995 ], [ -110.47346836754723, 37.794398114081609 ], [ -110.47356410899573, 37.794511205923996 ], [ -110.47368247039437, 37.79463791841976 ], [ -110.47385758926929, 37.794769390838525 ], [ -110.47416325990379, 37.794910458873289 ], [ -110.47455421134757, 37.795038386814007 ], [ -110.47516096368837, 37.795167275004815 ], [ -110.47585829475599, 37.795337122120699 ], [ -110.47636825510801, 37.795501625922427 ], [ -110.4766508680019, 37.795692157180582 ], [ -110.47694449082607, 37.795932308794704 ], [ -110.47717574167473, 37.796158663221249 ], [ -110.47730442211032, 37.796434134316449 ], [ -110.47735350146769, 37.79672277183515 ], [ -110.47738214689898, 37.797493520444206 ], [ -110.47737751152809, 37.7981514573694 ], [ -110.47736387350521, 37.798474967716274 ], [ -110.47729951518231, 37.798903706461196 ], [ -110.47718209506117, 37.799286242790835 ], [ -110.47694980884418, 37.800010767346109 ], [ -110.47669572258422, 37.800604504388225 ], [ -110.47648243763973, 37.801049705800928 ], [ -110.47602794025434, 37.801872384812995 ], [ -110.47578501871328, 37.802330972689312 ], [ -110.47547560617834, 37.802874888518616 ], [ -110.47511377758484, 37.803441102709925 ], [ -110.47499272020606, 37.803692930260894 ], [ -110.47484233856144, 37.804075316991124 ], [ -110.47449677180006, 37.80474975889004 ], [ -110.47412433396018, 37.805207765241519 ], [ -110.4738725087842, 37.80547703393426 ], [ -110.47361557779415, 37.805665161330317 ], [ -110.47327885659399, 37.806051219678999 ], [ -110.47306446324156, 37.806487396328571 ], [ -110.47292025816178, 37.806797703198406 ], [ -110.47281575312712, 37.807116299333593 ], [ -110.47261451628138, 37.807458797707511 ], [ -110.47214523800208, 37.807952416326586 ], [ -110.47172200304543, 37.808360615074882 ], [ -110.47141920574222, 37.808606215670906 ], [ -110.47114543628513, 37.808763617440633 ], [ -110.47071885935452, 37.808842819459791 ], [ -110.4700476879397, 37.808970491847816 ], [ -110.46966661309865, 37.809040881643753 ], [ -110.46939397346168, 37.809039653908648 ], [ -110.46890071792298, 37.808911247757933 ], [ -110.46854381573579, 37.808778948233837 ], [ -110.46788623262935, 37.808595717781863 ], [ -110.46724472132242, 37.80854775279478 ], [ -110.46627909704821, 37.808547888324057 ], [ -110.46557468565412, 37.80855821436807 ], [ -110.46489883647394, 37.808546133206114 ], [ -110.46421704712159, 37.808570073530483 ], [ -110.4634616136354, 37.808566635222824 ], [ -110.46250699006413, 37.8086163619517 ], [ -110.46183048039677, 37.808695292421433 ], [ -110.46117128429987, 37.808736443201887 ], [ -110.46034713242773, 37.808809281864725 ], [ -110.45934513961507, 37.808966923051742 ], [ -110.45843058155151, 37.809129464246944 ], [ -110.45771440864463, 37.809193767741782 ], [ -110.45674817599993, 37.809275841443146 ], [ -110.45606631837514, 37.809307846025291 ], [ -110.45493513716022, 37.809419787591132 ], [ -110.45390566191317, 37.809604294532427 ], [ -110.45343906977212, 37.80971479419371 ], [ -110.45285386055058, 37.809734610223046 ], [ -110.45202427651104, 37.809771312994833 ], [ -110.45130859253047, 37.809767981609461 ], [ -110.45084824303214, 37.809801888817127 ], [ -110.45046791460729, 37.809768569389199 ], [ -110.44983305528912, 37.8095898508411 ], [ -110.44909662866149, 37.809320523044001 ], [ -110.44796331385099, 37.808954693976389 ], [ -110.44731206601618, 37.808690260714293 ], [ -110.44685958658361, 37.808431263899266 ], [ -110.44609014655701, 37.808022059421191 ], [ -110.4454001993988, 37.807617730734187 ], [ -110.44470961862892, 37.807299019368294 ], [ -110.4442176345561, 37.807008280361607 ], [ -110.44371587019441, 37.806658908027124 ], [ -110.44279111167965, 37.806212896082904 ], [ -110.44228296801515, 37.805958124916096 ], [ -110.44175627963381, 37.805752835679634 ], [ -110.44114933130768, 37.805646307369962 ], [ -110.44013354866775, 37.805524314000799 ], [ -110.4396618615819, 37.805558123697828 ], [ -110.43920109047546, 37.805650568556253 ], [ -110.43884093969352, 37.805806582587671 ], [ -110.43828772986359, 37.806254600508517 ], [ -110.43770473928328, 37.806734019437236 ], [ -110.43747005629501, 37.806971745829721 ], [ -110.43722325975214, 37.80730855782631 ], [ -110.43686139228569, 37.807838600597215 ], [ -110.4365513510393, 37.808275154009102 ], [ -110.43634321611103, 37.808755457018485 ], [ -110.43624760899479, 37.809376902292357 ], [ -110.43615251423952, 37.809930751753051 ], [ -110.43597382810249, 37.810272393448678 ], [ -110.43576523100658, 37.810812179366742 ], [ -110.4354790147909, 37.811847312286105 ], [ -110.43547602963389, 37.812239366914625 ], [ -110.43544340790271, 37.812793514884916 ], [ -110.4354449016873, 37.81334331976452 ], [ -110.43543493182754, 37.813906589264988 ], [ -110.43539290439708, 37.81420381933188 ], [ -110.43540224025803, 37.814469749805355 ], [ -110.43546280269047, 37.814722406173672 ], [ -110.43555173328804, 37.814979704978228 ], [ -110.43563258258229, 37.815552422575017 ], [ -110.43561365424824, 37.815800191405089 ], [ -110.43556959816178, 37.816214581664582 ], [ -110.43560234701461, 37.816539209191582 ], [ -110.43564884031225, 37.81714781429622 ], [ -110.43571771377644, 37.817801591889896 ], [ -110.43580517393131, 37.818252664340484 ], [ -110.4358471895098, 37.818703519046998 ], [ -110.43579259876198, 37.819158417536642 ], [ -110.43556768714703, 37.819598980322638 ], [ -110.43547504443356, 37.819828369566345 ], [ -110.43542695511782, 37.82017514215179 ], [ -110.43541343094114, 37.820458988918119 ], [ -110.4352909746773, 37.820873002915562 ], [ -110.43523637875199, 37.821327900940219 ], [ -110.43514208425742, 37.821773595465899 ], [ -110.4350654154498, 37.822142763379382 ], [ -110.43505770782158, 37.822408611776844 ], [ -110.43503788237223, 37.822773545726818 ], [ -110.43491517950604, 37.823219103686469 ], [ -110.43480455900709, 37.823570082317133 ], [ -110.43476889157115, 37.823777211562522 ], [ -110.43479537239459, 37.824029704336425 ], [ -110.43488283379567, 37.824480777009917 ], [ -110.43483712034974, 37.825260187293104 ], [ -110.43477428643315, 37.826049429657644 ], [ -110.43471501477832, 37.827116291100189 ], [ -110.43459141619465, 37.828422590761342 ], [ -110.43442428688975, 37.829476315510178 ], [ -110.43424110571959, 37.830399273481135 ], [ -110.43382207883599, 37.831699645526768 ], [ -110.43354387857975, 37.832563560397958 ], [ -110.43321146958303, 37.833530863621249 ], [ -110.43301435548616, 37.834043658405292 ], [ -110.43284726967913, 37.834344790884487 ], [ -110.43257188085495, 37.834690466571239 ], [ -110.43224951422548, 37.835234202064555 ], [ -110.43202876624986, 37.835715335434202 ], [ -110.43183298177576, 37.836201095297056 ], [ -110.43146466909685, 37.836806796770816 ], [ -110.43110322996604, 37.837256604643159 ], [ -110.43068910192436, 37.837759333590441 ], [ -110.43011120930539, 37.838423503335854 ], [ -110.42961920819224, 37.838853747233351 ], [ -110.42887516602846, 37.839544145011715 ], [ -110.42793135777765, 37.840346230656614 ], [ -110.42735315469456, 37.840897722026298 ], [ -110.42694168622324, 37.841197657069657 ], [ -110.42659822925224, 37.841520454394264 ], [ -110.42608931429592, 37.841928068256813 ], [ -110.42528350480556, 37.84251449191698 ], [ -110.42470087770441, 37.842899207339912 ], [ -110.42424321074071, 37.843144828920821 ], [ -110.42382229493865, 37.843341056872269 ], [ -110.42321756212293, 37.843643638161083 ], [ -110.42239048506454, 37.844037058816319 ], [ -110.42160946591389, 37.844353187820388 ], [ -110.42109666030248, 37.844525520728482 ], [ -110.42070402052347, 37.844592088892867 ], [ -110.4201012692661, 37.844638693927692 ], [ -110.41914065004016, 37.844665505196907 ], [ -110.41849201124751, 37.844765953775884 ], [ -110.41791657269579, 37.844952384327108 ], [ -110.41719281337834, 37.845210182270598 ], [ -110.416668335241, 37.845419391432465 ], [ -110.41587118900401, 37.84561372651563 ], [ -110.41525027533977, 37.845799918388373 ], [ -110.41469151289151, 37.846031480994171 ], [ -110.41414983100411, 37.846258619394433 ], [ -110.41349452532704, 37.846480682925275 ], [ -110.41254345861131, 37.846732813289002 ], [ -110.41133676494435, 37.846970138850885 ], [ -110.40946876743799, 37.847465515048185 ], [ -110.40823277353442, 37.847810817928213 ], [ -110.406661232525, 37.848326566102131 ], [ -110.40622675400404, 37.848503735070359 ], [ -110.40586112834009, 37.848740735711118 ], [ -110.40547819807939, 37.849009193373071 ], [ -110.40487741977758, 37.849511788569721 ], [ -110.40452750025823, 37.849914703742989 ], [ -110.40400580723225, 37.850475377515494 ], [ -110.40346709314326, 37.851031456168435 ], [ -110.40324905592107, 37.851288123411386 ], [ -110.40306520350134, 37.851534147925101 ], [ -110.40288076105897, 37.851853174490472 ], [ -110.40273041641919, 37.852172373699233 ], [ -110.40261347913298, 37.852577365722048 ], [ -110.40252889463798, 37.853198833839976 ], [ -110.40255830317705, 37.85378032173881 ], [ -110.40265996005226, 37.854564968635671 ], [ -110.40266444495317, 37.855277018446145 ], [ -110.40287341106507, 37.856287534265483 ], [ -110.40297721879632, 37.856806308051702 ], [ -110.40304688981031, 37.857329415146225 ], [ -110.40312319022907, 37.857735386806453 ], [ -110.40321096784254, 37.858127897069195 ], [ -110.40356978574874, 37.858742598851997 ], [ -110.40401393894518, 37.859348718466102 ], [ -110.40414292468074, 37.859565683135379 ], [ -110.40422586022147, 37.859854518613439 ], [ -110.40426270898517, 37.860219731297704 ], [ -110.40423768832089, 37.86050351398633 ], [ -110.40413291148236, 37.860809425546066 ], [ -110.40390305117425, 37.861119210307592 ], [ -110.40358647713953, 37.861608815219839 ], [ -110.40312459341088, 37.862495155550448 ], [ -110.40301384146129, 37.862836186353753 ], [ -110.40300608533335, 37.863093017205443 ], [ -110.40312662813061, 37.863652433596414 ], [ -110.40316828499866, 37.864125826596293 ], [ -110.40318024937895, 37.864756796298508 ], [ -110.40319588460184, 37.864932628776096 ], [ -110.40327302891785, 37.865234954795369 ], [ -110.40340089622227, 37.865591615688047 ], [ -110.40349520387434, 37.865880509023476 ], [ -110.40354990369404, 37.866146669171641 ], [ -110.40364960639776, 37.866471641625637 ], [ -110.40377824009504, 37.866733669605594 ], [ -110.40390119031883, 37.866995668661851 ], [ -110.40401295409683, 37.867235078499888 ], [ -110.40409589732444, 37.867523913762348 ], [ -110.40417828961952, 37.867881244827714 ], [ -110.40434476708477, 37.86838591284004 ], [ -110.40445895442384, 37.869030918588294 ], [ -110.40459008862842, 37.869689529335155 ], [ -110.4047294114437, 37.8700372335175 ], [ -110.40482995812408, 37.870258559810758 ], [ -110.40486221718794, 37.870488553824231 ], [ -110.40493690915693, 37.871097307345956 ], [ -110.40498530352242, 37.871300343916339 ], [ -110.40500740346154, 37.871521273532871 ], [ -110.40498802975182, 37.871809590863428 ], [ -110.40505765522734, 37.87234170828598 ], [ -110.40514531447553, 37.872752241584337 ], [ -110.40514259684743, 37.87309021439453 ], [ -110.40510624105067, 37.873369432889668 ], [ -110.40511543653224, 37.873639868559529 ], [ -110.40526276951134, 37.874406715609787 ], [ -110.4053037568639, 37.874965726909075 ], [ -110.40529528227172, 37.875312683489256 ], [ -110.40525302341918, 37.875618911015678 ], [ -110.40523799380895, 37.876073990074886 ], [ -110.4052688433931, 37.87647972954337 ], [ -110.40532674225564, 37.877056852010767 ], [ -110.40535346529417, 37.877268791741578 ], [ -110.40540209602079, 37.877584491234941 ], [ -110.40548947324417, 37.878031074384474 ], [ -110.40549805473077, 37.878378116932033 ], [ -110.40541929224426, 37.878981587877632 ], [ -110.40523869956748, 37.879521453543703 ], [ -110.4050189953375, 37.879975498058464 ], [ -110.40467395550611, 37.880460453744405 ], [ -110.4042095530499, 37.880940297863397 ], [ -110.40366663788066, 37.881284547994547 ], [ -110.40298139833791, 37.881650606295217 ], [ -110.40209577416968, 37.882186889226901 ], [ -110.40148593274232, 37.882508256836864 ], [ -110.40085759474924, 37.882725878102626 ], [ -110.40026395560612, 37.88301126995087 ], [ -110.3993730125423, 37.883497933798445 ], [ -110.398739415363, 37.883801139914972 ], [ -110.39794085484185, 37.88411251198972 ], [ -110.39710234074637, 37.884441699903164 ], [ -110.39604156042668, 37.884832832354213 ], [ -110.39470227714308, 37.885209004066127 ], [ -110.39325446968382, 37.88564318534592 ], [ -110.39245143961904, 37.88580127675791 ], [ -110.39204667286764, 37.885929874831689 ], [ -110.3916755748065, 37.886112723190394 ], [ -110.39106399949613, 37.886497118007 ], [ -110.3903483998803, 37.887083762221209 ], [ -110.3899524815192, 37.887379138361958 ], [ -110.38945618962471, 37.887710044381215 ], [ -110.38892564581013, 37.887919095719894 ], [ -110.3883215167758, 37.888087204060483 ], [ -110.38739844683488, 37.888316740547545 ], [ -110.38657240733131, 37.888501710722963 ], [ -110.38545024115923, 37.888739207149399 ], [ -110.38482375852753, 37.888858510876794 ], [ -110.38426559650026, 37.888967353113429 ], [ -110.38351444780554, 37.889170719344115 ], [ -110.38237380308229, 37.889439634859635 ], [ -110.38169598425478, 37.889576678405902 ], [ -110.38105889159725, 37.889739168409378 ], [ -110.38043047100726, 37.889952173049274 ], [ -110.37988320564146, 37.890116030706388 ], [ -110.3793662623719, 37.890189916304266 ], [ -110.37801079504891, 37.890305337935978 ], [ -110.37733892752163, 37.890409039896952 ], [ -110.37699688541562, 37.89051087890315 ], [ -110.37664957416176, 37.890563117861113 ], [ -110.37627928968524, 37.890642272875048 ], [ -110.37566370005669, 37.890814761735982 ], [ -110.3747190023892, 37.890903481938579 ], [ -110.3736335834335, 37.89082200268269 ], [ -110.37261014886401, 37.890807539513901 ], [ -110.37192158626291, 37.890866958144628 ], [ -110.37102733106339, 37.891041540691312 ], [ -110.37000281138826, 37.891154131388546 ], [ -110.36864184838967, 37.891376669463156 ], [ -110.36754855410732, 37.891551059087462 ], [ -110.36650550416644, 37.89183386409875 ], [ -110.36567911211219, 37.892049329276034 ], [ -110.36504044819391, 37.892123397143735 ], [ -110.36436994768719, 37.892196388338917 ], [ -110.36347012050474, 37.892353758658658 ], [ -110.36271832738785, 37.892489391299172 ], [ -110.36210358602237, 37.892558164957258 ], [ -110.36134103872392, 37.892621627092105 ], [ -110.36027158586266, 37.89266539089094 ], [ -110.35891660531902, 37.892847290604315 ], [ -110.35821668814894, 37.892901159337612 ], [ -110.35756816619711, 37.892930068227251 ], [ -110.35686306286733, 37.892926217887904 ], [ -110.35590278220762, 37.892839851004879 ], [ -110.35470422995672, 37.892689079868163 ], [ -110.35352721182913, 37.892547427730079 ], [ -110.35223862900295, 37.892418669337786 ], [ -110.35117715505925, 37.892201019660099 ], [ -110.35000852065502, 37.891883626603772 ], [ -110.34914616589374, 37.891657143763908 ], [ -110.34822701814483, 37.891423129831274 ], [ -110.34758527393151, 37.891329445544528 ], [ -110.34668693671217, 37.891315450235652 ], [ -110.34613589529236, 37.891253806649921 ], [ -110.34505727856164, 37.89104952602078 ], [ -110.34350063187267, 37.890887635078045 ], [ -110.34170977759025, 37.89084608846396 ], [ -110.34057751251484, 37.890920867315621 ], [ -110.33976920285944, 37.891014577260435 ], [ -110.33912601536116, 37.891083972630113 ], [ -110.33864269223096, 37.891081258129134 ], [ -110.33810871826536, 37.891019672880645 ], [ -110.33692257670859, 37.890760635630365 ], [ -110.33621794202632, 37.890707093280895 ], [ -110.33586528100483, 37.890718623486762 ], [ -110.33534121783006, 37.890820215418486 ], [ -110.33464666646198, 37.890910025978641 ], [ -110.33448274347836, 37.890927125152487 ], [ -110.33404937864786, 37.890933687149641 ], [ -110.33341285635507, 37.890894032703443 ], [ -110.3318901945574, 37.890750206583412 ], [ -110.33100360836622, 37.890695600182454 ], [ -110.33041769363027, 37.890719307562286 ], [ -110.32955884491405, 37.890741457833897 ], [ -110.32921248240194, 37.890685407114667 ], [ -110.32875301198303, 37.890561113587758 ], [ -110.32819716619514, 37.89040472308529 ], [ -110.32768034673352, 37.890334175555672 ], [ -110.32719719366592, 37.890313389216537 ], [ -110.32654852887416, 37.890359250958696 ], [ -110.32579771923074, 37.890381991850496 ], [ -110.32504719717552, 37.890373184403586 ], [ -110.32439766593778, 37.890513664901121 ], [ -110.32386783719251, 37.890622382935511 ], [ -110.32313362054259, 37.890695674432578 ], [ -110.32269031068914, 37.890670592230705 ], [ -110.32198148186174, 37.890455609441126 ], [ -110.3214138328274, 37.890347788694825 ], [ -110.32104427918424, 37.890341151285547 ], [ -110.32025859804669, 37.890445673188374 ], [ -110.31971859427838, 37.89042362656371 ], [ -110.31883252060643, 37.890314854026578 ], [ -110.31738303020708, 37.890256886404508 ], [ -110.31632015276348, 37.890205653473046 ], [ -110.31532517575106, 37.890190857543111 ], [ -110.31409063239163, 37.890255773687009 ], [ -110.31290713601302, 37.890334494206151 ], [ -110.31193389611883, 37.890427951367506 ], [ -110.31146136458024, 37.890488278694328 ], [ -110.31115384620593, 37.890536951807412 ], [ -110.31069863212328, 37.890569437395058 ], [ -110.31013015012215, 37.890552587764368 ], [ -110.30984580406859, 37.890555427436212 ], [ -110.30952102415198, 37.890625626045058 ], [ -110.30859743424811, 37.890881579096479 ], [ -110.30796513792075, 37.890999537730004 ], [ -110.30750468952897, 37.890983310490519 ], [ -110.30702764766967, 37.890917412794103 ], [ -110.30617621229889, 37.89075467151973 ], [ -110.3054501284747, 37.890565625070685 ], [ -110.30474586037107, 37.890475844944689 ], [ -110.30396105585753, 37.890484726362189 ], [ -110.30343215823052, 37.890491511992032 ], [ -110.30265988177972, 37.890377883389277 ], [ -110.30172334229833, 37.890196579952324 ], [ -110.3013660158781, 37.890099824271701 ], [ -110.30084481837679, 37.889893939485987 ], [ -110.29998391437088, 37.889532813389451 ], [ -110.29930924623089, 37.889321502614017 ], [ -110.29851455280944, 37.889055395367585 ], [ -110.29809104049613, 37.888863599850225 ], [ -110.29740151017381, 37.88842236051125 ], [ -110.29690423627069, 37.888094926899534 ], [ -110.29667351586477, 37.887841187317335 ], [ -110.29638085320225, 37.887523986721241 ], [ -110.29588365424686, 37.887070368575131 ], [ -110.29559691941677, 37.886847836971761 ], [ -110.29508931503955, 37.886413080291462 ], [ -110.29476402035108, 37.885941559551938 ], [ -110.29458017511186, 37.885543890146593 ], [ -110.29453015405161, 37.884827064299031 ], [ -110.29439709486078, 37.883874503740365 ], [ -110.29423475828177, 37.882892024767862 ], [ -110.29408746338862, 37.882359379891582 ], [ -110.29403547002016, 37.881849838621299 ], [ -110.2941098884083, 37.881201355204873 ], [ -110.2941755495785, 37.880278826581197 ], [ -110.29416667346155, 37.879421645178844 ], [ -110.29412940610322, 37.878560688258794 ], [ -110.29397830896751, 37.877712567983473 ], [ -110.29384414110802, 37.876878068332957 ], [ -110.29376820810926, 37.876494563775331 ], [ -110.29362056619784, 37.875880799442179 ], [ -110.29357275856989, 37.875529008677184 ], [ -110.2936121179454, 37.87497945664402 ], [ -110.29373599291266, 37.874628695882194 ], [ -110.29366439530787, 37.874267749439547 ], [ -110.29353575344912, 37.874046160952155 ], [ -110.29339565671904, 37.873833516491977 ], [ -110.2930300222755, 37.873425739865446 ], [ -110.29273243604683, 37.873036396758387 ], [ -110.29250810736609, 37.872715090076106 ], [ -110.29232443537867, 37.872303898096838 ], [ -110.29218576813875, 37.871942547482504 ], [ -110.29213181070723, 37.871640290057634 ], [ -110.29186942202145, 37.871138494736464 ], [ -110.29164747570653, 37.870569345178374 ], [ -110.29143638381942, 37.870054338056335 ], [ -110.29129884725026, 37.869575825026281 ], [ -110.29119377839936, 37.869268752933436 ], [ -110.29108186023635, 37.86908331404166 ], [ -110.29093549079271, 37.86893371927944 ], [ -110.29074387149714, 37.868760418132936 ], [ -110.29048988061578, 37.868570517545521 ], [ -110.28981711756222, 37.868183411827772 ], [ -110.28918970615048, 37.867810095474354 ], [ -110.28853795050993, 37.867486199792147 ], [ -110.28825044611267, 37.867353774608212 ], [ -110.28767315805203, 37.867089809640575 ], [ -110.28722545673619, 37.866946498409462 ], [ -110.28671539575954, 37.866785683135397 ], [ -110.28609685231407, 37.866556610939625 ], [ -110.28542908058967, 37.866363288459048 ], [ -110.28505562206546, 37.866185269131577 ], [ -110.28469383860174, 37.865975774293993 ], [ -110.28441041502248, 37.865892935662551 ], [ -110.28413774133784, 37.865874153521027 ], [ -110.28326191073083, 37.865917494933846 ], [ -110.28276612272639, 37.866045163236677 ], [ -110.2825105983587, 37.866133735659425 ], [ -110.28222315490632, 37.866348293947532 ], [ -110.28195284974224, 37.866671111186754 ], [ -110.28160855965943, 37.867002489298592 ], [ -110.28141971081337, 37.867132024307999 ], [ -110.28113392252563, 37.867292512410579 ], [ -110.28051144663129, 37.867586136691294 ], [ -110.27969464678729, 37.867986724046418 ], [ -110.27927749322653, 37.868326662326282 ], [ -110.2790118471722, 37.868635981758899 ], [ -110.27869608847433, 37.868954006485858 ], [ -110.27815141208855, 37.869428353179266 ], [ -110.27784023112649, 37.869859065129987 ], [ -110.27740932029437, 37.870325093113699 ], [ -110.27725377021829, 37.870535941955787 ], [ -110.27712051702056, 37.870791992086303 ], [ -110.2770042636639, 37.871053554200095 ], [ -110.27696170617294, 37.871336298514734 ], [ -110.27697109350734, 37.871539146842601 ], [ -110.27702494477796, 37.871845916780345 ], [ -110.27713017825661, 37.872130469881469 ], [ -110.27724739816264, 37.872352006039662 ], [ -110.27749325341426, 37.872790641587422 ], [ -110.27762673745887, 37.873093393414784 ], [ -110.27773643474137, 37.873386986236483 ], [ -110.27778098174741, 37.873599063051934 ], [ -110.27777816611606, 37.873887459088159 ], [ -110.27778125519993, 37.874153359045081 ], [ -110.27781647339863, 37.874622246665076 ], [ -110.27779633931812, 37.874937575157247 ], [ -110.27782613699351, 37.875379390722017 ], [ -110.27787101006332, 37.876024089254386 ], [ -110.27792993713473, 37.876393980094406 ], [ -110.27799048345409, 37.876598043242254 ], [ -110.27823098843892, 37.877004197718811 ], [ -110.27862330736562, 37.877700596465715 ], [ -110.2787554918106, 37.8780213646749 ], [ -110.27885994074387, 37.878387928667344 ], [ -110.27882148021078, 37.878833832064998 ], [ -110.27876645580606, 37.879229161652958 ], [ -110.27881900141445, 37.879671116041663 ], [ -110.2788385786078, 37.879995700630701 ], [ -110.27898077139183, 37.880573397625106 ], [ -110.27906016424981, 37.881177748542463 ], [ -110.27906797674979, 37.881542819040199 ], [ -110.27901289869254, 37.881943555974949 ], [ -110.27889391834667, 37.88248360143762 ], [ -110.27881583308293, 37.882911235983492 ], [ -110.27867702397511, 37.883735066045418 ], [ -110.2785669912372, 37.884523020575251 ], [ -110.27849397179362, 37.885013776085593 ], [ -110.27828771832162, 37.885756075891614 ], [ -110.27796752600219, 37.886520208664514 ], [ -110.27776350765394, 37.887032692196748 ], [ -110.27750003037703, 37.887810690790005 ], [ -110.27734030284998, 37.888445119349242 ], [ -110.27701736514817, 37.889371464308773 ], [ -110.27678643603349, 37.889843222548173 ], [ -110.2763822335947, 37.890472542112967 ], [ -110.27590777865015, 37.891306921926386 ], [ -110.27539914291407, 37.892146496995473 ], [ -110.27496058644159, 37.892797230780566 ], [ -110.27449301595153, 37.893506367753076 ], [ -110.27419881335402, 37.893932666046013 ], [ -110.2739973146234, 37.894183784154869 ], [ -110.27367525029763, 37.894551325483519 ], [ -110.27316455772932, 37.895016842983665 ], [ -110.27233329915818, 37.89569578474331 ], [ -110.27150787167432, 37.896358533399876 ], [ -110.27068386111215, 37.8968761775876 ], [ -110.27000875764475, 37.897286584989786 ], [ -110.2694773254883, 37.897544661339033 ], [ -110.26813625263739, 37.898014012873823 ], [ -110.26717732929417, 37.898368561534824 ], [ -110.26657862361323, 37.898527064212395 ], [ -110.26550716211709, 37.898759224118486 ], [ -110.2643901109568, 37.899000102192502 ], [ -110.26307451276546, 37.899190155930164 ], [ -110.26245376466049, 37.899276396574002 ], [ -110.26179419848023, 37.899263248922978 ], [ -110.26115254857778, 37.89916458778459 ], [ -110.26048323358754, 37.898989139952917 ], [ -110.25990477290902, 37.898827778932585 ], [ -110.25912669514709, 37.898723742427421 ], [ -110.25800705959527, 37.898653599613247 ], [ -110.25696152470546, 37.898566789509481 ], [ -110.25577975851655, 37.898454774098667 ], [ -110.2554453374235, 37.89834450473505 ], [ -110.25508876134452, 37.898175510574397 ], [ -110.25450954655231, 37.898090727689876 ], [ -110.25343055108929, 37.897939682972293 ], [ -110.25289651389576, 37.897886723736349 ], [ -110.25254475756819, 37.897804276003441 ], [ -110.25215403506473, 37.897638661277824 ], [ -110.2513445096145, 37.897273000447939 ], [ -110.25070375980694, 37.897088665925715 ], [ -110.25034055454871, 37.897014250317241 ], [ -110.24980043446978, 37.896889135384399 ], [ -110.24921132097167, 37.896772718349261 ], [ -110.24827911308746, 37.896618056255093 ], [ -110.2475088541579, 37.896420259189668 ], [ -110.2467357813815, 37.896387374538421 ], [ -110.24566131856837, 37.896353454977948 ], [ -110.24515004474168, 37.896300606527923 ], [ -110.24453636978312, 37.896251605104304 ], [ -110.2436043938872, 37.896187036174332 ], [ -110.24268342323789, 37.896158582135428 ], [ -110.24167105457497, 37.896170089978717 ], [ -110.24038606149671, 37.896148285032581 ], [ -110.23912880572379, 37.896194241829456 ], [ -110.2379915210358, 37.896186884749454 ], [ -110.23694503341247, 37.896198131048862 ], [ -110.23588148636593, 37.896209257297123 ], [ -110.23486422351128, 37.896144065494795 ], [ -110.23416526143369, 37.896094455594643 ], [ -110.23313075570914, 37.896047162350811 ], [ -110.23227162661328, 37.89597847187926 ], [ -110.23148272937746, 37.895937272290972 ], [ -110.23081234449511, 37.895874309785768 ], [ -110.23008542554572, 37.895779428687561 ], [ -110.22939793731774, 37.89572085269041 ], [ -110.22890420989859, 37.895622984307224 ], [ -110.22827490509619, 37.895438602893464 ], [ -110.22756590059011, 37.895262707990042 ], [ -110.22670327452673, 37.895094812539753 ], [ -110.22592604150293, 37.89491845951941 ], [ -110.2251263032788, 37.894719421082854 ], [ -110.22460477156493, 37.89456276808685 ], [ -110.22370799583032, 37.894399132190564 ], [ -110.22283543806856, 37.894204104375689 ], [ -110.22206902833651, 37.893973720256092 ], [ -110.22142824037702, 37.893802745708044 ], [ -110.22067970262145, 37.893604015772205 ], [ -110.21982982172527, 37.893417227429453 ], [ -110.21913691206588, 37.893228770533746 ], [ -110.21846818321843, 37.893012530264592 ], [ -110.2176510942613, 37.892844870939825 ], [ -110.21631179338159, 37.892588108187439 ], [ -110.21546551858835, 37.892492342246683 ], [ -110.21491973841252, 37.892480591785393 ], [ -110.21388970040036, 37.892553931703816 ], [ -110.21271639426838, 37.892730853559172 ], [ -110.21187302266692, 37.892896453963409 ], [ -110.21090431167801, 37.893083740251221 ], [ -110.20979055173822, 37.893540430410631 ], [ -110.20920742799109, 37.893829431931934 ], [ -110.20878409276835, 37.894065427617875 ], [ -110.20844595191184, 37.894311007550584 ], [ -110.20820418556623, 37.894584273370889 ], [ -110.20791456114432, 37.895078031404147 ], [ -110.20771668694962, 37.895500303500484 ], [ -110.20750903206282, 37.89577379740971 ], [ -110.20722793611934, 37.896001732086489 ], [ -110.20672964355977, 37.89633185021065 ], [ -110.20622016729968, 37.896643865078197 ], [ -110.20578388414718, 37.897023967927126 ], [ -110.20550205156724, 37.897319489741477 ], [ -110.20530430278384, 37.897728239119047 ], [ -110.20512236103137, 37.898253360530774 ], [ -110.20503071360505, 37.898843082656519 ], [ -110.20490337417939, 37.899578571544389 ], [ -110.20483457657581, 37.900158533602443 ], [ -110.2048382754423, 37.900343321774244 ], [ -110.20483365975898, 37.900772301667956 ], [ -110.20481764135921, 37.901203908345494 ], [ -110.20478445566128, 37.901645313122543 ], [ -110.20472123506758, 37.902235226700064 ], [ -110.2046408775951, 37.902937684805039 ], [ -110.20454220149789, 37.903545384214873 ], [ -110.2044777642711, 37.90424794963684 ], [ -110.20442547607053, 37.904878494410426 ], [ -110.20433590042205, 37.905274453435808 ], [ -110.20423494956393, 37.905670335453046 ], [ -110.20411742155206, 37.906021041110002 ], [ -110.20401228614908, 37.906277195737225 ], [ -110.20376819103402, 37.906761336076627 ], [ -110.20341503456888, 37.907337569867586 ], [ -110.20317715378177, 37.907772180379865 ], [ -110.2027196419273, 37.908530665718047 ], [ -110.2026497502933, 37.908682508967154 ], [ -110.20240736990783, 37.909006229571588 ], [ -110.20213561736745, 37.909310823603661 ], [ -110.20185962254654, 37.9096919972039 ], [ -110.20156180382804, 37.910302849012062 ], [ -110.20124535648499, 37.910742329966553 ], [ -110.2010546478098, 37.911020432914952 ], [ -110.20086306027261, 37.911379644941498 ], [ -110.20083660533147, 37.911721952427129 ], [ -110.20094538509422, 37.912182344781016 ], [ -110.20090696998588, 37.91257864793743 ], [ -110.20077799058255, 37.912933778389259 ], [ -110.20047774523972, 37.913346328594265 ], [ -110.19999456212329, 37.913843256317776 ], [ -110.19957389885877, 37.914344212346847 ], [ -110.19923979750799, 37.914730391810323 ], [ -110.1988948643564, 37.915066024800886 ], [ -110.19865309151432, 37.915330256736183 ], [ -110.19847927789489, 37.915621989459588 ], [ -110.19839642017267, 37.915918847885564 ], [ -110.19832612589197, 37.916630381093462 ], [ -110.19831652514958, 37.916990828081438 ], [ -110.19834634899041, 37.917387594846332 ], [ -110.19846394117694, 37.917978734774337 ], [ -110.19861843767706, 37.918524160530502 ], [ -110.19871155648813, 37.91885466334427 ], [ -110.19878227552813, 37.919152567463627 ], [ -110.19903870069797, 37.919636498145842 ], [ -110.19914442073689, 37.919854426267179 ], [ -110.19920317559398, 37.920101776965957 ], [ -110.19916888818636, 37.920325962487823 ], [ -110.19910228702015, 37.920592288258291 ], [ -110.19910431010142, 37.920930282184671 ], [ -110.1991246197892, 37.921155740499543 ], [ -110.19934697281685, 37.921634932102101 ], [ -110.19959050944081, 37.922259373461529 ], [ -110.19992679322631, 37.922724918290598 ], [ -110.20023565409437, 37.92309654263925 ], [ -110.20048072511833, 37.923580392797099 ], [ -110.20064606249557, 37.924072713633244 ], [ -110.2007745085443, 37.924294399668646 ], [ -110.20089226097951, 37.924452923345171 ], [ -110.20115144791674, 37.924684509513796 ], [ -110.20169282466513, 37.925125304187972 ], [ -110.2022836627271, 37.925727760768233 ], [ -110.20283544848527, 37.926259649993924 ], [ -110.20323530947722, 37.926636389207452 ], [ -110.20346601909696, 37.92687228383619 ], [ -110.20360037128778, 37.927075079846482 ], [ -110.2038323405973, 37.927721965801176 ], [ -110.20398712918568, 37.928245755153227 ], [ -110.20416901168416, 37.92868410595586 ], [ -110.20444762877442, 37.929226757631042 ], [ -110.20474283138344, 37.929814584674709 ], [ -110.20484062195403, 37.930243353217008 ], [ -110.20514649436159, 37.931426095544033 ], [ -110.20532934865717, 37.932409724771425 ], [ -110.20557401333453, 37.933465873209357 ], [ -110.20576830504537, 37.934445072292256 ], [ -110.20579337426648, 37.935287937049111 ], [ -110.20582818337657, 37.935648683422798 ], [ -110.20583322374551, 37.936343603158541 ], [ -110.20591883515027, 37.936847995582916 ], [ -110.20593081319997, 37.937321247543075 ], [ -110.20589100328573, 37.9378482266522 ], [ -110.20586475391134, 37.93817250963987 ], [ -110.20577954862176, 37.938582016085341 ], [ -110.205662577168, 37.938982295206763 ], [ -110.20555049572974, 37.939351062468134 ], [ -110.20544376326443, 37.939751410443129 ], [ -110.2053250192732, 37.940210260223779 ], [ -110.20521182767341, 37.940681765237692 ], [ -110.20513323957353, 37.941110242544774 ], [ -110.20508374060378, 37.941479431974209 ], [ -110.20485183351175, 37.942406180829074 ], [ -110.20469305721124, 37.942882784730244 ], [ -110.20439528927793, 37.943583767905473 ], [ -110.20411565511834, 37.944185732399632 ], [ -110.2038105514488, 37.944616281152875 ], [ -110.20327861551718, 37.945289539319077 ], [ -110.20276003547528, 37.945884474378822 ], [ -110.20225850802375, 37.946480423957695 ], [ -110.20185045448267, 37.946851686302168 ], [ -110.20131161740044, 37.947213046674186 ], [ -110.20052667481737, 37.947703417543394 ], [ -110.19992100667329, 37.947929125832871 ], [ -110.19903420729831, 37.94836471732507 ], [ -110.19803231552768, 37.94891668348447 ], [ -110.19710060712329, 37.94929337115417 ], [ -110.19619910922603, 37.949508028116981 ], [ -110.19574352755809, 37.949536459318431 ], [ -110.19532110541192, 37.949655243141898 ], [ -110.19442548546269, 37.949851901142978 ], [ -110.19380340918642, 37.950013474763985 ], [ -110.19327765515773, 37.950213559174202 ], [ -110.19258481116363, 37.950600861215854 ], [ -110.19173217931525, 37.951027618857502 ], [ -110.1912514532044, 37.951272165955281 ], [ -110.19081075598704, 37.951498960883342 ], [ -110.19032537180455, 37.951648838206289 ], [ -110.18977872473464, 37.951780266119528 ], [ -110.18929818632732, 37.951903134295051 ], [ -110.18886910850811, 37.952107470069976 ], [ -110.18850773152286, 37.95236544648759 ], [ -110.18823748258697, 37.952616840386789 ], [ -110.18786470953567, 37.952875637427752 ], [ -110.18739403961123, 37.953238305004881 ], [ -110.18690656096113, 37.953576520066562 ], [ -110.18635785580797, 37.953892679048003 ], [ -110.18553167021814, 37.95439167604755 ], [ -110.18498795396549, 37.954667305725735 ], [ -110.18450059439883, 37.954992893625764 ], [ -110.18400823756262, 37.955255355600222 ], [ -110.18326378030675, 37.955669282205342 ], [ -110.18239830601071, 37.956217554177229 ], [ -110.18165877112756, 37.956699100236875 ], [ -110.18104307858223, 37.957303175726054 ], [ -110.18073859963873, 37.957557918793945 ], [ -110.18054930225898, 37.957690890179371 ], [ -110.18018875050689, 37.957869534197918 ], [ -110.17947904409647, 37.958225095824616 ], [ -110.17866537465795, 37.958716019638771 ], [ -110.17785271922214, 37.959115014926773 ], [ -110.17700106136269, 37.959438024719212 ], [ -110.17677784658115, 37.959549122092618 ], [ -110.1765251585871, 37.959751041335309 ], [ -110.17634138829148, 37.959897563628253 ], [ -110.17598052365945, 37.96010232931885 ], [ -110.17505929074422, 37.96053749668129 ], [ -110.17480182108562, 37.960657362770306 ], [ -110.17458383671546, 37.960809049902082 ], [ -110.17440603378087, 37.96093037534127 ], [ -110.17406234382651, 37.961125341592741 ], [ -110.17344953215841, 37.961463521167381 ], [ -110.17263158224731, 37.961821885456175 ], [ -110.17236850385366, 37.961933595252162 ], [ -110.17208185968055, 37.962116339147954 ], [ -110.17151390412636, 37.962513406906766 ], [ -110.17112979172991, 37.96275855104075 ], [ -110.17060126106725, 37.963191942984828 ], [ -110.17018827887335, 37.963472931331019 ], [ -110.16973545279724, 37.963753636991299 ], [ -110.16917961677787, 37.964083183373781 ], [ -110.1686517256628, 37.964457988191739 ], [ -110.16800227137878, 37.965012185284372 ], [ -110.16753554114371, 37.965514496881795 ], [ -110.16713793977755, 37.965943391726526 ], [ -110.1667756632438, 37.966368930307823 ], [ -110.16653302704916, 37.966583516624326 ], [ -110.16618094827903, 37.967012730638579 ], [ -110.16573563436921, 37.96763235191446 ], [ -110.16551409144009, 37.968094935297515 ], [ -110.16531052950825, 37.968477432654659 ], [ -110.16504223121599, 37.969046934563281 ], [ -110.16477448008105, 37.969567771028252 ], [ -110.16451938587547, 37.96997603783263 ], [ -110.16433726368575, 37.970474949577415 ], [ -110.16421678118915, 37.971059919709226 ], [ -110.16406967561331, 37.971482471704782 ], [ -110.16383299454172, 37.972273907762386 ], [ -110.16364281763668, 37.972980053176542 ], [ -110.16356228365187, 37.973555392413516 ], [ -110.16341249934578, 37.974213155902305 ], [ -110.16330251802174, 37.974874807334139 ], [ -110.16325648147136, 37.975419748357503 ], [ -110.16316347184924, 37.976090532943864 ], [ -110.16313861727254, 37.976775321353486 ], [ -110.16310483308426, 37.977243741362976 ], [ -110.16303801862618, 37.977612786609662 ], [ -110.1629939227807, 37.977986499812005 ], [ -110.16292028835603, 37.978454636080443 ], [ -110.1627713168855, 37.979039401086951 ], [ -110.16257008409454, 37.979713920711085 ], [ -110.1623593570517, 37.980221637439314 ], [ -110.1621547297503, 37.980693346410476 ], [ -110.16182383159743, 37.98125428213207 ], [ -110.16148261932138, 37.981720510054174 ], [ -110.16105452070191, 37.982316801228045 ], [ -110.16075634100369, 37.982603080058226 ], [ -110.16040520958565, 37.982839410336702 ], [ -110.16002644125142, 37.983102580243212 ], [ -110.15972768101983, 37.983339282463284 ], [ -110.15941199393791, 37.983562343901063 ], [ -110.15905732777459, 37.983708517940933 ], [ -110.15865225247484, 37.983881368376146 ], [ -110.15781176004916, 37.984091657469705 ], [ -110.15756049138787, 37.984157453122776 ], [ -110.15730229230277, 37.984331350806045 ], [ -110.15696232601115, 37.984684915544797 ], [ -110.15668538348764, 37.985003781706325 ], [ -110.15612717086331, 37.985521612256683 ], [ -110.15598877909918, 37.985673834825526 ], [ -110.15575225953897, 37.985942517755802 ], [ -110.15559140311429, 37.986067540535984 ], [ -110.15532770607867, 37.986223368939761 ], [ -110.15496732587415, 37.98636948944467 ], [ -110.15451062406859, 37.986474359377802 ], [ -110.15380362395192, 37.986559401592025 ], [ -110.15321007351102, 37.986681307139136 ], [ -110.15251833571072, 37.986924173372131 ], [ -110.15193554448555, 37.987100226051737 ], [ -110.15125362794383, 37.987478345767514 ], [ -110.15069685881537, 37.98776723850046 ], [ -110.15037693468935, 37.987958700339625 ], [ -110.15002217779478, 37.988109352521839 ], [ -110.14967404905714, 37.988178937468376 ], [ -110.14934951976062, 37.988275730096845 ], [ -110.14886100623006, 37.988569614031341 ], [ -110.14843036082897, 37.988782800857201 ], [ -110.14772620232638, 37.989210308504923 ], [ -110.14734228866577, 37.989419323593303 ], [ -110.14707979500723, 37.98956703059612 ], [ -110.14689615247669, 37.989690974782498 ], [ -110.14656719521166, 37.989972487293677 ], [ -110.14624517213417, 37.990245036526893 ], [ -110.14582076697339, 37.990507828636829 ], [ -110.14566051096425, 37.9905787659564 ], [ -110.14555853819678, 37.990632101168273 ], [ -110.1454825989307, 37.990699144451419 ], [ -110.14539588829975, 37.990811172758342 ], [ -110.14531424360892, 37.990977313825105 ], [ -110.14519822769904, 37.991161230351587 ], [ -110.14485780565059, 37.991546300296918 ], [ -110.14461428959972, 37.991823922076975 ], [ -110.144274371957, 37.992263069926942 ], [ -110.14400147917675, 37.992716223602294 ], [ -110.14377491885881, 37.993102118942993 ], [ -110.14351731969793, 37.993708598026487 ], [ -110.14312587425516, 37.99456194953396 ], [ -110.14281654715536, 37.99520860695123 ], [ -110.14275276014185, 37.995307281272666 ], [ -110.14262497577354, 37.995522653591337 ], [ -110.14248199254683, 37.99567392505157 ], [ -110.14231873616005, 37.995903458617747 ], [ -110.14210883502398, 37.996226383339462 ], [ -110.14193406129999, 37.996662222194431 ], [ -110.14171751695032, 37.997066211603538 ], [ -110.14138884052868, 37.997514445230067 ], [ -110.1410582329006, 37.998030258696836 ], [ -110.14067490071035, 37.998671863073298 ], [ -110.14029119351676, 37.999345007644315 ], [ -110.13990225859817, 37.999977555686371 ], [ -110.13984289452218, 38.000184412481289 ], [ -110.1398237061663, 38.000364525157522 ], [ -110.1397044501209, 38.000823297988596 ], [ -110.13958037376072, 38.001304567012482 ], [ -110.13937717282479, 38.001636548109914 ], [ -110.13926336280882, 38.002018752718286 ], [ -110.13915206017991, 38.002283811118573 ], [ -110.13892665622208, 38.002566059263607 ], [ -110.13851254090568, 38.002914519486808 ], [ -110.13813221969153, 38.003294770158845 ], [ -110.13770423762226, 38.003854021716002 ], [ -110.13745796500163, 38.00406942032707 ], [ -110.1372442777791, 38.004225574032212 ], [ -110.13697857549826, 38.004543573196962 ], [ -110.13651223655772, 38.00497275666433 ], [ -110.13628238814567, 38.005146815187182 ], [ -110.13606472117509, 38.005253367933108 ], [ -110.13582443345371, 38.005346235074249 ], [ -110.13525838261306, 38.005535845662081 ], [ -110.13460163701666, 38.005688735529787 ], [ -110.13321309817854, 38.006079571117724 ], [ -110.13249403049895, 38.006204050575775 ], [ -110.13163193222552, 38.006383347839737 ], [ -110.13119811924875, 38.006465763561899 ], [ -110.13086654545363, 38.006571464975067 ], [ -110.13026603786172, 38.006783328293423 ], [ -110.12963205050552, 38.006936358589762 ], [ -110.12901014325887, 38.007030892800806 ], [ -110.12844060815674, 38.0070311792322 ], [ -110.1280359986314, 38.007051612511155 ], [ -110.12763553896258, 38.007106323192396 ], [ -110.12692350000381, 38.007212795342028 ], [ -110.12615312570148, 38.007339558733122 ], [ -110.12569631860113, 38.007438907208964 ], [ -110.12522327173016, 38.007466933299625 ], [ -110.1249323525426, 38.007505325587147 ], [ -110.12447042676627, 38.007555962982472 ], [ -110.12395155183889, 38.007606174302467 ], [ -110.12383729006872, 38.007635965943358 ], [ -110.12355216097797, 38.007666286581724 ], [ -110.12324431661982, 38.0076910295858 ], [ -110.12287909395384, 38.007751394326355 ], [ -110.12263894301555, 38.007830716436864 ], [ -110.12223890522671, 38.007944895192864 ], [ -110.12181103682511, 38.008004788961834 ], [ -110.12136597553625, 38.008073565334399 ], [ -110.12096099291236, 38.008124614373472 ], [ -110.12058486102244, 38.008144333583552 ], [ -110.12013474921024, 38.008158991744324 ], [ -110.1196627811218, 38.008191509811326 ], [ -110.11923355474576, 38.008269409268593 ], [ -110.11885156505653, 38.008302597991616 ], [ -110.11843621503374, 38.008267940674074 ], [ -110.11798523315883, 38.008260052509641 ], [ -110.11752524761434, 38.008243082419845 ], [ -110.11706456650025, 38.008189153541053 ], [ -110.11656974923282, 38.00813226261851 ], [ -110.11614344444244, 38.008061464404527 ], [ -110.11583592103501, 38.008059152523401 ], [ -110.11548858766473, 38.00805203408131 ], [ -110.11520351890854, 38.008076927323998 ], [ -110.11493553461155, 38.008101948465395 ], [ -110.11473556359877, 38.008154518921401 ], [ -110.11445033161439, 38.008192928042348 ], [ -110.11414253668414, 38.008213141245747 ], [ -110.11390324297012, 38.00822035091668 ], [ -110.11355596339817, 38.008208720855556 ], [ -110.11324919947636, 38.008143319562961 ], [ -110.11299911339755, 38.008100876576478 ], [ -110.11274404961225, 38.007998912182856 ], [ -110.11244400352103, 38.007848840817758 ], [ -110.11216712930664, 38.007666498197622 ], [ -110.11200328337148, 38.007557109520185 ], [ -110.11172635698321, 38.007379271781936 ], [ -110.11145534428346, 38.007183452829288 ], [ -110.11122896654715, 38.007064577927714 ], [ -110.11090681217051, 38.006859358539977 ], [ -110.11059534143682, 38.006712801137986 ], [ -110.11034602417493, 38.006607269971745 ], [ -110.11003986909465, 38.006492295505005 ], [ -110.1098075831251, 38.006391398408503 ], [ -110.1095178110658, 38.006240496109719 ], [ -110.10910032113728, 38.006007511928324 ], [ -110.10878956676243, 38.005802373122286 ], [ -110.10850723294094, 38.005601955274791 ], [ -110.10824203921877, 38.00539716042011 ], [ -110.10798850168979, 38.005264554389548 ], [ -110.10781268518861, 38.005110005953284 ], [ -110.10758090917062, 38.004967650262557 ], [ -110.10728750952096, 38.004741008896048 ], [ -110.10705068595841, 38.004545439351595 ], [ -110.10683122069753, 38.004327469609557 ], [ -110.10667363146013, 38.004173057910258 ], [ -110.10653854768383, 38.004041348560094 ], [ -110.10628409779044, 38.003890706677339 ], [ -110.10601813952145, 38.003749890644926 ], [ -110.10572356739189, 38.003620572828503 ], [ -110.10542904010492, 38.003487649566893 ], [ -110.10503820037636, 38.00331343579694 ], [ -110.10468738824858, 38.003126006551049 ], [ -110.10444883505018, 38.002979988049717 ], [ -110.10426880478116, 38.002798364347825 ], [ -110.10415233381512, 38.002635249839123 ], [ -110.10397334695702, 38.00236801367349 ], [ -110.10382233979213, 38.002141547285433 ], [ -110.10361975496728, 38.00194172544024 ], [ -110.10338847991603, 38.001759709754879 ], [ -110.10323614774389, 38.001642285300839 ], [ -110.10299935588765, 38.00144580657544 ], [ -110.10282486254049, 38.001277741828616 ], [ -110.1026618135384, 38.001105257836208 ], [ -110.10249827100536, 38.000973326677602 ], [ -110.10235767104105, 38.000828051476567 ], [ -110.10222212149651, 38.000642257834464 ], [ -110.10207735190839, 38.000465406262613 ], [ -110.10194907646041, 38.000243617326461 ], [ -110.10179825567913, 38.000002729527033 ], [ -110.1015469521838, 37.999596142756381 ], [ -110.10120411574897, 37.999224005149607 ], [ -110.10089484244799, 37.9989016926177 ], [ -110.1003877088086, 37.998460701638749 ], [ -110.10019631131408, 37.998278984710439 ], [ -110.09989141863723, 37.998064854622342 ], [ -110.09968813947724, 37.997923602763819 ], [ -110.09925239679711, 37.997699456566316 ], [ -110.09877652284943, 37.997497532799841 ], [ -110.09827782029514, 37.997299938388821 ], [ -110.09769315834052, 37.997146745521249 ], [ -110.09739259103911, 37.997045300049507 ], [ -110.09717190614172, 37.996930948154365 ], [ -110.09696408019799, 37.99678965669473 ], [ -110.09678769916341, 37.996684656904726 ], [ -110.09638165883995, 37.996361589274393 ], [ -110.09571535063192, 37.995902231015535 ], [ -110.09545007250289, 37.995710024359646 ], [ -110.09523553137687, 37.995559665566525 ], [ -110.09478367633814, 37.995258771521733 ], [ -110.09446675952304, 37.995098610639438 ], [ -110.09407554719439, 37.994960408191758 ], [ -110.09369554656156, 37.994836711061424 ], [ -110.09349146748092, 37.994762135830669 ], [ -110.09329312700534, 37.994683999438152 ], [ -110.09310523134141, 37.994682550631019 ], [ -110.09288858917026, 37.994703411375433 ], [ -110.09267752967513, 37.994733327423013 ], [ -110.09211870309217, 37.994796609405206 ], [ -110.09139475485397, 37.994858613102394 ], [ -110.09116091907772, 37.994888350448392 ], [ -110.09042033296294, 37.994914169036406 ], [ -110.09019302541144, 37.99487636022085 ], [ -110.0898978377642, 37.99480197515701 ], [ -110.08955068236143, 37.994785769138986 ], [ -110.08927140708737, 37.994806138305854 ], [ -110.08887200418611, 37.994870639326152 ], [ -110.08838155526635, 37.994929926945893 ], [ -110.08809077995519, 37.994959216786945 ], [ -110.0877476212556, 37.994988099576886 ], [ -110.08717982456098, 37.994947643247194 ], [ -110.08655986898677, 37.994888753806926 ], [ -110.08593382920418, 37.994861358008926 ], [ -110.08563775108748, 37.994859056368661 ], [ -110.08514166207451, 37.994913780295661 ], [ -110.0848162188931, 37.994983349157138 ], [ -110.08444504528714, 37.995066981305392 ], [ -110.08419915752746, 37.995149785453201 ], [ -110.08363858333716, 37.995352709158034 ], [ -110.08341540185374, 37.995441096154941 ], [ -110.08285939496628, 37.995734177953416 ], [ -110.08234301636723, 37.996045591563856 ], [ -110.08174060662796, 37.996405900570196 ], [ -110.08113204730932, 37.996802208875792 ], [ -110.08062766069983, 37.997064139106698 ], [ -110.07988271544868, 37.997436842977713 ], [ -110.07915568994439, 37.997742087744939 ], [ -110.07886924167158, 37.997879539997925 ], [ -110.0783759007869, 37.99816768355425 ], [ -110.07803057945713, 37.998458788090907 ], [ -110.07757674017788, 37.998775177026019 ], [ -110.07720870411075, 37.999060693346088 ], [ -110.07675942188598, 37.999467240966744 ], [ -110.07655212698963, 37.999649470683948 ], [ -110.07637654328296, 38.000027522815664 ], [ -110.07616093988665, 38.000417877923141 ], [ -110.07605003577356, 38.000633309317926 ], [ -110.0758813967329, 38.000911375192871 ], [ -110.07568969645847, 38.001211791075491 ], [ -110.07549162139384, 38.001566232171783 ], [ -110.07532229901955, 38.001898367470382 ], [ -110.07519960528363, 38.00214524941584 ], [ -110.07506382387159, 38.002527217419605 ], [ -110.0749512715589, 38.002873317533393 ], [ -110.07485129600151, 38.003124884074467 ], [ -110.07477792345773, 38.003525367857961 ], [ -110.07475800886957, 38.00375052635426 ], [ -110.07474863375838, 38.004043362317162 ], [ -110.07471665033297, 38.00432250146293 ], [ -110.07471900380133, 38.004588391863059 ], [ -110.07474368250705, 38.004890508338505 ], [ -110.07468226293926, 38.005246022958268 ], [ -110.07463905931797, 38.005511554825183 ], [ -110.07462900372742, 38.005858460958777 ], [ -110.07458540303108, 38.006155533763874 ], [ -110.0744550220721, 38.00656007476406 ], [ -110.07433801206922, 38.006807000301251 ], [ -110.07419646006254, 38.007103301798118 ], [ -110.0740787737015, 38.007494423342358 ], [ -110.07400134101022, 38.007764191627018 ], [ -110.07396320458258, 38.008079332319681 ], [ -110.07399857923122, 38.00843650985783 ], [ -110.07407998921578, 38.008756196951872 ], [ -110.07416634670781, 38.009135406083146 ], [ -110.07420224410916, 38.009451129668534 ], [ -110.07413563279691, 38.00976604613453 ], [ -110.07406794397694, 38.010166573732761 ], [ -110.07407052157225, 38.010414440448145 ], [ -110.07407868082093, 38.010671363702095 ], [ -110.07408508302127, 38.011067968346843 ], [ -110.07413687581519, 38.011478449270591 ], [ -110.0743300835102, 38.011966650552722 ], [ -110.07448057128623, 38.012319326333717 ], [ -110.07465161973326, 38.012667657419016 ], [ -110.07476144486357, 38.012992975025249 ], [ -110.0749224146502, 38.013327707495648 ], [ -110.0751940635916, 38.013920169175918 ], [ -110.07528878846614, 38.014087647117009 ], [ -110.07540135378103, 38.014285908079351 ], [ -110.07551708784163, 38.014504021546081 ], [ -110.07570005335606, 38.014902013978066 ], [ -110.07588432212374, 38.015196371558289 ], [ -110.07608613105252, 38.015454816306288 ], [ -110.07621920058234, 38.015744264736817 ], [ -110.07634041981615, 38.015979544379213 ], [ -110.07645805290727, 38.016228314608362 ], [ -110.07656953068972, 38.016422960836245 ], [ -110.0766803871921, 38.016667171316641 ], [ -110.07677979688619, 38.016915798102751 ], [ -110.07685687733805, 38.017128199134717 ], [ -110.07693931464712, 38.017367679929777 ], [ -110.07701549177916, 38.017652174458057 ], [ -110.07713626219521, 38.018014527193941 ], [ -110.07721776339655, 38.018328804892754 ], [ -110.07727582731799, 38.018695171596434 ], [ -110.07733812981138, 38.019177833870479 ], [ -110.07734904732868, 38.019670006704416 ], [ -110.07731205931177, 38.019894129809082 ], [ -110.07728035998265, 38.020150739700682 ], [ -110.07727838236087, 38.020308444403078 ], [ -110.07720658617966, 38.02058276474213 ], [ -110.07708967511768, 38.020820680570537 ], [ -110.07698996379912, 38.021049718711652 ], [ -110.07688432988829, 38.021296735421394 ], [ -110.07678963468302, 38.021579888241817 ], [ -110.07663899771372, 38.021781488418689 ], [ -110.07649975169784, 38.021983177863113 ], [ -110.07637167047552, 38.022202980000671 ], [ -110.07627257723745, 38.022382453123996 ], [ -110.07610890447779, 38.022714632569347 ], [ -110.07591212963078, 38.022960932093604 ], [ -110.07569234308249, 38.023225075524572 ], [ -110.07549516911936, 38.02350291520191 ], [ -110.07525134934549, 38.023866007140256 ], [ -110.07493330833304, 38.024242033451685 ], [ -110.07465581678285, 38.024564302555312 ], [ -110.07445265570598, 38.024864624701507 ], [ -110.07425535918419, 38.025151473787751 ], [ -110.07403516305513, 38.025447154746132 ], [ -110.07382077477278, 38.025733868446849 ], [ -110.07362962351851, 38.025984714534154 ], [ -110.07349570551204, 38.026214381153814 ], [ -110.07340720896751, 38.026456121935148 ], [ -110.07329848988363, 38.026946450224465 ], [ -110.07315159823953, 38.027301288878682 ], [ -110.07302828535802, 38.027593225236757 ], [ -110.07293389612231, 38.027850240498303 ], [ -110.07285024015984, 38.028159613216545 ], [ -110.0727687337221, 38.028388790943808 ], [ -110.07268507316672, 38.02860803778713 ], [ -110.07259557934479, 38.028838053628405 ], [ -110.07246821575974, 38.029089400791726 ], [ -110.07224271312047, 38.02935259099543 ], [ -110.07208035893569, 38.029577525136169 ], [ -110.07190616731997, 38.029837514602363 ], [ -110.07167894297029, 38.030236779821934 ], [ -110.07154428289495, 38.030524118544044 ], [ -110.07136319588892, 38.030878684616852 ], [ -110.07110822200923, 38.031219147774365 ], [ -110.07088207038558, 38.031532800443614 ], [ -110.07066189812372, 38.03182396851129 ], [ -110.07037205422115, 38.032218229707453 ], [ -110.07014538363737, 38.032572433297851 ], [ -110.06989056879364, 38.032989501682103 ], [ -110.06966788090135, 38.033388798590458 ], [ -110.06947566902844, 38.033720742070308 ], [ -110.06928299922438, 38.03408873181727 ], [ -110.06909619540848, 38.034443248828758 ], [ -110.06897153058142, 38.034839715400587 ], [ -110.06884107617999, 38.035243345995603 ], [ -110.06874598873169, 38.0355535259935 ], [ -110.06862891154627, 38.035800443795758 ], [ -110.06843731634082, 38.03608282122245 ], [ -110.06828058665944, 38.036311399319743 ], [ -110.06811149130819, 38.036616485882448 ], [ -110.06798193114383, 38.036948923282331 ], [ -110.06785703876591, 38.037362510501069 ], [ -110.06780125271935, 38.037718063971163 ], [ -110.06773452577848, 38.038127605936715 ], [ -110.06763830169383, 38.038436874578395 ], [ -110.06754645829778, 38.038580346938964 ], [ -110.06736025151692, 38.038886197792024 ], [ -110.06715770607404, 38.039132435850412 ], [ -110.06694291124828, 38.039356044946857 ], [ -110.06674047747272, 38.039593270591006 ], [ -110.06658983249969, 38.039790350621971 ], [ -110.06649644544628, 38.039965353771784 ], [ -110.0664032295721, 38.040126839378082 ], [ -110.06622899229345, 38.04038681938377 ], [ -110.06603201026947, 38.040643013393037 ], [ -110.06581767149864, 38.04091979798239 ], [ -110.06561454259287, 38.041211091334489 ], [ -110.06528896014292, 38.041722218062546 ], [ -110.0650471989761, 38.042004190646701 ], [ -110.06476913276576, 38.042273256322559 ], [ -110.06438904183007, 38.042589275825691 ], [ -110.06409502948563, 38.042857311686326 ], [ -110.06388158332744, 38.043062900600994 ], [ -110.06363947620868, 38.043281779633858 ], [ -110.06339208339901, 38.043468170892325 ], [ -110.06310455383949, 38.043674069323892 ], [ -110.0628453496859, 38.043892810411883 ], [ -110.06262642922925, 38.04408032825738 ], [ -110.06234414448454, 38.044321415508485 ], [ -110.06207929564798, 38.044535603566011 ], [ -110.06176863419101, 38.044767450445534 ], [ -110.06150412719349, 38.044954602290701 ], [ -110.06121101546348, 38.045150537625076 ], [ -110.06090109693396, 38.0453238066073 ], [ -110.06057414146478, 38.045492432339898 ], [ -110.0603561895221, 38.045603347040327 ], [ -110.06009783451999, 38.045754494695679 ], [ -110.0598683127921, 38.045878834771884 ], [ -110.05958117898516, 38.046052282443377 ], [ -110.05933319207445, 38.046194498801917 ], [ -110.05907545341341, 38.046386205507268 ], [ -110.05885634286992, 38.04658723344351 ], [ -110.05857945993458, 38.046760760692358 ], [ -110.05825392099209, 38.046906859883428 ], [ -110.0579162613593, 38.047020415908491 ], [ -110.057619213188, 38.047077517591262 ], [ -110.05735002960152, 38.047183509644626 ], [ -110.05705229834165, 38.047293778342805 ], [ -110.05675369895027, 38.047471633293746 ], [ -110.05645463543658, 38.047685533868304 ], [ -110.05611999442188, 38.0480072983474 ], [ -110.05584958996673, 38.048207908670172 ], [ -110.05552871339627, 38.0483450251362 ], [ -110.05512300408307, 38.048431889937987 ], [ -110.05476299302599, 38.048510108287225 ], [ -110.05425558899799, 38.048528558325714 ], [ -110.05391941214371, 38.048525853096258 ], [ -110.05360027105719, 38.048527790328158 ], [ -110.05321833687333, 38.048538233473721 ], [ -110.05285303187922, 38.048584859475049 ], [ -110.05248293578644, 38.048649470770847 ], [ -110.0521563175928, 38.048700912699843 ], [ -110.0517624169281, 38.048755415990719 ], [ -110.0513465148386, 38.048748455228392 ], [ -110.05095318349093, 38.04875879902427 ], [ -110.05061648214415, 38.04879663646846 ], [ -110.05022896485455, 38.048798012271625 ], [ -110.04979633013069, 38.048762971998457 ], [ -110.04938631272208, 38.048741631830289 ], [ -110.04895379539187, 38.048697576884393 ], [ -110.04860674731557, 38.048654212141372 ], [ -110.0482022538276, 38.048646431340465 ], [ -110.04788346257331, 38.048621318306779 ], [ -110.04750123555328, 38.048654271800451 ], [ -110.04729552674863, 38.048697667357061 ], [ -110.04708864947033, 38.048831178304788 ], [ -110.04687025872208, 38.048973608047376 ], [ -110.04670861284849, 38.049134522627057 ], [ -110.04660394586365, 38.049295899132986 ], [ -110.04648718106615, 38.049511252531389 ], [ -110.04626814402253, 38.049703244743441 ], [ -110.04606655071056, 38.049868340538424 ], [ -110.04585315102847, 38.050064883963614 ], [ -110.04567501950672, 38.050266219587058 ], [ -110.04554536363403, 38.050508504889613 ], [ -110.04545074234942, 38.050773605841307 ], [ -110.04533338651572, 38.051034015801555 ], [ -110.04513549527762, 38.051352352798574 ], [ -110.04502294562594, 38.051681296584398 ], [ -110.04488181041354, 38.052017217980563 ], [ -110.04476427481109, 38.052291144610976 ], [ -110.04466412578608, 38.052542681129246 ], [ -110.04450141271191, 38.052784696472749 ], [ -110.0443385345035, 38.053039327753261 ], [ -110.04416968732495, 38.053314639035278 ], [ -110.04409897564437, 38.053493413026224 ], [ -110.04403923821555, 38.053704721268197 ], [ -110.04394577947103, 38.05387970514456 ], [ -110.04384039602628, 38.054095148243391 ], [ -110.04380309895603, 38.054333676416228 ], [ -110.04377743286425, 38.05455427416377 ], [ -110.04381415565888, 38.054797910718726 ], [ -110.04380047247189, 38.054973543377123 ], [ -110.04383924738133, 38.055059477661139 ], [ -110.04383830939092, 38.055131570118988 ], [ -110.04385370452862, 38.055262376760588 ], [ -110.04387955861131, 38.055465368559418 ], [ -110.04391628213617, 38.055709005055697 ], [ -110.04394178480393, 38.055939031498589 ], [ -110.04391676330449, 38.056110065657812 ], [ -110.04386219393605, 38.056361972033109 ], [ -110.04389689872264, 38.056673185895178 ], [ -110.04391214421844, 38.056903128873444 ], [ -110.04391497020349, 38.057123958311372 ], [ -110.0438496477517, 38.057326208374121 ], [ -110.04375113016042, 38.057451582020946 ], [ -110.04360150078925, 38.057563020940101 ], [ -110.04338901034562, 38.057687466833542 ], [ -110.0431201446963, 38.0578520096782 ], [ -110.04296291231145, 38.058021967160954 ], [ -110.04286909316922, 38.058223984596651 ], [ -110.04282045193598, 38.058457913636168 ], [ -110.0428113489826, 38.058719202154087 ], [ -110.04284119777596, 38.059052907904245 ], [ -110.04290664779775, 38.059278753484421 ], [ -110.04301046362811, 38.059622073954145 ], [ -110.04311369360505, 38.060010452064283 ], [ -110.04317250763746, 38.060308343466843 ], [ -110.04324142898507, 38.060705454628966 ], [ -110.04328226738136, 38.061070793384644 ], [ -110.04333462127438, 38.061427213335044 ], [ -110.04340959533627, 38.06179733609838 ], [ -110.04354725859675, 38.062167968955961 ], [ -110.04373045641913, 38.062543478370948 ], [ -110.04387864107029, 38.062981790158155 ], [ -110.04394515296462, 38.063126531194534 ], [ -110.04400408986635, 38.063415410558136 ], [ -110.04409975487876, 38.063947926048613 ], [ -110.04410769408641, 38.064213859302491 ], [ -110.04411028596273, 38.0644527115629 ], [ -110.0440952527304, 38.064731976702589 ], [ -110.04415527258675, 38.065025370979264 ], [ -110.04424191955962, 38.065287438011588 ], [ -110.04444351548155, 38.065563958338778 ], [ -110.04461778869194, 38.065750131261957 ], [ -110.044849231011, 38.065923249801166 ], [ -110.04521569977555, 38.06623265231346 ], [ -110.04549627236271, 38.066572899850279 ], [ -110.04568677051712, 38.066826796661509 ], [ -110.0459712912929, 38.067302262525402 ], [ -110.04614975059503, 38.067605629564589 ], [ -110.04630611573886, 38.067854742081245 ], [ -110.0465016759962, 38.068158247338509 ], [ -110.04674920496535, 38.068498223757167 ], [ -110.04692112325962, 38.068779005311413 ], [ -110.04711069669878, 38.069104992214875 ], [ -110.04719239001082, 38.069398560531162 ], [ -110.04719893781298, 38.069772632011798 ], [ -110.04715442325062, 38.070128264509563 ], [ -110.04700725688835, 38.070487570873986 ], [ -110.04679774396025, 38.070819333904979 ], [ -110.04654544853112, 38.071285035537869 ], [ -110.04627918487041, 38.071684832063596 ], [ -110.04604028866916, 38.072083948844472 ], [ -110.04586514082256, 38.072402470290932 ], [ -110.04573047531414, 38.072676257738458 ], [ -110.04558423353271, 38.072963469730865 ], [ -110.04543781489373, 38.073264198812474 ], [ -110.04522217685484, 38.073627452747829 ], [ -110.04503720386649, 38.073824224489186 ], [ -110.04499078468392, 38.073886934673048 ], [ -110.04491545588826, 38.073980953589384 ], [ -110.04468406150589, 38.074240434866006 ], [ -110.04448186854395, 38.074446078200374 ], [ -110.04435430114668, 38.074611771858251 ], [ -110.04413976799796, 38.074889414087487 ], [ -110.04405250929372, 38.075023891557549 ], [ -110.04389015348704, 38.075234364106734 ], [ -110.04368090598118, 38.075543592134437 ], [ -110.04348254025051, 38.075892563244452 ], [ -110.04329114062365, 38.076144255924994 ], [ -110.04308852744947, 38.076381437004038 ], [ -110.04287506553723, 38.076663591752677 ], [ -110.04276251106215, 38.076901505675366 ], [ -110.04270868439907, 38.077094835492481 ], [ -110.04260913895222, 38.077296805305899 ], [ -110.0424348447837, 38.077547734602888 ], [ -110.04223203683895, 38.077799332490002 ], [ -110.04199023151992, 38.077981216046332 ], [ -110.04170971074785, 38.078159178407631 ], [ -110.04144406797181, 38.078332755205608 ], [ -110.0412080650711, 38.078506573218391 ], [ -110.04096036634105, 38.078702826483976 ], [ -110.04066013958114, 38.078992380141223 ], [ -110.0404807703092, 38.079194597629808 ], [ -110.04024376112088, 38.079445011453537 ], [ -110.04002903312835, 38.079735261669626 ], [ -110.03983114515874, 38.080045476500295 ], [ -110.03962007819491, 38.080404250611267 ], [ -110.03953793564341, 38.080669447156701 ], [ -110.03942835272645, 38.081114668723977 ], [ -110.03931165226973, 38.081406619995342 ], [ -110.03900992159681, 38.081809714018092 ], [ -110.03871489100987, 38.082136256058014 ], [ -110.03843762029149, 38.082412472834754 ], [ -110.03816073708244, 38.082658950966987 ], [ -110.03779770594038, 38.082953390389662 ], [ -110.03753905440733, 38.083113496628897 ], [ -110.03724043860011, 38.083277781107995 ], [ -110.03682240459118, 38.083418554919774 ], [ -110.03650739376563, 38.083528628348539 ], [ -110.03603164091351, 38.083723000850291 ], [ -110.03569394351649, 38.083823873513239 ], [ -110.03540886859156, 38.083911658465574 ], [ -110.03519003877395, 38.08399097417076 ], [ -110.03506332193686, 38.08408907080139 ], [ -110.03501160158771, 38.084120189710752 ], [ -110.03492532193192, 38.084178062166735 ], [ -110.03477027887612, 38.084262407147349 ], [ -110.03458032046082, 38.084400539845554 ], [ -110.0343672030307, 38.084565519309024 ], [ -110.03413656760259, 38.084761898003258 ], [ -110.03388420895993, 38.084962603866629 ], [ -110.03368633861545, 38.085181782173628 ], [ -110.03353010561314, 38.085356240292654 ], [ -110.03337232925969, 38.085647847463505 ], [ -110.03327850630421, 38.085845349734178 ], [ -110.03313901718036, 38.086046982421422 ], [ -110.03295326790969, 38.086297802759262 ], [ -110.0327958433876, 38.086562374612477 ], [ -110.03266644694136, 38.086863226793142 ], [ -110.03253235809552, 38.087087434302155 ], [ -110.03227219551314, 38.087360171953108 ], [ -110.03208115488302, 38.087579403655717 ], [ -110.03195408228409, 38.087790149572974 ], [ -110.03182544174223, 38.087946807697712 ], [ -110.03164508681999, 38.088220201419169 ], [ -110.03150541024193, 38.088435349175555 ], [ -110.03139250298669, 38.088695779679874 ], [ -110.03127510390101, 38.089037285100709 ], [ -110.03122568966194, 38.089325276184667 ], [ -110.03113060703544, 38.089617396919003 ], [ -110.03097416800352, 38.089806269652314 ], [ -110.03073199758181, 38.090010657438832 ], [ -110.03054159999535, 38.090180323310371 ], [ -110.0303845272727, 38.090416955981759 ], [ -110.03018176104044, 38.09065952002473 ], [ -110.03000240550097, 38.09085631346904 ], [ -110.02980445643597, 38.091165608712224 ], [ -110.02973983734034, 38.0913092743249 ], [ -110.02957728474205, 38.091528736947616 ], [ -110.02937945120458, 38.091829019928539 ], [ -110.02917086915058, 38.092079645293055 ], [ -110.02893965943511, 38.092316564605575 ], [ -110.02871403024305, 38.092562542020183 ], [ -110.02847063949177, 38.092857940576451 ], [ -110.02824957480294, 38.093189573019579 ], [ -110.0281073658833, 38.093508338616047 ], [ -110.02798964500273, 38.093872368806529 ], [ -110.0278935286124, 38.094241083810964 ], [ -110.02771705371559, 38.094649689784433 ], [ -110.02760478571061, 38.09494617131363 ], [ -110.02735376986035, 38.09538570331727 ], [ -110.02714391616121, 38.095730944935994 ], [ -110.02685316309527, 38.096156628109028 ], [ -110.02657422821189, 38.096550864890361 ], [ -110.02627212505826, 38.096971946283425 ], [ -110.02602930764178, 38.097222282005454 ], [ -110.02574693586136, 38.097445251934445 ], [ -110.02530347892127, 38.097775034233877 ], [ -110.0249240541027, 38.098006209438161 ], [ -110.02460860365169, 38.098143283928032 ], [ -110.02427526794688, 38.098338789860215 ], [ -110.02397007957539, 38.098561565949488 ], [ -110.02375671704294, 38.098740042049641 ], [ -110.02354305365679, 38.098941046332527 ], [ -110.0232093396074, 38.099164484574935 ], [ -110.02304832160821, 38.099265887587144 ], [ -110.02282347915047, 38.099449673954339 ], [ -110.02269090907838, 38.099555819269703 ], [ -110.02256985032307, 38.099653949005116 ], [ -110.02247111834041, 38.099788314088435 ], [ -110.02240065509353, 38.099940939151963 ], [ -110.02224910454304, 38.100187519933847 ], [ -110.02208080763283, 38.100406923837141 ], [ -110.02178736823274, 38.100602754599066 ], [ -110.02149387919636, 38.100802189171326 ], [ -110.02104478914596, 38.101123796904481 ], [ -110.02077949307163, 38.101346896861955 ], [ -110.0205832807149, 38.101521003750442 ], [ -110.02039246859582, 38.101717686391716 ], [ -110.02021137457473, 38.102040623712796 ], [ -110.02009264021615, 38.102391118107427 ], [ -110.01994689917017, 38.102628731778587 ], [ -110.01973825375285, 38.102879339086257 ], [ -110.01945560014073, 38.103120315963217 ], [ -110.01914486786505, 38.103328613013197 ], [ -110.01871921143935, 38.103601740131545 ], [ -110.01855841861163, 38.103685113866668 ], [ -110.01827090003441, 38.103862960233457 ], [ -110.01786891459682, 38.104071392567057 ], [ -110.01756434666258, 38.104244588445994 ], [ -110.01733852153987, 38.104499553912525 ], [ -110.01716875111487, 38.104827087203319 ], [ -110.01713043265434, 38.10513318891347 ], [ -110.01711547833813, 38.105398028927169 ], [ -110.01695794260804, 38.10566347851411 ], [ -110.01669225519286, 38.105913602898703 ], [ -110.01630123569872, 38.106153664949936 ], [ -110.01592701844315, 38.106416397451738 ], [ -110.01584051607959, 38.106487772218628 ], [ -110.01552351265904, 38.106736562782103 ], [ -110.01512670999767, 38.106981979836895 ], [ -110.01479943495282, 38.107145965600537 ], [ -110.01448404757329, 38.107274000500254 ], [ -110.01417381651196, 38.107442633672484 ], [ -110.01386170616654, 38.107750942643307 ], [ -110.01356014977695, 38.108122426254418 ], [ -110.01331282216314, 38.108278066610069 ], [ -110.01304808288189, 38.108456091198462 ], [ -110.01269810793495, 38.108610867903217 ], [ -110.01222226350245, 38.108795227560506 ], [ -110.01188343535384, 38.10896902158926 ], [ -110.01160170393889, 38.109137887542843 ], [ -110.01118292759227, 38.109319118070488 ], [ -110.01058682241205, 38.109539409677858 ], [ -110.01008875239128, 38.109679412629269 ], [ -110.00954128867144, 38.109760416407035 ], [ -110.00921467442397, 38.109789205869326 ], [ -110.00849003106993, 38.109813734723531 ], [ -110.00810218163342, 38.109815868305404 ], [ -110.00757833572199, 38.109752863817121 ], [ -110.00703253443945, 38.109626584595745 ], [ -110.00665701876021, 38.109560323369955 ], [ -110.00613335921845, 38.109483795418377 ], [ -110.00550826444596, 38.109317183743599 ], [ -110.00495769675165, 38.1091223602822 ], [ -110.00429459861772, 38.108814826776701 ], [ -110.0035922008058, 38.108461894220902 ], [ -110.00251865633956, 38.107722779755484 ], [ -110.00131735324725, 38.106734728420179 ], [ -110.0006912683082, 38.106224710115733 ], [ -110.00043332172771, 38.105902575414952 ], [ -110.00033344392196, 38.105698946480317 ], [ -110.00027372798833, 38.105477634388109 ], [ -110.0002036519201, 38.105179628631987 ], [ -110.00017204426909, 38.104904481210902 ], [ -110.00018233816644, 38.104651320130884 ], [ -110.00011108404196, 38.104439823386819 ], [ -110.0000060596717, 38.104195594499316 ], [ -109.99982120626792, 38.103950685970922 ], [ -109.99963610832108, 38.103723799885685 ], [ -109.999433290716, 38.103541824655515 ], [ -109.99916161892024, 38.103390806004924 ], [ -109.99886070006555, 38.10329361197946 ], [ -109.99859275200384, 38.103287723545492 ], [ -109.99837700846649, 38.103217390208563 ], [ -109.99816787805578, 38.103080421034328 ], [ -109.99794734434667, 38.102943354234398 ], [ -109.99769309175555, 38.102769949737301 ], [ -109.99732510801384, 38.102573043146414 ], [ -109.99694584547861, 38.102367026708684 ], [ -109.99658307476625, 38.102206211945969 ], [ -109.99607334927926, 38.101949510190757 ], [ -109.99597697091309, 38.101908130796197 ], [ -109.99566407334066, 38.101770270405076 ], [ -109.99542189328591, 38.101632112604122 ], [ -109.99521300745458, 38.101478016699112 ], [ -109.99503326158349, 38.101278206379234 ], [ -109.99480851888113, 38.101032948779597 ], [ -109.99464005544765, 38.100842246789306 ], [ -109.99446589102752, 38.100651495766414 ], [ -109.99429123340791, 38.100496789906629 ], [ -109.99413312607251, 38.100382781324463 ], [ -109.99400799459697, 38.100359178985173 ], [ -109.99380836864896, 38.100361975819553 ], [ -109.99354001165625, 38.100386714610941 ], [ -109.99328894547597, 38.100398082323913 ], [ -109.99300893716489, 38.100440744889866 ], [ -109.9928154458037, 38.100412049176434 ], [ -109.99263447181761, 38.100302348774967 ], [ -109.99247605815252, 38.100210866374091 ], [ -109.99231702605516, 38.100164440507442 ], [ -109.99212328813698, 38.100153766363533 ], [ -109.99180888350239, 38.100209649628042 ], [ -109.9915510631111, 38.100297561153248 ], [ -109.99122458473427, 38.100402006227249 ], [ -109.99089801868557, 38.1005127583201 ], [ -109.99054909062308, 38.100590872706867 ], [ -109.99025216061548, 38.100619864691232 ], [ -109.98987546654382, 38.100643663997459 ], [ -109.98959613805347, 38.100636756012939 ], [ -109.98916292186959, 38.100624017321827 ], [ -109.98879248825284, 38.100607311181157 ], [ -109.98830706402728, 38.100576095184636 ], [ -109.98790380886636, 38.100541078813663 ], [ -109.98755624555932, 38.100520059577207 ], [ -109.98716859548973, 38.100511311130845 ], [ -109.98687202552696, 38.100514161691706 ], [ -109.98653940229849, 38.100650084131921 ], [ -109.9862060680925, 38.100837370194995 ], [ -109.985895614413, 38.101019445341251 ], [ -109.98564844057785, 38.101161510161639 ], [ -109.98540709230217, 38.101294612355105 ], [ -109.98522314855751, 38.101400271404103 ], [ -109.98507440651341, 38.101517049127267 ], [ -109.98493442549193, 38.101660038315934 ], [ -109.98480549181429, 38.101911271617631 ], [ -109.98474691364167, 38.102023420490191 ], [ -109.98463013090763, 38.102220684161402 ], [ -109.98457055439351, 38.10240492352343 ], [ -109.98458497871312, 38.102598814817476 ], [ -109.98462841201474, 38.102756907199911 ], [ -109.9846032342232, 38.102927925229089 ], [ -109.98447529503279, 38.103107067488033 ], [ -109.98438219124563, 38.103241448726244 ], [ -109.98432323703622, 38.103380631303132 ], [ -109.98430363558664, 38.103560709850832 ], [ -109.98436936560371, 38.10375594589204 ], [ -109.98439564288752, 38.103917494987662 ], [ -109.98432484724631, 38.104088118584144 ], [ -109.98416263018429, 38.104271470324505 ], [ -109.98397779098443, 38.104441107606142 ], [ -109.98378644984599, 38.104668367696014 ], [ -109.98367033436313, 38.1048169691148 ], [ -109.98360550050458, 38.104968717775741 ], [ -109.98358513513207, 38.105203765156517 ], [ -109.98352353888545, 38.105451073171288 ], [ -109.98339642077399, 38.105652752235692 ], [ -109.98326791169994, 38.10587244390603 ], [ -109.98304772843261, 38.106122885334031 ], [ -109.98290818775735, 38.10631544391201 ], [ -109.9827448841732, 38.106494277977383 ], [ -109.98253291496573, 38.106645653181836 ], [ -109.98240515159951, 38.106811275944906 ], [ -109.98230571174658, 38.106990662496486 ], [ -109.98217104192371, 38.107160731360949 ], [ -109.98200970291821, 38.107362112360157 ], [ -109.98179495050358, 38.107631524409769 ], [ -109.98147312729778, 38.10780808147539 ], [ -109.98110084465598, 38.107922014550908 ], [ -109.98083640576077, 38.108072931563662 ], [ -109.98064045745288, 38.108219936047348 ], [ -109.98039293594049, 38.108384517408879 ], [ -109.98012742887873, 38.108612028837179 ], [ -109.97996005267953, 38.108754773987677 ], [ -109.97972368208315, 38.10893747549769 ], [ -109.97962592514629, 38.108995207036919 ], [ -109.97947659494004, 38.10907051529724 ], [ -109.97924648897873, 38.109212714496458 ], [ -109.97905040901026, 38.109368727509214 ], [ -109.97887664899369, 38.109560082492152 ], [ -109.97869741139586, 38.109735167294048 ], [ -109.97854149768895, 38.109873503817475 ], [ -109.97828274908687, 38.110024464438105 ], [ -109.97808741824693, 38.110126407999488 ], [ -109.97772590842698, 38.110284584633156 ], [ -109.97739205847006, 38.110422272416756 ], [ -109.97712366931637, 38.110528084610159 ], [ -109.97688942300465, 38.110557588255823 ], [ -109.97673450997519, 38.110623831975147 ], [ -109.97659613863635, 38.110730775311374 ], [ -109.97640099226523, 38.110819199064444 ], [ -109.9761599099582, 38.110929753137114 ], [ -109.97587934892985, 38.111008419233904 ], [ -109.97553593245713, 38.111095548952314 ], [ -109.9753408468174, 38.11117946526462 ], [ -109.97507688820043, 38.111294323759964 ], [ -109.9748586759931, 38.111400568458869 ], [ -109.97453736765368, 38.111456344810563 ], [ -109.97416688987833, 38.111520703336275 ], [ -109.97386916609793, 38.111602819689367 ], [ -109.97360423973934, 38.111705049060802 ], [ -109.97327279563255, 38.111832832425712 ], [ -109.97300870531667, 38.111956697458389 ], [ -109.97284800748514, 38.112028292859378 ], [ -109.97267148879185, 38.112007823424761 ], [ -109.97233091781379, 38.111891288825177 ], [ -109.97205913755201, 38.111831231911921 ], [ -109.97180194467674, 38.111788425560142 ], [ -109.97144907349804, 38.11173576865226 ], [ -109.97125556168309, 38.111707037179379 ], [ -109.97103886004278, 38.111705139421126 ], [ -109.97069600399395, 38.111751704133923 ], [ -109.97043849798217, 38.11181253440725 ], [ -109.97018751673048, 38.111814840850798 ], [ -109.96992544653497, 38.111794518587537 ], [ -109.96973687834559, 38.111819902225996 ], [ -109.96957017116773, 38.111913070134335 ], [ -109.96933458798226, 38.112037176898042 ], [ -109.9691619237737, 38.112148316710687 ], [ -109.96897202421403, 38.11226831738427 ], [ -109.96879352948248, 38.112388417852117 ], [ -109.96856389968413, 38.112494550548973 ], [ -109.96834611838885, 38.112569243523865 ], [ -109.96803677577155, 38.112665662788608 ], [ -109.96771173102934, 38.112743017275029 ], [ -109.9672698164496, 38.112857195535909 ], [ -109.9669150395612, 38.112939693863829 ], [ -109.96654258213538, 38.113062591265432 ], [ -109.96626206661682, 38.113136728472206 ], [ -109.96598161407458, 38.113206359372725 ], [ -109.96563862101044, 38.113261920420307 ], [ -109.96539757843583, 38.11336794638634 ], [ -109.9651564715908, 38.113478477471801 ], [ -109.96493253605155, 38.113584653159791 ], [ -109.96466246843427, 38.113726471355676 ], [ -109.96439778446754, 38.113890867306161 ], [ -109.96416168991567, 38.114050107306511 ], [ -109.96398804568211, 38.114229724778106 ], [ -109.9638428003573, 38.114417703593475 ], [ -109.96372074785977, 38.114578849695341 ], [ -109.96361567615435, 38.114749157834865 ], [ -109.96353790851292, 38.115005324268608 ], [ -109.96344271304382, 38.115283867787248 ], [ -109.96341531542727, 38.115608071290048 ], [ -109.96341041102291, 38.115955004160107 ], [ -109.96343707889477, 38.116085918787512 ], [ -109.96345150009593, 38.11627620697125 ], [ -109.96346062595941, 38.116437608853026 ], [ -109.96342379631126, 38.116622037398436 ], [ -109.96340420303252, 38.116797605650845 ], [ -109.96341248803881, 38.117018481715647 ], [ -109.96342000872177, 38.117293425219096 ], [ -109.96348038613058, 38.117460686707886 ], [ -109.96352397289688, 38.117605269111181 ], [ -109.96354474730467, 38.117749650232653 ], [ -109.96348447347464, 38.117897822455205 ], [ -109.96339764638874, 38.118068291251006 ], [ -109.96332678776366, 38.118238900890965 ], [ -109.96328368021939, 38.118463829565954 ], [ -109.96319488305376, 38.11869286116297 ], [ -109.96314030464708, 38.118922194706911 ], [ -109.96298369210959, 38.119106466975744 ], [ -109.96283363610608, 38.11923041408815 ], [ -109.96270593364665, 38.119387002886981 ], [ -109.96260072495211, 38.119566321083397 ], [ -109.96258080998714, 38.119764417159274 ], [ -109.9625961347628, 38.119890725542845 ], [ -109.96254308367564, 38.120011923910994 ], [ -109.96245606757138, 38.120114797553931 ], [ -109.96227760676862, 38.120230381917324 ], [ -109.9620994643286, 38.120323437917669 ], [ -109.96197309800836, 38.120385407902376 ], [ -109.96181174581808, 38.120501142719192 ], [ -109.96163802921215, 38.120684360711714 ], [ -109.96148725285948, 38.12085876888154 ], [ -109.96129033803712, 38.121068818329952 ], [ -109.96114608490697, 38.121265814614745 ], [ -109.9610626064506, 38.121440817328619 ], [ -109.96098609941194, 38.121606869279269 ], [ -109.96089235397729, 38.12178178104886 ], [ -109.96075317207476, 38.121942772246207 ], [ -109.96060745564621, 38.122162285767878 ], [ -109.9604731964169, 38.122378295540663 ], [ -109.96035600855321, 38.122597159939907 ], [ -109.96026200469284, 38.122790093584825 ], [ -109.9601230111938, 38.122937567125959 ], [ -109.96000176694983, 38.123040135863967 ], [ -109.95988456380013, 38.12325990085516 ], [ -109.9598143310719, 38.123385451930005 ], [ -109.95975455898937, 38.123577787006717 ], [ -109.95965541134332, 38.123731020215736 ], [ -109.95955031666824, 38.123901324131587 ], [ -109.95946182070115, 38.124107824385746 ], [ -109.95934469091951, 38.12432218201959 ], [ -109.95925611707833, 38.12453408881936 ], [ -109.95919056209712, 38.124731779735079 ], [ -109.95916576420279, 38.124871251458671 ], [ -109.95925529584926, 38.124993711453861 ], [ -109.95927125546372, 38.125074964007432 ], [ -109.95924716127355, 38.125164874047066 ], [ -109.95924530610759, 38.125295536692654 ], [ -109.9592663937522, 38.125417390252586 ], [ -109.95932189574006, 38.125526030169524 ], [ -109.95931388916823, 38.125688181537015 ], [ -109.95926095621402, 38.125800366949811 ], [ -109.95923628599168, 38.125930827444137 ], [ -109.95920109298696, 38.126079219394384 ], [ -109.95905447862896, 38.12628069811398 ], [ -109.95886888561142, 38.126495349696171 ], [ -109.95868944338017, 38.126678512278417 ], [ -109.95856069455357, 38.126907185760302 ], [ -109.95840201704415, 38.127234729527032 ], [ -109.95830146552439, 38.1274861835861 ], [ -109.95814329791051, 38.127777682096614 ], [ -109.95803838588799, 38.127934467595232 ], [ -109.95792168120481, 38.128118185413875 ], [ -109.95783291904968, 38.128342706571125 ], [ -109.95765763575793, 38.128634052512439 ], [ -109.9574992066717, 38.128943572439411 ], [ -109.95728911958609, 38.129275164442454 ], [ -109.95701692729762, 38.129561142905814 ], [ -109.95665853056792, 38.129891416769986 ], [ -109.95638671845794, 38.130150360070218 ], [ -109.95613861926795, 38.130346427065504 ], [ -109.95585725695173, 38.130474605297437 ], [ -109.95564530613437, 38.130535807445391 ], [ -109.95530401086089, 38.130866229107028 ], [ -109.95512474160407, 38.131035869030299 ], [ -109.95489432681181, 38.131191535116216 ], [ -109.95473371063309, 38.131253192324429 ], [ -109.95449310725279, 38.131323149731635 ], [ -109.95431044522272, 38.131330536101842 ], [ -109.95389314038646, 38.131389906756439 ], [ -109.95344178553606, 38.131516565082386 ], [ -109.95304448137252, 38.131693271284732 ], [ -109.95270486129886, 38.131825428771769 ], [ -109.95238572929475, 38.131881163141628 ], [ -109.95203084411675, 38.131963614672259 ], [ -109.95153167663202, 38.132161937703373 ], [ -109.95126209481906, 38.132263172951347 ], [ -109.95077964897759, 38.132488679049523 ], [ -109.95060070845071, 38.132554673040225 ], [ -109.95022907165666, 38.132691043426377 ], [ -109.94984436755298, 38.132863345129579 ], [ -109.94935607999642, 38.133097805414209 ], [ -109.94894272094234, 38.1332788601486 ], [ -109.94850725371832, 38.133410147683897 ], [ -109.94815754395691, 38.133528683073273 ], [ -109.94778430407902, 38.133696574446397 ], [ -109.94737139090586, 38.133846084431738 ], [ -109.94704397680732, 38.134000865592455 ], [ -109.94657349852604, 38.134185906010799 ], [ -109.94613704986236, 38.134384768339423 ], [ -109.94580502831971, 38.134462899881768 ], [ -109.94533564644821, 38.134571340353254 ], [ -109.9450259868327, 38.134681213608808 ], [ -109.94473881956884, 38.134813818930773 ], [ -109.94443408364407, 38.134977808799626 ], [ -109.94416973195382, 38.135110617744637 ], [ -109.94394615466166, 38.135185212576332 ], [ -109.94363694511046, 38.135263543041056 ], [ -109.94345958721759, 38.135297997142203 ], [ -109.94312840364701, 38.135317548494513 ], [ -109.94272345198323, 38.135309397957052 ], [ -109.94228368835945, 38.135341488003924 ], [ -109.94202653225611, 38.135370715163269 ], [ -109.94171311218525, 38.135345360901113 ], [ -109.94139509445473, 38.1352433596197 ], [ -109.94111726916375, 38.135123695172382 ], [ -109.94079297569345, 38.135061289913047 ], [ -109.94045128284593, 38.135018553919849 ], [ -109.9402063832474, 38.134989307559159 ], [ -109.93987001747075, 38.134972753677673 ], [ -109.93951005168097, 38.135010059694849 ], [ -109.93928115705539, 38.13505756064599 ], [ -109.93894302970028, 38.135162654544281 ], [ -109.93855913527483, 38.135276346207782 ], [ -109.93822612279033, 38.135422039691456 ], [ -109.93789323961248, 38.13555872106857 ], [ -109.93769247273474, 38.135633510202439 ], [ -109.93748613163901, 38.135699236246339 ], [ -109.93720602398278, 38.135737257529193 ], [ -109.9368234183729, 38.135761733176061 ], [ -109.93646949191104, 38.135775652472105 ], [ -109.93611515975036, 38.135817505213979 ], [ -109.93569211156405, 38.135876758892984 ], [ -109.93526394746667, 38.13589540923774 ], [ -109.93481204824765, 38.135976928999568 ], [ -109.9343656559867, 38.13607201545301 ], [ -109.93401571489215, 38.136204024847643 ], [ -109.93369350835404, 38.136390358870464 ], [ -109.93330200611575, 38.136633741519582 ], [ -109.93292846717944, 38.136897113125627 ], [ -109.93255259121743, 38.137164067203408 ], [ -109.93227542264719, 38.137391361969236 ], [ -109.93190605891907, 38.137680903908745 ], [ -109.93161594197977, 38.137935116265538 ], [ -109.9314310935282, 38.138091150193347 ], [ -109.93123545010029, 38.138283134841927 ], [ -109.93097454578739, 38.138568253231035 ], [ -109.93077754852706, 38.138774644462394 ], [ -109.93053924911689, 38.139074387313258 ], [ -109.93037624092277, 38.13929730947271 ], [ -109.93006973093595, 38.13957930674394 ], [ -109.92975759277462, 38.139855844519616 ], [ -109.9295033562009, 38.140074329180422 ], [ -109.92927678618609, 38.140351645486739 ], [ -109.92914798715003, 38.140575778937887 ], [ -109.92900147992697, 38.140840306142003 ], [ -109.92893549873196, 38.141060505970039 ], [ -109.92888623657051, 38.141307895138432 ], [ -109.92880607775047, 38.141717223981836 ], [ -109.92872611564211, 38.142113036075756 ], [ -109.9286998695794, 38.14234711658667 ], [ -109.92869082508614, 38.142653452411011 ], [ -109.9286743864746, 38.142919165410618 ], [ -109.92865750728109, 38.143293022006191 ], [ -109.9286762629648, 38.143649179021203 ], [ -109.92865418478333, 38.143910334380415 ], [ -109.92859350928471, 38.144157619183346 ], [ -109.9285095514532, 38.144436234592312 ], [ -109.92838578863163, 38.144705474447917 ], [ -109.9282853729858, 38.144938878001398 ], [ -109.9281505936238, 38.145180980153569 ], [ -109.9280860763748, 38.145378661922777 ], [ -109.92805265088711, 38.145635207366261 ], [ -109.92806050079795, 38.145878611065875 ], [ -109.92800021715931, 38.146098862144534 ], [ -109.92787208313713, 38.146354543014048 ], [ -109.92774239161558, 38.146560641875745 ], [ -109.92756668053846, 38.146869961786315 ], [ -109.92743653161982, 38.147185104885239 ], [ -109.92734070621091, 38.147494252698486 ], [ -109.92726046519327, 38.147908085377821 ], [ -109.92722712064482, 38.14823672954811 ], [ -109.92722814052718, 38.148556675293378 ], [ -109.92722398286006, 38.14884052455632 ], [ -109.92722559663653, 38.149119920377487 ], [ -109.92731266133539, 38.149409108981246 ], [ -109.92743224440785, 38.149815754286394 ], [ -109.9274804405199, 38.150031588203078 ], [ -109.92756696621137, 38.150357722058139 ], [ -109.92765317596931, 38.150705482449219 ], [ -109.92775622641661, 38.151072322326513 ], [ -109.92786101925306, 38.151320215778071 ], [ -109.9279632272947, 38.151744726409042 ], [ -109.92810300251303, 38.152331801007954 ], [ -109.92825374777789, 38.152559385214019 ], [ -109.92841533854646, 38.152825821021722 ], [ -109.9286338436326, 38.153102689338979 ], [ -109.92885327303499, 38.1533164796638 ], [ -109.92910959269348, 38.153661284138082 ], [ -109.92931311455509, 38.153870422401987 ], [ -109.92948648441559, 38.154034224033545 ], [ -109.92970240803164, 38.154175882516718 ], [ -109.9299226996925, 38.154331098835016 ], [ -109.93024324137915, 38.154577350829562 ], [ -109.9305833170807, 38.154814767545531 ], [ -109.9308770007089, 38.155024724092414 ], [ -109.93115901097235, 38.155252598238029 ], [ -109.93152044689681, 38.15551273736682 ], [ -109.93179701793358, 38.155722535924063 ], [ -109.93206071960424, 38.156032253176697 ], [ -109.93231349751106, 38.156308525064262 ], [ -109.93245273345434, 38.156544110270048 ], [ -109.93246250336296, 38.156656852647465 ], [ -109.93250565601087, 38.156828478325416 ], [ -109.93262895739869, 38.156982807903205 ], [ -109.93267348988159, 38.157059817065587 ], [ -109.93265082135807, 38.157127203175698 ], [ -109.93256244587273, 38.157239053480659 ], [ -109.93234836189337, 38.157439883770785 ], [ -109.93208764155229, 38.157707881702912 ], [ -109.93182180469309, 38.15793527722181 ], [ -109.93156201430014, 38.158139295197927 ], [ -109.93134273165725, 38.15830492839639 ], [ -109.93115644888364, 38.158555576975246 ], [ -109.93091463814886, 38.158778682906224 ], [ -109.93070576819126, 38.15893449616226 ], [ -109.93038253049991, 38.159183896353746 ], [ -109.93004893151947, 38.159361102995355 ], [ -109.92973881488305, 38.159493461292371 ], [ -109.92931942030395, 38.159683402306761 ], [ -109.92895190801499, 38.159837765891822 ], [ -109.92854995824231, 38.16000533253272 ], [ -109.92818277257051, 38.160137165970781 ], [ -109.92782739425988, 38.160242069222207 ], [ -109.92755762387254, 38.160346851992919 ], [ -109.9272475382825, 38.160476500238651 ], [ -109.92706953083045, 38.160550577126209 ], [ -109.92679436888631, 38.16063367940415 ], [ -109.92647828364858, 38.160783097771905 ], [ -109.92619063673315, 38.160939083913405 ], [ -109.92593770316424, 38.161062942652038 ], [ -109.92562226236385, 38.161168204436997 ], [ -109.92531252712217, 38.161273517582003 ], [ -109.92496736131517, 38.161459616016131 ], [ -109.92458264555496, 38.161618314420465 ], [ -109.92418625032442, 38.161794929097113 ], [ -109.92384758055287, 38.161927010075786 ], [ -109.92353226563482, 38.162023255074018 ], [ -109.92307939710084, 38.162158793067334 ], [ -109.92260907579858, 38.162316699854458 ], [ -109.92216164499121, 38.162470308708293 ], [ -109.92169185072538, 38.162592167551992 ], [ -109.92137639744935, 38.162697417714369 ], [ -109.9210494504718, 38.162807968779951 ], [ -109.92067581364101, 38.162988385490692 ], [ -109.92039366644933, 38.163157024973394 ], [ -109.92016785285919, 38.163375749260922 ], [ -109.91986207874989, 38.163598243772313 ], [ -109.91948145143159, 38.163865110066503 ], [ -109.91918191206534, 38.16405161107339 ], [ -109.91879033242969, 38.164286831348932 ], [ -109.91841640295397, 38.164486163808284 ], [ -109.918053165611, 38.164734259792596 ], [ -109.91765545895186, 38.164997357775334 ], [ -109.91735000367737, 38.165197317885152 ], [ -109.91705582692985, 38.165406393458241 ], [ -109.91676695520552, 38.165642553996726 ], [ -109.91652446958419, 38.16582957437371 ], [ -109.91629883629733, 38.166034774282295 ], [ -109.91620035292112, 38.166133000228641 ], [ -109.91599290590962, 38.166266269303406 ], [ -109.91586583427915, 38.166367835954894 ], [ -109.91570940046772, 38.16652500735119 ], [ -109.91553028543674, 38.166672055582218 ], [ -109.91525415301828, 38.166818207362795 ], [ -109.91491504351052, 38.166977294946228 ], [ -109.9146850448483, 38.167091427532597 ], [ -109.91445448414797, 38.167243405944852 ], [ -109.91420694882503, 38.167385313456911 ], [ -109.91384387011702, 38.16762078044146 ], [ -109.91354933924701, 38.167852374392432 ], [ -109.91334021019181, 38.168098276307916 ], [ -109.91328690749916, 38.168228460723014 ], [ -109.91322178923419, 38.16838557251959 ], [ -109.91303018001916, 38.168604599230854 ], [ -109.91278297556516, 38.16880058024843 ], [ -109.9126657526937, 38.168930172514223 ], [ -109.91251993058127, 38.169140610075139 ], [ -109.91238552172928, 38.16935115315578 ], [ -109.91224607468415, 38.169516588140823 ], [ -109.91208346380093, 38.169704338973546 ], [ -109.91190937089736, 38.169896489300072 ], [ -109.91171889273977, 38.170038920121371 ], [ -109.91148322600209, 38.170149388860423 ], [ -109.91130442871732, 38.170273902775811 ], [ -109.91119391533519, 38.170412567968434 ], [ -109.91112919277204, 38.170542645431105 ], [ -109.91090332860047, 38.170761350870762 ], [ -109.91068330438364, 38.170971097788275 ], [ -109.91035398351369, 38.171237508476999 ], [ -109.91015744271117, 38.171403312279267 ], [ -109.91004162084305, 38.171514890326691 ], [ -109.90997132221798, 38.171635903103443 ], [ -109.90987772458503, 38.171788242397156 ], [ -109.9097216824256, 38.171917471204402 ], [ -109.90956543830275, 38.172060216291968 ], [ -109.90943759563494, 38.172212237194778 ], [ -109.90929209334143, 38.172400142897345 ], [ -109.90903714401114, 38.172654623422552 ], [ -109.90887437003336, 38.172852281578294 ], [ -109.90871054696832, 38.173120225250031 ], [ -109.90856980750081, 38.173371259977586 ], [ -109.90842389736073, 38.173586197480127 ], [ -109.90827254784274, 38.173783059730233 ], [ -109.90806486300391, 38.17392983056974 ], [ -109.90792029511204, 38.174054657474159 ], [ -109.90787113898776, 38.174288518566762 ], [ -109.90766150135281, 38.174565948001067 ], [ -109.90744165810827, 38.174762171913464 ], [ -109.90711685826678, 38.175106120517256 ], [ -109.90685679012232, 38.175319993373833 ], [ -109.90664217868657, 38.175547807282094 ], [ -109.90643340812906, 38.175766662942138 ], [ -109.90608107161431, 38.176042760321437 ], [ -109.90576807910665, 38.176359778341705 ], [ -109.90561100900285, 38.176556583684054 ], [ -109.90530513549734, 38.176779038292892 ], [ -109.90505701077535, 38.176956969444888 ], [ -109.9047791326157, 38.177215732650495 ], [ -109.90454019958167, 38.177465846294496 ], [ -109.90425184136664, 38.177738028782578 ], [ -109.9040148562684, 38.177934086093295 ], [ -109.90376027416437, 38.178161521435712 ], [ -109.9035289265894, 38.178362136486427 ], [ -109.90321814196957, 38.178530466256028 ], [ -109.90279897595484, 38.17869327633899 ], [ -109.90244151968599, 38.178852155654567 ], [ -109.90200120151098, 38.178978716211226 ], [ -109.90160016836514, 38.179074099812993 ], [ -109.90128931743187, 38.179170325954999 ], [ -109.90100337699994, 38.179280302775886 ], [ -109.90062999987671, 38.179434521385254 ], [ -109.90012656037172, 38.179506410455211 ], [ -109.89969738945643, 38.179574487249383 ], [ -109.89938813931128, 38.179715784460285 ], [ -109.89901899503836, 38.17981596421653 ], [ -109.89854509663535, 38.179897135702085 ], [ -109.89816776779342, 38.179934150402865 ], [ -109.89785947587849, 38.179935763041392 ], [ -109.89760106099116, 38.180036977660819 ], [ -109.89746964441493, 38.180044755939349 ], [ -109.89715000426474, 38.180041754036736 ], [ -109.89697870055798, 38.180044650991263 ], [ -109.89659627401909, 38.180041057728147 ], [ -109.89617905655834, 38.180073185048791 ], [ -109.89572779562347, 38.180091472374087 ], [ -109.89512833425887, 38.180094845140566 ], [ -109.89466545308359, 38.180126537366228 ], [ -109.89422533490162, 38.180162948254832 ], [ -109.89383685961076, 38.180181819589237 ], [ -109.89343512836459, 38.180322229708523 ], [ -109.89302225253955, 38.180444508925632 ], [ -109.89263275253494, 38.180530958263134 ], [ -109.89225073335861, 38.180500318006509 ], [ -109.89193618547721, 38.18053790493282 ], [ -109.89158105401981, 38.180616564112334 ], [ -109.89125442034658, 38.180698194990036 ], [ -109.89099055925973, 38.180781319104241 ], [ -109.89075537377524, 38.180855701314705 ], [ -109.89042858782098, 38.180947241881761 ], [ -109.88995807748766, 38.181105014459568 ], [ -109.88946845782611, 38.181393281553056 ], [ -109.88915030023885, 38.181593046748475 ], [ -109.88880017623404, 38.181792508534386 ], [ -109.88839705752707, 38.182023010294493 ], [ -109.88814350884911, 38.182178323302324 ], [ -109.8877166632674, 38.182467177393086 ], [ -109.88743231005385, 38.182770898544838 ], [ -109.88715551322484, 38.182953025714461 ], [ -109.88684656472564, 38.183297067233866 ], [ -109.88666718956833, 38.183529683991665 ], [ -109.88649114520307, 38.183843441957805 ], [ -109.88629164926412, 38.184197532133915 ], [ -109.88605625545217, 38.184659427882131 ], [ -109.88593756236847, 38.184955704629772 ], [ -109.88569301237422, 38.185268811230138 ], [ -109.88557830886408, 38.185677778044187 ], [ -109.88554537389855, 38.185965856093937 ], [ -109.88551312517441, 38.186208879594446 ], [ -109.88546381986167, 38.186447235055624 ], [ -109.88542524432494, 38.186730753381212 ], [ -109.88539851092693, 38.18698644626312 ], [ -109.8853318597311, 38.187239056487705 ], [ -109.88516948355442, 38.187404240566501 ], [ -109.885131730441, 38.187633693318261 ], [ -109.88509363365955, 38.187885673296918 ], [ -109.88509494640226, 38.188174076317445 ], [ -109.88525433717413, 38.188504535281247 ], [ -109.88542249033279, 38.188784608863081 ], [ -109.88550474005537, 38.189007089883944 ], [ -109.88570667768487, 38.189243323955715 ], [ -109.88591556063083, 38.189398513755087 ], [ -109.88621488971964, 38.189613140583049 ], [ -109.88665040393238, 38.189883131404677 ], [ -109.88706576096294, 38.189977191574044 ], [ -109.88756138250436, 38.190049480330828 ], [ -109.88800012431984, 38.190107709964757 ], [ -109.88854630375948, 38.190234546650274 ], [ -109.88900338366413, 38.190288440045698 ], [ -109.88955570674754, 38.190311689832768 ], [ -109.88998426557569, 38.190288705905658 ], [ -109.89053752575602, 38.190325478242102 ], [ -109.89094895850029, 38.190302328948164 ], [ -109.8914064699951, 38.190252576704445 ], [ -109.8919621883384, 38.190127145820632 ], [ -109.89251804129574, 38.189992701354207 ], [ -109.89275807650513, 38.18997694097277 ], [ -109.89303319540062, 38.189906536431891 ], [ -109.89338820713918, 38.18983868675582 ], [ -109.89369778108312, 38.189755087093296 ], [ -109.89403145609539, 38.189587900104954 ], [ -109.89433082358664, 38.189423993947941 ], [ -109.89484677513649, 38.189284656492099 ], [ -109.89521328111179, 38.189211502131791 ], [ -109.8955451267308, 38.189165057200334 ], [ -109.89587201162529, 38.189068997514049 ], [ -109.89614296621694, 38.18889580726141 ], [ -109.89649417893959, 38.188700840225181 ], [ -109.89676961585485, 38.188608800540955 ], [ -109.89705110034897, 38.188494286486304 ], [ -109.89745927154534, 38.188307962590301 ], [ -109.89771246939118, 38.188176058084885 ], [ -109.89794203126688, 38.18809710322553 ], [ -109.89830885417254, 38.188002312791568 ], [ -109.8987097506143, 38.187919556704827 ], [ -109.8992808806901, 38.187830284367621 ], [ -109.89973944571562, 38.187785015481445 ], [ -109.90029262526686, 38.18782624711757 ], [ -109.90094345897568, 38.18782783537241 ], [ -109.90131342689408, 38.187903395852757 ], [ -109.90170025042552, 38.187997137285002 ], [ -109.90206424098919, 38.188090663923354 ], [ -109.90243829721467, 38.188274405706302 ], [ -109.90268676774761, 38.188456972600903 ], [ -109.90299749282461, 38.188676169544358 ], [ -109.90322857017367, 38.188876597210609 ], [ -109.90349751470701, 38.189217067444446 ], [ -109.90370326171812, 38.1895839835977 ], [ -109.90393150770335, 38.18997363996867 ], [ -109.90397917167121, 38.190221920867096 ], [ -109.9039708970251, 38.190393075705529 ], [ -109.90396725059611, 38.190636371462837 ], [ -109.90400894974964, 38.190901719846885 ], [ -109.90401515427342, 38.19124964922711 ], [ -109.90392472835158, 38.191568738619289 ], [ -109.90384082085676, 38.191833815505731 ], [ -109.90375386623808, 38.19222593605614 ], [ -109.90362517163724, 38.192507717742053 ], [ -109.90351883179866, 38.192745548220365 ], [ -109.90342431441043, 38.192956452384095 ], [ -109.90326135729488, 38.193162211023768 ], [ -109.90305266037802, 38.193372048163305 ], [ -109.90288405994833, 38.193573247419614 ], [ -109.90273103036219, 38.193878232357186 ], [ -109.90261938227459, 38.1940889756997 ], [ -109.90249135047705, 38.194249998618588 ], [ -109.90236250649126, 38.194465087043461 ], [ -109.9021772480897, 38.194634586750141 ], [ -109.90190669183633, 38.194780757834955 ], [ -109.90172862946318, 38.19485118984845 ], [ -109.90152745988526, 38.194939429796122 ], [ -109.90137135284634, 38.19506864603008 ], [ -109.90109427176827, 38.195268827386968 ], [ -109.90081759557108, 38.195441975249523 ], [ -109.9002413893319, 38.195788956113404 ], [ -109.89978087873729, 38.196036081740822 ], [ -109.89930940801787, 38.196252461284374 ], [ -109.89881374078753, 38.196558733971422 ], [ -109.89839357851631, 38.196780097143815 ], [ -109.89793834364781, 38.197055202755713 ], [ -109.89764424037212, 38.197247105025774 ], [ -109.89707394533646, 38.197578804831714 ], [ -109.89687806409898, 38.19769412297407 ], [ -109.89653197381195, 38.197925187566788 ], [ -109.89621408758683, 38.198179046797364 ], [ -109.89591387136637, 38.19839702253919 ], [ -109.89570058600606, 38.198530199386695 ], [ -109.89547520055672, 38.19870832297768 ], [ -109.89519284330161, 38.198877798998666 ], [ -109.89492314063527, 38.199041084913517 ], [ -109.8946385626223, 38.199281735013351 ], [ -109.89433813276803, 38.199513222910952 ], [ -109.89400378547903, 38.19972185999594 ], [ -109.89365801748008, 38.199930388479764 ], [ -109.8933756649695, 38.20009895886772 ], [ -109.89306401356923, 38.200316819359031 ], [ -109.89270600226396, 38.200579302689775 ], [ -109.89242344028243, 38.200761387052303 ], [ -109.89213544054131, 38.200925395021848 ], [ -109.89190508080114, 38.201053897600893 ], [ -109.89167485687641, 38.201173388812421 ], [ -109.89145523133409, 38.201347052785657 ], [ -109.89125177660529, 38.20158395439298 ], [ -109.89096199378034, 38.201865101038045 ], [ -109.8906431138485, 38.202182020727832 ], [ -109.89034224907461, 38.202440530593364 ], [ -109.89005341711945, 38.202658598596052 ], [ -109.88977376587096, 38.202948850186303 ], [ -109.88955552452921, 38.203181102793685 ], [ -109.88936836598826, 38.203472228259983 ], [ -109.8891847466449, 38.203830978278475 ], [ -109.88904264638643, 38.204163084363941 ], [ -109.88883725807818, 38.204526133849342 ], [ -109.88871392819507, 38.204750270962457 ], [ -109.88858523030078, 38.204951826654415 ], [ -109.88840813531834, 38.205256564007335 ], [ -109.88818124889956, 38.20560589039588 ], [ -109.8880094943834, 38.206009811660607 ], [ -109.88788540525185, 38.20628350761568 ], [ -109.88779502613794, 38.206593571534789 ], [ -109.88773924868805, 38.206881432778395 ], [ -109.88774015895768, 38.207196867654147 ], [ -109.88772428208911, 38.207489613006246 ], [ -109.88772766073347, 38.20764285204266 ], [ -109.88779282098965, 38.207864267789283 ], [ -109.88795566915505, 38.208046054174758 ], [ -109.88822728309191, 38.208210846161819 ], [ -109.88852262926268, 38.20831728308444 ], [ -109.88875564521301, 38.208391586606368 ], [ -109.88913705479698, 38.208471800154413 ], [ -109.88958148139325, 38.20853909033228 ], [ -109.89016418224932, 38.208526576641994 ], [ -109.89074866098444, 38.208396918534589 ], [ -109.89123008336453, 38.208284308483741 ], [ -109.89160301345379, 38.208170672076342 ], [ -109.89193672356937, 38.208007097274162 ], [ -109.89225358896456, 38.207824436971897 ], [ -109.89264540647311, 38.207594718316685 ], [ -109.89329018014607, 38.20725382995191 ], [ -109.89351450630542, 38.207147798469393 ], [ -109.89379613600788, 38.207028788295375 ], [ -109.89403880078227, 38.206918422520154 ], [ -109.8942506993028, 38.206803260341083 ], [ -109.8945094867714, 38.206684033265248 ], [ -109.89473931497282, 38.206591569502379 ], [ -109.89498042620357, 38.206508223681745 ], [ -109.89530595984222, 38.206506781525434 ], [ -109.89567718648462, 38.206504867112905 ], [ -109.89605939744469, 38.206531893818685 ], [ -109.89647567781027, 38.206571856621871 ], [ -109.89697733567903, 38.206630644596515 ], [ -109.8974515187256, 38.206693678472845 ], [ -109.89791811634326, 38.206729602663152 ], [ -109.898344800218, 38.20683724791845 ], [ -109.89871465731783, 38.206926334139617 ], [ -109.89913543001451, 38.20704743935363 ], [ -109.89943615883307, 38.207176429839876 ], [ -109.89965178150294, 38.20726857308415 ], [ -109.89994700561114, 38.207383992387228 ], [ -109.90036683401866, 38.207568169663446 ], [ -109.90096232042198, 38.207844112053266 ], [ -109.90131417532494, 38.207991600781973 ], [ -109.90171742222127, 38.208139569302816 ], [ -109.90219415727221, 38.208337790764446 ], [ -109.90253438041654, 38.208499586567932 ], [ -109.90294751082911, 38.208750382215463 ], [ -109.90332697827424, 38.2089612083006 ], [ -109.90372391629636, 38.209149665857971 ], [ -109.904200528396, 38.209356890243996 ], [ -109.90474063044778, 38.209519644177412 ], [ -109.90524157356697, 38.209627957311611 ], [ -109.90575983769703, 38.209723812716163 ], [ -109.90623231373245, 38.209826448952533 ], [ -109.90680097506124, 38.209989459543337 ], [ -109.90706404584175, 38.21004147625483 ], [ -109.9073978533208, 38.210175260502716 ], [ -109.90764829535743, 38.210231664455328 ], [ -109.90790961962362, 38.210324217871985 ], [ -109.90817658749971, 38.210421329296182 ], [ -109.90857435376168, 38.210555705093029 ], [ -109.90902297587679, 38.210726600970972 ], [ -109.90942605226579, 38.210888059810777 ], [ -109.90982294964907, 38.211081002545463 ], [ -109.91035098502702, 38.211288679630854 ], [ -109.91068527482898, 38.211467519987032 ], [ -109.91109924267677, 38.211665122930754 ], [ -109.91135439636147, 38.211789154127075 ], [ -109.91160968513523, 38.21190417383513 ], [ -109.91196675535585, 38.212087727872174 ], [ -109.91222150959555, 38.21223879005418 ], [ -109.91236862541386, 38.212331176381966 ], [ -109.9125836229455, 38.212467449898575 ], [ -109.91280451941279, 38.212591160595387 ], [ -109.91317879438812, 38.21277036421565 ], [ -109.91347186209538, 38.212956925961095 ], [ -109.91374454773768, 38.213131582517889 ], [ -109.9140962536992, 38.213292549991323 ], [ -109.9144706693628, 38.213462738622439 ], [ -109.91479261695936, 38.213627934906121 ], [ -109.91504288096107, 38.213774443381695 ], [ -109.91522912104456, 38.213924865762635 ], [ -109.91534730345097, 38.214043116325925 ], [ -109.91561806654515, 38.214270922689657 ], [ -109.91592827064707, 38.214535141446348 ], [ -109.91617566028377, 38.214798779406074 ], [ -109.91641667288026, 38.215107418909781 ], [ -109.91668644119524, 38.215402805028717 ], [ -109.91697978904052, 38.215648841061906 ], [ -109.91724538660488, 38.215840547266225 ], [ -109.91749473459633, 38.215972622582399 ], [ -109.91781836282746, 38.216102678570017 ], [ -109.91807872056148, 38.216262791933651 ], [ -109.91828083802172, 38.216498971599144 ], [ -109.91852380751867, 38.216753551688647 ], [ -109.9186669442162, 38.217038754267044 ], [ -109.91887264298022, 38.21741916086706 ], [ -109.91902190199637, 38.217753986404993 ], [ -109.91913185282505, 38.218043388855335 ], [ -109.91942767422186, 38.218586843629225 ], [ -109.91959677393486, 38.21904802162328 ], [ -109.9198807712998, 38.219541799364585 ], [ -109.91998103791126, 38.219713953476138 ], [ -109.92013077268825, 38.22001723927179 ], [ -109.92030992960932, 38.22026221633201 ], [ -109.92042500091493, 38.220592219421327 ], [ -109.9204550726174, 38.220876379728836 ], [ -109.92030883249564, 38.221109351309323 ], [ -109.92019161327491, 38.221311047049731 ], [ -109.92015064631394, 38.221454865044279 ], [ -109.92016217844478, 38.22167937442687 ], [ -109.92024039978453, 38.22187475712483 ], [ -109.92028867029958, 38.222086987394881 ], [ -109.9202393178208, 38.222334368322507 ], [ -109.92028214377349, 38.222528524136251 ], [ -109.92032979199398, 38.222705601148668 ], [ -109.92029752975543, 38.223033347666096 ], [ -109.92030064368942, 38.223209113781373 ], [ -109.92025155680999, 38.223438472752676 ], [ -109.92014375788, 38.223775437661203 ], [ -109.91999651146148, 38.224075990767062 ], [ -109.91988956316953, 38.224355285296731 ], [ -109.91970804616606, 38.22465552261685 ], [ -109.91950388196339, 38.224942032885572 ], [ -109.91928272851355, 38.225218472952783 ], [ -109.91908460587968, 38.22548250764239 ], [ -109.91891578607709, 38.225696343718873 ], [ -109.91867746692976, 38.225974426905779 ], [ -109.91839770281743, 38.226273756873447 ], [ -109.91815064737121, 38.2264472172441 ], [ -109.91782201961475, 38.226651467585441 ], [ -109.91732775495323, 38.226854189176741 ], [ -109.91701154838729, 38.226990960516524 ], [ -109.91656948550653, 38.227140087529634 ], [ -109.91626483320302, 38.227267951323988 ], [ -109.91588088634367, 38.22735002106343 ], [ -109.91558859178102, 38.227414912055124 ], [ -109.91514752743542, 38.227496451636512 ], [ -109.91475771930307, 38.227588376890502 ], [ -109.91441369688405, 38.227674415827849 ], [ -109.91390342030105, 38.227800371348103 ], [ -109.91351934750965, 38.227890543105488 ], [ -109.91300965808301, 38.227976846623491 ], [ -109.91252235784965, 38.228093996732454 ], [ -109.91209862388204, 38.228238770528186 ], [ -109.91163295768567, 38.228360623531088 ], [ -109.91115176752699, 38.228450788082057 ], [ -109.91071008751952, 38.228572859926544 ], [ -109.91022331769179, 38.228653956703731 ], [ -109.90973614324946, 38.228762084181994 ], [ -109.9093350465877, 38.228843973080693 ], [ -109.90902016302495, 38.228890613384245 ], [ -109.90873961660905, 38.228933066028539 ], [ -109.90820143702807, 38.229013676370855 ], [ -109.90785846519633, 38.22902850969065 ], [ -109.90744708758092, 38.229033693081263 ], [ -109.90696676486884, 38.22906526944039 ], [ -109.90646204322991, 38.229200256331318 ], [ -109.90608426006816, 38.229250808738065 ], [ -109.90570143982387, 38.229256252167509 ], [ -109.90522050717469, 38.22932837038838 ], [ -109.90481456935711, 38.229351619595242 ], [ -109.90424883818079, 38.229364363480464 ], [ -109.90393993166671, 38.229393021602824 ], [ -109.90357861231452, 38.229412177127543 ], [ -109.90310649337424, 38.229353692731181 ], [ -109.90252933863897, 38.229366321558729 ], [ -109.90196462338098, 38.229311472758376 ], [ -109.90119489754922, 38.229214147365127 ], [ -109.90038525983853, 38.229111936921925 ], [ -109.89934878669668, 38.228899448015326 ], [ -109.8989784105964, 38.228837395058974 ], [ -109.89849358432036, 38.22878868629774 ], [ -109.89793467027788, 38.228728465291915 ], [ -109.89751268737781, 38.228679441350842 ], [ -109.89698252389826, 38.22860686887018 ], [ -109.89648112399924, 38.228521046218638 ], [ -109.89592913796717, 38.228380672657217 ], [ -109.89547329767912, 38.228304286436938 ], [ -109.89510286001295, 38.228246726773683 ], [ -109.89477763858855, 38.228221134280147 ], [ -109.89450409475891, 38.228178003354238 ], [ -109.89400242803531, 38.228110191928437 ], [ -109.89352319913004, 38.22806962635255 ], [ -109.89300364813906, 38.228051208890918 ], [ -109.89263831063961, 38.228034244246885 ], [ -109.89213066184587, 38.227984392692122 ], [ -109.89170188207009, 38.228007380938251 ], [ -109.89119926174264, 38.228002633592368 ], [ -109.89079924491396, 38.228012372042457 ], [ -109.8905194452759, 38.228005221319286 ], [ -109.89026065726844, 38.228119031403281 ], [ -109.89007629742514, 38.228221829001086 ], [ -109.88987596650161, 38.228247871977246 ], [ -109.8896817717509, 38.228246035 ], [ -109.88944039053347, 38.2283419836332 ], [ -109.8891816545208, 38.228452186946939 ], [ -109.88900228661332, 38.228527092426404 ], [ -109.88877311271015, 38.228646586809873 ], [ -109.88854265859194, 38.228775080762276 ], [ -109.88847743032969, 38.228932175599333 ], [ -109.88846828987279, 38.229157392696315 ], [ -109.88849280234382, 38.229423483156104 ], [ -109.88851126037424, 38.229712046626453 ], [ -109.8886188436617, 38.230150154479162 ], [ -109.8887457575548, 38.230444250928983 ], [ -109.88887852135764, 38.230729390472135 ], [ -109.88906593683909, 38.231177265780104 ], [ -109.8893066802768, 38.23149947545609 ], [ -109.88951834065395, 38.231780854809919 ], [ -109.8897140778078, 38.232057577069391 ], [ -109.88992754665159, 38.232370515285787 ], [ -109.89007121631425, 38.232615201948761 ], [ -109.89017257162092, 38.232787391157778 ], [ -109.89021504890312, 38.232999578173569 ], [ -109.89023045120743, 38.233188978796072 ], [ -109.89032230444948, 38.233460211569565 ], [ -109.89044881988316, 38.233781338746027 ], [ -109.89061582141449, 38.233994702801127 ], [ -109.89082957339679, 38.234289617727768 ], [ -109.89103199221292, 38.234503315909116 ], [ -109.89123820859017, 38.234843219578465 ], [ -109.89151235710146, 38.235224319159848 ], [ -109.8917034245088, 38.23543340288952 ], [ -109.89191699987772, 38.235665229173414 ], [ -109.89223746799937, 38.236006209756027 ], [ -109.89255889587839, 38.236284113547391 ], [ -109.89284700914021, 38.236498617205541 ], [ -109.8929654636661, 38.236598868165515 ], [ -109.89313423610605, 38.236771690699349 ], [ -109.8932576524616, 38.236921554923079 ], [ -109.89348266170187, 38.237153486180695 ], [ -109.8936512318049, 38.237339824268794 ], [ -109.89384713571226, 38.237607528992093 ], [ -109.89400903983396, 38.237856888695504 ], [ -109.89415875589796, 38.238156601293461 ], [ -109.89438826960647, 38.238468781269134 ], [ -109.89460056605971, 38.238786205901775 ], [ -109.8947776345594, 38.239166383335935 ], [ -109.89505195382631, 38.239538464049339 ], [ -109.89528766539878, 38.239819158123261 ], [ -109.89546153604088, 38.240033481106458 ], [ -109.89564577209643, 38.240242494092392 ], [ -109.8959955740729, 38.240610776815132 ], [ -109.89637314071815, 38.240956789265887 ], [ -109.89666067062349, 38.241211832684286 ], [ -109.89706741952634, 38.241517562662295 ], [ -109.89746220204643, 38.241859227346467 ], [ -109.89803884297474, 38.242265683459713 ], [ -109.898474371246, 38.242558160613321 ], [ -109.89889956493586, 38.242778442119857 ], [ -109.89925198982273, 38.24289890608263 ], [ -109.89970234824321, 38.242966214456565 ], [ -109.90014168930043, 38.243006381445717 ], [ -109.90083319420445, 38.242995737335256 ], [ -109.90140584261813, 38.242910077022827 ], [ -109.90188251133065, 38.242747813881032 ], [ -109.90229028610699, 38.242607434717073 ], [ -109.9029167012586, 38.242365458731165 ], [ -109.90309494721004, 38.242290521776248 ], [ -109.90341146250204, 38.242139372282388 ], [ -109.90371054062442, 38.242007885734274 ], [ -109.90410152150228, 38.241843911766637 ], [ -109.90448152155123, 38.241650093914124 ], [ -109.90488424862184, 38.241464597823814 ], [ -109.90517890616147, 38.241246549687595 ], [ -109.90544963046071, 38.241100374699826 ], [ -109.90569104754186, 38.241003492572737 ], [ -109.90601828851209, 38.240898397887001 ], [ -109.90637476667452, 38.240748514036241 ], [ -109.90661624888325, 38.240647124521658 ], [ -109.90702434041435, 38.240484201328293 ], [ -109.9074214770102, 38.240289632208402 ], [ -109.90786424467717, 38.240099992460387 ], [ -109.90827851466103, 38.239905579848077 ], [ -109.90866327675967, 38.239773976367715 ], [ -109.90897943316334, 38.239645338686245 ], [ -109.90937607544727, 38.23948320199694 ], [ -109.90984215429874, 38.239262228823954 ], [ -109.91021575431598, 38.239112492219661 ], [ -109.91072087451441, 38.238954963084041 ], [ -109.91116261773725, 38.238832892353692 ], [ -109.91159911725376, 38.238679228797004 ], [ -109.91213198820456, 38.238576023801329 ], [ -109.91251492447991, 38.238566054675516 ], [ -109.91296573933663, 38.238601773803069 ], [ -109.9132449928337, 38.238648519631816 ], [ -109.91354142435456, 38.238692720183543 ], [ -109.91391166265079, 38.23876824437383 ], [ -109.91435515902003, 38.238912036247321 ], [ -109.91465040001817, 38.239036431130444 ], [ -109.91493341339778, 38.239214785120879 ], [ -109.91533598965779, 38.239421280003462 ], [ -109.9156421910384, 38.239577316228477 ], [ -109.915936500271, 38.23976478433142 ], [ -109.91625205600803, 38.240060593707327 ], [ -109.91665303597048, 38.240375215146443 ], [ -109.91690644012743, 38.240624487040151 ], [ -109.91713643398474, 38.240911393402534 ], [ -109.91730904893367, 38.24121489304013 ], [ -109.91750411521151, 38.241545635960144 ], [ -109.9176641051809, 38.241930127938865 ], [ -109.91785950888853, 38.242238342991413 ], [ -109.91809477014316, 38.242555937322514 ], [ -109.91824594381889, 38.242764610323064 ], [ -109.91834536916497, 38.242995336534719 ], [ -109.91839815773763, 38.243288717856274 ], [ -109.91839448570654, 38.243536518040898 ], [ -109.91838503398408, 38.243788771017698 ], [ -109.91839836701227, 38.244045740059391 ], [ -109.91844684556101, 38.244244454064265 ], [ -109.91847300672752, 38.244406913785618 ], [ -109.91845132802737, 38.244713126913837 ], [ -109.91843045030544, 38.244965274538764 ], [ -109.91835715391981, 38.245284530085229 ], [ -109.91820400810657, 38.245594037354891 ], [ -109.91799890919884, 38.245939113959594 ], [ -109.91778856290581, 38.246252599286755 ], [ -109.91758432881018, 38.246539104164896 ], [ -109.91734735164478, 38.246721666965286 ], [ -109.91700329485971, 38.246804107555498 ], [ -109.91668740165154, 38.246913843548533 ], [ -109.91618230512476, 38.2470668920759 ], [ -109.91564763665697, 38.24728725619989 ], [ -109.91518723615837, 38.247508304446413 ], [ -109.91485205020976, 38.247685448133105 ], [ -109.91454139757751, 38.247903372398738 ], [ -109.91418429696787, 38.248093829640226 ], [ -109.9138386209565, 38.248284391524109 ], [ -109.91343574368648, 38.248478928805703 ], [ -109.91303879228617, 38.248659100159585 ], [ -109.91268778673651, 38.248823474045771 ], [ -109.91236596378174, 38.24894666153584 ], [ -109.9118256913749, 38.24915794395401 ], [ -109.91117034310842, 38.249422228947445 ], [ -109.91069943075313, 38.249580076887931 ], [ -109.9101305150063, 38.249795591593596 ], [ -109.90976875747796, 38.249913894917903 ], [ -109.90949874908787, 38.250010519458932 ], [ -109.90863205766166, 38.250268319856524 ], [ -109.90810870288585, 38.250493260526291 ], [ -109.90764819235416, 38.250718783861998 ], [ -109.9069571175699, 38.251077339837366 ], [ -109.9062885522205, 38.251458631798847 ], [ -109.9059829018551, 38.251645037211233 ], [ -109.90577512240347, 38.251782787806675 ], [ -109.9054043905507, 38.252117284840729 ], [ -109.90499788659957, 38.252550580218035 ], [ -109.90437054104508, 38.253229645695924 ], [ -109.90399394637291, 38.253573095493174 ], [ -109.9038374449655, 38.25372033362067 ], [ -109.90350043457779, 38.254091187912834 ], [ -109.9031850476799, 38.254619955403157 ], [ -109.9029732664756, 38.254946917975225 ], [ -109.90278030940179, 38.255238007685996 ], [ -109.90255347477701, 38.255501743862823 ], [ -109.90213320203601, 38.256088106066748 ], [ -109.9020161457323, 38.25627175916933 ], [ -109.90186895985659, 38.256558769506363 ], [ -109.90177958973788, 38.256801260199069 ], [ -109.90178231942475, 38.256999552271886 ], [ -109.90185919416544, 38.257207550380855 ], [ -109.90203634312134, 38.257587716935774 ], [ -109.90213097123612, 38.257755326464519 ], [ -109.90224757425459, 38.257981720240828 ], [ -109.90229588140782, 38.258189450775632 ], [ -109.90237360155439, 38.258645289532424 ], [ -109.90251702533823, 38.259444203019243 ], [ -109.90264426790284, 38.260103277200365 ], [ -109.90275626768849, 38.260636039107837 ], [ -109.90293270608748, 38.26144427270907 ], [ -109.90298259814183, 38.261926886990587 ], [ -109.90297588978028, 38.262372923607202 ], [ -109.90296482220243, 38.262728798363874 ], [ -109.90304572634911, 38.263049484559687 ], [ -109.90312588586754, 38.263419730309153 ], [ -109.90323570223535, 38.263718156362756 ], [ -109.90340029294109, 38.26417480608675 ], [ -109.9035352294935, 38.264703275277796 ], [ -109.90368954642435, 38.265083225652432 ], [ -109.9039387778452, 38.265612762213735 ], [ -109.90426442960538, 38.266381832648925 ], [ -109.90453747557177, 38.266848505562294 ], [ -109.9047998398554, 38.267265511558783 ], [ -109.9049668968746, 38.267559062911914 ], [ -109.90547691479112, 38.268231618515934 ], [ -109.90590346387586, 38.268753792690376 ], [ -109.90643541216696, 38.269489633290625 ], [ -109.90703685513257, 38.270165737794791 ], [ -109.90748925195395, 38.270566483620989 ], [ -109.90770888663096, 38.270709117342896 ], [ -109.90795329430371, 38.270800612279686 ], [ -109.90817543632349, 38.270852246274622 ], [ -109.90845425641214, 38.270935949518119 ], [ -109.90904182172937, 38.271013511300602 ], [ -109.90940200123026, 38.271007847805798 ], [ -109.90986034599447, 38.270935504611046 ], [ -109.91038848156464, 38.270782698891452 ], [ -109.9112430947421, 38.270584255526884 ], [ -109.91224383010687, 38.27016906785051 ], [ -109.91303315649355, 38.269748308302589 ], [ -109.9132468237332, 38.26960158790417 ], [ -109.91370891467236, 38.269276925350965 ], [ -109.91426450508149, 38.268814339779112 ], [ -109.91476357071232, 38.268308871779851 ], [ -109.91536615168764, 38.267760199230246 ], [ -109.91627117775667, 38.266858339112922 ], [ -109.91680469120733, 38.266340563330687 ], [ -109.91762095416713, 38.265640645439369 ], [ -109.9185967408572, 38.264973734483512 ], [ -109.91955603370486, 38.264261602772855 ], [ -109.92043543916363, 38.263539715902276 ], [ -109.92143038057003, 38.262733269218252 ], [ -109.92276591590688, 38.26177222917476 ], [ -109.92332477924053, 38.261389837411748 ], [ -109.92407374821812, 38.260982149915854 ], [ -109.9249375242394, 38.260539461010417 ], [ -109.92569046457622, 38.260248957067617 ], [ -109.92647104154013, 38.260021785991633 ], [ -109.9269926876228, 38.259913905856195 ], [ -109.9274799148167, 38.25981472091653 ], [ -109.92808109262366, 38.259739105307581 ], [ -109.92864193940227, 38.259685648692667 ], [ -109.92918446576073, 38.259712230156133 ], [ -109.9297040434233, 38.259744908277426 ], [ -109.9302009959903, 38.259839561520579 ], [ -109.93079247489432, 38.259957604382286 ], [ -109.93121918935294, 38.26008766179374 ], [ -109.93162199279342, 38.260289596990368 ], [ -109.93217763128231, 38.260592055228855 ], [ -109.93286962539855, 38.260949823819296 ], [ -109.93353412208155, 38.261234340164982 ], [ -109.93410191546374, 38.261488234296706 ], [ -109.93459530826887, 38.261749561072762 ], [ -109.93497389158273, 38.262045892253788 ], [ -109.93528318215816, 38.262391160174253 ], [ -109.9355250206762, 38.262659212255123 ], [ -109.93587871714483, 38.26309500274477 ], [ -109.93598893070688, 38.263375378248121 ], [ -109.93603619460406, 38.263583085805962 ], [ -109.93605132622328, 38.263799514103766 ], [ -109.93604298281507, 38.263979681013787 ], [ -109.93603391638567, 38.26420940806463 ], [ -109.93606452298214, 38.264462025174716 ], [ -109.93616100996162, 38.26489998822165 ], [ -109.93618073951612, 38.265193061223975 ], [ -109.93618668841179, 38.265490515327784 ], [ -109.93615496077108, 38.265706518677625 ], [ -109.93599932171215, 38.266110653027887 ], [ -109.93570651286456, 38.266671255130767 ], [ -109.93539192055516, 38.26707935389323 ], [ -109.93490215724434, 38.267740904772722 ], [ -109.93441922959276, 38.268403416779414 ], [ -109.93400548368164, 38.268868288628987 ], [ -109.93368576339574, 38.269234880224523 ], [ -109.93344782811658, 38.269480550800886 ], [ -109.93322795879786, 38.269663300313702 ], [ -109.93273199041481, 38.269965201766588 ], [ -109.93228606738938, 38.270362183745576 ], [ -109.93185018356408, 38.270853882583644 ], [ -109.93169270946336, 38.27106873957073 ], [ -109.93155809465981, 38.271283804507213 ], [ -109.93145836372339, 38.271458632474889 ], [ -109.93143358868095, 38.271589082483565 ], [ -109.93140762503766, 38.27180063067884 ], [ -109.93141003872155, 38.272025955492623 ], [ -109.93135503693024, 38.272268781571789 ], [ -109.93102825193384, 38.272725422329152 ], [ -109.93067242422882, 38.273213339805189 ], [ -109.92999411051021, 38.273941642410286 ], [ -109.929341742818, 38.274692707979213 ], [ -109.92895711867256, 38.275193875341351 ], [ -109.92854033658993, 38.275938074533137 ], [ -109.92818295273459, 38.276529609003511 ], [ -109.92791255451277, 38.277036322235986 ], [ -109.92775984293198, 38.277314301823587 ], [ -109.92766874198311, 38.277678459317322 ], [ -109.92762735711807, 38.278160228479756 ], [ -109.92760437782493, 38.278556550875152 ], [ -109.92761562586686, 38.278957692159999 ], [ -109.92772332485995, 38.279408380351086 ], [ -109.92792205262609, 38.279888739015973 ], [ -109.92822694464876, 38.280535889864893 ], [ -109.92856607071752, 38.281187858591927 ], [ -109.92888505373379, 38.281654894408057 ], [ -109.92914952943391, 38.281941189881913 ], [ -109.92952739908749, 38.282291604182149 ], [ -109.9301884245114, 38.282824841677694 ], [ -109.93074756297953, 38.283289556136147 ], [ -109.93121749831712, 38.283600249658704 ], [ -109.93184676072332, 38.283961958631728 ], [ -109.93252301186565, 38.284238476911781 ], [ -109.93279586618466, 38.284344598501846 ], [ -109.93301149441265, 38.284454705036694 ], [ -109.93333487204698, 38.284624369558074 ], [ -109.93383327598029, 38.284944323583005 ], [ -109.93429246176861, 38.2852098466592 ], [ -109.93500191180824, 38.28556325510236 ], [ -109.93556458976722, 38.285789158280778 ], [ -109.93595716599451, 38.285918889028814 ], [ -109.93625329120417, 38.285998177391541 ], [ -109.9365728736704, 38.28603712322051 ], [ -109.93766907560121, 38.286137176120036 ], [ -109.93835283049317, 38.286215462745652 ], [ -109.93886160411644, 38.286296668778981 ], [ -109.93951201097047, 38.28638816515091 ], [ -109.94010479820079, 38.286510679690736 ], [ -109.94126849548884, 38.286687911632733 ], [ -109.94225551653307, 38.286827490774293 ], [ -109.94288744456955, 38.286932319998151 ], [ -109.94360136290034, 38.287060414435089 ], [ -109.94477495824079, 38.28734494477898 ], [ -109.94536716282379, 38.287508883208496 ], [ -109.94580484564379, 38.287684047105373 ], [ -109.94613996143606, 38.287835757754969 ], [ -109.9465827132384, 38.288056024795672 ], [ -109.94705229213371, 38.288398194312137 ], [ -109.94748686088536, 38.288789614387973 ], [ -109.94815314408521, 38.289367858772273 ], [ -109.94909038860558, 38.290187347711246 ], [ -109.94963080173741, 38.290773468115617 ], [ -109.9497882696364, 38.290955119928938 ], [ -109.94997302303659, 38.291227136740481 ], [ -109.95010457488186, 38.291620340419591 ], [ -109.95036255009065, 38.292366146962252 ], [ -109.95051729755525, 38.292737027438967 ], [ -109.95061435937326, 38.293143440047082 ], [ -109.95066679061367, 38.293472850524019 ], [ -109.95073017724384, 38.293915010128735 ], [ -109.95075177857962, 38.294320747549207 ], [ -109.95070527140658, 38.294770936182061 ], [ -109.95066558374435, 38.295144582984371 ], [ -109.95058509788663, 38.295571937312488 ], [ -109.95046076225742, 38.296264755880891 ], [ -109.95031989686738, 38.296993474663822 ], [ -109.95008611111238, 38.29766278294607 ], [ -109.94996352019439, 38.29823395314957 ], [ -109.94987198161522, 38.298634171529272 ], [ -109.9497212163964, 38.299096944111952 ], [ -109.94945631063909, 38.299702887600965 ], [ -109.94914952033955, 38.300358021635475 ], [ -109.94886585416309, 38.300995337826578 ], [ -109.948730516937, 38.301259981360545 ], [ -109.94852963300268, 38.301707883613439 ], [ -109.9483231981705, 38.302144020002714 ], [ -109.94808168772499, 38.302633012693668 ], [ -109.9478586284265, 38.303032049557878 ], [ -109.94768208868082, 38.303377430854979 ], [ -109.94741048382797, 38.303969790899735 ], [ -109.94702282686437, 38.304678265439186 ], [ -109.94667454795734, 38.30543125136731 ], [ -109.94652000742846, 38.305836307955772 ], [ -109.94628743060056, 38.306496606127325 ], [ -109.94613328977387, 38.306873728280664 ], [ -109.94605900238854, 38.307265085869076 ], [ -109.94603058808342, 38.307647843532621 ], [ -109.94607196277308, 38.30795011965548 ], [ -109.94618833395762, 38.308523431662394 ], [ -109.94628725128673, 38.308880297070701 ], [ -109.94636852365677, 38.309191943533683 ], [ -109.94670781041116, 38.309852871857196 ], [ -109.94703261999119, 38.310328921825935 ], [ -109.9473461276596, 38.310795857380803 ], [ -109.94772773710268, 38.311299451357335 ], [ -109.94816640428265, 38.311812567853693 ], [ -109.94845945978737, 38.312112593772845 ], [ -109.94904655351368, 38.312645061730031 ], [ -109.94944267647128, 38.312936996626235 ], [ -109.94994023897691, 38.313333477160029 ], [ -109.95043182867562, 38.313747926264107 ], [ -109.95083747729019, 38.314094014083658 ], [ -109.95107618657819, 38.314277291676746 ], [ -109.95129740266573, 38.314404537576578 ], [ -109.95157585632377, 38.314528689904812 ], [ -109.952105730356, 38.314668606292017 ], [ -109.95250408069168, 38.314807345693566 ], [ -109.95288045273931, 38.314883704284867 ], [ -109.95322247558154, 38.314962458723862 ], [ -109.95378699104427, 38.315080146552006 ], [ -109.95436216895504, 38.315251999116924 ], [ -109.9552965201524, 38.31550365130299 ], [ -109.95634056466935, 38.315684175717777 ], [ -109.9575370168935, 38.316005732634963 ], [ -109.9582265194726, 38.316183088448938 ], [ -109.95903618148385, 38.316357000744958 ], [ -109.95973654911714, 38.316574998437382 ], [ -109.96017476260894, 38.316727583536505 ], [ -109.96052154326811, 38.316874850633823 ], [ -109.96094234692715, 38.317045302701736 ], [ -109.96133963487749, 38.317260605340586 ], [ -109.96185483412737, 38.317630155534545 ], [ -109.96222796832529, 38.317935362025501 ], [ -109.96255502135392, 38.318263591084751 ], [ -109.96295857213782, 38.31884303108108 ], [ -109.9632433672447, 38.31932769445946 ], [ -109.96333834255364, 38.319486245125191 ], [ -109.96343197091704, 38.319739410476735 ], [ -109.96348537486607, 38.3200057383455 ], [ -109.96350061599622, 38.320542090790603 ], [ -109.96351907413758, 38.321254206820349 ], [ -109.963597417919, 38.321777598727195 ], [ -109.96366714714483, 38.322102649095335 ], [ -109.96373719769674, 38.322405172097355 ], [ -109.96389290782804, 38.322717463913641 ], [ -109.96401513790204, 38.322970881381629 ], [ -109.9642032419748, 38.323418639805865 ], [ -109.96443016498021, 38.323952355245623 ], [ -109.96453352032485, 38.324246159732603 ], [ -109.96461969879398, 38.324702029501211 ], [ -109.96476508363685, 38.325338662961222 ], [ -109.96493676104049, 38.326137745244679 ], [ -109.96502990704663, 38.326827989504011 ], [ -109.96525283220664, 38.327563537853415 ], [ -109.96537314942532, 38.328435163693676 ], [ -109.96543084383181, 38.329205301884997 ], [ -109.96544943068734, 38.329507369556282 ], [ -109.96549094777068, 38.329806034673624 ], [ -109.96554430177031, 38.330076866825237 ], [ -109.96558666498636, 38.330316059822771 ], [ -109.96557157452222, 38.330572770112695 ], [ -109.96551650942455, 38.33082462173774 ], [ -109.96537532639064, 38.33109824368632 ], [ -109.96519455196002, 38.331339973923484 ], [ -109.96508826257354, 38.33157334918414 ], [ -109.96498782054319, 38.331797763898088 ], [ -109.96484232388941, 38.331972214558178 ], [ -109.96451861204616, 38.3322081758363 ], [ -109.96412941315711, 38.33262379864744 ], [ -109.96357439499461, 38.333033448670626 ], [ -109.96296724842787, 38.333487695240088 ], [ -109.96292071775898, 38.333541355999415 ], [ -109.96271866766732, 38.333669342351435 ], [ -109.96233901343335, 38.333815583399044 ], [ -109.96209863096234, 38.333903576482989 ], [ -109.96180981385356, 38.334018176397848 ], [ -109.96155149894187, 38.334079874668276 ], [ -109.96102963678554, 38.334168977380322 ], [ -109.96024289945422, 38.334378293240725 ], [ -109.95910691059656, 38.334607034315248 ], [ -109.95821251374241, 38.334743284498217 ], [ -109.95699520448215, 38.335056896897115 ], [ -109.95600824208395, 38.335264403131575 ], [ -109.95517649451828, 38.335419211873599 ], [ -109.95413681031728, 38.335711846843822 ], [ -109.95288423916966, 38.336088186046609 ], [ -109.95201826039873, 38.336314762849007 ], [ -109.9512176565655, 38.336609508165033 ], [ -109.95038939414751, 38.336917518441695 ], [ -109.94995257442267, 38.337057800156536 ], [ -109.94927940000215, 38.337322131030504 ], [ -109.94872634695517, 38.33758753496808 ], [ -109.94837356608475, 38.337850226496805 ], [ -109.94794472411728, 38.338229390890831 ], [ -109.94747329258068, 38.338783905878913 ], [ -109.94720493808303, 38.339141977810748 ], [ -109.94696563970403, 38.339468767947722 ], [ -109.9467138543589, 38.33986754158434 ], [ -109.94650685139963, 38.34033430714782 ], [ -109.94634028112846, 38.340774399557027 ], [ -109.94617266433312, 38.341286578442116 ], [ -109.94609065856856, 38.341813044558094 ], [ -109.94602013324395, 38.342731636544798 ], [ -109.9459118459975, 38.343492178593195 ], [ -109.94576864362584, 38.344292960590742 ], [ -109.9457318368359, 38.344463857947879 ], [ -109.94561647835965, 38.344922433425637 ], [ -109.94538807238629, 38.345285365888891 ], [ -109.94513566941207, 38.345724684098428 ], [ -109.94482196708313, 38.346050799944649 ], [ -109.94436978120255, 38.34645677634019 ], [ -109.94386802694099, 38.34712365276151 ], [ -109.94336139337514, 38.347731904885599 ], [ -109.94288361891078, 38.34832239088869 ], [ -109.94247625989173, 38.348791847878125 ], [ -109.94211420634542, 38.349293254178875 ], [ -109.94181223206729, 38.349597838624121 ], [ -109.94157985465127, 38.349838164104547 ], [ -109.94133997015003, 38.350200984573746 ], [ -109.94112823044512, 38.350595600703663 ], [ -109.94089117480947, 38.351156709773129 ], [ -109.94078062929009, 38.351674802442666 ], [ -109.9406997526731, 38.35212016580661 ], [ -109.94070438179288, 38.352587930423297 ], [ -109.94073549410558, 38.352809005494073 ], [ -109.94078396799718, 38.353016719397438 ], [ -109.94092878899988, 38.353288387590723 ], [ -109.94119836943564, 38.353637784295671 ], [ -109.94167287964673, 38.354061126340376 ], [ -109.94211891843123, 38.354475197579809 ], [ -109.9425839621255, 38.354763270559772 ], [ -109.94306676402476, 38.355010947798533 ], [ -109.94362499852971, 38.355187206744475 ], [ -109.94404696243856, 38.355290139835979 ], [ -109.94462887321971, 38.355412535264534 ], [ -109.94525655962866, 38.355535339621383 ], [ -109.94621597691049, 38.355670134652158 ], [ -109.94709672938049, 38.355705083441954 ], [ -109.94814406469125, 38.355696460224763 ], [ -109.94939152995477, 38.355698633142566 ], [ -109.95007943800586, 38.35561467531442 ], [ -109.95088795561976, 38.355500250710477 ], [ -109.95151917606975, 38.35537882794462 ], [ -109.95181220406856, 38.355296735189249 ], [ -109.95213398273239, 38.35520498545165 ], [ -109.95247929652338, 38.355068385081125 ], [ -109.9526697994872, 38.354952930905789 ], [ -109.95283754500369, 38.35482826115885 ], [ -109.95294215713042, 38.354716545381635 ], [ -109.95308207200466, 38.354537554702226 ], [ -109.95318765644701, 38.354358257338987 ], [ -109.95325304638583, 38.354188514239418 ], [ -109.95329417178624, 38.354034776091282 ], [ -109.95331975926079, 38.353926860446343 ], [ -109.95334459151908, 38.35379190203308 ], [ -109.95333678071779, 38.353539496126601 ], [ -109.95331584041227, 38.353404129090606 ], [ -109.9533238970445, 38.353241984888527 ], [ -109.95334527765777, 38.352949285516388 ], [ -109.95339077632335, 38.352571187340281 ], [ -109.95336612529935, 38.352296101039187 ], [ -109.95337085992247, 38.351967204984831 ], [ -109.95341635772272, 38.351589106725662 ], [ -109.95344209682686, 38.351391072260142 ], [ -109.95342798071563, 38.351179164024302 ], [ -109.95342543708831, 38.350958347066268 ], [ -109.95353019919679, 38.350517693595393 ], [ -109.95356668978424, 38.350288212980736 ], [ -109.95364787449833, 38.349815806878119 ], [ -109.95371072745647, 38.34942434521237 ], [ -109.95376779365924, 38.349037337855826 ], [ -109.95383669048161, 38.348623399958392 ], [ -109.95393233742949, 38.348020448325748 ], [ -109.95408920932672, 38.347377488622996 ], [ -109.95415946326521, 38.346868936330772 ], [ -109.95429355410911, 38.346297869156388 ], [ -109.95445527584098, 38.345794638289775 ], [ -109.95466835394478, 38.345300877020378 ], [ -109.95491646652711, 38.344757861456912 ], [ -109.9551291499352, 38.344291131779002 ], [ -109.95552791669003, 38.343695385037002 ], [ -109.95601000564476, 38.343113896762631 ], [ -109.95643479571673, 38.342617510713808 ], [ -109.95691048441111, 38.34216212995883 ], [ -109.95741296197244, 38.341833153775525 ], [ -109.95785128162663, 38.341589219465043 ], [ -109.95836441793203, 38.341314406027266 ], [ -109.95903895191813, 38.340955408941753 ], [ -109.95970666328593, 38.340672949645402 ], [ -109.96031722856011, 38.340385473818401 ], [ -109.96057092809714, 38.340248036483842 ], [ -109.96102034699167, 38.340026718617729 ], [ -109.9613531659345, 38.33995757081675 ], [ -109.96185804939385, 38.339858403418006 ], [ -109.962322823812, 38.339763384921064 ], [ -109.96299404837231, 38.339634142382188 ], [ -109.96330925283841, 38.33959637534609 ], [ -109.96365261004154, 38.339590398396901 ], [ -109.9638867646716, 38.339619503718794 ], [ -109.96411615062144, 38.339662084498983 ], [ -109.96438856355064, 38.339736586961834 ], [ -109.96485487412482, 38.339935364301979 ], [ -109.96537192860632, 38.340186857336747 ], [ -109.96592310503074, 38.340453068269717 ], [ -109.96648617480692, 38.340687839327565 ], [ -109.96679297368962, 38.340839241586174 ], [ -109.96706538629905, 38.340994846159631 ], [ -109.96733754421238, 38.341168471927972 ], [ -109.96772874951922, 38.341419747431758 ], [ -109.96828508952943, 38.341726546910962 ], [ -109.968931432278, 38.342142279606961 ], [ -109.96962946044609, 38.342544944880984 ], [ -109.9702361556669, 38.342933285906668 ], [ -109.97044508111297, 38.343128879238144 ], [ -109.9705696626384, 38.343220093368423 ], [ -109.97062044818647, 38.343270105399256 ], [ -109.9707845656304, 38.343397714506331 ], [ -109.97088664735973, 38.343461694708381 ], [ -109.97116523285302, 38.343586703049162 ], [ -109.97154052529682, 38.343751310728656 ], [ -109.97183069484042, 38.343866505860305 ], [ -109.97217114307068, 38.344067755327245 ], [ -109.97243213768768, 38.344223247384754 ], [ -109.97268220082819, 38.344342594957304 ], [ -109.97299544897389, 38.344444471363104 ], [ -109.97331454610959, 38.344537386114915 ], [ -109.97392846079246, 38.344822132926936 ], [ -109.97447906885986, 38.345133358971417 ], [ -109.97502980985259, 38.345516679864112 ], [ -109.97562289388105, 38.345981476399487 ], [ -109.97610347010034, 38.346391215351574 ], [ -109.97663440008664, 38.346882500108137 ], [ -109.97701893331772, 38.347205782724636 ], [ -109.97746112473858, 38.347498024807152 ], [ -109.97800528729404, 38.347863250315449 ], [ -109.978668144772, 38.348333145615662 ], [ -109.97929725263019, 38.348762189245619 ], [ -109.97960901195194, 38.348972179462166 ], [ -109.98007404647107, 38.349269116520034 ], [ -109.98077798982281, 38.34966726105754 ], [ -109.98147495735988, 38.350155461087809 ], [ -109.98211509888981, 38.350616127585525 ], [ -109.98275505944098, 38.351090307068986 ], [ -109.98320226302991, 38.351436643212395 ], [ -109.98333712077975, 38.351613547201133 ], [ -109.98349506665005, 38.351776231953096 ], [ -109.98370322186074, 38.352031274402528 ], [ -109.9838768101522, 38.352303139769134 ], [ -109.98410052115489, 38.352673670278293 ], [ -109.98435803516395, 38.353082343683056 ], [ -109.98464945382189, 38.353521951016447 ], [ -109.98498996841582, 38.354052102911879 ], [ -109.98533341786863, 38.354618327300301 ], [ -109.9856732509588, 38.35519803740933 ], [ -109.98591814431698, 38.355610202933214 ], [ -109.98623285994842, 38.356104079892738 ], [ -109.98653549421283, 38.356561803463066 ], [ -109.98677512862376, 38.357023487823021 ], [ -109.98696364538728, 38.357457693939665 ], [ -109.98708362637321, 38.35788229562344 ], [ -109.98716864896588, 38.358351655280295 ], [ -109.98718933978651, 38.358509544397293 ], [ -109.98720292759059, 38.358766504380583 ], [ -109.98720425526908, 38.35908193657805 ], [ -109.98717728642265, 38.359374594266889 ], [ -109.98710435216648, 38.359680372861568 ], [ -109.98698494953808, 38.360035316001401 ], [ -109.98681958003196, 38.360403379791414 ], [ -109.98662603759202, 38.360739657745484 ], [ -109.98628772885296, 38.361197247162288 ], [ -109.98606715443429, 38.361419738986861 ], [ -109.98592240122886, 38.361540149244007 ], [ -109.98574878477079, 38.361678333655099 ], [ -109.98548317113639, 38.36184726381051 ], [ -109.9852752194258, 38.361985150385266 ], [ -109.98501004401618, 38.362122541190125 ], [ -109.98451465359409, 38.362352563724613 ], [ -109.98388783555214, 38.362567927111819 ], [ -109.98315164922057, 38.362746290538333 ], [ -109.98219262069475, 38.363062401106816 ], [ -109.98167388373419, 38.363323750870464 ], [ -109.98144201290852, 38.363452410777867 ], [ -109.98114294031998, 38.363639064287447 ], [ -109.98087737212414, 38.3638034782471 ], [ -109.98062884362663, 38.36397705176288 ], [ -109.98021151812688, 38.364351926774297 ], [ -109.97982833349238, 38.364740615356148 ], [ -109.97956110079247, 38.365023069072159 ], [ -109.97935747193684, 38.365259213464164 ], [ -109.97912401380422, 38.365581612996188 ], [ -109.97896551682045, 38.36586411088944 ], [ -109.9787886478161, 38.366232062558979 ], [ -109.9786771321907, 38.366429355213896 ], [ -109.97845944172475, 38.366851022724177 ], [ -109.97822584767093, 38.367182431152735 ], [ -109.97792250171207, 38.367589833009987 ], [ -109.97774047077851, 38.367917183934154 ], [ -109.97760523453958, 38.368172846648918 ], [ -109.97750471437375, 38.368401775984722 ], [ -109.97745022949361, 38.368613082766842 ], [ -109.97740592176578, 38.368914598283752 ], [ -109.97730400480084, 38.369242647216396 ], [ -109.97717378670723, 38.36946681113772 ], [ -109.97705736612268, 38.369686589297423 ], [ -109.97692174343038, 38.369969283739628 ], [ -109.97647912400083, 38.37051064600476 ], [ -109.97628658527994, 38.37077031272824 ], [ -109.97597610582881, 38.371275877624164 ], [ -109.97575347461068, 38.371639819689236 ], [ -109.97557822642527, 38.371890624244173 ], [ -109.97536825739718, 38.372168161033137 ], [ -109.97506023156033, 38.372498912110977 ], [ -109.97468746827316, 38.372955264042595 ], [ -109.9743145094392, 38.373425131004765 ], [ -109.97404584856174, 38.373804888456455 ], [ -109.97380583913453, 38.374182192470187 ], [ -109.97365741191531, 38.374559396606124 ], [ -109.97335286277564, 38.375047883197929 ], [ -109.9731744773985, 38.375519450139159 ], [ -109.97313854529192, 38.375631785228485 ], [ -109.97310165946891, 38.375730593969763 ], [ -109.97303850982931, 38.375824666623039 ], [ -109.97299151281386, 38.375909868766406 ], [ -109.97296664475934, 38.376049336681945 ], [ -109.97296517970045, 38.376152961684582 ], [ -109.97295265006478, 38.376229453789179 ], [ -109.9729336963065, 38.37635545552768 ], [ -109.97290870253077, 38.376422826434897 ], [ -109.97288599806777, 38.376490217394405 ], [ -109.97287842723287, 38.376620824845027 ], [ -109.97286526035572, 38.376742371274716 ], [ -109.97286881777924, 38.376895606186459 ], [ -109.97284935401532, 38.377057651364879 ], [ -109.97288286450373, 38.377197630742849 ], [ -109.97292604229179, 38.37730164687337 ], [ -109.97297023749331, 38.377414683884567 ], [ -109.97306091952059, 38.377559670074618 ], [ -109.97312063132813, 38.377708890892002 ], [ -109.97313671906777, 38.377785633678791 ], [ -109.97315242469553, 38.377889409065624 ], [ -109.97311591806019, 38.378042292989122 ], [ -109.9730455796344, 38.37815883258309 ], [ -109.97299837721141, 38.378258452061253 ], [ -109.97293847893927, 38.378446277712079 ], [ -109.97289007845384, 38.378630599275645 ], [ -109.97283054910838, 38.378792293341917 ], [ -109.97278233924803, 38.378963098545839 ], [ -109.97274557637039, 38.37913400403697 ], [ -109.97266270570994, 38.379327035386083 ], [ -109.97263166598555, 38.379497990986088 ], [ -109.97258358261344, 38.37965978521158 ], [ -109.97255858486677, 38.379808263786515 ], [ -109.97256175925419, 38.379988531209598 ], [ -109.97254223008754, 38.380155081662622 ], [ -109.97250578466156, 38.380303459872785 ], [ -109.97245337642531, 38.380447192151685 ], [ -109.97241006218998, 38.380595510112208 ], [ -109.97240140625975, 38.380802709742461 ], [ -109.97239326022597, 38.380973865921618 ], [ -109.97236628542238, 38.381262012745289 ], [ -109.97235909544935, 38.381365587457537 ], [ -109.97235139546369, 38.381505205606288 ], [ -109.97232633277227, 38.381658189499746 ], [ -109.97232512150909, 38.381743792663606 ], [ -109.97233446537533, 38.381892572201224 ], [ -109.97232636893567, 38.3824647617243 ], [ -109.97227809150498, 38.38264007199335 ], [ -109.97224202672921, 38.382761417461879 ], [ -109.97226803216957, 38.382946390964719 ], [ -109.97228335496402, 38.383077198947447 ], [ -109.97230916933886, 38.383275688719692 ], [ -109.97235241070598, 38.383456307313196 ], [ -109.97240856374741, 38.38361450914055 ], [ -109.97242910357581, 38.38370030295544 ], [ -109.97245078824554, 38.383786106801537 ], [ -109.97247291918978, 38.383840372645544 ], [ -109.97247775072255, 38.383903498816245 ], [ -109.97249332904076, 38.38401628504613 ], [ -109.97253135720806, 38.38416080996415 ], [ -109.97256925803741, 38.384314345724455 ], [ -109.97260735023855, 38.384454365186947 ], [ -109.97266204107015, 38.384635083990212 ], [ -109.97275037545866, 38.384865663457283 ], [ -109.97282211170456, 38.385055543527592 ], [ -109.97286020475163, 38.385195562902716 ], [ -109.97290478671418, 38.385281567288139 ], [ -109.97297169171195, 38.385408321121041 ], [ -109.97304922962032, 38.385592844690642 ], [ -109.97309856774658, 38.385747381652997 ], [ -109.97317049685059, 38.38592374522414 ], [ -109.97324891489535, 38.386046093759987 ], [ -109.97336702017455, 38.386195825760076 ], [ -109.97345695088092, 38.386313769001291 ], [ -109.97352970931995, 38.386431561795519 ], [ -109.97364234631661, 38.38656322168714 ], [ -109.9736873120804, 38.386622193213199 ], [ -109.97374334428294, 38.386708297523668 ], [ -109.97388924508665, 38.386916850153625 ], [ -109.97401905618115, 38.387048660021271 ], [ -109.97410930724547, 38.387144075634914 ], [ -109.9741488040947, 38.387184975176829 ], [ -109.97423854633891, 38.387316434117672 ], [ -109.97428891909671, 38.387397982652267 ], [ -109.97437898003457, 38.387506914347867 ], [ -109.97445822899803, 38.387570691529142 ], [ -109.97457703907951, 38.387670862631182 ], [ -109.97479786898911, 38.387844021713356 ], [ -109.97496699033009, 38.388030246159133 ], [ -109.97508014113504, 38.388125861276407 ], [ -109.97519920732917, 38.388208010048508 ], [ -109.97542073966665, 38.388331608268253 ], [ -109.97559692291468, 38.388423267856091 ], [ -109.9757569513136, 38.388523797986046 ], [ -109.97591469041241, 38.388624307896833 ], [ -109.97607389249461, 38.388702300452984 ], [ -109.97631947024057, 38.388826107025764 ], [ -109.97654043306872, 38.388909144301124 ], [ -109.97667101449673, 38.38898688614313 ], [ -109.97678499442621, 38.389023929058112 ], [ -109.97696168894279, 38.389079543187833 ], [ -109.97718398857786, 38.389149072967854 ], [ -109.97736073448038, 38.389201082158593 ], [ -109.97745202049487, 38.389223507279588 ], [ -109.9776119234153, 38.389251938036772 ], [ -109.97780547526366, 38.389330227857236 ], [ -109.97790805821973, 38.389363565504809 ], [ -109.97798217133675, 38.389385840466915 ], [ -109.97810772826386, 38.389413971072642 ], [ -109.97834160572205, 38.389474587631611 ], [ -109.97853566603892, 38.389516832804198 ], [ -109.97870135787369, 38.389540806541845 ], [ -109.9789069941973, 38.389574139994231 ], [ -109.97903846633108, 38.389588803180303 ], [ -109.97922107848727, 38.389630947503527 ], [ -109.97940979528896, 38.389646108787296 ], [ -109.97963902653919, 38.389630080563691 ], [ -109.97985108435499, 38.389613902426142 ], [ -109.97996576319628, 38.389601382503244 ], [ -109.98018926976067, 38.389585303383335 ], [ -109.98040736812644, 38.389546646866286 ], [ -109.98060244199576, 38.389516801672812 ], [ -109.9807746811985, 38.389482251612677 ], [ -109.98092949399468, 38.389465573734633 ], [ -109.98108971503798, 38.389471472592511 ], [ -109.98125025218577, 38.389454844050427 ], [ -109.98145131537713, 38.389406124355318 ], [ -109.98167499800086, 38.389377427165627 ], [ -109.98186447286248, 38.389338519250408 ], [ -109.98204268816917, 38.389285995284958 ], [ -109.98220359101639, 38.38924323388931 ], [ -109.98232432170565, 38.389207333073429 ], [ -109.98247963870631, 38.389154609628946 ], [ -109.98266917570757, 38.389111194958879 ], [ -109.98288211502883, 38.389031935163032 ], [ -109.98299717112411, 38.388992379618763 ], [ -109.98317551098278, 38.388930843026024 ], [ -109.98343996878435, 38.388852029115633 ], [ -109.98361283581218, 38.388772420440219 ], [ -109.98381432437539, 38.38869305964333 ], [ -109.98396982836198, 38.388626817867369 ], [ -109.98415414302713, 38.388547307613528 ], [ -109.98432700856245, 38.388467697859767 ], [ -109.9844999493352, 38.388382681314745 ], [ -109.98470702163003, 38.388313280514936 ], [ -109.98485687524442, 38.388241581421354 ], [ -109.98496065670261, 38.388189309521216 ], [ -109.98513377240177, 38.388091676778089 ], [ -109.98520315707761, 38.388042711632629 ], [ -109.98531292676435, 38.387971566109258 ], [ -109.98539948417789, 38.387922749501847 ], [ -109.98554951255765, 38.387838434255691 ], [ -109.98564789591205, 38.387762683879878 ], [ -109.98576313732667, 38.387709609231592 ], [ -109.98586706839939, 38.387646523438889 ], [ -109.98601148462164, 38.387554048256348 ], [ -109.9860867686364, 38.387492516842023 ], [ -109.98620239930436, 38.387411507991963 ], [ -109.9862890812531, 38.387353679815682 ], [ -109.98637588884776, 38.387286840682613 ], [ -109.98648007032747, 38.387205732545105 ], [ -109.98658988780856, 38.387130981424548 ], [ -109.98667090772862, 38.387068598018509 ], [ -109.98679689101949, 38.386984073275329 ], [ -109.98689659277183, 38.386895716453374 ], [ -109.98698945033505, 38.386805497999383 ], [ -109.98706537379174, 38.386698010372612 ], [ -109.98718129116968, 38.386596275458594 ], [ -109.98725684967449, 38.386514919289077 ], [ -109.98731472015875, 38.386470359372915 ], [ -109.98738988885523, 38.386416936884416 ], [ -109.98747059318097, 38.386377080134061 ], [ -109.9875979076234, 38.386279048037274 ], [ -109.98770804914891, 38.386180867493849 ], [ -109.98778919265007, 38.386109472380994 ], [ -109.98785901322509, 38.386028967459389 ], [ -109.98792960172449, 38.3859755050674 ], [ -109.98803262219427, 38.385895286687003 ], [ -109.98810231672866, 38.385823792508212 ], [ -109.98814784410443, 38.385761101652804 ], [ -109.98823025707858, 38.385680705201821 ], [ -109.98830598919861, 38.385586733056655 ], [ -109.98835882456902, 38.385492563253024 ], [ -109.98841172256144, 38.385393887972789 ], [ -109.98851104093686, 38.385250553331922 ], [ -109.98864520553276, 38.38507147132848 ], [ -109.98878446618191, 38.384937493040411 ], [ -109.98887780817658, 38.38481213048027 ], [ -109.98897674847217, 38.384695828111148 ], [ -109.98908713658311, 38.384579624383115 ], [ -109.98918664062151, 38.384422772762839 ], [ -109.98927991854268, 38.384301915304306 ], [ -109.98934426246545, 38.38420333826469 ], [ -109.9894547746169, 38.384078123258732 ], [ -109.98950131913233, 38.384024452601217 ], [ -109.98959453332444, 38.38390810032206 ], [ -109.98968755917986, 38.383805264319598 ], [ -109.98979273469223, 38.383652065828784 ], [ -109.98985731546577, 38.383536367758538 ], [ -109.98993316853036, 38.383433383562227 ], [ -109.99005550234229, 38.383281233868772 ], [ -109.99015487716981, 38.383133392245902 ], [ -109.99023664125836, 38.383016940784806 ], [ -109.99035274870489, 38.382900785076266 ], [ -109.99046879315068, 38.382789134699593 ], [ -109.99054470717564, 38.382681644617449 ], [ -109.9905977253257, 38.382573957325612 ], [ -109.99066079588127, 38.382484380540426 ], [ -109.9907491140404, 38.382390515105683 ], [ -109.99081861468068, 38.382332535551541 ], [ -109.99091711024683, 38.382247769593441 ], [ -109.99099258487404, 38.382171817382591 ], [ -109.99104491348065, 38.382113689876348 ], [ -109.99112058810761, 38.382023320119309 ], [ -109.99122034031473, 38.381930453923324 ], [ -109.99128882051465, 38.381863453310821 ], [ -109.99137008077098, 38.381783044639569 ], [ -109.99148027288339, 38.381680354856378 ], [ -109.99156763189967, 38.381572962545036 ], [ -109.99163738130997, 38.381496960650281 ], [ -109.99172436458932, 38.381416600954772 ], [ -109.99182285784916, 38.381331834190817 ], [ -109.9919039918439, 38.381260436040691 ], [ -109.99199784310893, 38.381180135199855 ], [ -109.99210657604196, 38.381099962237712 ], [ -109.99224482240064, 38.381038066884543 ], [ -109.99234300200247, 38.380975826953808 ], [ -109.99241828629953, 38.38091339014511 ], [ -109.99251086679899, 38.380842089952182 ], [ -109.99259772334341, 38.38077074049307 ], [ -109.9927194846755, 38.380659136943329 ], [ -109.99281212703238, 38.380583331041713 ], [ -109.99290489413879, 38.380498514144406 ], [ -109.99297343389401, 38.380427007032054 ], [ -109.99302696685872, 38.380364382959314 ], [ -109.9930911147551, 38.380279320058953 ], [ -109.99313199284367, 38.380221093229693 ], [ -109.99326557456124, 38.380082554642975 ], [ -109.99338739614562, 38.379966444896077 ], [ -109.9935614298699, 38.379800316141328 ], [ -109.99365449472567, 38.379693872400935 ], [ -109.99376474283646, 38.379586674884777 ], [ -109.99384618501895, 38.379492748009056 ], [ -109.99392088340041, 38.379389751200698 ], [ -109.99399177296391, 38.379313757639061 ], [ -109.99405646788247, 38.379189046101743 ], [ -109.99413270968549, 38.379057224010189 ], [ -109.99417935978529, 38.378995441525774 ], [ -109.99430721359981, 38.378856852554243 ], [ -109.99436551026857, 38.378780750717056 ], [ -109.99444732498733, 38.378659790610357 ], [ -109.99454655969434, 38.378520955865689 ], [ -109.99463409740228, 38.378400044707185 ], [ -109.99472169716964, 38.378274628013202 ], [ -109.99478590355147, 38.378185058639041 ], [ -109.99487910166815, 38.378068701823622 ], [ -109.99496676294214, 38.377938779464003 ], [ -109.99506568399286, 38.37782247155797 ], [ -109.99514176044035, 38.377702362942948 ], [ -109.99523484517978, 38.377594115655604 ], [ -109.99533339143954, 38.377504840294812 ], [ -109.9954327474581, 38.377356993797463 ], [ -109.99553757736165, 38.377227218111628 ], [ -109.99562492494354, 38.377119822539996 ], [ -109.99567050255989, 38.377052623040832 ], [ -109.99571270829212, 38.376980888635828 ], [ -109.99577106424024, 38.376900280568591 ], [ -109.99584671502241, 38.37681080861897 ], [ -109.9959510451918, 38.376717076262473 ], [ -109.99601518638322, 38.376632011618469 ], [ -109.99608523766599, 38.376533479550666 ], [ -109.99617861832446, 38.376403605210918 ], [ -109.99629501685118, 38.376264915874906 ], [ -109.99641060575313, 38.376184797492925 ], [ -109.99650902416292, 38.376104532012022 ], [ -109.99657876308949, 38.376028526963943 ], [ -109.99664880056929, 38.375930895624485 ], [ -109.99670131922042, 38.37585834790994 ], [ -109.9967883398655, 38.375774379836095 ], [ -109.99686947516931, 38.375702076936385 ], [ -109.99695084670819, 38.375612653196093 ], [ -109.99702058469465, 38.375536647866049 ], [ -109.99708528338232, 38.375411033366532 ], [ -109.9971553942099, 38.375307995133667 ], [ -109.99721953272477, 38.37522292977409 ], [ -109.9972724731672, 38.37511974458716 ], [ -109.99731360612184, 38.375042593190614 ], [ -109.99756908825979, 38.37477982522676 ], [ -109.99797695476396, 38.374341724018564 ], [ -109.99826227681122, 38.373907080240571 ], [ -109.99852454295321, 38.373566864823431 ], [ -109.99874185526933, 38.373248794862391 ], [ -109.99907842847855, 38.372832610712258 ], [ -109.99942198965134, 38.372407473182029 ], [ -109.99958620768983, 38.372120490409685 ], [ -109.99974401901989, 38.371883018775158 ], [ -109.99988391587573, 38.371699466143134 ], [ -110.00001734483524, 38.371569930224922 ], [ -110.00015637236541, 38.3714494539093 ], [ -110.00046440481236, 38.371109624243729 ], [ -110.00056896866455, 38.370997865584798 ], [ -110.00066756130958, 38.37090407995106 ], [ -110.00097447394396, 38.370645347453973 ], [ -110.00114975607143, 38.370385492677968 ], [ -110.001584476527, 38.36998906241957 ], [ -110.00206544578262, 38.369558778540885 ], [ -110.00252329517504, 38.369144517544036 ], [ -110.00312527357204, 38.368653977022511 ], [ -110.00365247677495, 38.368189833907628 ], [ -110.00424287061639, 38.367708201052793 ], [ -110.0048043344662, 38.367248849615272 ], [ -110.00556719532818, 38.366710095717785 ], [ -110.00628826129068, 38.366297150806545 ], [ -110.00684865456141, 38.365914382467508 ], [ -110.00774162940084, 38.365484860601676 ], [ -110.00868203367473, 38.364934070559983 ], [ -110.00932504804804, 38.364786301443175 ], [ -110.00979102969657, 38.364609997591167 ], [ -110.01031337529818, 38.364497251880522 ], [ -110.01095681187927, 38.364317935230908 ], [ -110.01139307099946, 38.36422248246798 ], [ -110.01176016892711, 38.364162493227745 ], [ -110.01234936029927, 38.364099868007933 ], [ -110.0130607060982, 38.36406079827978 ], [ -110.01366138447659, 38.364079371423202 ], [ -110.01405580882088, 38.364114231191941 ], [ -110.01458111802994, 38.364204262009984 ], [ -110.01488915625647, 38.364278946987405 ], [ -110.01519098418092, 38.364389627112708 ], [ -110.01561207078234, 38.364568898105254 ], [ -110.01580448927623, 38.364729125321141 ], [ -110.01599066140703, 38.36492805152367 ], [ -110.01606821529563, 38.365117955060207 ], [ -110.01611051901638, 38.365375152939635 ], [ -110.01606199310083, 38.365577516347344 ], [ -110.01582065382954, 38.366071152187132 ], [ -110.01550114675975, 38.366419938640071 ], [ -110.01528647697798, 38.366634424398484 ], [ -110.01504343661873, 38.366830647344699 ], [ -110.01476117495467, 38.367049070233826 ], [ -110.01444222490196, 38.367271690019066 ], [ -110.01416453793178, 38.367490149895353 ], [ -110.01385817424067, 38.36771287389444 ], [ -110.01356812079655, 38.367998818481517 ], [ -110.01329486645751, 38.3683119397868 ], [ -110.01283901096477, 38.368668583104686 ], [ -110.0125263218528, 38.368850696170796 ], [ -110.01228163208684, 38.369082947435921 ], [ -110.01196391317843, 38.369382172869308 ], [ -110.01175513091516, 38.369583183545856 ], [ -110.01154037938309, 38.369802167547903 ], [ -110.01133220778722, 38.369958122495568 ], [ -110.01104244200215, 38.3702215330079 ], [ -110.01079235476561, 38.370513214853588 ], [ -110.01045626067511, 38.370815885821521 ], [ -110.01019504209678, 38.371084041137408 ], [ -110.00988674772705, 38.371446424441281 ], [ -110.00969863529905, 38.371809822186357 ], [ -110.00963881263019, 38.371999470355327 ], [ -110.00957943185558, 38.372156678964522 ], [ -110.00946856715849, 38.372311650137114 ], [ -110.0093928026204, 38.372411043311253 ], [ -110.00929742321225, 38.372689609760052 ], [ -110.00921324365251, 38.372986294800043 ], [ -110.00905521470645, 38.373241801474727 ], [ -110.00897817026579, 38.373434908474771 ], [ -110.00899909651115, 38.373579277583545 ], [ -110.00899559337968, 38.373836090329426 ], [ -110.00900924773954, 38.37409394930684 ], [ -110.00901209475654, 38.374304854452348 ], [ -110.00900385162518, 38.374489531006851 ], [ -110.00889962197712, 38.374996927272498 ], [ -110.00903599430694, 38.375490135912777 ], [ -110.00911279083083, 38.375735010540907 ], [ -110.00926137472881, 38.376172447637146 ], [ -110.00940643641701, 38.37644853980381 ], [ -110.00959605850221, 38.376815128351154 ], [ -110.00979837011926, 38.377090802486741 ], [ -110.01024357849226, 38.37760464193844 ], [ -110.01074720718574, 38.378032457436319 ], [ -110.01116736721544, 38.37828473377597 ], [ -110.01147997071317, 38.378448685204106 ], [ -110.01184217602538, 38.378753641243875 ], [ -110.01218148968532, 38.379058403264438 ], [ -110.0127295210123, 38.379590222483202 ], [ -110.01316559494373, 38.37993635056403 ], [ -110.0134824529482, 38.380209377750795 ], [ -110.01397662842308, 38.380492907729227 ], [ -110.01443074109483, 38.380776098802272 ], [ -110.01477354223032, 38.380909654538087 ], [ -110.01534093171911, 38.381198300106526 ], [ -110.0159857121027, 38.381352412533737 ], [ -110.01646998280185, 38.381523198818009 ], [ -110.01705107410717, 38.381730843046867 ], [ -110.01741062972216, 38.381896073605944 ], [ -110.01787031869733, 38.38210720209414 ], [ -110.01851267729107, 38.382441520484768 ], [ -110.01935532022659, 38.382782017074099 ], [ -110.01978279435434, 38.382920772534391 ], [ -110.0202502773745, 38.38306436685086 ], [ -110.02058154039355, 38.383121207167861 ], [ -110.02131884456087, 38.38320847333128 ], [ -110.02209694676532, 38.383242003185941 ], [ -110.02290391238292, 38.383257744459158 ], [ -110.02429442638645, 38.383300868913771 ], [ -110.02501607737985, 38.383275331448814 ], [ -110.02582395096765, 38.383223470105392 ], [ -110.02649764656834, 38.383358839926771 ], [ -110.02729218942289, 38.383447445100316 ], [ -110.02785803759862, 38.383514322067974 ], [ -110.02822309941865, 38.383527262269858 ], [ -110.02884153820719, 38.383599977674592 ], [ -110.0294626187622, 38.383817805060545 ], [ -110.02989723941461, 38.383852043579026 ], [ -110.03052412166944, 38.384064506164478 ], [ -110.03093367160614, 38.384261650887879 ], [ -110.03130351545977, 38.384431430031157 ], [ -110.03172898053319, 38.38472332961355 ], [ -110.03201194519195, 38.384968990931121 ], [ -110.03220856853157, 38.385249986778632 ], [ -110.03249998395528, 38.385721016922076 ], [ -110.03265111722746, 38.385979106512536 ], [ -110.03281600389347, 38.386494151626721 ], [ -110.03291640586251, 38.386778858274624 ], [ -110.03300307018333, 38.387063451497426 ], [ -110.03320374762505, 38.387470647169664 ], [ -110.03341467658822, 38.387968047083255 ], [ -110.03347152799607, 38.388428128189396 ], [ -110.03352927960917, 38.388820626619697 ], [ -110.03350748838938, 38.38916740913573 ], [ -110.03342188737425, 38.389576749484142 ], [ -110.03318238189227, 38.389935254372908 ], [ -110.03294882664474, 38.390276685025306 ], [ -110.03269257478775, 38.39060260747685 ], [ -110.03250476416589, 38.390948019484597 ], [ -110.03228164286203, 38.391365235646987 ], [ -110.03186894267859, 38.391830451647792 ], [ -110.03162477889261, 38.392107806676165 ], [ -110.03144490788837, 38.392286560473956 ], [ -110.03101688684073, 38.392611960780535 ], [ -110.03062525613838, 38.392784456495541 ], [ -110.02999860465583, 38.39289192219573 ], [ -110.02931209981402, 38.392936706097345 ], [ -110.02881315062001, 38.39299926175746 ], [ -110.02828092438247, 38.393066946613246 ], [ -110.02751108487431, 38.393263331764516 ], [ -110.02711974663231, 38.393327674179048 ], [ -110.02613229712961, 38.393526749811727 ], [ -110.02557553665432, 38.393630266465301 ], [ -110.02507517609045, 38.393797333544128 ], [ -110.02472974788236, 38.393938651737983 ], [ -110.02423395758814, 38.394191367143399 ], [ -110.02381782786594, 38.394480791865867 ], [ -110.02364895756608, 38.394691167087082 ], [ -110.0234276526687, 38.394968695111388 ], [ -110.02331403607361, 38.395242614100873 ], [ -110.02314271829039, 38.395719723021571 ], [ -110.02305188328415, 38.39608755625418 ], [ -110.02297109056391, 38.396560012152726 ], [ -110.02271178719396, 38.39710758153241 ], [ -110.02245466416537, 38.397492952717904 ], [ -110.02215641820764, 38.397955483291518 ], [ -110.02185740339611, 38.398474782132062 ], [ -110.02162768252138, 38.398950499878637 ], [ -110.02135926956969, 38.399407870093569 ], [ -110.02108801616444, 38.399905769832728 ], [ -110.02083738988496, 38.400232613587605 ], [ -110.0204385189386, 38.400936721012705 ], [ -110.0201822717309, 38.401340118115165 ], [ -110.01990612912431, 38.401774890166315 ], [ -110.0196662724981, 38.402151387187722 ], [ -110.01928796549436, 38.402603327049199 ], [ -110.01906990898044, 38.403061112959143 ], [ -110.01880592293175, 38.403527525881771 ], [ -110.01850636084357, 38.404083759963839 ], [ -110.01817944567395, 38.404545138356347 ], [ -110.01778948231308, 38.405010493398649 ], [ -110.01729308981191, 38.405384835027647 ], [ -110.01697446465523, 38.405571414324115 ], [ -110.01646674974288, 38.405851031731935 ], [ -110.0157976693361, 38.406205893646813 ], [ -110.01496642393653, 38.406694568334956 ], [ -110.01436117000914, 38.406986874594317 ], [ -110.01374439820889, 38.407283586745073 ], [ -110.01311075002724, 38.407557623587195 ], [ -110.01238560469058, 38.407821873995559 ], [ -110.01194378702523, 38.407885739711006 ], [ -110.01105387085565, 38.408053966961958 ], [ -110.01025458289459, 38.408295048527556 ], [ -110.00974774576015, 38.408507054173157 ], [ -110.00887721326389, 38.408932269452961 ], [ -110.00817383481925, 38.409277785298116 ], [ -110.00711179550792, 38.409886111557519 ], [ -110.00660243592654, 38.410197213590742 ], [ -110.00600848272346, 38.41057969156109 ], [ -110.00542415101111, 38.411011813868818 ], [ -110.00489745761745, 38.411416485567166 ], [ -110.00444012861004, 38.411773980764643 ], [ -110.00417294927053, 38.412046575312395 ], [ -110.00399208274006, 38.41228926218772 ], [ -110.00381739909058, 38.412498657105147 ], [ -110.00365926222561, 38.412754153377357 ], [ -110.00345918321887, 38.413144472026474 ], [ -110.00320651223986, 38.413610944548424 ], [ -110.00311507530428, 38.414096812018414 ], [ -110.0030755771722, 38.414803913936261 ], [ -110.00308931946537, 38.415470914913783 ], [ -110.00322985149367, 38.416080416670177 ], [ -110.00341232914684, 38.416555095753466 ], [ -110.00367872861675, 38.417174679161654 ], [ -110.00403087771625, 38.417722895186749 ], [ -110.00421723142408, 38.417999343125793 ], [ -110.00444782232849, 38.418307708385356 ], [ -110.00468844675827, 38.418719795744977 ], [ -110.00490579572408, 38.419158720779564 ], [ -110.00523189577683, 38.419603074581033 ], [ -110.00535953566823, 38.419901552091211 ], [ -110.00562079254595, 38.420480533503998 ], [ -110.00583629947084, 38.421054620207357 ], [ -110.00596042441433, 38.421609907465481 ], [ -110.00611054663301, 38.421940116586306 ], [ -110.00637834609367, 38.422460574074897 ], [ -110.00664658132081, 38.422949492838569 ], [ -110.00685490634689, 38.423212604803034 ], [ -110.00718177632243, 38.423602887934692 ], [ -110.00745833820537, 38.423902624677453 ], [ -110.00780726041388, 38.424356176387647 ], [ -110.00813888187601, 38.424818592543723 ], [ -110.00836895617942, 38.425167499266124 ], [ -110.00857082720802, 38.425484625138999 ], [ -110.00884109570816, 38.425910472425606 ], [ -110.00932370131247, 38.426558906819892 ], [ -110.00961088793775, 38.426837099619931 ], [ -110.01003534170545, 38.427298492523619 ], [ -110.0102669579824, 38.427535660520405 ], [ -110.01063451147253, 38.42788572385431 ], [ -110.01114365967888, 38.428354136147476 ], [ -110.0115583934771, 38.428605463468543 ], [ -110.0124317269608, 38.429252674336425 ], [ -110.01286365335598, 38.429504141945607 ], [ -110.01341285984536, 38.429977387804328 ], [ -110.01390491875047, 38.430441138243388 ], [ -110.01437390136368, 38.430917309208894 ], [ -110.01467031451034, 38.431362287903042 ], [ -110.01486205459491, 38.431669404518438 ], [ -110.01502521120774, 38.431887963634487 ], [ -110.01517729252774, 38.43207849245514 ], [ -110.01541895248941, 38.432422075413456 ], [ -110.015615072806, 38.43274454785638 ], [ -110.01578270630581, 38.432971254247839 ], [ -110.0160085661462, 38.433297580588018 ], [ -110.01620007620495, 38.433538004772792 ], [ -110.01640890600153, 38.433768660910665 ], [ -110.01666914258028, 38.434010562412141 ], [ -110.0169158138369, 38.434323543743936 ], [ -110.01720980889317, 38.43469549901554 ], [ -110.01736177960059, 38.43489503596787 ], [ -110.01759266233152, 38.435189859597415 ], [ -110.01782476784138, 38.435394573758856 ], [ -110.01804894935212, 38.435761435713211 ], [ -110.01826722185588, 38.436141765605527 ], [ -110.01852583815763, 38.436504409175456 ], [ -110.01895927640189, 38.437072185533154 ], [ -110.01923442589573, 38.43748363033265 ], [ -110.01952102305688, 38.437811359382934 ], [ -110.01987764296348, 38.438214472452515 ], [ -110.02014730497942, 38.438608746521069 ], [ -110.02036608399634, 38.438953028967497 ], [ -110.02067432853471, 38.439460273402062 ], [ -110.02090987195805, 38.439836236655083 ], [ -110.02109434799425, 38.440175725093347 ], [ -110.02173553964553, 38.44105974261204 ], [ -110.02208530111552, 38.441463692811048 ], [ -110.02247797863818, 38.442084286071633 ], [ -110.02283726251923, 38.442632504139333 ], [ -110.02309738199813, 38.442887006976449 ], [ -110.02335605818882, 38.443248739022557 ], [ -110.02365969313459, 38.443675730947497 ], [ -110.02393109477796, 38.443943843812576 ], [ -110.02417715627465, 38.444391983326071 ], [ -110.02453523907199, 38.445031206439559 ], [ -110.02495482495827, 38.445358226826315 ], [ -110.02531126281815, 38.445694633495073 ], [ -110.02548510915391, 38.445889835796528 ], [ -110.0256673958196, 38.446139179517452 ], [ -110.02580662783984, 38.446352117302112 ], [ -110.02594549234094, 38.446677700787717 ], [ -110.02625001640004, 38.447040708706524 ], [ -110.02657715721557, 38.447426433522921 ], [ -110.02701472789018, 38.447695919696152 ], [ -110.02756869860092, 38.447831191726408 ], [ -110.02833055176596, 38.447846524578708 ], [ -110.0293804311887, 38.447747084121417 ], [ -110.03003414254594, 38.447622726441942 ], [ -110.03054156036971, 38.44746921772667 ], [ -110.03128291580451, 38.447303222233444 ], [ -110.03221391730159, 38.447094630327939 ], [ -110.03330388471113, 38.446995485744651 ], [ -110.03426799007727, 38.446881775737253 ], [ -110.03500895942288, 38.446743690341052 ], [ -110.03562942423613, 38.446619027483486 ], [ -110.03621554871971, 38.446491375266767 ], [ -110.03742796327683, 38.446317499288241 ], [ -110.03812605753301, 38.446300702790566 ], [ -110.03877753044192, 38.446342998333819 ], [ -110.03982996393408, 38.446567012995629 ], [ -110.04035620101207, 38.44663440793812 ], [ -110.04100889584716, 38.446671293944014 ], [ -110.04184880359243, 38.446849392318192 ], [ -110.04252740806963, 38.447093756004172 ], [ -110.0432778186543, 38.447541470429769 ], [ -110.04378654328143, 38.448068315068269 ], [ -110.04410710277155, 38.448526032999816 ], [ -110.04430705495187, 38.449005296083833 ], [ -110.0443229713042, 38.449536228075864 ], [ -110.04434153833296, 38.44986621582138 ], [ -110.04438185810397, 38.450284697792597 ], [ -110.04438492569341, 38.450920964313546 ], [ -110.04436473072175, 38.451583175580808 ], [ -110.04435849042294, 38.452056250343581 ], [ -110.04447556597461, 38.452737604973898 ], [ -110.04454238453678, 38.453319418492882 ], [ -110.0446201879881, 38.453937369161203 ], [ -110.04445449307495, 38.454769619837627 ], [ -110.04429511836359, 38.455556862146167 ], [ -110.04392688818166, 38.456103584214901 ], [ -110.04343820650458, 38.456658333517034 ], [ -110.04291734063267, 38.457046097455439 ], [ -110.0422606789634, 38.457302076276072 ], [ -110.04163761726029, 38.457616903649964 ], [ -110.04118329522538, 38.45773845165445 ], [ -110.04072678744507, 38.457938383572291 ], [ -110.04031967442376, 38.458043192138426 ], [ -110.03987655668517, 38.458183751826176 ], [ -110.0393813894248, 38.458359930655583 ], [ -110.03906349091845, 38.458564597289062 ], [ -110.03883786869473, 38.45872496064802 ], [ -110.03853643942227, 38.45898383236436 ], [ -110.03816726457454, 38.459165545918061 ], [ -110.03749277837376, 38.459466410904454 ], [ -110.03684807545447, 38.459681903774744 ], [ -110.03597953521202, 38.45992258701876 ], [ -110.0354862668737, 38.459954574455466 ], [ -110.03511439869047, 38.459907353872154 ], [ -110.03467994439787, 38.459826272380809 ], [ -110.03409636481349, 38.459754774101903 ], [ -110.03361883740752, 38.459466059847998 ], [ -110.0329715062295, 38.459019135046951 ], [ -110.03271726555182, 38.45874667910644 ], [ -110.03246205176767, 38.458547210965797 ], [ -110.03220095289858, 38.45835940912194 ], [ -110.03183712577219, 38.458140117304488 ], [ -110.03157517459333, 38.45801629151741 ], [ -110.03120284512094, 38.45766174894073 ], [ -110.03082237743375, 38.457401762810825 ], [ -110.03043401138923, 38.457218311237135 ], [ -110.02985728840652, 38.456636775075566 ], [ -110.02945620570972, 38.45620538766488 ], [ -110.02878402596582, 38.455478864914625 ], [ -110.02796355311506, 38.454701542503855 ], [ -110.02737553157225, 38.454110888424616 ], [ -110.02693950688798, 38.453723360588896 ], [ -110.02658989036969, 38.453302303868469 ], [ -110.02615176704481, 38.452645299697984 ], [ -110.02586780156068, 38.452030129332307 ], [ -110.02563683261731, 38.451735321689519 ], [ -110.02495131563822, 38.450728395562507 ], [ -110.02442472272179, 38.450260799729968 ], [ -110.02411137760856, 38.450041904288128 ], [ -110.02376667892877, 38.449768675308043 ], [ -110.02325717899437, 38.449309327369164 ], [ -110.02285471742138, 38.44898604862837 ], [ -110.02240185179451, 38.448576734799616 ], [ -110.02199488523902, 38.448163296421164 ], [ -110.0209089098219, 38.447455803082491 ], [ -110.02054674381432, 38.447204948430901 ], [ -110.01996470687791, 38.446943241759122 ], [ -110.01925380810759, 38.446635394029791 ], [ -110.01854231886918, 38.446286983458855 ], [ -110.01812532369122, 38.446193370449926 ], [ -110.01744443031062, 38.446124578840916 ], [ -110.01683758698083, 38.446087946379002 ], [ -110.01624116241855, 38.446127999484155 ], [ -110.01541533339457, 38.446184145746486 ], [ -110.01502557933281, 38.446194387588356 ], [ -110.01451946869531, 38.446334322135108 ], [ -110.01413403286899, 38.446448234259044 ], [ -110.01366247682505, 38.446574937979513 ], [ -110.01338022199182, 38.446685210255112 ], [ -110.01307412973929, 38.446862870340389 ], [ -110.01268205129634, 38.447043409794162 ], [ -110.01234625428583, 38.44729832000241 ], [ -110.01204009550193, 38.447480482732992 ], [ -110.0118777767742, 38.447618798364651 ], [ -110.01169765560724, 38.447802023110931 ], [ -110.01130813781535, 38.448214185397042 ], [ -110.0110676598585, 38.448621296141653 ], [ -110.01074068349772, 38.449488184134978 ], [ -110.01065136131469, 38.449735257133725 ], [ -110.01064114081913, 38.450064105163527 ], [ -110.01073404760839, 38.450393824019706 ], [ -110.01077532975313, 38.450727612850805 ], [ -110.0107659478584, 38.451078997665277 ], [ -110.01082844847949, 38.451453519142348 ], [ -110.01087386160904, 38.451904497423769 ], [ -110.01081029254166, 38.452363567421095 ], [ -110.01085742848014, 38.45268839365184 ], [ -110.01086427370248, 38.453026397523246 ], [ -110.01087494145536, 38.453504118014294 ], [ -110.01095067345796, 38.454252744585879 ], [ -110.01095530456571, 38.454752943743834 ], [ -110.01102499209438, 38.455104995852295 ], [ -110.01119678166694, 38.455533609611258 ], [ -110.01133509258598, 38.455896153765302 ], [ -110.01148352399605, 38.456357012745237 ], [ -110.01149986417319, 38.456839286746536 ], [ -110.01138337255068, 38.457397040890463 ], [ -110.01127373854976, 38.457788132804737 ], [ -110.01111304215604, 38.458309465935443 ], [ -110.01086140224056, 38.458775959630998 ], [ -110.01038307361767, 38.459308127134058 ], [ -110.01014931683028, 38.459639591978586 ], [ -110.00977994737886, 38.460249278508606 ], [ -110.00946984475425, 38.460715274800371 ], [ -110.00914152489197, 38.461172104248398 ], [ -110.00885634415187, 38.461575226430647 ], [ -110.00858085779805, 38.462023489322043 ], [ -110.00830684871261, 38.462363621466885 ], [ -110.00804934899239, 38.462753458069685 ], [ -110.00783824444697, 38.463103133569753 ], [ -110.00776014318586, 38.463449429361411 ], [ -110.00762564436411, 38.463979990801398 ], [ -110.00750486191912, 38.464429561359317 ], [ -110.0072461767345, 38.464904998774394 ], [ -110.00701158391003, 38.465295026984514 ], [ -110.00672958707895, 38.465798202356737 ], [ -110.00647756195504, 38.466205204155813 ], [ -110.00616926709831, 38.466536028267157 ], [ -110.00590089800731, 38.466880708171118 ], [ -110.00556307819997, 38.467274363153393 ], [ -110.00524882625236, 38.467537545143735 ], [ -110.00493705003974, 38.467787229494242 ], [ -110.00431593825328, 38.468358711332442 ], [ -110.00398634138749, 38.468986740032285 ], [ -110.00384471186936, 38.469282927297833 ], [ -110.00365069788293, 38.469637245944007 ], [ -110.00347362642444, 38.470009732104259 ], [ -110.00326190737444, 38.470400848065566 ], [ -110.00313580210836, 38.470817925446788 ], [ -110.00302089662158, 38.471254022892467 ], [ -110.00291745163914, 38.471690217740608 ], [ -110.00269067496583, 38.472341647139295 ], [ -110.00258933686627, 38.472624657910117 ], [ -110.00249223905327, 38.473015847006707 ], [ -110.00246310632765, 38.473466191896179 ], [ -110.002462691001, 38.473912275378886 ], [ -110.00236865181462, 38.474497245269056 ], [ -110.00221860279035, 38.474987113426536 ], [ -110.00200084881718, 38.475814349092708 ], [ -110.00197164940717, 38.476269198988945 ], [ -110.00191286082767, 38.476791385620359 ], [ -110.00188490292101, 38.477156127461704 ], [ -110.00185171031629, 38.477484777253324 ], [ -110.00187452716948, 38.477908528760651 ], [ -110.00179256173426, 38.478448541378839 ], [ -110.00169190885998, 38.479096536817984 ], [ -110.00160557626859, 38.479537381617419 ], [ -110.00166964603726, 38.480294923051723 ], [ -110.00170434832616, 38.480688135413949 ], [ -110.00185184587345, 38.481215684363562 ], [ -110.00196593661398, 38.481671754851014 ], [ -110.00215571000933, 38.482043758635562 ], [ -110.00248700467169, 38.482545836849553 ], [ -110.00272988468022, 38.482808347433746 ], [ -110.00302967550455, 38.483101081035819 ], [ -110.00331872476924, 38.483341453762421 ], [ -110.00369197557633, 38.483628502459425 ], [ -110.00406123210293, 38.483956069304696 ], [ -110.00466866304666, 38.484389295448274 ], [ -110.00503222650907, 38.484631198332146 ], [ -110.005339153452, 38.48482305398467 ], [ -110.0056917525549, 38.48502881433577 ], [ -110.00618056152112, 38.485334859754893 ], [ -110.0064653704363, 38.485467947800458 ], [ -110.00694870090925, 38.485755919861383 ], [ -110.00726099897457, 38.485974851560265 ], [ -110.00764171373177, 38.486221397656266 ], [ -110.00814872369672, 38.486455494344604 ], [ -110.00879706617859, 38.486834974510572 ], [ -110.00917834601445, 38.487040967111746 ], [ -110.00945706496171, 38.4872010319136 ], [ -110.0098207203399, 38.487438414822655 ], [ -110.0104253175039, 38.487664314826411 ], [ -110.01082349522935, 38.487892974465041 ], [ -110.01115387325667, 38.488048965604527 ], [ -110.01164506470509, 38.488183783375135 ], [ -110.01191300579731, 38.488294186261477 ], [ -110.01219716045907, 38.488476820026833 ], [ -110.01288276426598, 38.488649319508397 ], [ -110.0131688892771, 38.488687778041019 ], [ -110.01347153585776, 38.488775940178456 ], [ -110.01373362681416, 38.488895301478927 ], [ -110.01396595156999, 38.489095518186694 ], [ -110.01426164078018, 38.489273738145734 ], [ -110.01448823581235, 38.489473905593805 ], [ -110.01466989317557, 38.48960610573198 ], [ -110.01491972681282, 38.489783938241864 ], [ -110.01520334303885, 38.490007113495622 ], [ -110.01552117185967, 38.490244093413445 ], [ -110.01578222958074, 38.490440042116106 ], [ -110.01599785771866, 38.490604067113388 ], [ -110.01623086815052, 38.490754719958616 ], [ -110.0165087597086, 38.490977843967322 ], [ -110.01728970902487, 38.491308825586891 ], [ -110.01768360326861, 38.491433789842915 ], [ -110.01797296710403, 38.491657006607973 ], [ -110.0182172668279, 38.491821267932366 ], [ -110.01850053448693, 38.492071467815848 ], [ -110.01934609627426, 38.492628273257239 ], [ -110.01951304873266, 38.492746825004808 ], [ -110.01959044984198, 38.492873638740669 ], [ -110.01963929631584, 38.493076814049118 ], [ -110.01968820410848, 38.493275483924791 ], [ -110.01970802113921, 38.49350545172291 ], [ -110.01972582346649, 38.493884097998837 ], [ -110.01979497683043, 38.494281197721286 ], [ -110.01987186496301, 38.494615279243355 ], [ -110.0199587198821, 38.494890867156784 ], [ -110.02008764550138, 38.495108230066982 ], [ -110.02018790751555, 38.495325353028477 ], [ -110.0203565376774, 38.495574589235702 ], [ -110.02059890380326, 38.495883018794672 ], [ -110.02094989298821, 38.496214885552895 ], [ -110.02121682958229, 38.496402760615574 ], [ -110.02169329170866, 38.496784337636079 ], [ -110.02210747530742, 38.497107716961239 ], [ -110.0226632840894, 38.497558442503241 ], [ -110.02298720781543, 38.497772923414907 ], [ -110.02324300568363, 38.497937270165991 ], [ -110.02357224016492, 38.498183335179384 ], [ -110.02382127393395, 38.498424224872586 ], [ -110.02400839138976, 38.498664598051555 ], [ -110.02426762638395, 38.498914583640861 ], [ -110.02446085241228, 38.499042359053398 ], [ -110.02457387528555, 38.499164960243924 ], [ -110.02465792876367, 38.499309849647943 ], [ -110.02476455856231, 38.499396350071947 ], [ -110.02488970960147, 38.499555099287754 ], [ -110.02527959375024, 38.499981901149489 ], [ -110.01444840072078, 38.49997235809758 ], [ -110.00065808718907, 38.499995176110566 ], [ -109.98956403714736, 38.499922510853246 ], [ -109.97763165427165, 38.499936102766107 ], [ -109.9615483077514, 38.499925261702636 ], [ -109.93219079141998, 38.499936116925831 ], [ -109.92420908312805, 38.499948678665866 ], [ -109.91374463593485, 38.499960222918524 ], [ -109.8947713762381, 38.499958425418178 ], [ -109.87959950741394, 38.499967454341871 ], [ -109.87566668462313, 38.499929761809511 ], [ -109.87084427553022, 38.499946445228801 ], [ -109.8698465991755, 38.499945833037643 ], [ -109.86283986846007, 38.499945592192944 ], [ -109.84954319729012, 38.499941884617847 ], [ -109.81785831269852, 38.499932722099963 ], [ -109.78206777632899, 38.499944448514967 ], [ -109.75841127951283, 38.499948348245034 ], [ -109.7506693274393, 38.499960630841827 ], [ -109.74292892490689, 38.4999498889092 ], [ -109.7349304894783, 38.499940353700971 ], [ -109.72830209848468, 38.499949663989369 ], [ -109.71889298369457, 38.499950739789199 ], [ -109.70682938141259, 38.499938897667974 ], [ -109.69485169353186, 38.499933077941954 ], [ -109.68127403497198, 38.499942269609505 ], [ -109.66838460418347, 38.499942394731697 ], [ -109.65813861725339, 38.499932671817234 ], [ -109.65485894146077, 38.499931991405909 ], [ -109.63845603544074, 38.499926257052792 ], [ -109.62882798681163, 38.499926558462242 ], [ -109.6275551306862, 38.49992516444464 ], [ -109.62566308745365, 38.499920996927301 ], [ -109.58849051049572, 38.499974453749928 ], [ -109.54874501481947, 38.499957209583378 ], [ -109.5331264545819, 38.4999608495853 ], [ -109.52163038154056, 38.499965863380005 ], [ -109.50067367136052, 38.499977856744643 ], [ -109.49679200429891, 38.499977653146018 ], [ -109.48292786731945, 38.49998809123619 ], [ -109.48301938641927, 38.494346147840879 ], [ -109.47840390616199, 38.494348173709326 ], [ -109.47378872753205, 38.494346867478946 ], [ -109.47377324821474, 38.490711551392394 ], [ -109.46916446144772, 38.490711860044129 ], [ -109.46915952108357, 38.483153919416409 ], [ -109.46454285323324, 38.483154036856895 ], [ -109.46454051976836, 38.475905397105329 ], [ -109.45992623429781, 38.475906989296007 ], [ -109.44148601273477, 38.47592708342394 ], [ -109.44148578789058, 38.476166423390232 ], [ -109.43736623633571, 38.476163705984156 ], [ -109.43737463365153, 38.483435384762245 ], [ -109.42350449078825, 38.483428724588279 ], [ -109.42354121245945, 38.499977512384611 ], [ -109.41932503025458, 38.499984833314265 ], [ -109.39748057708228, 38.499962753935904 ], [ -109.38203938811466, 38.499993712282986 ], [ -109.37566935697613, 38.499995631058631 ], [ -109.36355531379219, 38.499953111314944 ], [ -109.36176640080376, 38.499955129814936 ], [ -109.35377403059492, 38.499946663798397 ], [ -109.35060337217409, 38.499947099377529 ], [ -109.33336119404379, 38.499959766786468 ], [ -109.3147229912084, 38.499945302616332 ], [ -109.30251051991715, 38.499949113462314 ], [ -109.29082560802368, 38.499950340491949 ], [ -109.27388930869603, 38.499931674334618 ], [ -109.26137853130281, 38.499944815915065 ], [ -109.25066800517635, 38.499961002329194 ], [ -109.23445904903647, 38.499979031752588 ], [ -109.2128552439946, 38.499984682975558 ], [ -109.19454896025293, 38.499960645005729 ], [ -109.1816658578381, 38.499964025278381 ], [ -109.1747109901456, 38.499972951384748 ], [ -109.16541107296655, 38.499985292139748 ], [ -109.14592312615295, 38.499944133969457 ], [ -109.13378043555164, 38.499963875154435 ], [ -109.12567353544316, 38.499959626905891 ], [ -109.10836361752892, 38.499992113909052 ], [ -109.08987967154627, 38.499975857849158 ], [ -109.07457778815555, 38.499959494779951 ], [ -109.06199260791546, 38.499978021690609 ], [ -109.06018787837998, 38.499973364361509 ], [ -109.0601882196832, 38.486453316844766 ], [ -109.06004803642122, 38.46795143689846 ] ] ] } }]}'); } -/* jscs:enable validateQuoteMarks, maximumLineLength */ -/* jshint +W109, +W101, +W098 */ diff --git a/web/js/jasmine-jsreporter.js b/spec/helpers/jasmine-jsreporter.js similarity index 100% rename from web/js/jasmine-jsreporter.js rename to spec/helpers/jasmine-jsreporter.js diff --git a/spec/helpers/load-jsreporter.js b/spec/helpers/load-jsreporter.js deleted file mode 100644 index 20430fb891..0000000000 --- a/spec/helpers/load-jsreporter.js +++ /dev/null @@ -1,37 +0,0 @@ -// reporter for saucelabs -jasmine.getEnv().addReporter(new jasmine.JSReporter2()); - -(function () { - var oldJSReport = window.jasmine.getJSReport; - window.jasmine.getJSReport = function () { - var results = oldJSReport(); - if (results) { - return { - durationSec: results.durationSec, - suites: removePassingTests(results.suites), - passed: results.passed - }; - } else { - return null; - } - }; - - function removePassingTests (suites) { - return suites.filter(specFailed) - .map(mapSuite); - } - - function mapSuite (suite) { - var result = {}; - for (var s in suite) { - result[s] = suite[s]; - } - result.specs = suite.specs.filter(specFailed); - result.suites = removePassingTests(suite.suites); - return result; - } - - function specFailed (item) { - return !item.passed; - } -})(); diff --git a/spec/helpers/spec-helper.js b/spec/helpers/spec-helper.js index 0e96ceef62..7551684173 100644 --- a/spec/helpers/spec-helper.js +++ b/spec/helpers/spec-helper.js @@ -1,30 +1,27 @@ /* global parseTranslate */ -beforeEach(function () { - jasmine.clock().install(); +/* eslint "no-unused-vars": 0 */ + +/*exported appendChartID, coordsFromTranslate, makeDate, cleanDateRange, flushAllD3Transitions */ +/*exported simulateChartBrushing, simulateChart2DBrushing */ - // If we're using browserify bundle, pull d3 and crossfilter out of it, - // so that tests don't have to deal with this incidental complexity. - /* jshint -W020 */ - if (typeof d3 === 'undefined') { d3 = dc.d3; } - if (typeof crossfilter === 'undefined') { crossfilter = dc.crossfilter; } - /* jshint +W020 */ +beforeEach(() => { + jasmine.clock().install(); d3.select('body').append('div').attr('id', 'test-content'); }); -afterEach(function () { +afterEach(() => { dc.deregisterAllCharts(); dc.renderlet(null); d3.selectAll('#test-content').remove(); jasmine.clock().uninstall(); }); -/* jshint -W098 */ function appendChartID (id) { return d3.select('#test-content').append('div').attr('id', id); } function coordsFromTranslate (translationString) { - var result = parseTranslate(translationString); + const result = parseTranslate(translationString); expect(result).not.toBeNull(); return {x: +result[1], y: +result[2]}; } @@ -45,9 +42,30 @@ function cleanDateRange (range) { // http://stackoverflow.com/questions/20068497/d3-transition-in-unit-testing function flushAllD3Transitions () { - var now = Date.now; - Date.now = function () { return Infinity; }; - d3.timer.flush(); - Date.now = now; + d3.timerFlush(); } -/* jshint +W098 */ + +// Simulate a dummy event - just enough for the handler to get fooled +const simulateChartBrushing = function (chart, domainSelection) { + // D3v4 needs scaled coordinates for the event + const scaledSelection = domainSelection.map(coord => chart.x()(coord)); + + // an event with fields that dc cares about + chart._brushing({ + selection: scaledSelection + }); +}; + +// Simulate a dummy event - just enough for the handler to get fooled +const simulateChart2DBrushing = function (chart, domainSelection) { + // D3v4 needs scaled coordinates for the event + const scaledSelection = domainSelection.map(point => point.map((coord, i) => { + const scale = i === 0 ? chart.x() : chart.y(); + return scale(coord); + })); + + // an event with fields that dc cares about + chart._brushing({ + selection: scaledSelection + }); +}; diff --git a/spec/html-legend-spec.js b/spec/html-legend-spec.js new file mode 100644 index 0000000000..94eeb9de23 --- /dev/null +++ b/spec/html-legend-spec.js @@ -0,0 +1,145 @@ +/* global appendChartID, loadDateFixture */ +describe('dc.htmlLegend', () => { + let id, chart, dateDimension, dateValueSumGroup, dateIdSumGroup, legend, legendId; + + function legendItem (n, orientation) { + return d3.select(legend.selectAll(`div.dc-html-legend div.dc-legend-item-${orientation}`).nodes()[n]); + } + + function legendLabel (n, orientation) { + return d3.select(legend.selectAll(`div.dc-html-legend div.dc-legend-item-${ + orientation} span.dc-legend-item-label`).nodes()[n]); + } + + function legendIcon (n, orientation) { + return d3.select(legend.selectAll(`div.dc-html-legend div.dc-legend-item-${ + orientation} span.dc-legend-item-color`).nodes()[n]); + } + + describe('htmlLegend for lineChart', () => { + beforeEach(() => { + const data = crossfilter(loadDateFixture()); + dateDimension = data.dimension(d => d3.timeDay(d.dd)); + dateValueSumGroup = dateDimension.group().reduceSum(d => d.value); + dateIdSumGroup = dateDimension.group().reduceSum(d => d.id); + + id = 'html-legend-chart'; + legendId = 'html-legend-chart-legend'; + appendChartID(id); + appendChartID(legendId); + + chart = new dc.LineChart(`#${id}`); + chart + .dimension(dateDimension) + .group(dateIdSumGroup, 'Id Sum') + .stack(dateValueSumGroup, 'Value Sum') + .stack(dateValueSumGroup, 'Fixed', () => { + }) + .x(d3.scaleTime().domain([new Date(2012, 4, 20), new Date(2012, 7, 15)])) + .legend(new dc.HtmlLegend().container(`#${legendId}`)); + legend = d3.select(`#${legendId}`); + }); + + describe('rendering the legend', () => { + beforeEach(() => { + chart.render(); + }); + + it('should generate a legend', () => { + expect(legend.select('div.dc-html-legend').empty()).toBeFalsy(); + }); + + it('should generate a legend item for each stacked line', () => { + expect(legend.select('div.dc-html-legend').selectAll('.dc-legend-item-vertical').size()).toBe(3); + }); + + it('should generate legend item boxes', () => { + expect(legendIcon(0, 'vertical').style('background-color')).toBe('rgb(31, 119, 180)'); + expect(legendIcon(1, 'vertical').style('background-color')).toBe('rgb(255, 127, 14)'); + expect(legendIcon(2, 'vertical').style('background-color')).toBe('rgb(44, 160, 44)'); + }); + + it('should generate legend labels', () => { + expect(legendLabel(0, 'vertical').text()).toBe('Id Sum'); + expect(legendLabel(1, 'vertical').text()).toBe('Value Sum'); + expect(legendLabel(2, 'vertical').text()).toBe('Fixed'); + }); + + it('not allow hiding stacks be default', () => { + dc.d3compat.callHandler(legendItem(0, 'vertical').on('click'), + legendItem(0).nodes()[0], {}, legendItem(0, 'vertical').datum()); + expect(chart.selectAll('path.line').size()).toBe(3); + }); + + }); + + describe('with .horizontal(true)', () => { + beforeEach(() => { + chart.legend(new dc.HtmlLegend().container(`#${legendId}`).horizontal(true)); + chart.render(); + }); + + it('should generate a legend', () => { + expect(legend.select('div.dc-html-legend').empty()).toBeFalsy(); + }); + + it('should generate a legend item for each stacked line', () => { + expect(legend.select('div.dc-html-legend').selectAll('div.dc-legend-item-horizontal').size()).toBe(3); + }); + + it('should generate legend item boxes', () => { + expect(legendIcon(0, 'horizontal').style('background-color')).toBe('rgb(31, 119, 180)'); + expect(legendIcon(1, 'horizontal').style('background-color')).toBe('rgb(255, 127, 14)'); + expect(legendIcon(2, 'horizontal').style('background-color')).toBe('rgb(44, 160, 44)'); + }); + + it('should generate legend labels', () => { + expect(legendLabel(0, 'horizontal').text()).toBe('Id Sum'); + expect(legendLabel(1, 'horizontal').text()).toBe('Value Sum'); + expect(legendLabel(2, 'horizontal').text()).toBe('Fixed'); + }); + + it('not allow hiding stacks be default', () => { + const firstLegendItem = legendItem(0, 'horizontal'); + dc.d3compat.callHandler(firstLegendItem.on('click'), firstLegendItem.nodes()[0], {}, firstLegendItem.datum()); + expect(chart.selectAll('path.line').size()).toBe(3); + }); + }); + + describe('with .maxItems(2)', () => { + beforeEach(() => { + chart.legend(new dc.HtmlLegend().container(`#${legendId}`).horizontal(true).maxItems(2)); + chart.render(); + }); + it('should display two items', () => { + expect(legend.select('div.dc-html-legend').selectAll('div.dc-legend-item-horizontal').size()).toBe(2); + }); + }); + + describe('with invalid .maxItems', () => { + beforeEach(() => { + chart.legend(new dc.HtmlLegend().container(`#${legendId}`).horizontal(true).maxItems('foo')); + chart.render(); + }); + it('should display three items', () => { + expect(legend.select('div.dc-html-legend').selectAll('div.dc-legend-item-horizontal').size()).toBe(3); + }); + }); + + describe('with .legendText()', () => { + beforeEach(() => { + chart.legend(new dc.HtmlLegend().container(`#${legendId}`).legendText((d, i) => { + const _i = i + 1; + return `${_i}. ${d.name}`; + })); + chart.render(); + }); + + it('should label the legend items with the names of their associated stacks', () => { + expect(legendLabel(0, 'vertical').text()).toBe('1. Id Sum'); + expect(legendLabel(1, 'vertical').text()).toBe('2. Value Sum'); + expect(legendLabel(2, 'vertical').text()).toBe('3. Fixed'); + }); + }); + }); +}); diff --git a/spec/legend-spec.js b/spec/legend-spec.js index 43b8ce506f..f395a1f1c1 100644 --- a/spec/legend-spec.js +++ b/spec/legend-spec.js @@ -1,59 +1,59 @@ /* global appendChartID, coordsFromTranslate, loadDateFixture */ -describe('dc.legend', function () { - var id, chart, dateDimension, dateValueSumGroup, dateIdSumGroup; +describe('dc.legend', () => { + let id, chart, dateDimension, dateValueSumGroup, dateIdSumGroup; - beforeEach(function () { - var data = crossfilter(loadDateFixture()); - dateDimension = data.dimension(function (d) { return d3.time.day.utc(d.dd); }); - dateValueSumGroup = dateDimension.group().reduceSum(function (d) { return d.value; }); - dateIdSumGroup = dateDimension.group().reduceSum(function (d) { return d.id; }); + beforeEach(() => { + const data = crossfilter(loadDateFixture()); + dateDimension = data.dimension(d => d3.utcDay(d.dd)); + dateValueSumGroup = dateDimension.group().reduceSum(d => d.value); + dateIdSumGroup = dateDimension.group().reduceSum(d => d.id); id = 'legend-chart'; appendChartID(id); - chart = dc.lineChart('#' + id); + chart = new dc.LineChart(`#${id}`); chart .dimension(dateDimension) .group(dateIdSumGroup, 'Id Sum') .stack(dateValueSumGroup, 'Value Sum') - .stack(dateValueSumGroup, 'Fixed', function () {}) - .x(d3.time.scale.utc().domain([new Date(2012, 4, 20), new Date(2012, 7, 15)])) - .legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)); + .stack(dateValueSumGroup, 'Fixed', () => {}) + .x(d3.scaleUtc().domain([new Date(2012, 4, 20), new Date(2012, 7, 15)])) + .legend(new dc.Legend().x(400).y(10).itemHeight(13).gap(5)); }); - describe('rendering the legend', function () { - beforeEach(function () { + describe('rendering the legend', () => { + beforeEach(() => { chart.render(); }); - it('should generate a legend', function () { + it('should generate a legend', () => { expect(chart.select('g.dc-legend').empty()).toBeFalsy(); }); - it('should place the legend using the provided x and y values', function () { - expect(chart.select('g.dc-legend').attr('transform')).toMatchTranslate(400,10); + it('should place the legend using the provided x and y values', () => { + expect(chart.select('g.dc-legend').attr('transform')).toMatchTranslate(400, 10); }); - it('should generate a legend item for each stacked line', function () { + it('should generate a legend item for each stacked line', () => { expect(chart.select('g.dc-legend').selectAll('g.dc-legend-item').size()).toBe(3); }); - it('should generate legend item boxes', function () { - expect(legendIcon(0).attr('width')).toBeWithinDelta(13,2); + it('should generate legend item boxes', () => { + expect(legendIcon(0).attr('width')).toBeWithinDelta(13, 2); expect(legendIcon(0).attr('height')).toBeWithinDelta(13, 2); }); - it('should color the legend item boxes using the chart line colors', function () { - expect(legendIcon(0).attr('fill')).toBe('#1f77b4'); - expect(legendIcon(1).attr('fill')).toBe('#ff7f0e'); - expect(legendIcon(2).attr('fill')).toBe('#2ca02c'); + it('should color the legend item boxes using the chart line colors', () => { + expect(legendIcon(0).attr('fill')).toMatch(/#1f77b4/i); + expect(legendIcon(1).attr('fill')).toMatch(/#ff7f0e/i); + expect(legendIcon(2).attr('fill')).toMatch(/#2ca02c/i); }); - it('should generate a legend label for each chart line', function () { + it('should generate a legend label for each chart line', () => { expect(chart.selectAll('g.dc-legend g.dc-legend-item text').size()).toBe(3); }); - it('should position the legend labels', function () { + it('should position the legend labels', () => { expect(legendLabel(0).attr('x')).toBeWithinDelta(15, 2); expect(legendLabel(0).attr('y')).toBeWithinDelta(11.75, 2); expect(legendLabel(1).attr('x')).toBeWithinDelta(15, 2); @@ -62,205 +62,253 @@ describe('dc.legend', function () { expect(legendLabel(2).attr('y')).toBeWithinDelta(11.75, 2); }); - it('should label the legend items with the names of their associated stacks', function () { + it('should label the legend items with the names of their associated stacks', () => { expect(legendLabel(0).text()).toBe('Id Sum'); expect(legendLabel(1).text()).toBe('Value Sum'); expect(legendLabel(2).text()).toBe('Fixed'); }); - it('not allow hiding stacks be default', function () { - legendItem(0).on('click').call(legendItem(0)[0][0], legendItem(0).datum()); + it('not allow hiding stacks be default', () => { + dc.d3compat.callHandler(legendItem(0).on('click'), legendItem(0).nodes()[0], {}, legendItem(0).datum()); expect(chart.selectAll('path.line').size()).toBe(3); }); - describe('without .horizontal(true)', function () { - it('should place legend items vertically', function () { + describe('without .horizontal(true)', () => { + it('should place legend items vertically', () => { expect(coordsFromTranslate(legendItem(0).attr('transform')).y).toBeWithinDelta(0, 1); expect(coordsFromTranslate(legendItem(1).attr('transform')).y).toBeWithinDelta(18, 2); expect(coordsFromTranslate(legendItem(2).attr('transform')).y).toBeWithinDelta(36, 4); }); }); - describe('with .horizontal(true)', function () { - beforeEach(function () { - chart.legend(dc.legend().horizontal(true)); + describe('with .horizontal(true)', () => { + beforeEach(() => { + chart.legend(new dc.Legend().horizontal(true)); chart.render(); }); - it('should place legend items horizontally', function () { + it('should place legend items horizontally', () => { expect(coordsFromTranslate(legendItem(0).attr('transform')).x).toBeWithinDelta(0, 1); expect(coordsFromTranslate(legendItem(1).attr('transform')).x).toBeWithinDelta(65, 5); expect(coordsFromTranslate(legendItem(2).attr('transform')).x).toBeWithinDelta(155, 15); }); }); - describe('with .horizontal(true) and defined legendWidth and itemWidth', function () { - beforeEach(function () { - chart.legend(dc.legend().horizontal(true).legendWidth(60).itemWidth(30)); + describe('with .horizontal(true) and defined legendWidth and itemWidth', () => { + let legendCoords; + beforeEach(() => { + chart.legend(new dc.Legend().horizontal(true).legendWidth(60).itemWidth(30)); chart.render(); + legendCoords = d3.range(3).map(i => coordsFromTranslate(legendItem(i).attr('transform'))); }); - it('should place legend items in two columns. third item is new row', function () { - expect(coordsFromTranslate(legendItem(0).attr('transform')).x).toBeWithinDelta(0, 1); - expect(coordsFromTranslate(legendItem(1).attr('transform')).x).toBeWithinDelta(30, 5); - expect(coordsFromTranslate(legendItem(2).attr('transform')).x).toBeWithinDelta(0, 1); - expect(coordsFromTranslate(legendItem(0).attr('transform')).y).toBeWithinDelta(0, 1); - expect(coordsFromTranslate(legendItem(1).attr('transform')).y).toBeWithinDelta(0, 1); - expect(coordsFromTranslate(legendItem(2).attr('transform')).y).toBeWithinDelta(13, 5); + it('should place legend items in two columns. third item is new row', () => { + expect(legendCoords[0].x).toBeWithinDelta(0, 1); + expect(legendCoords[0].y).toBeWithinDelta(0, 1); + expect(legendCoords[1].x).toBeWithinDelta(30, 5); + expect(legendCoords[1].y).toBeWithinDelta(0, 1); + expect(legendCoords[2].x).toBeWithinDelta(0, 1); + expect(legendCoords[2].y).toBeWithinDelta(13, 5); }); }); - describe('with .autoItemWidth not called', function () { - beforeEach(function () { - chart.legend(dc.legend()); + describe('with .autoItemWidth not called', () => { + beforeEach(() => { + chart.legend(new dc.Legend()); }); - it('_autoItemWidth should be false', function () { + it('_autoItemWidth should be false', () => { expect(chart.legend().autoItemWidth()).toBe(false); }); }); - describe('with .autoItemWidth(false)', function () { - beforeEach(function () { - chart.legend(dc.legend().autoItemWidth(false)); + describe('with .autoItemWidth(false)', () => { + beforeEach(() => { + chart.legend(new dc.Legend().autoItemWidth(false)); }); - it('_autoItemWidth should be false', function () { + it('_autoItemWidth should be false', () => { expect(chart.legend().autoItemWidth()).toBe(false); }); }); - describe('with .autoItemWidth(true)', function () { - beforeEach(function () { - chart.legend(dc.legend().autoItemWidth(true)); + describe('with .autoItemWidth(true)', () => { + beforeEach(() => { + chart.legend(new dc.Legend().autoItemWidth(true)); }); - it('_autoItemWidth should be true', function () { + it('_autoItemWidth should be true', () => { expect(chart.legend().autoItemWidth()).toBe(true); }); }); - describe('with .horizontal(true) and .autoItemWidth(true)', function () { + describe('with .horizontal(true) and .autoItemWidth(true)', () => { - var - autoWidthOffset1, fixedWidthOffset1, - autoWidthOffset2, fixedWidthOffset2; + let fixedWidthOffset1, autoWidthCoords; - beforeEach(function () { - chart.legend(dc.legend().horizontal(true).itemWidth(30).autoItemWidth(false)); + beforeEach(() => { + chart.legend(new dc.Legend().horizontal(true).itemWidth(30).autoItemWidth(false)); chart.render(); fixedWidthOffset1 = coordsFromTranslate(legendItem(1).attr('transform')).x; - fixedWidthOffset2 = coordsFromTranslate(legendItem(2).attr('transform')).x; - chart.legend(dc.legend().horizontal(true).itemWidth(30).autoItemWidth(true)); + chart.legend(new dc.Legend().horizontal(true).itemWidth(30).autoItemWidth(true).legendWidth(160)); chart.render(); - autoWidthOffset1 = coordsFromTranslate(legendItem(1).attr('transform')).x; - autoWidthOffset2 = coordsFromTranslate(legendItem(2).attr('transform')).x; + autoWidthCoords = d3.range(3).map(i => coordsFromTranslate(legendItem(i).attr('transform'))); }); - it('autoWidth x offset should be greater than fixedWidth x offset for some legend items', function () { - expect(autoWidthOffset1).toBeGreaterThan(fixedWidthOffset1); - expect(autoWidthOffset2).toBeGreaterThan(fixedWidthOffset2); + it('autoWidth x offset should be greater than fixedWidth x offset for the second item', () => { + expect(autoWidthCoords[1].x).toBeGreaterThan(fixedWidthOffset1); + }); + it('should wrap the third item based on actual widths', () => { + expect(autoWidthCoords[2].x).toBe(0); + expect(autoWidthCoords[2].y).toBeWithinDelta(13, 5); }); }); - describe('with .legendText()', function () { - beforeEach(function () { - chart.legend(dc.legend().legendText(function (d, i) { - var _i = i + 1; + describe('with .legendText()', () => { + beforeEach(() => { + chart.legend(new dc.Legend().legendText((d, i) => { + const _i = i + 1; - return _i + '. ' + d.name; + return `${_i}. ${d.name}`; })); chart.render(); }); - it('should label the legend items with the names of their associated stacks', function () { + it('should label the legend items with the names of their associated stacks', () => { expect(legendLabel(0).text()).toBe('1. Id Sum'); expect(legendLabel(1).text()).toBe('2. Value Sum'); expect(legendLabel(2).text()).toBe('3. Fixed'); }); }); + + describe('with .maxItems(2)', () => { + beforeEach(() => { + chart.legend() + .maxItems(2); + chart.render(); + }); + it('should display two items', () => { + expect(chart.select('g.dc-legend').selectAll('g.dc-legend-item').size()).toBe(2); + }); + }); + + describe('with invalid .maxItems', () => { + beforeEach(() => { + chart.legend() + .maxItems('foo'); + chart.render(); + }); + it('should display three items', () => { + expect(chart.select('g.dc-legend').selectAll('g.dc-legend-item').size()).toBe(3); + }); + }); }); - describe('legends with dashed lines', function () { - beforeEach(function () { + describe('legends with dashed lines', () => { + beforeEach(() => { id = 'legend-chart-dashed'; appendChartID(id); - chart = dc.compositeChart('#' + id); + chart = new dc.CompositeChart(`#${id}`); - var subChart1 = dc.lineChart(chart); + const subChart1 = new dc.LineChart(chart); subChart1 .dimension(dateDimension) .group(dateIdSumGroup, 'Id Sum') .dashStyle([10,1]); - var subChart2 = dc.lineChart(chart); + const subChart2 = new dc.LineChart(chart); subChart2 .dimension(dateDimension) .group(dateValueSumGroup, 'Value Sum') .dashStyle([2,1]); chart - .x(d3.scale.linear().domain([0,20])) - .legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) + .x(d3.scaleLinear().domain([0,20])) + .legend(new dc.Legend().x(400).y(10).itemHeight(13).gap(5)) .compose([subChart1, subChart2]) .render(); }); - it('should style legend line correctly', function () { - expect(legendLine(0).attr('stroke-dasharray')).toEqualIntList('10,1'); - expect(legendLine(1).attr('stroke-dasharray')).toEqualIntList('2,1'); + it('should style legend line correctly', () => { + expect(legendLine(0).attr('stroke-dasharray')).toEqualIntOrPixelList('10,1'); + expect(legendLine(1).attr('stroke-dasharray')).toEqualIntOrPixelList('2,1'); }); }); - describe('legends with hidable stacks', function () { - beforeEach(function () { + describe('legends with hidable stacks', () => { + beforeEach(() => { chart.hidableStacks(true).render(); }); - describe('clicking on a legend item', function () { - beforeEach(function () { - legendItem(0).on('click').call(legendItem(0)[0][0], legendItem(0).datum()); + describe('clicking on a legend item', () => { + beforeEach(() => { + dc.d3compat.callHandler(legendItem(0).on('click'), legendItem(0).nodes()[0], {}, legendItem(0).datum()); }); - it('should fade out the legend item', function () { + it('should fade out the legend item', () => { expect(legendItem(0).classed('fadeout')).toBeTruthy(); }); - it('should hide its associated stack', function () { + it('should hide its associated stack', () => { expect(chart.selectAll('path.line').size()).toEqual(2); }); - it('disable hover highlighting for that legend item', function () { - legendItem(0).on('mouseover')(legendItem(0).datum()); - expect(d3.select(chart.selectAll('path.line')[0][1]).classed('fadeout')).toBeFalsy(); + it('disable hover highlighting for that legend item', () => { + dc.d3compat.callHandler(legendItem(0).on('mouseover'), null, {}, legendItem(0).datum()); + expect(d3.select(chart.selectAll('path.line').nodes()[1]).classed('fadeout')).toBeFalsy(); }); - describe('clicking on a faded out legend item', function () { - beforeEach(function () { - legendItem(0).on('click').call(legendItem(0)[0][0], legendItem(0).datum()); + describe('clicking on a faded out legend item', () => { + beforeEach(() => { + dc.d3compat.callHandler(legendItem(0).on('click'), legendItem(0).nodes()[0], {}, legendItem(0).datum()); }); - it('should unfade the legend item', function () { + it('should unfade the legend item', () => { expect(legendItem(0).classed('fadeout')).toBeFalsy(); }); - it('should unfade its associated stack', function () { + it('should unfade its associated stack', () => { expect(chart.selectAll('path.line').size()).toEqual(3); }); }); }); }); + describe('accessible legends', () => { + beforeEach(() => { + chart.legend(new dc.Legend().keyboardAccessible(true)).render(); + }); + + it('legend items should be focusable from keyboard', () => { + + chart.select('g.dc-legend').selectAll('g.dc-legend-item text').each(function () { + const item = d3.select(this); + expect(item.attr('tabindex')).toEqual('0'); + }); + + }); + + it('keyboard focus on legend item should highlight chart item', () => { + + dc.d3compat.callHandler( + chart.select('g.dc-legend').select('g.dc-legend-item text').on('focus'), + legendItem(0).nodes()[0], {}, legendItem(0).datum()); + + expect(d3.select(chart.selectAll('path.line').nodes()[0]).classed('highlight')).toBeTruthy(); + }); + + }); + function legendItem (n) { - return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item')[0][n]); + return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item').nodes()[n]); } function legendLabel (n) { - return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item text')[0][n]); + return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item text').nodes()[n]); } function legendIcon (n) { - return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item rect')[0][n]); + return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item rect').nodes()[n]); } function legendLine (n) { - return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item line')[0][n]); + return d3.select(chart.selectAll('g.dc-legend g.dc-legend-item line').nodes()[n]); } }); diff --git a/spec/line-chart-spec.js b/spec/line-chart-spec.js index c78b836966..016642adcd 100644 --- a/spec/line-chart-spec.js +++ b/spec/line-chart-spec.js @@ -1,109 +1,109 @@ /* global appendChartID, loadDateFixture, makeDate */ -describe('dc.lineChart', function () { - var id, chart, data; - var dimension, group; +describe('dc.lineChart', () => { + let id, chart, data; + let dimension, group; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { return d3.time.day.utc(d.dd); }); + dimension = data.dimension(d => d3.utcDay(d.dd)); group = dimension.group(); id = 'line-chart'; appendChartID(id); - chart = dc.lineChart('#' + id); + chart = new dc.LineChart(`#${id}`); chart.dimension(dimension).group(group) .width(1100).height(200) - .x(d3.time.scale.utc().domain([makeDate(2012, 1, 1), makeDate(2012, 11, 31)])) + .x(d3.scaleUtc().domain([makeDate(2012, 1, 1), makeDate(2012, 11, 31)])) .transitionDuration(0); }); - describe('rendering', function () { - beforeEach(function () { + describe('rendering', () => { + beforeEach(() => { chart.render(); }); - describe('with a specified dash style', function () { - beforeEach(function () { + describe('with a specified dash style', () => { + beforeEach(() => { chart.dashStyle([3, 1, 1, 1]).render(); }); - it('should be dash-dot-dot-dot to match the specified style', function () { - expect(chart.selectAll('path.line').attr('stroke-dasharray')).toEqualIntList('3,1,1,1'); + it('should be dash-dot-dot-dot to match the specified style', () => { + expect(chart.selectAll('path.line').attr('stroke-dasharray')).toEqualIntOrPixelList('3,1,1,1'); }); }); - describe('render data markers', function () { - beforeEach(function () { + describe('render data markers', () => { + beforeEach(() => { chart.dotRadius(5) .brushOn(false) .renderDataPoints({}).render(); }); - it('should use default options', function () { + it('should use default options', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); + const dot = d3.select(this); expect(dot.style('fill-opacity')).toBeWithinDelta(0.8); - expect(dot.style('stroke-opacity')).toBeWithinDelta(0.8); + expect(dot.style('stroke-opacity')).toBeWithinDelta(0.0); expect(dot.attr('r')).toBe('2'); }); }); - it('should use supplied options', function () { + it('should use supplied options', () => { chart.renderDataPoints({radius: 3, fillOpacity: 1, strokeOpacity: 1}) .render(); chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); + const dot = d3.select(this); expect(dot.style('fill-opacity')).toBe('1'); expect(dot.style('stroke-opacity')).toBe('1'); expect(dot.attr('r')).toBe('3'); }); }); - it('should change the radius on mousemove', function () { + it('should change the radius on mousemove', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); expect(dot.attr('r')).toBe('5'); }); }); - it('should revert to original radius on mouseout', function () { + it('should revert to original radius on mouseout', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); - dot.on('mouseout').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); + dc.d3compat.callHandler(dot.on('mouseout'), this, {}); expect(dot.attr('r')).toBe('2'); }); }); - describe('hiding all data markers', function () { - beforeEach(function () { + describe('hiding all data markers', () => { + beforeEach(() => { chart.renderDataPoints(false).render(); }); - it('should not change the default opacity and radius', function () { + it('should not change the default opacity and radius', () => { chart.selectAll('circle.dot').each(function () { expect(d3.select(this).style('fill-opacity')).toBeWithinDelta(1e-6); expect(d3.select(this).style('stroke-opacity')).toBeWithinDelta(1e-6); }); }); - it('should not change showing the data point on mousemove', function () { + it('should not change showing the data point on mousemove', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); expect(dot.style('fill-opacity')).toBeWithinDelta(0.8); expect(dot.style('stroke-opacity')).toBeWithinDelta(0.8); }); }); - it('should not change returning to extremely low opacity on hover out', function () { + it('should not change returning to extremely low opacity on hover out', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); - dot.on('mouseout').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); + dc.d3compat.callHandler(dot.on('mouseout'), this, {}); expect(dot.style('fill-opacity')).toBeWithinDelta(1e-6); expect(dot.style('stroke-opacity')).toBeWithinDelta(1e-6); }); @@ -111,31 +111,58 @@ describe('dc.lineChart', function () { }); }); - describe('title rendering', function () { - beforeEach(function () { + describe('title rendering', () => { + beforeEach(() => { chart.renderTitle(false); chart.render(); }); - it('should not render tooltips when boolean flag is false', function () { - expect(chart.select('.sub._0 .dc-tooltip._0 .dot').empty()).toBeTruthy(); - expect(chart.select('.sub._1 .dc-tooltip._0 .dot').empty()).toBeTruthy(); + it('should not render dots and tips when boolean flag is false', () => { + expect(chart.select('.dc-tooltip._0 .dot').empty()).toBeTruthy(); + expect(chart.select('.dc-tooltip._0 .dot title').empty()).toBeTruthy(); }); + }); - describe('label rendering off', function () { - beforeEach(function () { + describe('title rendering with brushOn', () => { + beforeEach(() => { + chart.brushOn(true) + .xyTipsOn(true); // default, for exposition + chart.render(); + }); + + it('should not render tips', () => { + expect(chart.select('.dc-tooltip._0 .dot').empty()).toBeTruthy(); + expect(chart.select('.dc-tooltip._0 .dot title').empty()).toBeTruthy(); + }); + + describe('with xyTipsOn always', () => { + beforeEach(() => { + chart.brushOn(true) + .xyTipsOn('always'); + chart.render(); + }); + + it('should render dots', () => { + expect(chart.select('.dc-tooltip._0 .dot').empty()).toBeFalsy(); + expect(chart.select('.dc-tooltip._0 .dot title').empty()).toBeFalsy(); + }); + }); + }); + + describe('label rendering off', () => { + beforeEach(() => { chart.renderLabel(false); chart.render(); }); - it('should produce no labels', function () { + it('should produce no labels', () => { expect(chart.selectAll('.lineLabel').empty()).toBeTruthy(); }); }); - describe('label rendering', function () { - beforeEach(function () { + describe('label rendering', () => { + beforeEach(() => { chart.renderLabel(true); chart.render(); }); @@ -144,125 +171,125 @@ describe('dc.lineChart', function () { it('should generate labels with positions corresponding to their data', lineLabelPositions); }); - describe('data point highlights and refs off', function () { - beforeEach(function () { - chart.title(function (d) { return d.value; }); + describe('data point highlights and refs off', () => { + beforeEach(() => { + chart.title(d => d.value); chart.brushOn(false).xyTipsOn(false).render(); }); - it('should not generate per data points', function () { + it('should not generate per data points', () => { expect(chart.selectAll('circle.dot').size()).toBe(0); }); - it('should not generate x and y refs', function () { + it('should not generate x and y refs', () => { expect(chart.selectAll('path.xRef').size()).toBe(0); expect(chart.selectAll('path.yRef').size()).toBe(0); }); }); - describe('data point highlights', function () { - beforeEach(function () { - chart.title(function (d) { return d.value; }); + describe('data point highlights', () => { + beforeEach(() => { + chart.title(d => d.value); chart.brushOn(false).dotRadius(10).render(); }); - it('should not generate a chart brush', function () { + it('should not generate a chart brush', () => { expect(chart.selectAll('g.brush').empty()).toBeTruthy(); }); - it('should be generated per data point', function () { + it('should be generated per data point', () => { expect(chart.selectAll('circle.dot').size()).toBe(6); }); - it('should have configurable radius', function () { + it('should have configurable radius', () => { chart.selectAll('circle.dot').each(function () { expect(d3.select(this).attr('r')).toBe('10'); }); }); - it('should be have extremely low opacity by default', function () { + it('should be have extremely low opacity by default', () => { chart.selectAll('circle.dot').each(function () { expect(d3.select(this).style('fill-opacity')).toBeWithinDelta(1e-6); expect(d3.select(this).style('stroke-opacity')).toBeWithinDelta(1e-6); }); }); - it('should become visible when hovered over', function () { + it('should become visible when hovered over', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); expect(dot.style('fill-opacity')).toBeWithinDelta(0.8); expect(dot.style('stroke-opacity')).toBeWithinDelta(0.8); }); }); - it('should return to extremely low opacity on hover out', function () { + it('should return to extremely low opacity on hover out', () => { chart.selectAll('circle.dot').each(function () { - var dot = d3.select(this); - dot.on('mousemove').call(this); - dot.on('mouseout').call(this); + const dot = d3.select(this); + dc.d3compat.callHandler(dot.on('mousemove'), this, {}); + dc.d3compat.callHandler(dot.on('mouseout'), this, {}); expect(dot.style('fill-opacity')).toBeWithinDelta(1e-6); expect(dot.style('stroke-opacity')).toBeWithinDelta(1e-6); }); }); - it('should render titles on to each circle', function () { + it('should render titles on to each circle', () => { chart.selectAll('g._0 circle.dot').each(function (d) { expect(+d3.select(this).select('title').text()).toBe(d.data.value); }); }); - describe('ref lines', function () { - it('should generate lines that are hidden by default', function () { + describe('ref lines', () => { + it('should generate lines that are hidden by default', () => { expect(chart.select('path.xRef').style('display')).toBe('none'); expect(chart.select('path.yRef').style('display')).toBe('none'); }); - it('should have a stroke dash', function () { - expect(chart.selectAll('path.xRef').attr('stroke-dasharray')).toEqualIntList('5,5'); - expect(chart.selectAll('path.yRef').attr('stroke-dasharray')).toEqualIntList('5,5'); + it('should have a stroke dash', () => { + expect(chart.selectAll('path.xRef').attr('stroke-dasharray')).toEqualIntOrPixelList('5,5'); + expect(chart.selectAll('path.yRef').attr('stroke-dasharray')).toEqualIntOrPixelList('5,5'); }); - describe('when dot is hovered over', function () { - describe('for vertical ref lines', function () { - var x; - beforeEach(function () { - var dot = chart.select('circle.dot'); - dot.on('mousemove').call(dot[0][0]); + describe('when dot is hovered over', () => { + describe('for vertical ref lines', () => { + let x; + beforeEach(() => { + const dot = chart.select('circle.dot'); + dc.d3compat.callHandler(dot.on('mousemove'), dot.nodes()[0], {}); x = dot.attr('cx'); }); - it('shows the ref line from the bottom of the graph', function () { - var path = 'M' + x + ' 160 L ' + x + ' 107'; + it('shows the ref line from the bottom of the graph', () => { + const path = `M${x} 160 L ${x} 107`; expect(chart.select('path.xRef').attr('d')).toMatchPath(path); expect(chart.select('path.xRef').attr('display')).not.toBe('none'); }); }); - describe('for horizontal ref lines', function () { - describe('for a left y-axis chart', function () { - var x; - beforeEach(function () { - var dot = chart.select('circle.dot'); - dot.on('mousemove').call(dot[0][0]); + describe('for horizontal ref lines', () => { + describe('for a left y-axis chart', () => { + let x; + beforeEach(() => { + const dot = chart.select('circle.dot'); + dc.d3compat.callHandler(dot.on('mousemove'), dot.nodes()[0], {}); x = dot.attr('cx'); }); - it('shows the ref line on the left', function () { - var path = 'M0 107 L ' + x + ' 107'; + it('shows the ref line on the left', () => { + const path = `M0 107 L ${x} 107`; expect(chart.select('path.yRef').attr('d')).toMatchPath(path); expect(chart.select('path.yRef').attr('display')).not.toBe('none'); }); }); - describe('for a right y-axis chart', function () { - var x; - beforeEach(function () { + describe('for a right y-axis chart', () => { + let x; + beforeEach(() => { chart.useRightYAxis(true).render(); - var dot = chart.select('circle.dot'); - dot.on('mousemove').call(dot[0][0]); + const dot = chart.select('circle.dot'); + dc.d3compat.callHandler(dot.on('mousemove'), dot.nodes()[0], {}); x = dot.attr('cx'); }); - it('shows the ref line on the right', function () { - var path = 'M1020 107L' + x + ' 107'; + it('shows the ref line on the right', () => { + const path = `M1020 107L${x} 107`; expect(chart.select('path.yRef').attr('d')).toMatchPath(path); //"M1020 107L405 107"); expect(chart.select('path.yRef').attr('display')).not.toBe('none'); }); @@ -272,152 +299,152 @@ describe('dc.lineChart', function () { }); }); - describe('undefined points', function () { - beforeEach(function () { - chart.defined(function (d) { return d.x.valueOf() !== makeDate(2012, 5, 10).getTime(); }); + describe('undefined points', () => { + beforeEach(() => { + chart.defined(d => d.x.valueOf() !== makeDate(2012, 5, 10).getTime()); chart.brushOn(false).render(); }); - it('should not show line where not defined', function () { + it('should not show line where not defined', () => { expect(chart.select('path.line').attr('d').indexOf('M', 1)).not.toBe(-1); }); - it('should not draw dots on undefined points', function () { + it('should not draw dots on undefined points', () => { expect(chart.selectAll('.dot').size()).toBe(5); }); }); - describe('with chart area enabled', function () { - beforeEach(function () { + describe('with chart area enabled', () => { + beforeEach(() => { chart.renderArea(true).render(); }); - it('should draw the chart line', function () { + it('should draw the chart line', () => { expect(chart.select('path.line').attr('d')).toMatchPath('M348,107 L390,107 L397,0 L461,107 L488,53 L583,53'); }); - it('should draw the chart area', function () { + it('should draw the chart area', () => { expect(chart.select('path.area').attr('d')).toMatchPath('M348,107 L390,107 L397,0 L461,107 L488,53 L583,' + '53 L583,160 L488,160 L461,160 L397,160 L390,160 L348,160Z'); }); }); - describe('with an ordinal x domain', function () { - beforeEach(function () { - var stateDimension = data.dimension(function (d) { return d.state; }); - var stateGroup = stateDimension.group(); + describe('with an ordinal x domain', () => { + beforeEach(() => { + const stateDimension = data.dimension(d => d.state); + const stateGroup = stateDimension.group(); chart.dimension(stateDimension) .group(stateGroup) .xUnits(dc.units.ordinal) - .x(d3.scale.ordinal().domain(['California', 'Colorado', 'Delaware', 'Mississippi', 'Oklahoma', 'Ontario'])) + .x(d3.scaleBand().domain(['California', 'Colorado', 'Delaware', 'Mississippi', 'Oklahoma', 'Ontario'])) .render(); }); - it('should automatically disable the brush', function () { + it('should automatically disable the brush', () => { expect(chart.brushOn()).toBeFalsy(); }); - it('should generate an ordinal path', function () { + it('should generate an ordinal path', () => { expect(chart.select('path.line').attr('d')).toMatchPath('M85,0L255,107L425,107L595,53L765,107L935,53'); }); }); - describe('with stacked data', function () { - describe('with positive data', function () { - beforeEach(function () { - var idGroup = dimension.group().reduceSum(function (d) { return d.id; }); - var valueGroup = dimension.group().reduceSum(function (d) { return d.value; }); + describe('with stacked data', () => { + describe('with positive data', () => { + beforeEach(() => { + const idGroup = dimension.group().reduceSum(d => d.id); + const valueGroup = dimension.group().reduceSum(d => d.value); chart.dimension(dimension) .brushOn(false) - .x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) + .x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])) .group(idGroup, 'stack 0') - .title('stack 0', function (d) { return 'stack 0: ' + d.value; }) + .title('stack 0', d => `stack 0: ${d.value}`) .stack(valueGroup, 'stack 1') - .title('stack 1', function (d) { return 'stack 1: ' + d.value; }) + .title('stack 1', d => `stack 1: ${d.value}`) .stack(valueGroup, 'stack 2') .elasticY(true) .render(); }); - it('should render the correct number of lines', function () { + it('should render the correct number of lines', () => { expect(chart.selectAll('path.line').size()).toBe(3); }); - it('should set the path for stack 0 line', function () { + it('should set the path for stack 0 line', () => { expect(chart.select('g._0 path.line').attr('d')).toMatchPath('M58 159L222 157L246 150L492 158L597 151L961 153'); }); - it('should set the path for stack 1 line', function () { + it('should set the path for stack 1 line', () => { expect(chart.select('g._1 path.line').attr('d')).toMatchPath('M58 134L222 119L246 75L492 133L597 120L961 109'); }); - it('should set the path for stack 2 line', function () { + it('should set the path for stack 2 line', () => { expect(chart.select('g._2 path.line').attr('d')).toMatchPath('M58 109L222 81L246 0L492 108L597 89L961 65'); }); - it('should have its own title accessor', function () { + it('should have its own title accessor', () => { expect(chart.title()({value: 1})).toBe('stack 0: 1'); expect(chart.title('stack 0')({value: 2})).toBe('stack 0: 2'); expect(chart.title('stack 1')({value: 3})).toBe('stack 1: 3'); }); - it('should have titles rendered for extra stacks', function () { + it('should have titles rendered for extra stacks', () => { chart.selectAll('g._1 circle.dot').each(function (d) { - expect(d3.select(this).select('title').text()).toBe('stack 1: ' + d.data.value); + expect(d3.select(this).select('title').text()).toBe(`stack 1: ${d.data.value}`); }); }); - it('should default to first stack title for untitled stacks', function () { + it('should default to first stack title for untitled stacks', () => { chart.selectAll('g._2 circle.dot').each(function (d) { - expect(d3.select(this).select('title').text()).toBe('stack 0: ' + d.data.value); + expect(d3.select(this).select('title').text()).toBe(`stack 0: ${d.data.value}`); }); }); - describe('with chart area enabled', function () { - beforeEach(function () { + describe('with chart area enabled', () => { + beforeEach(() => { chart.renderArea(true).render(); }); - it('should render the correct number of areas', function () { + it('should render the correct number of areas', () => { expect(chart.selectAll('path.area').size()).toBe(3); }); - it('should set the area for stack 0', function () { + it('should set the area for stack 0', () => { expect(chart.select('g._0 path.area').attr('d')).toMatchPath('M58 159L222 157L246 150L492 158L597 ' + '151L961 153L961 160L597 160L492 160L246 160L222 160L58 160Z'); }); - it('should set the area for stack 1', function () { + it('should set the area for stack 1', () => { expect(chart.select('g._1 path.area').attr('d')).toMatchPath('M58 134L222 119L246 75L492 133L597 ' + '120L961 109L961 153L597 151L492 158L246 150L222 157L58 159Z'); }); - it('should set the area for stack 2', function () { + it('should set the area for stack 2', () => { expect(chart.select('g._2 path.area').attr('d')).toMatchPath('M58 109L222 81L246 0L492 108L597 89L961 ' + '65L961 109L597 120L492 133L246 75L222 119L58 134Z'); }); - it('should draw tooltip dots on top of paths and areas', function () { - var list = chart.selectAll('circle.dot, path.line, path.area'); + it('should draw tooltip dots on top of paths and areas', () => { + const list = chart.selectAll('circle.dot, path.line, path.area'); - var indexOfLastLine = list[0].indexOf(list.filter('path.line')[0][2]); - var indexOfLastArea = list[0].indexOf(list.filter('path.area')[0][2]); - var indexOfDot = list[0].indexOf(list.filter('circle.dot')[0][0]); + const indexOfLastLine = list.nodes().indexOf(list.filter('path.line').nodes()[2]); + const indexOfLastArea = list.nodes().indexOf(list.filter('path.area').nodes()[2]); + const indexOfDot = list.nodes().indexOf(list.filter('circle.dot').nodes()[0]); expect(indexOfDot).toBeGreaterThan(indexOfLastArea); expect(indexOfDot).toBeGreaterThan(indexOfLastLine); }); - it('should draw tooltip ref lines on top of paths', function () { - var list = chart.selectAll('path.yRef, path.xRef, path.line, path.area'); + it('should draw tooltip ref lines on top of paths', () => { + const list = chart.selectAll('path.yRef, path.xRef, path.line, path.area'); - var indexOfLastLine = list[0].indexOf(list.filter('path.line')[0][2]); - var indexOfLastArea = list[0].indexOf(list.filter('path.area')[0][2]); + const indexOfLastLine = list.nodes().indexOf(list.filter('path.line').nodes()[2]); + const indexOfLastArea = list.nodes().indexOf(list.filter('path.area').nodes()[2]); - var indexOfFirstYRef = list[0].indexOf(list.filter('path.yRef')[0][0]); - var indexOfFirstXRef = list[0].indexOf(list.filter('path.xRef')[0][0]); + const indexOfFirstYRef = list.nodes().indexOf(list.filter('path.yRef').nodes()[0]); + const indexOfFirstXRef = list.nodes().indexOf(list.filter('path.xRef').nodes()[0]); expect(indexOfLastLine).toBeLessThan(indexOfFirstXRef); expect(indexOfLastLine).toBeLessThan(indexOfFirstYRef); @@ -428,66 +455,66 @@ describe('dc.lineChart', function () { }); - describe('stack hiding', function () { - describe('first stack', function () { - beforeEach(function () { + describe('stack hiding', () => { + describe('first stack', () => { + beforeEach(() => { chart.hideStack('stack 0').render(); }); - it('should hide the stack', function () { + it('should hide the stack', () => { expect(chart.select('g._0 path.line').attr('d')).toMatchPath('M58 133L222 120L246 80L492 133L597 127L961 113'); }); - it('should show the stack', function () { + it('should show the stack', () => { chart.showStack('stack 0').render(); expect(chart.select('g._0 path.line').attr('d')).toMatchPath('M58 159L222 157L246 150L492 158L597 151L961 153'); }); }); - describe('any other stack', function () { - beforeEach(function () { - chart.title('stack 2', function (d) { return 'stack 2: ' + d.value; }); + describe('any other stack', () => { + beforeEach(() => { + chart.title('stack 2', d => `stack 2: ${d.value}`); chart.hideStack('stack 1').render(); }); - it('should hide the stack', function () { + it('should hide the stack', () => { expect(chart.select('g._1 path.line').attr('d')).toMatchPath('M58 112L222 83L246 0L492 108L597 85L961 64'); }); - it('should show the stack', function () { + it('should show the stack', () => { chart.showStack('stack 1').render(); expect(chart.select('g._1 path.line').attr('d')).toMatchPath('M58 134L222 119L246 75L492 133L597 120L961 109'); }); - it('should color chart dots the same as line paths', function () { - var lineColor = chart.select('g._1 path.line').attr('stroke'); - var circleColor = chart.select('g._1 circle.dot').attr('fill'); + it('should color chart dots the same as line paths', () => { + const lineColor = chart.select('g._1 path.line').attr('stroke'); + const circleColor = chart.select('g._1 circle.dot').attr('fill'); expect(lineColor).toEqual(circleColor); }); - it('should still show the title for a visible stack', function () { + it('should still show the title for a visible stack', () => { chart.selectAll('g._1 circle.dot').each(function (d) { - expect(d3.select(this).select('title').text()).toBe('stack 2: ' + d.data.value); + expect(d3.select(this).select('title').text()).toBe(`stack 2: ${d.data.value}`); }); }); }); - describe('hiding all the stacks', function () { - beforeEach(function () { + describe('hiding all the stacks', () => { + beforeEach(() => { chart.hideStack('stack 0') .hideStack('stack 1') .hideStack('stack 2') .render(); }); - it('should show a blank graph', function () { + it('should show a blank graph', () => { expect(chart.selectAll('path.line').size()).toBe(0); }); }); }); - describe('label rendering', function () { - beforeEach(function () { + describe('label rendering', () => { + beforeEach(() => { chart.renderLabel(true); chart.render(); }); @@ -497,12 +524,12 @@ describe('dc.lineChart', function () { }); }); - describe('with mixed positive and negative data', function () { - beforeEach(function () { - var mixedGroup = dimension.group().reduceSum(function (d) { return d.nvalue; }); + describe('with mixed positive and negative data', () => { + beforeEach(() => { + const mixedGroup = dimension.group().reduceSum(d => d.nvalue); chart.group(mixedGroup).stack(mixedGroup).stack(mixedGroup); - chart.x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + chart.x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.margins({top: 30, right: 50, bottom: 30, left: 30}) .renderArea(true) @@ -513,33 +540,35 @@ describe('dc.lineChart', function () { chart.render(); }); - it('should generate a line and area for each stack', function () { + it('should generate a line and area for each stack', () => { expect(chart.selectAll('path.line').size()).toBe(3); expect(chart.selectAll('path.area').size()).toBe(3); }); - it('should generate negative lines and area for stack 0', function () { + it('should generate negative lines and area for stack 0', () => { expect(chart.select('g._0 path.line').attr('d')).toMatchPath('M58 81L222 81L246 92L492 79L597 52L961 67'); expect(chart.select('g._0 path.area').attr('d')).toMatchPath('M58 81L222 81L246 92L492 79L597 52L961 ' + '67L961 73L597 73L492 73L246 73L222 73L58 73Z'); }); - it('should generate negative lines and area for stack 1', function () { + it('should generate negative lines and area for stack 1', () => { expect(chart.select('g._1 path.line').attr('d')).toMatchPath('M58 88L222 88L246 111L492 84L597 31L961 61'); expect(chart.select('g._1 path.area').attr('d')).toMatchPath('M58 88L222 88L246 111L492 84L597 31L961 ' + '61L961 67L597 52L492 79L246 92L222 81L58 81Z'); }); - it('should generate y axis domain dynamically', function () { - var nthText = function (n) { return d3.select(chart.selectAll('g.axis.y .tick text')[0][n]); }; + it('should generate y axis domain dynamically', () => { + const nthText = function (n) { + return d3.select(chart.selectAll('g.axis.y .tick text').nodes()[n]); + }; - expect(nthText(0).text()).toBe('-20'); + expect(nthText(0).text()).toMatch(/[\-−]20/); expect(nthText(1).text()).toBe('0'); expect(nthText(2).text()).toBe('20'); }); - describe('label rendering', function () { - beforeEach(function () { + describe('label rendering', () => { + beforeEach(() => { chart.renderLabel(true); chart.render(); }); @@ -549,171 +578,192 @@ describe('dc.lineChart', function () { }); }); - describe('with negative data', function () { - beforeEach(function () { - var negativeGroup = dimension.group().reduceSum(function (d) { return -Math.abs(d.nvalue); }); + describe('with negative data', () => { + beforeEach(() => { + const negativeGroup = dimension.group().reduceSum(d => -Math.abs(d.nvalue)); chart.group(negativeGroup).stack(negativeGroup).stack(negativeGroup); - chart.x(d3.time.scale.utc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); + chart.x(d3.scaleUtc().domain([makeDate(2012, 4, 20), makeDate(2012, 7, 15)])); chart.margins({top: 30, right: 50, bottom: 30, left: 30}) .elasticY(true) - .xUnits(d3.time.days.utc) + .xUnits(d3.utcDays) .yAxis().ticks(3); chart.render(); }); - it('should generate y axis domain dynamically', function () { - var nthText = function (n) { return d3.select(chart.selectAll('g.axis.y .tick text')[0][n]); }; + it('should generate y axis domain dynamically', () => { + const nthText = function (n) { + return d3.select(chart.selectAll('g.axis.y .tick text').nodes()[n]); + }; - expect(nthText(0).text()).toBe('-30'); - expect(nthText(1).text()).toBe('-20'); - expect(nthText(2).text()).toBe('-10'); + // d3@5 and d3@6 uses different characters to format negative numbers + expect(nthText(0).text()).toMatch(/[\-−]30/); + expect(nthText(1).text()).toMatch(/[\-−]20/); + expect(nthText(2).text()).toMatch(/[\-−]10/); expect(nthText(3).text()).toBe('0'); }); }); }); - describe('legend hovering', function () { - var firstItem; + describe('legend hovering', () => { + let firstItem; - beforeEach(function () { + beforeEach(() => { chart.stack(group) - .legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) + .legend(new dc.Legend().x(400).y(10).itemHeight(13).gap(5)) .renderArea(true) .render(); firstItem = chart.select('g.dc-legend g.dc-legend-item'); - firstItem.on('mouseover')(firstItem.datum()); + dc.d3compat.callHandler(firstItem.on('mouseover'), {}, null, firstItem.datum()); }); - describe('when a legend item is hovered over', function () { - it('should highlight corresponding lines and areas', function () { + describe('when a legend item is hovered over', () => { + it('should highlight corresponding lines and areas', () => { expect(nthLine(0).classed('highlight')).toBeTruthy(); expect(nthArea(0).classed('highlight')).toBeTruthy(); }); - it('should fade out non-corresponding lines and areas', function () { + it('should fade out non-corresponding lines and areas', () => { expect(nthLine(1).classed('fadeout')).toBeTruthy(); expect(nthArea(1).classed('fadeout')).toBeTruthy(); }); }); - describe('when a legend item is hovered out', function () { - it('should remove highlighting from corresponding lines and areas', function () { - firstItem.on('mouseout')(firstItem.datum()); + describe('when a legend item is hovered out', () => { + it('should remove highlighting from corresponding lines and areas', () => { + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); expect(nthLine(0).classed('highlight')).toBeFalsy(); expect(nthArea(0).classed('highlight')).toBeFalsy(); }); - it('should fade in non-corresponding lines and areas', function () { - firstItem.on('mouseout')(firstItem.datum()); + it('should fade in non-corresponding lines and areas', () => { + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); expect(nthLine(1).classed('fadeout')).toBeFalsy(); expect(nthArea(1).classed('fadeout')).toBeFalsy(); }); }); function nthLine (n) { - return d3.select(chart.selectAll('path.line')[0][n]); + return d3.select(chart.selectAll('path.line').nodes()[n]); } function nthArea (n) { - return d3.select(chart.selectAll('path.area')[0][n]); + return d3.select(chart.selectAll('path.area').nodes()[n]); } }); - describe('filtering', function () { - beforeEach(function () { + describe('filtering', () => { + beforeEach(() => { chart.filter([makeDate(2012, 5, 1), makeDate(2012, 5, 30)]).redraw(); }); - it('should set the chart filter', function () { + it('should set the chart filter', () => { expect(chart.filter()).toEqual([makeDate(2012, 5, 1), makeDate(2012, 5, 30)]); }); - it('should set the filter printer', function () { + it('should set the filter printer', () => { expect(chart.filterPrinter()).not.toBeNull(); }); - it('should not generate tooltip circles with the default brush', function () { + it('should not generate tooltip circles with the default brush', () => { expect(chart.selectAll('circle.dot').empty()).toBeTruthy(); }); - describe('when a brush is defined', function () { - it('should position the brush with an offset', function () { + describe('when a brush is defined', () => { + it('should position the brush with an offset', () => { expect(chart.select('g.brush').attr('transform')).toMatchTranslate(chart.margins().left, 10); }); - it('should create a fancy brush resize handle', function () { - chart.select('g.brush').selectAll('.resize path').each(function (d, i) { + it('should create a fancy brush resize handle', () => { + const selectAll = chart.select('g.brush').selectAll('path.custom-brush-handle'); + expect(selectAll.size()).toBe(2); + selectAll.each(function (d, i) { if (i === 0) { expect(d3.select(this).attr('d')) - .toMatchPath('M0.5,53 A6,6 0 0 1 6.5,59 V100 A6,6 0 0 1 0.5,106 ZM2.5,61 V98 M4.5,61 V98'); + .toMatchPath('M-0.5,53 A6,6 0 0 0 -6.5,59 V100 A6,6 0 0 0 -0.5,106 ZM-2.5,61 V98 M-4.5,61 V98'); } else { expect(d3.select(this).attr('d')) - .toMatchPath('M-0.5,53 A6,6 0 0 0 -6.5,59 V100 A6,6 0 0 0 -0.5,106 ZM-2.5,61 V98 M-4.5,61 V98'); + .toMatchPath('M0.5,53 A6,6 0 0 1 6.5,59 V100 A6,6 0 0 1 0.5,106 ZM2.5,61 V98 M4.5,61 V98'); } }); }); - it('should stretch the background', function () { - expect(chart.select('g.brush rect.background').attr('width')).toBe('1020'); + it('should stretch the background', () => { + expect(chart.select('g.brush rect.overlay').attr('width')).toBe('1020'); }); - it('should set the background height to the chart height', function () { - expect(chart.select('g.brush rect.background').attr('height')).toBe('160'); + it('should set the background height to the chart height', () => { + expect(chart.select('g.brush rect.overlay').attr('height')).toBe('160'); }); - it('should set extent height to the chart height', function () { - expect(chart.select('g.brush rect.extent').attr('height')).toBe('160'); + it('should set extent height to the chart height', () => { + expect(chart.select('g.brush rect.selection').attr('height')).toBe('160'); }); - it('should set extent width based on filter set', function () { - expect(chart.select('g.brush rect.extent').attr('width')).toBeWithinDelta(88, 1); + it('should set extent width based on filter set', () => { + expect(chart.select('g.brush rect.selection').attr('width')).toBeWithinDelta(88, 1); }); - it('should not have an area path', function () { + it('should not have an area path', () => { expect(chart.selectAll('path.area').empty()).toBeTruthy(); }); - it('should set the dash style to solid', function () { + it('should set the dash style to solid', () => { expect(chart.selectAll('path.line').attr('stroke-dasharray')).toBeNull(); }); }); }); - describe('changing data', function () { - var stateDimension; - beforeEach(function () { + describe('changing data', () => { + let stateDimension; + beforeEach(() => { chart.brushOn(false) - .title(function (d) { return d.value; }) + .title(d => d.value) .render(); - stateDimension = data.dimension(function (d) { return d.state; }); + stateDimension = data.dimension(d => d.state); stateDimension.filter('CA'); chart.redraw(); }); - it('should update dot titles', function () { + it('should update dot titles', () => { chart.selectAll('g._0 circle.dot').each(function (d) { expect(d3.select(this).select('title').size()).toBe(1); expect(+d3.select(this).select('title').text()).toBe(d.data.value); }); }); - afterEach(function () { + afterEach(() => { stateDimension.filter(null); }); }); }); - describe('change color', function () { - beforeEach(function () { + describe('change color', () => { + beforeEach(() => { chart.brushOn(false) - .ordinalColors(['#FF0000']) - .colorAccessor(function () { return 0; }) + .ordinalColors(['#ff0000']) + .colorAccessor(() => 0) .render(); }); - it('updates dot colors', function () { - expect(chart.select('circle.dot')[0][0].attributes.fill.value).toMatch(/#FF0000/i); + it('updates dot colors', () => { + expect(chart.select('circle.dot').nodes()[0].attributes.fill.value).toMatch(/#ff0000/i); + }); + }); + + describe('accessibility bar chart', () => { + + beforeEach(() => { + chart.keyboardAccessible(true); + chart.brushOn(false); + }) + + it('internal elements are focusable by keyboard', () => { + chart.render(); + chart.selectAll('circle.dot').each(function () { + const dot = d3.select(this); + expect(dot.attr('tabindex')).toEqual('0'); + }); }); }); @@ -722,9 +772,9 @@ describe('dc.lineChart', function () { } function lineLabelPositions () { - var LABEL_PADDING = 3; - chart.selectAll('.stack')[0].forEach(function (stack, i) { - d3.select(stack).selectAll('text.lineLabel')[0].forEach(function (lineLabel, j) { + const LABEL_PADDING = 3; + chart.selectAll('.stack').nodes().forEach((stack, i) => { + d3.select(stack).selectAll('text.lineLabel').nodes().forEach((lineLabel, j) => { expect(+d3.select(lineLabel).attr('x')).toBeCloseTo(chart.x()(chart.data()[i].values[j].x)); expect(+d3.select(lineLabel).attr('y') + LABEL_PADDING).toBeCloseTo(chart.y()(chart.data()[i].values[j].y + chart.data()[i].values[j].y0)); diff --git a/spec/logger-spec.js b/spec/logger-spec.js index 6da0ffe1f8..2a69fde314 100644 --- a/spec/logger-spec.js +++ b/spec/logger-spec.js @@ -1,80 +1,106 @@ -describe('dc.logger', function () { - var message = 'Watch out for the bears'; +describe('dc.logger', () => { + const message = 'Watch out for the bears'; - describe('logging a warning', function () { - describe('when console.warn is defined', function () { - beforeEach(function () { + describe('logging a warning', () => { + describe('when console.warn is defined', () => { + beforeEach(() => { console.warn = function (msg) {}; spyOn(console, 'warn'); dc.logger.warn(message); }); - it('should log the message using console.warn', function () { + it('should log the message using console.warn', () => { expect(console.warn).toHaveBeenCalledWith(message); }); }); - describe('when console.warn is not defined but console.log is', function () { - beforeEach(function () { + describe('when console.warn is not defined but console.log is', () => { + beforeEach(() => { console.warn = undefined; spyOn(console, 'log'); dc.logger.warn(message); }); - it('should log the message using console.log', function () { + it('should log the message using console.log', () => { expect(console.log).toHaveBeenCalledWith(message); }); }); }); - describe('debug flag', function () { - it('is off by default', function () { + describe('debug flag', () => { + it('is off by default', () => { expect(dc.logger.enableDebugLog).toBeFalsy(); }); }); - describe('debug logging', function () { - describe('when debugging is disabled', function () { - beforeEach(function () { + describe('debug logging', () => { + describe('when debugging is disabled', () => { + beforeEach(() => { dc.logger.enableDebugLog = false; console.debug = function (msg) {}; spyOn(console, 'debug'); dc.logger.debug(message); }); - it('should log nothing', function () { + it('should log nothing', () => { expect(console.debug).not.toHaveBeenCalled(); }); }); - describe('when debugging is enabled', function () { - beforeEach(function () { + describe('when debugging is enabled', () => { + beforeEach(() => { dc.logger.enableDebugLog = true; }); - describe('when console.debug is defined', function () { - beforeEach(function () { + describe('when console.debug is defined', () => { + beforeEach(() => { console.debug = function (msg) {}; spyOn(console, 'debug'); dc.logger.debug(message); }); - it('should log the message using console.debug', function () { + it('should log the message using console.debug', () => { expect(console.debug).toHaveBeenCalledWith(message); }); }); - describe('when console.debug is not defined', function () { - beforeEach(function () { + describe('when console.debug is not defined', () => { + beforeEach(() => { console.debug = undefined; spyOn(console, 'log'); dc.logger.debug(message); }); - it('should log the message using console.log', function () { + it('should log the message using console.log', () => { expect(console.log).toHaveBeenCalledWith(message); }); }); }); }); + + describe('warnOnce', () => { + beforeEach(() => { + spyOn(dc.logger, 'warn'); + }); + + it('should warn only once for the same message', () => { + dc.logger.warnOnce('Message 01'); + dc.logger.warnOnce('Message 01'); + + expect(dc.logger.warn.calls.count()).toBe(1); + }); + + // Please remember that during run of the entire test suite warnOnce remembers messages. + // So, ensure to use distinct messages in different test cases. + it('should warn only once each for different messages', () => { + dc.logger.warnOnce('Message 02'); + dc.logger.warnOnce('Message 03'); + dc.logger.warnOnce('Message 02'); + dc.logger.warnOnce('Message 03'); + + expect(dc.logger.warn.calls.count()).toBe(2); + expect(dc.logger.warn.calls.argsFor(0)).toEqual(['Message 02']); + expect(dc.logger.warn.calls.argsFor(1)).toEqual(['Message 03']); + }); + }); }); diff --git a/spec/number-display-spec.js b/spec/number-display-spec.js index 9044569636..3d2dbadbd2 100644 --- a/spec/number-display-spec.js +++ b/spec/number-display-spec.js @@ -1,194 +1,259 @@ /* global appendChartID, loadDateFixture */ -describe('dc.numberDisplay', function () { - var data, meanGroup; - var countryDimension; +describe('dc.numberDisplay', () => { + let data, meanGroup; + let countryDimension; + function average (d) { return d.n ? d.tot / d.n : 0; } - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - var groupAll = data.groupAll(); + const groupAll = data.groupAll(); meanGroup = groupAll.reduce( - function (p, v) { + (p, v) => { ++p.n; p.tot += +v.value; return p; }, - function (p, v) { + (p, v) => { --p.n; p.tot -= +v.value; return p; }, - function () { return {n: 0,tot: 0}; } + () => ({n: 0,tot: 0}) ); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + countryDimension = data.dimension(d => d.countrycode); countryDimension.filter('CA'); }); function buildChart (id) { - var chart = dc.numberDisplay(id) - .transitionDuration(0) - .group(meanGroup) - .formatNumber(d3.format('.3s')) - .valueAccessor(average); + const chart = new dc.NumberDisplay(id) + .transitionDuration(0) + .group(meanGroup) + .formatNumber(d3.format('.3s')) + .valueAccessor(average); chart.render(); - d3.timer.flush(); + d3.timerFlush(); return chart; } - describe('Empty Div', function () { - var chart; - beforeEach(function () { - var id = 'empty-div'; + describe('Empty Div', () => { + let chart; + beforeEach(() => { + const id = 'empty-div'; appendChartID(id); - chart = buildChart('#' + id); + chart = buildChart(`#${id}`); }); - it('should generate something', function () { + it('should generate something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('should return a value', function () { + it('should return a value', () => { expect(chart.value()).toEqual(38.5); }); - it('should have text value in child', function () { + it('should have text value in child', () => { expect(chart.select('span.number-display').text()).toEqual('38.5'); }); - describe('redraw', function () { - beforeEach(function () { + describe('redraw', () => { + beforeEach(() => { countryDimension.filterAll(); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should update value', function () { + it('should update value', () => { expect(chart.select('span.number-display').text()).toEqual('41.8'); }); }); - describe('html with one, some and none', function () { - beforeEach(function () { + describe('html with one, some and none', () => { + beforeEach(() => { chart.html({one: '%number number',none: 'no number',some: '%number numbers'}); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should use some for some', function () { + it('should use some for some', () => { expect(chart.select('span.number-display').text()).toEqual('38.5 numbers'); }); }); - describe('html with one, some and none', function () { - beforeEach(function () { + describe('html with one, some and none', () => { + beforeEach(() => { chart.html({one: '%number number',none: 'no number',some: '%number numbers'}); - chart.valueAccessor(function (d) {return 1;}); + chart.valueAccessor(d => 1); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should use one for one', function () { + it('should use one for one', () => { expect(chart.select('span.number-display').text()).toEqual('1.00 number'); }); }); - describe('html with one, some and none', function () { - beforeEach(function () { + describe('html with one, some and none', () => { + beforeEach(() => { chart.html({one: '%number number',none: 'no number',some: '%number numbers'}); - chart.valueAccessor(function (d) {return 0;}); + chart.valueAccessor(d => 0); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should use zero for zero', function () { + it('should use zero for zero', () => { expect(chart.select('span.number-display').text()).toEqual('no number'); }); }); - describe('html with just one', function () { - beforeEach(function () { + describe('html with just one', () => { + beforeEach(() => { chart.html({one: '%number number'}); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should use one for showing some', function () { + it('should use one for showing some', () => { expect(chart.select('span.number-display').text()).toEqual('38.5 number'); }); }); - describe('html with just some', function () { - beforeEach(function () { + describe('html with just some', () => { + beforeEach(() => { chart.html({some: '%number numbers'}); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should use some for showing one', function () { + it('should use some for showing one', () => { expect(chart.select('span.number-display').text()).toEqual('38.5 numbers'); }); }); - describe('html with just none', function () { - beforeEach(function () { + describe('html with just none', () => { + beforeEach(() => { chart.html({}); chart.redraw(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should just show the number in case of some and one', function () { + it('should just show the number in case of some and one', () => { expect(chart.select('span.number-display').text()).toEqual('38.5'); }); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('Div with embedded span', function () { - var chart; - beforeEach(function () { - var id = 'full-div'; - var div = appendChartID(id); + describe('Div with embedded span', () => { + let chart; + beforeEach(() => { + const id = 'full-div'; + const div = appendChartID(id); div.append('p').html('There are _ Total Widgets.'); - chart = buildChart('#' + id); + chart = buildChart(`#${id}`); }); - it('should have text value in child', function () { + it('should have text value in child', () => { expect(chart.root().text()).toEqual('There are 38.5 Total Widgets.'); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); }); }); - describe('Inline nonspan element' , function () { - beforeEach(function () { - var div = d3.select('body').append('div').attr('id','number-display-test-section'); + describe('Inline nonspan element' , () => { + beforeEach(() => { + const div = d3.select('body').append('div').attr('id', 'number-display-test-section'); div.append('p').html('There are Total Widgets.'); buildChart('#nonspan'); }); - it('should have text value in child', function () { + it('should have text value in child', () => { expect(d3.select('body').select('#number-display-test-section').html()) .toMatch(new RegExp('

There are ' + '38.5 Total Widgets.

')); }); - afterEach(function () { + afterEach(() => { countryDimension.filterAll(); d3.select('#number-display-test-section').remove(); }); }); - describe('Infinity', function () { - var chart; - beforeEach(function () { - var id = 'empty-div'; + describe('with group with multiple values', () => { + let group, chart; + beforeEach(() => { + countryDimension.filterAll(); + group = countryDimension.group().reduceSum(d => +d.value); + const id = 'empty-div'; + appendChartID(id); + chart = buildChart(`#${id}`); + chart + .group(group) + .valueAccessor(kv => kv.value) + .render(); + d3.timerFlush(); + }); + + it('should show the largest value', () => { + expect(chart.select('span.number-display').text()).toEqual('341'); + }); + + describe('with reversed ordering', () => { + beforeEach(() => { + chart.ordering(kv => -kv.value) + .render(); + d3.timerFlush(); + }); + it('should show the smallest value', () => { + expect(chart.select('span.number-display').text()).toEqual('77.0'); + }); + }); + + }); + describe('Infinity', () => { + let chart; + beforeEach(() => { + const id = 'empty-div'; appendChartID(id); - chart = buildChart('#' + id); - chart.valueAccessor(function (x) { return x; }) + chart = buildChart(`#${id}`); + chart.valueAccessor(x => x) .group({value: function () { return Infinity; }}) - .formatNumber(function (d) { return d; }) + .formatNumber(d => d) .render(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should display as Infinity', function () { + it('should display as Infinity', () => { expect(chart.root().text()).toEqual('Infinity'); }); - describe('returning to finite', function () { - beforeEach(function () { + describe('returning to finite', () => { + beforeEach(() => { chart.group({value: function () { return 17; }}) .render(); - d3.timer.flush(); + d3.timerFlush(); }); - it('should display finite', function () { + it('should display finite', () => { expect(chart.root().text()).toEqual('17'); }); }); }); + + describe('accessibility number display' , () => { + let chart; + beforeEach(() => { + + const id = 'empty-div'; + appendChartID(id); + + chart = new dc.NumberDisplay(`#${id}`) + .transitionDuration(0) + .group(meanGroup) + .formatNumber(d3.format('.3s')) + .valueAccessor(average); + }); + + it('should have aria-live', () => { + chart.ariaLiveRegion(true); + chart.render(); + d3.timerFlush(); + + expect(chart.select('span.number-display').attr('aria-live')).toEqual('polite'); + + }); + + it('should be focusable', () => { + chart.keyboardAccessible(true); + chart.render(); + d3.timerFlush(); + + expect(chart.select('span.number-display').attr('tabindex')).toEqual('0'); + + }); + + }); + }); diff --git a/spec/pie-chart-spec.js b/spec/pie-chart-spec.js index 2b5f93452d..2834c47089 100644 --- a/spec/pie-chart-spec.js +++ b/spec/pie-chart-spec.js @@ -1,60 +1,48 @@ /* global appendChartID, loadDateFixture, makeDate */ -describe('dc.pieChart', function () { - var width = 200; - var height = 200; - var radius = 100; - var defaultCenter = {x: width / 2, y: height / 2}; - var newCenter = {x: 101, y: 99}; - var innerRadius = 30; - var data, valueDimension, valueGroup; - var regionDimension, statusDimension; - var countryDimension, countryGroup, dateDimension; - var statusGroup, statusMultiGroup; - beforeEach(function () { +describe('dc.pieChart', () => { + const width = 200; + const height = 200; + const radius = 100; + const defaultCenter = {x: width / 2, y: height / 2}; + const newCenter = {x: 101, y: 99}; + const innerRadius = 30; + let data, valueDimension, valueGroup; + let regionDimension, statusDimension; + let countryDimension, countryGroup, dateDimension; + let statusGroup, statusMultiGroup; + beforeEach(() => { data = crossfilter(loadDateFixture()); - valueDimension = data.dimension(function (d) { - return d.value; - }); + valueDimension = data.dimension(d => d.value); valueGroup = valueDimension.group(); - regionDimension = data.dimension(function (d) { - return d.region; - }); - statusDimension = data.dimension(function (d) { - return d.status; - }); - countryDimension = data.dimension(function (d) { - return d.countrycode; - }); + regionDimension = data.dimension(d => d.region); + statusDimension = data.dimension(d => d.status); + countryDimension = data.dimension(d => d.countrycode); countryGroup = countryDimension.group(); - dateDimension = data.dimension(function (d) { - return d3.time.day.utc(d.dd); - }); + dateDimension = data.dimension(d => d3.utcDay(d.dd)); statusGroup = statusDimension.group(); statusMultiGroup = statusGroup.reduce( //add - function (p, v) { + (p, v) => { ++p.count; - p.value += +v.value; + p.total += +v.value; return p; }, //remove - function (p, v) { + (p, v) => { --p.count; - p.value -= +v.value; + p.total -= +v.value; return p; }, //init - function () { - return {count: 0, value: 0}; - } + () => ({count: 0, total: 0, getTotal: function () { return this.total; }}) ); }); function buildChart (id) { - var div = appendChartID(id); + const div = appendChartID(id); div.append('a').attr('class', 'reset').style('display', 'none'); div.append('span').attr('class', 'filter').style('display', 'none'); - var chart = dc.pieChart('#' + id); + const chart = new dc.PieChart(`#${id}`); chart.dimension(valueDimension).group(valueGroup) .width(width) .height(height) @@ -64,211 +52,228 @@ describe('dc.pieChart', function () { return chart; } - describe('generation', function () { - var chart; - beforeEach(function () { + function buildCountryChart (id) { + const div = appendChartID(id); + div.append('a').attr('class', 'reset').style('display', 'none'); + div.append('span').attr('class', 'filter').style('display', 'none'); + const chart = new dc.PieChart(`#${id}`); + chart.dimension(countryDimension).group(countryGroup) + .width(width) + .height(height) + .radius(radius) + .transitionDuration(0); + chart.render(); + return chart; + } + + describe('generation', () => { + let chart, + countryChart; + + beforeEach(() => { chart = buildChart('pie-chart-age'); chart.innerRadius(innerRadius); chart.render(); }); - it('we get something', function () { + it('we get something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('dc-chart class should be turned on for parent div', function () { + it('dc-chart class should be turned on for parent div', () => { expect(d3.select('#pie-chart-age').attr('class')).toEqual('dc-chart'); }); - it('inner radius can be set', function () { + it('inner radius can be set', () => { expect(chart.innerRadius()).toEqual(innerRadius); }); - it('svg should be created', function () { + it('svg should be created', () => { expect(chart.select('svg').empty()).toBeFalsy(); }); - it('default color scheme should be created', function () { + it('default color scheme should be created', () => { expect(chart.colors().length > 0).toBeTruthy(); }); - it('dimension should be set', function () { + it('dimension should be set', () => { expect(chart.dimension()).toBe(valueDimension); }); - it('group should be set', function () { + it('group should be set', () => { expect(chart.group()).toEqual(valueGroup); }); - it('width should be set', function () { + it('width should be set', () => { expect(chart.width()).toEqual(width); }); - it('height should be set', function () { + it('height should be set', () => { expect(chart.height()).toEqual(height); }); - it('radius should be set', function () { + it('radius should be set', () => { expect(chart.radius()).toEqual(radius); }); - it('cx should be set', function () { + it('cx should be set', () => { expect(chart.cx()).toEqual(defaultCenter.x); }); - it('cy should be set', function () { + it('cy should be set', () => { expect(chart.cy()).toEqual(defaultCenter.y); }); - it('height should be used for svg', function () { + it('height should be used for svg', () => { expect(chart.select('svg').attr('height')).toEqual(String(height)); }); - it('root g should be created', function () { + it('root g should be created', () => { expect(chart.select('svg g').empty()).toBeFalsy(); }); - it('root g should be translated to center', function () { + it('root g should be translated to center', () => { expect(chart.select('svg g').attr('transform')).toMatchTranslate(defaultCenter.x, defaultCenter.y); }); - it('slice g should be created with class', function () { + it('slice g should be created with class', () => { expect(chart.selectAll('svg g g.pie-slice').data().length).toEqual(5); }); - it('slice path should be created', function () { + it('slice path should be created', () => { expect(chart.selectAll('svg g g.pie-slice path').data().length).toEqual(5); }); - it('slice css class should be numbered with index', function () { + it('slice css class should be numbered with index', () => { chart.selectAll('g.pie-slice').each(function (p, i) { - expect(d3.select(this).attr('class')).toEqual('pie-slice _' + i); + expect(d3.select(this).attr('class')).toEqual(`pie-slice _${i}`); }); }); - it('slice path should be filled', function () { + it('slice path should be filled', () => { chart.selectAll('svg g g.pie-slice path').each(function (p) { expect(d3.select(this).attr('fill') !== '').toBeTruthy(); }); }); - it('slice path d should be created', function () { + it('slice path d should be created', () => { chart.selectAll('svg g g.pie-slice path').each(function (p) { expect(d3.select(this).attr('d') !== '').toBeTruthy(); }); }); - it('slice path fill should be set correctly', function () { - expect(d3.select(chart.selectAll('g.pie-slice path')[0][0]).attr('fill')).toEqual('#3182bd'); - expect(d3.select(chart.selectAll('g.pie-slice path')[0][1]).attr('fill')).toEqual('#6baed6'); - expect(d3.select(chart.selectAll('g.pie-slice path')[0][2]).attr('fill')).toEqual('#9ecae1'); - expect(d3.select(chart.selectAll('g.pie-slice path')[0][3]).attr('fill')).toEqual('#c6dbef'); + it('slice path fill should be set correctly', () => { + const numSlices = 5; + for (let i = 0; i < numSlices; i++) { + expect(d3.select(chart.selectAll('g.pie-slice path').nodes()[i]).attr('fill')) + .toMatchColor(dc.config.defaultColors()[i]); + } }); - it('slice label should be created', function () { + it('slice label should be created', () => { expect(chart.selectAll('svg text.pie-slice').data().length).toEqual(5); }); - it('slice label transform to centroid', function () { + it('slice label transform to centroid', () => { expect(chart.selectAll('svg g text.pie-slice').attr('transform')) - .toMatchTranslate(38.20604139901076, -52.58610463437158, 3); + .toMatchTranslate(52.58610463437159, -38.20604139901075, 3); }); - it('slice label text should be set', function () { - chart.selectAll('svg g text.pie-slice').call(function (p) { + it('slice label text should be set', () => { + chart.selectAll('svg g text.pie-slice').call(p => { expect(p.text()).toEqual(p.datum().data.key); }); }); - it('slice label should be middle anchored', function () { + it('slice label should be middle anchored', () => { chart.selectAll('svg g text.pie-slice').each(function (p) { expect(d3.select(this).attr('text-anchor')).toEqual('middle'); }); }); - it('reset link hidden after init rendering', function () { + it('reset link hidden after init rendering', () => { expect(chart.select('a.reset').style('display')).toEqual('none'); }); - it('filter printer should be set', function () { + it('filter printer should be set', () => { expect(chart.filterPrinter()).not.toBeNull(); }); - it('filter info should be hidden after init rendering', function () { + it('filter info should be hidden after init rendering', () => { expect(chart.select('span.filter').style('display')).toEqual('none'); }); - describe('center positioning', function () { - beforeEach(function () { + describe('center positioning', () => { + beforeEach(() => { chart .cx(newCenter.x) .cy(newCenter.y) .render(); return chart; }); - afterEach(function () { + afterEach(() => { chart .cx(defaultCenter.x) .cy(defaultCenter.y) .render(); return chart; }); - it('root g should be translated to ' + newCenter.x + ',' + newCenter.y, function () { + it(`root g should be translated to ${newCenter.x},${newCenter.y}`, () => { expect(chart.select('svg g').attr('transform')).toMatchTranslate(newCenter.x, newCenter.y); }); }); - describe('with radius padding', function () { - beforeEach(function () { + describe('with radius padding', () => { + beforeEach(() => { chart.externalRadiusPadding(17) .render(); return chart; }); - it('should not change center', function () { + it('should not change center', () => { expect(chart.select('svg g').attr('transform')).toMatchTranslate(defaultCenter.x, defaultCenter.y); }); - it('should decrease outer radius', function () { - expect(chart.select('svg g.pie-slice path').attr('d')).toContainPath('A83,83 0 0,1 78,-25'); + it('should decrease outer radius', () => { + expect(chart.select('svg g.pie-slice path').attr('d')).toMatch(/83[, ]83/); // i.e. 100-17 }); }); - describe('re-render', function () { - beforeEach(function () { + describe('re-render', () => { + beforeEach(() => { chart.render(); return chart; }); - it('multiple invocation of render should update chart', function () { - expect(d3.selectAll('#pie-chart-age svg')[0].length).toEqual(1); + it('multiple invocation of render should update chart', () => { + expect(d3.selectAll('#pie-chart-age svg').nodes().length).toEqual(1); }); }); - describe('filter', function () { - beforeEach(function () { + describe('filter', () => { + beforeEach(() => { regionDimension.filter('East'); chart.render(); }); - it('label should be hidden if filtered out', function () { - expect(chart.selectAll('svg g text.pie-slice')[0][0].textContent).toEqual('22'); - expect(chart.selectAll('svg g text.pie-slice')[0][1].textContent).toEqual(''); + it('label should be hidden if filtered out', () => { + expect(chart.selectAll('svg g text.pie-slice').nodes()[0].textContent).toEqual('22'); + expect(chart.selectAll('svg g text.pie-slice').nodes()[1].textContent).toEqual(''); }); - afterEach(function () { + afterEach(() => { regionDimension.filterAll(); }); }); - describe('n/a filter', function () { - beforeEach(function () { + describe('n/a filter', () => { + beforeEach(() => { statusDimension.filter('E'); chart.render(); return chart; }); - it('should draw an empty chart', function () { + it('should draw an empty chart', () => { expect(chart.select('g').classed('empty-chart')).toBeTruthy(); }); - it('should have one slice', function () { - expect(chart.selectAll('svg g text.pie-slice').length).toBe(1); + it('should have one slice', () => { + expect(chart.selectAll('svg g text.pie-slice').nodes().length).toBe(1); }); - afterEach(function () { + afterEach(() => { statusDimension.filterAll(); }); }); - describe('slice selection', function () { - it('on click function should be defined', function () { + describe('slice selection', () => { + it('on click function should be defined', () => { expect(chart.selectAll('svg g g.pie-slice path').on('click') !== undefined).toBeTruthy(); }); - it('by default no slice should be selected', function () { + it('by default no slice should be selected', () => { expect(chart.hasFilter()).toBeFalsy(); }); - it('be able to set selected slice', function () { + it('be able to set selected slice', () => { expect(chart.filter('66').filter()).toEqual('66'); expect(chart.hasFilter()).toBeTruthy(); chart.filterAll(); }); - it('should filter dimension by single selection', function () { + it('should filter dimension by single selection', () => { chart.filter('22'); expect(countryGroup.all()[0].value).toEqual(1); expect(countryGroup.all()[1].value).toEqual(1); chart.filterAll(); }); - it('should filter dimension by multiple selections', function () { + it('should filter dimension by multiple selections', () => { chart.filter('66'); chart.filter('22'); expect(countryGroup.all()[0].value).toEqual(1); expect(countryGroup.all()[1].value).toEqual(2); chart.filterAll(); }); - it('should filter dimension with deselection', function () { + it('should filter dimension with deselection', () => { chart.filter('22'); chart.filter('66'); chart.filter('22'); @@ -276,7 +281,7 @@ describe('dc.pieChart', function () { expect(countryGroup.all()[1].value).toEqual(1); chart.filterAll(); }); - it('should highlight selected slices', function () { + it('should highlight selected slices', () => { chart.filter('66'); chart.filter('22'); chart.render(); @@ -289,327 +294,430 @@ describe('dc.pieChart', function () { }); chart.filterAll(); }); - it('reset link shown after slice selection', function () { + it('reset link shown after slice selection', () => { chart.filter('66'); expect(chart.select('a.reset').style('display')).not.toEqual('none'); }); - it('filter info shown after slice selection', function () { + it('filter info shown after slice selection', () => { chart.filter(null); chart.filter('66'); expect(chart.select('span.filter').style('display')).not.toEqual('none'); expect(chart.select('span.filter').text()).toEqual('66'); }); - it('should remove highlight if no slice selected', function () { + it('should remove highlight if no slice selected', () => { chart.filterAll(); chart.redraw(); chart.selectAll('.pie-slice path').each(function (d) { - var cls = d3.select(this).attr('class'); + const cls = d3.select(this).attr('class'); expect(cls === null || cls === '').toBeTruthy(); }); }); }); - describe('filter through clicking', function () { - it('onClick should trigger filtering of according group', function () { + describe('filter through clicking', () => { + it('onClick should trigger filtering of according group', () => { chart.onClick(chart.group().all()[0]); expect(chart.filter()).toEqual('22'); }); - it('onClick should reset filter if clicked twice', function () { + it('onClick should reset filter if clicked twice', () => { chart.onClick(chart.group().all()[0]); chart.onClick(chart.group().all()[0]); expect(chart.filter()).toEqual(null); }); - it('multiple onClick should trigger filtering of according groups', function () { + it('multiple onClick should trigger filtering of according groups', () => { chart.onClick(chart.group().all()[0]); chart.onClick(chart.group().all()[1]); expect(chart.hasFilter('22')).toBeTruthy(); expect(chart.hasFilter('33')).toBeTruthy(); }); }); - describe('group order', function () { - beforeEach(function () { - chart.cap(4).ordering(dc.pluck('value')); + describe('group order with capping', () => { + beforeEach(() => { + chart.cap(4); }); - it('group should be orderd', function () { - expect(['33','55','22','44','Others']).toEqual(chart.data().map(dc.pluck('key'))); - chart.ordering(dc.pluck('key')); - expect(['22','33','44','55','Others']).toEqual(chart.data().map(dc.pluck('key'))); + // group.all starts with 22 -> 2, 33 -> 2, 44 -> 3, 55 -> 2, 66 -> 1 + describe('with usual top->bottom sorting and cap', () => { + beforeEach(() => { + chart.cap(4).ordering(kv => -kv.value).redraw(); + }); + it('should show top 4 groups and others', () => { + // crossfilter's quicksort is stable for < 32 elements, so the value:2's are still in alphabetical order + expect(['44', '22', '33', '55', 'Others']).toEqual(chart.data().map(dc.pluck('key'))); + }); }); - afterEach(function () { - chart.cap(Infinity).ordering(dc.pluck('key')); + describe('with key ordering', () => { + beforeEach(() => { + chart + .ordering(dc.pluck('key')) + .redraw(); + }); + it('should show lowest 4 groups by key and others', () => { + expect(['22', '33', '44', '55', 'Others']).toEqual(chart.data().map(dc.pluck('key'))); + }); + }); + }); + describe('comparing crossfilter and chart ordering', () => { + let crossfilterOrder, + crossfilterTop2; + beforeEach(() => { + countryChart = buildCountryChart('country-chart'); + countryChart.innerRadius(innerRadius); + + // group.all returns array sorted in ascending key order. + // [{"key":"CA","value":2},{"key":"US","value":8}] + crossfilterOrder = countryGroup.all(); + + // group.top returns array sorted in descending value order + // [{"key":"US","value":8}] + crossfilterTop2 = countryGroup.top(2); + }); + describe('with ordering and capping not set', () => { + it('should match the crossfilter top 2', () => { + expect(countryChart.data()).toEqual(crossfilterTop2); + }); + }); + describe('with ordering by key', () => { + beforeEach(() => { + countryChart.ordering(kv => kv.key).redraw(); + }); + it('should should match crossfilter top(2)', () => { + expect(countryChart.data()).toEqual(crossfilterOrder); + }); + describe('with cap(1)', () => { + beforeEach(() => { + countryChart.cap(1).redraw(); + }); + it('should show the top value, and others', () => { + expect(countryChart.data().map(dc.pluck('key'))).toEqual(['CA', 'Others']); + }); + }); + + }); + describe('with default ordering and cap(1)', () => { + beforeEach(() => { + countryChart.cap(1).redraw(); + }); + it('should show the largest value\'s key, and others', () => { + expect(['US', 'Others']).toEqual(countryChart.data().map(dc.pluck('key'))); + }); + describe('and takeFront(false)', () => { + beforeEach(() => { + countryChart.takeFront(false).redraw(); + }); + it('should show the smallest value\'s key, and others', () => { + expect(['CA','Others']).toEqual(countryChart.data().map(dc.pluck('key'))); + }); + }); }); }); }); - describe('redraw after empty selection', function () { - var chart; - beforeEach(function () { + describe('redraw after empty selection', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart2'); dateDimension.filter([makeDate(2010, 0, 1), makeDate(2010, 0, 3)]); chart.redraw(); dateDimension.filter([makeDate(2012, 0, 1), makeDate(2012, 11, 30)]); chart.redraw(); }); - it('pie chart should be restored', function () { + it('pie chart should be restored', () => { chart.selectAll('g.pie-slice path').each(function (p) { expect(d3.select(this).attr('d').indexOf('NaN') < 0).toBeTruthy(); }); }); - afterEach(function () { + afterEach(() => { dateDimension.filterAll(); }); }); - describe('small slices', function () { - var chart; - beforeEach(function () { + describe('small slices', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart3'); chart.minAngleForLabel(1) .renderTitle(true); chart.render(); }); - it('label should not be generated if the slice is too small', function () { + it('label should not be generated if the slice is too small', () => { // slice '66' - expect(d3.select(chart.selectAll('text.pie-slice')[0][4]).text()).toEqual(''); + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[4]).text()).toEqual(''); }); - describe('selected', function () { - beforeEach(function () { + describe('selected', () => { + beforeEach(() => { chart.filter('66').redraw(); }); - it('a small slice should be labelled if it is selected', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][4]).text()).toEqual('66'); + it('a small slice should be labelled if it is selected', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[4]).text()).toEqual('66'); }); - afterEach(function () { + afterEach(() => { chart.filter(null); }); }); }); - describe('custom label & title generation', function () { - var chart; - beforeEach(function () { + describe('custom label & title generation', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart3'); - chart.label(function (d) { - return 'custom'; - }) - .title(function (d) { - return 'custom'; - }) + chart.label(d => 'custom') + .title(d => 'custom') .minAngleForLabel(1) .renderTitle(true); chart.render(); }); - it('should render correct number of text', function () { - expect(chart.selectAll('text.pie-slice')[0].length).toEqual(5); + it('should render correct number of text', () => { + expect(chart.selectAll('text.pie-slice').nodes().length).toEqual(5); }); - it('custom function should be used to dynamically generate label', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][0]).text()).toEqual('custom'); + it('custom function should be used to dynamically generate label', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[0]).text()).toEqual('custom'); }); - it('label should not be generated if the slice is too small', function () { + it('label should not be generated if the slice is too small', () => { // slice '66' - expect(d3.select(chart.selectAll('text.pie-slice')[0][4]).text()).toEqual(''); + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[4]).text()).toEqual(''); }); - it('should render correct number of title', function () { - expect(chart.selectAll('g.pie-slice title')[0].length).toEqual(5); + it('should render correct number of title', () => { + expect(chart.selectAll('g.pie-slice title').nodes().length).toEqual(5); }); - it('custom function should be used to dynamically generate title', function () { + it('custom function should be used to dynamically generate title', () => { chart.selectAll('g.pie-slice title').each(function (p) { expect(d3.select(this).text()).toEqual('custom'); }); }); }); - describe('pie chart slices cap and group switching', function () { - var chart; - beforeEach(function () { + describe('pie chart slices cap and group switching', () => { + // again, group.all starts with 22 -> 2, 33 -> 2, 44 -> 3, 55 -> 2, 66 -> 1 + let chart; + beforeEach(() => { chart = buildChart('pie-chart4'); chart.slicesCap(2) .renderTitle(true) .othersLabel('small'); chart.render(); }); - describe('with normal valueAccessor', function () { - beforeEach(function () { + describe('with normal valueAccessor and descending value ordering', () => { + beforeEach(() => { chart.dimension(valueDimension).group(valueGroup) .valueAccessor(dc.pluck('value')) + .ordering(kv => -kv.value) .render(); }); - it('produce expected number of slices', function () { - expect(chart.selectAll('text.pie-slice')[0].length).toEqual(3); + it('produce expected number of slices', () => { + expect(chart.selectAll('text.pie-slice').nodes().length).toEqual(3); }); - it('others slice should use custom name', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][2]).text()).toEqual('small'); + it('others slice should use custom name', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[2]).text()).toEqual('small'); }); - it('remaining slices should be in numerical order', function () { + it('remaining slices should be in descending value order', () => { expect(chart.selectAll('text.pie-slice').data().map(dc.pluck('value'))) - .toEqual([2,3,5]); + .toEqual([3,2,5]); + }); + describe('clicking others slice', () => { + let event; + beforeEach(() => { + event = document.createEvent('MouseEvents'); + event.initEvent('click', true, true); + chart.selectAll('.pie-slice path').nodes()[2].dispatchEvent(event); + }); + it('should filter three smallest', () => { + expect(chart.filters()).toEqual(['33', '55', '66','small']); + }); + describe('clicking again', () => { + beforeEach(() => { + chart.selectAll('.pie-slice path').nodes()[2].dispatchEvent(event); + }); + it('should reset filter', () => { + expect(chart.filters()).toEqual([]); + }); + }); + }); + }); + describe('with custom valueAccessor', () => { + // statusMultiGroup has + // [{"key":"F","value":{"count":5,"total":220}},{"key":"T","value":{"count":5,"total":198}}] + beforeEach(() => { + chart.dimension(statusDimension).group(statusMultiGroup) + .valueAccessor(d => d.value.total) + .ordering(d => -d.value.total) + .render(); + return chart; }); - it('clicking others slice should filter all groups slices', function () { - var event = document.createEvent('MouseEvents'); - event.initEvent('click',true,true); - chart.selectAll('.pie-slice path')[0][2].dispatchEvent(event); - expect(chart.filters()).toEqual(['22','55','66','small']); - chart.selectAll('.pie-slice path')[0][2].dispatchEvent(event); - expect(chart.filters()).toEqual([]); + it('correct values, no others slice', () => { + expect(chart.selectAll('g.pie-slice').data().map(dc.pluck('value'))) + .toEqual([220, 198]); + }); + describe('with cap(1)', () => { + beforeEach(() => { + chart.cap(1).render(); + }); + it('correct values, others slice', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'small: 198']); + }); }); }); - describe('with custom valueAccessor', function () { - beforeEach(function () { + describe('with custom valueAccessor calling function', () => { + // statusMultiGroup has + // [{"key":"F","value":{"count":5,"total":220}},{"key":"T","value":{"count":5,"total":198}}] + beforeEach(() => { chart.dimension(statusDimension).group(statusMultiGroup) - .valueAccessor(function (d) {return d.value.value;}) + .valueAccessor(d => d.value.getTotal()) + .ordering(d => -d.value.getTotal()) .render(); return chart; }); - it('correct values, no others row', function () { + it('correct values, no others slice', () => { expect(chart.selectAll('g.pie-slice').data().map(dc.pluck('value'))) .toEqual([220, 198]); }); - it('correct values, others row', function () { - chart.cap(1).render(); - expect(chart.selectAll('title')[0].map(function (t) {return d3.select(t).text();})) - .toEqual(['F: 220', 'small: 198']); - chart.cap(3); //teardown + describe('with cap(1)', () => { + beforeEach(() => { + chart.cap(1).render(); + }); + it('correct values, others slice', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'small: 198']); + }); }); }); - afterEach(function () { + afterEach(() => { valueDimension.filterAll(); }); }); - describe('pie chart wo/ label', function () { - var chart; - beforeEach(function () { + describe('pie chart w/o label', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart4'); chart.innerRadius(innerRadius); chart.renderLabel(false); chart.render(); }); - it('slice label should not be created', function () { + it('slice label should not be created', () => { expect(chart.selectAll('svg g text.pie-slice').data().length).toEqual(0); }); }); - describe('renderlet', function () { - var chart; - beforeEach(function () { + describe('renderlet', () => { + let chart; + beforeEach(() => { chart = buildChart('chart-renderlet'); - chart.on('renderlet', function () { + chart.on('renderlet', () => { chart.selectAll('path').attr('fill', 'red'); }); }); - it('custom renderlet should be invoked with render', function () { + it('custom renderlet should be invoked with render', () => { chart.render(); expect(chart.selectAll('path').attr('fill')).toEqual('red'); }); - it('custom renderlet should be invoked with redraw', function () { + it('custom renderlet should be invoked with redraw', () => { chart.redraw(); expect(chart.selectAll('path').attr('fill')).toEqual('red'); }); }); - describe('pie chart label and title w/ value accessor', function () { - var chart; - beforeEach(function () { + describe('pie chart label and title w/ value accessor', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart-default-label-title'); chart.dimension(statusGroup) .group(statusMultiGroup) - .valueAccessor(function (d) { - return d.value.count; - }) + .valueAccessor(d => d.value.count) .renderLabel(true).renderTitle(true); chart.render(); return chart; }); - it('default function should be used to dynamically generate label', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][0]).text()).toEqual('F'); + it('default function should be used to dynamically generate label', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[0]).text()).toEqual('F'); }); - it('default function should be used to dynamically generate title', function () { - expect(d3.select(chart.selectAll('g.pie-slice title')[0][0]).text()).toEqual('F: 5'); + it('default function should be used to dynamically generate title', () => { + expect(d3.select(chart.selectAll('g.pie-slice title').nodes()[0]).text()).toEqual('F: 5'); }); - describe('with n/a filter', function () { - beforeEach(function () { + describe('with n/a filter', () => { + beforeEach(() => { regionDimension.filter('nowhere'); chart.render(); return chart; }); - it('should draw an empty chart', function () { + it('should draw an empty chart', () => { expect(chart.select('g').classed('empty-chart')).toBeTruthy(); }); - it('should have one slice', function () { - expect(chart.selectAll('svg g text.pie-slice').length).toBe(1); + it('should have one slice', () => { + expect(chart.selectAll('svg g text.pie-slice').nodes().length).toBe(1); }); - it('should have slice labeled empty', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][0]).text()).toEqual('empty'); + it('should have slice labeled empty', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[0]).text()).toEqual('empty'); }); - describe('with emptyTitle', function () { - beforeEach(function () { + describe('with emptyTitle', () => { + beforeEach(() => { chart.emptyTitle('nothing').render(); }); - it('should respect the emptyTitle', function () { - expect(d3.select(chart.selectAll('text.pie-slice')[0][0]).text()).toEqual('nothing'); + it('should respect the emptyTitle', () => { + expect(d3.select(chart.selectAll('text.pie-slice').nodes()[0]).text()).toEqual('nothing'); }); - afterEach(function () { + afterEach(() => { chart.emptyTitle('empty'); }); }); - afterEach(function () { + afterEach(() => { regionDimension.filterAll(); }); }); }); - describe('custom filter handler', function () { - var chart; - beforeEach(function () { + describe('custom filter handler', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart-filter-handler'); - chart.filterHandler(function (dimension, filters) { + chart.filterHandler((dimension, filters) => { dimension.filter('66'); return ['66']; }); return chart; }); - it('default function should be used to dynamically generate label', function () { + it('default function should be used to dynamically generate label', () => { chart.filter(6); expect(chart.filter()).toEqual('66'); }); - afterEach(function () { + afterEach(() => { valueDimension.filterAll(); }); }); - describe('external labeling', function () { - var chart; - beforeEach(function () { + describe('external labeling', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart-external-labeling') .externalLabels(10) .drawPaths(true) .render(); }); - it('should place labels outside of pie offset by given radius', function () { - var label = d3.select('#pie-chart-external-labeling svg g text.pie-slice'); + it('should place labels outside of pie offset by given radius', () => { + const label = d3.select('#pie-chart-external-labeling svg g text.pie-slice'); - var centroid = d3.svg.arc() + const centroid = d3.arc() .outerRadius(chart.radius() + 10) .innerRadius(chart.radius() + 10) .centroid(label.datum()); expect(label.attr('transform')).toMatchTranslate(centroid[0], centroid[1], 3); }); - it('gives labels class "external"', function () { + it('gives labels class "external"', () => { d3.selectAll('#pie-chart-external-labeling svg g text.pie-slice').each(function () { expect(d3.select(this).classed('external')).toBeTruthy(); }); }); - it('returns radius when given no arguments', function () { + it('returns radius when given no arguments', () => { expect(chart.externalLabels()).toEqual(10); }); - it('resets to default when given falsey argument', function () { + it('resets to default when given falsey argument', () => { chart.externalLabels(false).render(); d3.selectAll('#pie-chart-external-labeling svg g text.pie-slice').each(function () { - var label = d3.select(this); + const label = d3.select(this); - var centroid = d3.svg.arc() + const centroid = d3.arc() .outerRadius(chart.radius()) .innerRadius(chart.innerRadius()) .centroid(label.datum()); @@ -618,98 +726,136 @@ describe('dc.pieChart', function () { expect(label.classed('external')).toBeFalsy(); }); }); - it('hovering on label should highlight corresponding slice', function () { + it('hovering on label should highlight corresponding slice', () => { chart.selectAll('#pie-chart-external-labeling text.pie-slice').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum(), i); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum(), i); - expect(chart.select('g.pie-slice._' + i).classed('highlight')).toBeTruthy(); - legendItem.on('mouseout')(legendItem.datum()); + expect(chart.select(`g.pie-slice._${i}`).classed('highlight')).toBeTruthy(); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum()); }); }); - it('unhovering label removes highlight from corresponding slice', function () { + it('unhovering label removes highlight from corresponding slice', () => { chart.selectAll('#pie-chart-external-labeling text.pie-slice').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum(), i); - legendItem.on('mouseout')(legendItem.datum(), i); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum(), i); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum(), i); - expect(chart.select('.pie-slice._' + i).classed('highlight')).toBeFalsy(); + expect(chart.select(`.pie-slice._${i}`).classed('highlight')).toBeFalsy(); }); }); - it('hovering on path should highlight corresponding slice', function () { + it('hovering on path should highlight corresponding slice', () => { chart.selectAll('#pie-chart-external-labeling polyline.pie-path').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum(), i); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum(), i); - expect(chart.select('g.pie-slice._' + i).classed('highlight')).toBeTruthy(); - legendItem.on('mouseout')(legendItem.datum()); + expect(chart.select(`g.pie-slice._${i}`).classed('highlight')).toBeTruthy(); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum()); }); }); - it('unhovering label removes highlight from corresponding slice', function () { + it('unhovering label removes highlight from corresponding slice', () => { chart.selectAll('#pie-chart-external-labeling polyline.pie-path').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum(), i); - legendItem.on('mouseout')(legendItem.datum(), i); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum(), i); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum(), i); - expect(chart.select('.pie-slice._' + i).classed('highlight')).toBeFalsy(); + expect(chart.select(`.pie-slice._${i}`).classed('highlight')).toBeFalsy(); }); }); }); - describe('legends', function () { - var chart; - beforeEach(function () { + describe('legends', () => { + let chart; + beforeEach(() => { chart = buildChart('pie-chart-legend') .cap(3) - .legend(dc.legend()) + .legend(new dc.Legend()) .render(); }); - it('should generate items for each slice', function () { + it('should generate items for each slice', () => { expect(chart.selectAll('g.dc-legend g.dc-legend-item').size()).toEqual(chart.data().length); }); - it('should include "others" item', function () { - var numOthersGroups = chart.selectAll('g.dc-legend g.dc-legend-item text').filter(function (d, i) { - return d.name === 'Others'; - }).size(); + it('should include "others" item', () => { + const numOthersGroups = chart.selectAll('g.dc-legend g.dc-legend-item text').filter((d, i) => d.name === 'Others').size(); expect(numOthersGroups).toEqual(1); }); - it('items should be colored', function () { + it('items should be colored', () => { chart.selectAll('g.dc-legend g.dc-legend-item').each(function () { expect(d3.select(this).select('rect').attr('fill')).not.toEqual(undefined); }); }); - it('hovering on items should highlight corresponding slice', function () { + it('hovering on items should highlight corresponding slice', () => { chart.selectAll('g.dc-legend g.dc-legend-item').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum()); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum()); - expect(chart.select('g.pie-slice._' + i).classed('highlight')).toBeTruthy(); - legendItem.on('mouseout')(legendItem.datum()); + expect(chart.select(`g.pie-slice._${i}`).classed('highlight')).toBeTruthy(); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum()); }); }); - it('unhovering removes highlight from corresponding slice', function () { + it('unhovering removes highlight from corresponding slice', () => { chart.selectAll('g.dc-legend g.dc-legend-item').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('mouseover')(legendItem.datum()); - legendItem.on('mouseout')(legendItem.datum()); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('mouseover'), null, {}, legendItem.datum()); + dc.d3compat.callHandler(legendItem.on('mouseout'), null, {}, legendItem.datum()); - expect(chart.select('g.pie-slice._' + i).classed('highlight')).toBeFalsy(); + expect(chart.select(`g.pie-slice._${i}`).classed('highlight')).toBeFalsy(); }); }); - it('clicking on items filters them', function () { + it('clicking on items filters them', () => { chart.selectAll('g.dc-legend g.dc-legend-item').each(function (d, i) { - var legendItem = d3.select(this); - legendItem.on('click')(legendItem.datum()); + const legendItem = d3.select(this); + dc.d3compat.callHandler(legendItem.on('click'), null, {}, legendItem.datum()); expect(chart.hasFilter(d.name)).toBeTruthy(); }); }); - afterEach(function () { + afterEach(() => { valueDimension.filterAll(); }); }); + + describe('accessibility pie chart', () => { + + let chart; + beforeEach(() => { + chart = buildChart('pie-chart-legend'); + chart.keyboardAccessible(true); + + }); + + it('internal elements are focusable by keyboard', () => { + + chart.render(); + chart.selectAll('g.pie-slice').each(function () { + const pie = d3.select(this); + expect(pie.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + const clickHandlerSpy = jasmine.createSpy(); + chart._onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('g.pie-slice').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + }); + + + + + }); diff --git a/spec/row-chart-spec.js b/spec/row-chart-spec.js index 38b625d1b4..7ee41adc5e 100644 --- a/spec/row-chart-spec.js +++ b/spec/row-chart-spec.js @@ -1,201 +1,306 @@ /* global appendChartID, loadDateFixture, makeDate */ -describe('dc.rowChart', function () { - var id, chart; - var data, dimension, nvdimension; - var positiveGroupHolder = {groupType: 'positive signed'}; - var negativeGroupHolder = {groupType: 'negative signed'}; - var mixedGroupHolder = {groupType: 'mixed signed'}; - var largerGroupHolder = {groupType: 'larger'}; - - beforeEach(function () { +describe('dc.rowChart', () => { + let id, chart; + let data, dimension, nvdimension; + const positiveGroupHolder = {groupType: 'positive signed'}; + const negativeGroupHolder = {groupType: 'negative signed'}; + const mixedGroupHolder = {groupType: 'mixed signed'}; + const largerGroupHolder = {groupType: 'larger'}; + let statusDimension, statusMultiGroup; + + beforeEach(() => { data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { return +d.value; }); + dimension = data.dimension(d => +d.value); - positiveGroupHolder.group = dimension.group().reduceSum(function (d) {return Math.abs(+d.nvalue);}); + positiveGroupHolder.group = dimension.group().reduceSum(d => Math.abs(+d.nvalue)); positiveGroupHolder.dimension = dimension; - negativeGroupHolder.group = dimension.group().reduceSum(function (d) {return -Math.abs(+d.nvalue);}); + negativeGroupHolder.group = dimension.group().reduceSum(d => -Math.abs(+d.nvalue)); negativeGroupHolder.dimension = dimension; - mixedGroupHolder.group = dimension.group().reduceSum(function (d) {return +d.nvalue;}); + mixedGroupHolder.group = dimension.group().reduceSum(d => +d.nvalue); mixedGroupHolder.dimension = dimension; - nvdimension = data.dimension(function (d) { return +d.nvalue; }); - largerGroupHolder.group = nvdimension.group().reduceSum(function (d) {return +d.value;}); + nvdimension = data.dimension(d => +d.nvalue); + largerGroupHolder.group = nvdimension.group().reduceSum(d => +d.value); largerGroupHolder.dimension = nvdimension; + statusDimension = data.dimension(d => d.status); + statusMultiGroup = statusDimension.group().reduce( + //add + (p, v) => { + ++p.count; + p.total += +v.value; + return p; + }, + //remove + (p, v) => { + --p.count; + p.total -= +v.value; + return p; + }, + //init + () => ({count: 0, total: 0, getTotal: function () { return this.total; }}) + ); + id = 'row-chart'; appendChartID(id); - chart = dc.rowChart('#' + id); + chart = new dc.RowChart(`#${id}`); chart.dimension(dimension) .width(600).height(200).gap(10) .transitionDuration(0); }); - describe('enabling the chart title and label with a value accessor', function () { - beforeEach(function () { + describe('enabling the chart title and label with a value accessor', () => { + beforeEach(() => { chart.group(mixedGroupHolder.group); - chart.valueAccessor(function (d) { - return d.value + 100; - }).renderLabel(true).renderTitle(true).render(); + chart.valueAccessor(d => d.value + 100).renderLabel(true).renderTitle(true).render(); }); - it('should use the default function to dynamically generate the label', function () { + it('should use the default function to dynamically generate the label', () => { expect(chart.select('text.row').text()).toBe('22'); }); - it('should use the default function to dynamically generate the title', function () { + it('should use the default function to dynamically generate the title', () => { expect(chart.select('g.row title').text()).toBe('22: 108'); }); }); - describe('with a logarithmic X axis and positive data', function () { - beforeEach(function () { + describe('with a logarithmic X axis and positive data', () => { + beforeEach(() => { chart.group(positiveGroupHolder.group); chart.elasticX(false); - chart.x(d3.scale.log()); + chart.x(d3.scaleLog()); chart.render(); }); - it('should render valid rect widths', function () { + it('should render valid rect widths', () => { expect(chart.select('g.row rect').attr('width')).toBeWithinDelta(1, 0.5); }); }); - describe('with a fixedBarHeight', function () { - beforeEach(function () { + describe('with a fixedBarHeight', () => { + beforeEach(() => { chart.group(positiveGroupHolder.group); chart.elasticX(false); - chart.x(d3.scale.log()); + chart.x(d3.scaleLog()); chart.fixedBarHeight(10); chart.render(); }); - it('should render fixed rect height', function () { + it('should render fixed rect height', () => { expect(chart.select('g.row rect').attr('height')).toBeWithinDelta(10, 0.0); }); }); - describe('with renderTitleLabel', function () { - beforeEach(function () { + describe('with renderTitleLabel', () => { + beforeEach(() => { chart.group(positiveGroupHolder.group); - chart.x(d3.scale.linear()); - chart.title(function () { - return 'test title'; - }); + chart.x(d3.scaleLinear()); + chart.title(() => 'test title'); chart.renderTitleLabel(true); chart.render(); }); - it('should render title label centered', function () { + it('should render title label centered', () => { expect(chart.select('g.row .titlerow').attr('dy')).toBeDefined(); }); }); + describe('row chart cap', () => { + beforeEach(() => { + chart.dimension(statusDimension) + .group(statusMultiGroup) + .othersLabel('small'); + return chart; + }); + describe('with custom valueAccessor', () => { + // statusMultiGroup has + // [{"key":"F","value":{"count":5,"total":220}},{"key":"T","value":{"count":5,"total":198}}] + beforeEach(() => { + chart.dimension(statusDimension).group(statusMultiGroup) + .valueAccessor(d => d.value.total) + .ordering(d => -d.value.total) + .render(); + return chart; + }); + it('correct values, no others row', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'T: 198']); + }); + describe('with cap(1)', () => { + beforeEach(() => { + chart.cap(1).render(); + }); + it('correct values, others row', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'small: 198']); + }); + }); + }); + describe('with custom valueAccessor calling function', () => { + // statusMultiGroup has + // [{"key":"F","value":{"count":5,"total":220}},{"key":"T","value":{"count":5,"total":198}}] + beforeEach(() => { + chart.dimension(statusDimension).group(statusMultiGroup) + .valueAccessor(d => d.value.getTotal()) + .ordering(d => -d.value.getTotal()) + .render(); + return chart; + }); + it('correct values, no others row', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'T: 198']); + }); + describe('with cap(1)', () => { + beforeEach(() => { + chart.cap(1).render(); + }); + it('correct values, others row', () => { + expect(chart.selectAll('title').nodes().map(t => d3.select(t).text())) + .toEqual(['F: 220', 'small: 198']); + }); + }); + }); + }); + + describe('accessibility row chart', () => { + + beforeEach(() => { + chart.group(positiveGroupHolder.group); + chart.x(d3.scaleLinear()); + chart.keyboardAccessible(true); + }); + + it('internal elements are focusable by keyboard', () => { + + chart.render(); + chart.selectAll('rect').each(function () { + const row = d3.select(this); + expect(row.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + const clickHandlerSpy = jasmine.createSpy(); + chart._onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('rect').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + }); + function itShouldBehaveLikeARowChartWithGroup (groupHolder, N, xAxisTicks) { - describe('for ' + groupHolder.groupType + ' data', function () { - beforeEach(function () { + describe(`for ${groupHolder.groupType} data`, () => { + beforeEach(() => { chart.group(groupHolder.group); }); - describe('rendering the row chart', function () { - beforeEach(function () { + describe('rendering the row chart', () => { + beforeEach(() => { chart.render(); }); - it('should create a root svg node', function () { + it('should create a root svg node', () => { expect(chart.select('svg').size()).toBe(1); }); - it('should create a row group for each datum', function () { + it('should create a row group for each datum', () => { expect(chart.selectAll('svg g g.row').size()).toBe(N); }); - it('should number each row sequentially with classes', function () { + it('should number each row sequentially with classes', () => { chart.selectAll('svg g g.row').each(function (r, i) { - expect(d3.select(this).attr('class')).toBe('row _' + i); + expect(d3.select(this).attr('class')).toBe(`row _${i}`); }); }); - it('should fill each row rect with pre-defined colors', function () { - expect(d3.select(chart.selectAll('g.row rect')[0][0]).attr('fill')).toBe('#3182bd'); - expect(d3.select(chart.selectAll('g.row rect')[0][1]).attr('fill')).toBe('#6baed6'); - expect(d3.select(chart.selectAll('g.row rect')[0][2]).attr('fill')).toBe('#9ecae1'); - expect(d3.select(chart.selectAll('g.row rect')[0][3]).attr('fill')).toBe('#c6dbef'); - expect(d3.select(chart.selectAll('g.row rect')[0][4]).attr('fill')).toBe('#e6550d'); + it('should fill each row rect with pre-defined colors', () => { + for (let i = 0; i < N; i++) { + expect(d3.select(chart.selectAll('g.row rect').nodes()[i]).attr('fill')) + .toMatchColor(dc.config.defaultColors()[i]); + } }); - it('should create a row label from the data for each row', function () { + it('should create a row label from the data for each row', () => { expect(chart.selectAll('svg text.row').size()).toBe(N); - chart.selectAll('svg g text.row').call(function (t) { + chart.selectAll('svg g text.row').call(t => { expect(+t.text()).toBe(t.datum().key); }); }); - describe('row label vertical position', function () { - var labels, rows; - beforeEach(function () { + describe('row label vertical position', () => { + let labels, rows; + beforeEach(() => { labels = chart.selectAll('svg text.row'); rows = chart.selectAll('g.row rect'); }); function itShouldVerticallyCenterLabelWithinRow (i) { - it('should place label ' + i + ' within row ' + i, function () { - var rowpos = rows[0][i].getBoundingClientRect(), - textpos = labels[0][i].getBoundingClientRect(); + it(`should place label ${i} within row ${i}`, () => { + const rowpos = rows.nodes()[i].getBoundingClientRect(), + textpos = labels.nodes()[i].getBoundingClientRect(); expect((textpos.top + textpos.bottom) / 2) .toBeWithinDelta((rowpos.top + rowpos.bottom) / 2, 2); }); } - for (var i = 0; i < N ; ++i) { + for (let i = 0; i < N ; ++i) { itShouldVerticallyCenterLabelWithinRow(i); } }); - describe('re-rendering the chart', function () { - beforeEach(function () { + describe('re-rendering the chart', () => { + beforeEach(() => { chart.render(); }); - it('should leave a single instance of the chart', function () { + it('should leave a single instance of the chart', () => { expect(d3.selectAll('#row-chart svg').size()).toBe(1); }); }); }); - describe('chart filters', function () { - beforeEach(function () { + describe('chart filters', () => { + beforeEach(() => { chart.render(); - d3.select('#' + id).append('span').classed('filter', true); + d3.select(`#${id}`).append('span').classed('filter', true); }); - it('should not have filter by default', function () { + it('should not have filter by default', () => { expect(chart.hasFilter()).toBeFalsy(); }); - it('should not modify the underlying crossfilter group', function () { - var oldGroupData = chart.group().all().slice(0); + it('should not modify the underlying crossfilter group', () => { + const oldGroupData = chart.group().all().slice(0); chart.ordering(dc.pluck('value')); chart.filter('66').render(); expect(chart.group().all().length).toBe(oldGroupData.length); - for (var i = 0; i < oldGroupData.length; i++) { + for (let i = 0; i < oldGroupData.length; i++) { expect(chart.group().all()[i]).toBe(oldGroupData[i]); } }); - describe('filtering a row', function () { - beforeEach(function () { + describe('filtering a row', () => { + beforeEach(() => { chart.filter('66'); chart.render(); }); - it('should apply a filter to the chart', function () { + it('should apply a filter to the chart', () => { expect(chart.filter()).toBe('66'); expect(chart.hasFilter()).toBeTruthy(); }); - it('should highlight any selected rows', function () { + it('should highlight any selected rows', () => { chart.filter('22'); chart.render(); chart.selectAll('g.row rect').each(function (d) { @@ -209,18 +314,18 @@ describe('dc.rowChart', function () { }); }); - it('should generate filter info in a filter-classed element', function () { + it('should generate filter info in a filter-classed element', () => { expect(chart.select('span.filter').style('display')).not.toBe('none'); expect(chart.select('span.filter').text()).toBe('66'); }); - describe('removing filters', function () { - beforeEach(function () { + describe('removing filters', () => { + beforeEach(() => { chart.filterAll(); chart.render(); }); - it('should remove highlighting', function () { + it('should remove highlighting', () => { chart.selectAll('g.row rect').each(function (d) { expect(d3.select(this).classed('deselected')).toBeFalsy(); expect(d3.select(this).classed('selected')).toBeFalsy(); @@ -230,58 +335,58 @@ describe('dc.rowChart', function () { }); }); - describe('filtering related dimensions', function () { - beforeEach(function () { + describe('filtering related dimensions', () => { + beforeEach(() => { chart.render(); - data.dimension(function (d) { return d.status; }).filter('E'); + data.dimension(d => d.status).filter('E'); }); - it('should preserve the labels', function () { + it('should preserve the labels', () => { chart.selectAll('svg g text.row').each(function () { expect(d3.select(this).text()).not.toBe(''); }); }); }); - describe('clicking on a row', function () { - beforeEach(function () { + describe('clicking on a row', () => { + beforeEach(() => { chart.render(); chart.onClick(chart.group().all()[0]); }); - it('should filter the corresponding group', function () { + it('should filter the corresponding group', () => { expect(chart.filter()).toBe(chart.group().all()[0].key); }); - describe('clicking again', function () { - beforeEach(function () { + describe('clicking again', () => { + beforeEach(() => { chart.onClick(chart.group().all()[0]); }); - it('should reset the filter', function () { + it('should reset the filter', () => { expect(chart.filter()).toBe(null); }); }); }); - describe('specifying a group ordering', function () { - beforeEach(function () { + describe('specifying a group ordering', () => { + beforeEach(() => { chart.render(); }); - it('should order values when by value', function () { + it('should order values when by value', () => { chart.ordering(dc.pluck('value')); expect(chart.data().map(dc.pluck('value')).sort(d3.ascending)).toEqual(chart.data().map(dc.pluck('value'))); }); - it('should order keys when by keys', function () { + it('should order keys when by keys', () => { chart.ordering(dc.pluck('key')); expect(chart.data().map(dc.pluck('key')).sort(d3.ascending)).toEqual(chart.data().map(dc.pluck('key'))); }); }); - describe('redrawing after an empty selection', function () { - beforeEach(function () { + describe('redrawing after an empty selection', () => { + beforeEach(() => { chart.render(); // fixme: huh? this isn't even the right data type groupHolder.dimension.filter([makeDate(2010, 0, 1), makeDate(2010, 0, 3)]); @@ -290,17 +395,17 @@ describe('dc.rowChart', function () { chart.redraw(); }); - it('should restore the row chart', function () { + it('should restore the row chart', () => { chart.selectAll('g.row rect').each(function (p) { expect(d3.select(this).attr('width').indexOf('NaN') < 0).toBeTruthy(); }); }); }); - describe('removing all the data and restoring the data', function () { + describe('removing all the data and restoring the data', () => { // this test mainly exists to produce console errors for #1008; // I can't seem to find any way to detect invalid setAttribute calls - beforeEach(function () { + beforeEach(() => { chart.render(); chart.group({all: function () { return []; }}); chart.redraw(); @@ -308,83 +413,80 @@ describe('dc.rowChart', function () { chart.redraw(); }); - it('should restore the row chart', function () { + it('should restore the row chart', () => { chart.selectAll('g.row rect').each(function (p) { expect(d3.select(this).attr('width').indexOf('NaN') < 0).toBeTruthy(); }); }); }); - describe('custom labels', function () { - beforeEach(function () { - chart.label(function () { - return 'custom label'; - }).render(); + describe('custom labels', () => { + beforeEach(() => { + chart.label(() => 'custom label').render(); }); - it('should render a label for each datum', function () { + it('should render a label for each datum', () => { expect(chart.selectAll('text.row').size()).toBe(N); }); - it('should use the custom function for each label', function () { + it('should use the custom function for each label', () => { chart.selectAll('text.row').each(function () { expect(d3.select(this).text()).toBe('custom label'); }); }); - describe('with labels disabled', function () { - beforeEach(function () { + describe('with labels disabled', () => { + beforeEach(() => { chart.renderLabel(false).render(); }); - it('should not display labels', function () { + it('should not display labels', () => { expect(chart.selectAll('text.row').size()).toBe(0); }); }); }); - describe('custom titles', function () { - beforeEach(function () { - chart.title(function () { - return 'custom title'; - }).render(); + describe('custom titles', () => { + beforeEach(() => { + chart.title(() => 'custom title').render(); }); - it('should render a title for each datum', function () { + it('should render a title for each datum', () => { expect(chart.selectAll('g.row title').size()).toBe(N); }); - it('should use the custom function for each title', function () { + it('should use the custom function for each title', () => { chart.selectAll('g.row title').each(function () { expect(d3.select(this).text()).toBe('custom title'); }); }); - describe('with titles disabled', function () { - beforeEach(function () { + describe('with titles disabled', () => { + beforeEach(() => { chart.renderTitle(false).render(); }); - it('should not display labels', function () { + it('should not display labels', () => { expect(chart.selectAll('g.row title').size()).toBe(0); }); }); }); if (xAxisTicks) { - describe('with elasticX', function () { - beforeEach(function () { + describe('with elasticX', () => { + beforeEach(() => { chart.elasticX(true) .xAxis().ticks(3); chart.render(); }); - it('should generate x axis domain dynamically', function () { - var nthText = function (n) { return d3.select(chart.selectAll('g.axis .tick text')[0][n]); }; + it('should generate x axis domain dynamically', () => { + const nthText = function (n) { return d3.select(chart.selectAll('g.axis .tick text').nodes()[n]); }; - for (var i = 0; i < xAxisTicks.length; i++) { - expect(nthText(i).text()).toBe(xAxisTicks[i]); + for (let i = 0; i < xAxisTicks.length; i++) { + // d3@5 and d3@6 uses different characters to format negative numbers + expect(nthText(i).text().replace('-','−')).toBe(xAxisTicks[i].replace('-','−')); } }); }); @@ -393,7 +495,7 @@ describe('dc.rowChart', function () { } itShouldBehaveLikeARowChartWithGroup(positiveGroupHolder, 5, ['0', '5', '10']); - itShouldBehaveLikeARowChartWithGroup(negativeGroupHolder, 5, ['-10', '-5', '0']); - itShouldBehaveLikeARowChartWithGroup(mixedGroupHolder, 5, ['-5', '0', '5']); + itShouldBehaveLikeARowChartWithGroup(negativeGroupHolder, 5, ['−10', '−5', '0']); + itShouldBehaveLikeARowChartWithGroup(mixedGroupHolder, 5, ['−5', '0', '5']); itShouldBehaveLikeARowChartWithGroup(largerGroupHolder, 7); }); diff --git a/spec/scatter-plot-spec.js b/spec/scatter-plot-spec.js index 869b680c8b..635b971c49 100644 --- a/spec/scatter-plot-spec.js +++ b/spec/scatter-plot-spec.js @@ -1,201 +1,365 @@ -/* global appendChartID, comparePaths, loadDateFixture, makeDate */ -describe('dc.scatterPlot', function () { - var id, chart; - var data, group, dimension; +/* global appendChartID, comparePaths, loadDateFixture, makeDate, simulateChart2DBrushing */ +describe('dc.scatterPlot', () => { + let id, chart; + let data, group, dimension; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - dimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); + dimension = data.dimension(d => [+d.value, +d.nvalue]); group = dimension.group(); id = 'scatter-plot'; appendChartID(id); - chart = dc.scatterPlot('#' + id); + chart = new dc.ScatterPlot(`#${id}`); chart.dimension(dimension) .group(group) .width(500).height(180) - .x(d3.scale.linear().domain([0, 70])) + .x(d3.scaleLinear().domain([0, 70])) + .symbolSize(10) + .nonemptyOpacity(0.9) + .excludedSize(2) .excludedColor('#ccc') .excludedOpacity(0.25) + .emptySize(4) + .emptyOpacity(0.5) + .emptyColor('#DFFF00') .transitionDuration(0); }); - describe('rendering the scatter plot', function () { - beforeEach(function () { + describe('rendering the scatter plot', () => { + beforeEach(() => { chart.render(); }); - it('should create an svg', function () { + it('should create an svg', () => { expect(chart.svg().empty()).toBeFalsy(); }); - it('should create the correct number of symbols', function () { + it('should create the correct number of symbols', () => { expect(chart.group().all().length).toBe(chart.selectAll('path.symbol').size()); }); - it('should correctly place the symbols', function () { - expect(nthSymbol(4).attr('transform')).toMatchTranslate(264,131); - expect(nthSymbol(5).attr('transform')).toMatchTranslate(264,75); - expect(nthSymbol(8).attr('transform')).toMatchTranslate(396,131); + it('treats hiddenSize as synonym of emptySize', () => { + expect(chart.hiddenSize()).toEqual(chart.emptySize()); + const newVal = 5; + chart.hiddenSize(newVal); + expect(chart.emptySize()).toEqual(newVal); }); - it('should generate a default color fill for symbols', function () { - expect(nthSymbol(4).attr('fill')).toBe('#1f77b4'); - expect(nthSymbol(5).attr('fill')).toBe('#1f77b4'); - expect(nthSymbol(8).attr('fill')).toBe('#1f77b4'); + it('should correctly place the symbols', () => { + expect(nthSymbol(4).attr('transform')).toMatchTranslate(264, 131); + expect(nthSymbol(5).attr('transform')).toMatchTranslate(264, 75); + expect(nthSymbol(8).attr('transform')).toMatchTranslate(396, 131); }); - describe('with a custom color', function () { - beforeEach(function () { + it('should generate a default color fill for symbols', () => { + expect(nthSymbol(4).attr('fill')).toMatch(/#1f77b4/i); + expect(nthSymbol(5).attr('fill')).toMatch(/#1f77b4/i); + expect(nthSymbol(8).attr('fill')).toMatch(/#1f77b4/i); + }); + + it('should generate the correct titles', () => { + const titles = chart.selectAll('path.symbol title'); + const expected = ['22,-2: 1', '22,10: 1', '33,1: 2', '44,-3: 1', '44,-4: 1', '44,2: 1', '55,-3: 1', '55,-5: 1', '66,-4: 1']; + expect(titles.size()).toBe(expected.length); + titles.each(function (d) { + expect(this.textContent).toBe(expected.shift()); + }); + }); + + describe('with a custom color', () => { + beforeEach(() => { chart.colors('red').render(); }); - it('should color the symbols to the provided color', function () { + it('should color the symbols to the provided color', () => { expect(nthSymbol(4).attr('fill')).toBe('red'); expect(nthSymbol(5).attr('fill')).toBe('red'); expect(nthSymbol(8).attr('fill')).toBe('red'); }); }); - function nthSymbol (i) { - return d3.select(chart.selectAll('path.symbol')[0][i]); + function fishSymbol () { + let size; + const points = [[2, 0], [1, -1], [-1, 1], [-1, -1], [1, 1]]; + + function symbol (d, i) { + // native size is 3 square pixels, so to get size N, multiply by sqrt(N)/3 + let m = size.call(this, d, i); + m = Math.sqrt(m) / 3; + const path = d3.line() + .x(_d => _d[0] * m) + .y(_d => _d[1] * m); + return `${path(points)}Z`; + } + + symbol.type = function () { + if (arguments.length) { + throw new Error('no, you must have fish'); + } + return 'fish'; + }; + symbol.size = function (_) { + if (!arguments.length) { + return size; + } + size = typeof _ === 'function' ? _ : dc.utils.constant(_); + return symbol; + }; + return symbol; } - describe('filtering the chart', function () { - var otherDimension; + describe('with a fish symbol', () => { + beforeEach(() => { + chart.customSymbol(fishSymbol().size(chart.symbolSize())) + .render(); + }); + + it('should draw fishes', () => { + expect(symbolsMatching(matchSymbol(fishSymbol(), chart.symbolSize())).length).toBe(9); + }); + }); - beforeEach(function () { - otherDimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); + describe('with title rendering disabled', () => { + beforeEach(() => { + chart.renderTitle(false).render(); + }); + + it('should not generate title elements', () => { + expect(chart.selectAll('rect.bar title').empty()).toBeTruthy(); + }); + }); + + describe('filtering the chart', () => { + let otherDimension; + + beforeEach(() => { + otherDimension = data.dimension(d => [+d.value, +d.nvalue]); chart.filterAll(); chart.filter([[22, -3], [44, 2]]); }); - it('should filter dimensions based on the same data', function () { + it('should filter dimensions based on the same data', () => { expect(otherDimension.top(Infinity).length).toBe(3); }); - describe('when filtering with null', function () { - beforeEach(function () { + describe('when filtering with null', () => { + beforeEach(() => { chart.filter(null); }); - it('should remove all filtering from the dimensions based on the same data', function () { + it('should remove all filtering from the dimensions based on the same data', () => { expect(otherDimension.top(Infinity).length).toBe(10); }); }); }); - describe('filtering another dimension', function () { - var otherDimension; + function filteringAnotherDimension () { + describe('filtering another dimension', () => { + let otherDimension; + + beforeEach(() => { + otherDimension = data.dimension(d => [+d.value, +d.nvalue]); + const ff = dc.filters.RangedTwoDimensionalFilter([[22, -3], [44, 2]]).isFiltered; + otherDimension.filterFunction(ff); + chart.redraw(); + }); + + it('should show the included points', () => { + const shownPoints = symbolsOfRadius(10); // test symbolSize + expect(shownPoints.length).toBe(2); + expect(shownPoints[0].key).toEqual([22, -2]); + expect(shownPoints[1].key).toEqual([33, 1]); + }); + it('should hide the excluded points', () => { + const emptyPoints = symbolsOfRadius(4); // test emptySize + expect(emptyPoints.length).toBe(7); + }); + it('should use emptyOpacity for excluded points', () => { + const translucentPoints = symbolsMatching(function () { + return +d3.select(this).attr('opacity') === 0.5; // emptyOpacity + }); + expect(translucentPoints.length).toBe(7); + }); + it('should use emptyColor for excluded points', () => { + const chartreusePoints = symbolsMatching(function () { // don't try this at home + return /#DFFF00/i.test(d3.select(this).attr('fill')); // emptyColor + }); + expect(chartreusePoints.length).toBe(7); + }); + it('should update the titles', () => { + const titles = chart.selectAll('path.symbol title'); + const expected = + ['22,-2: 1', '22,10: 0', '33,1: 2', '44,-3: 0', '44,-4: 0', '44,2: 0', '55,-3: 0', '55,-5: 0', '66,-4: 0']; + expect(titles.size()).toBe(expected.length); + titles.each(function (d) { + expect(this.textContent).toBe(expected.shift()); + }); + }); + }); + } + + filteringAnotherDimension(); + + function cloneGroup (grp) { + return { + all: function () { + return grp.all().map(kv => ({ + key: kv.key.slice(0), + value: kv.value + })); + } + }; + } + + describe('with cloned data', () => { + beforeEach(() => { + chart.group(cloneGroup(group)) + .render(); + }); + + filteringAnotherDimension(); + }); - beforeEach(function () { - otherDimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); - var ff = dc.filters.RangedTwoDimensionalFilter([[22, -3], [44, 2]]).isFiltered; + function removeEmptyBins (sourceGroup) { + return { + all: function () { + //return Math.abs(d.value) > 0.00001; // if using floating-point numbers + return sourceGroup.all().filter(d => d.value !== 0); // if integers only + } + }; + } + + describe('with empty bins removed', () => { + let otherDimension; + beforeEach(() => { + chart.group(removeEmptyBins(group)) + .render(); + otherDimension = data.dimension(d => [+d.value, +d.nvalue]); + const ff = dc.filters.RangedTwoDimensionalFilter([[22, -3], [44, 2]]).isFiltered; otherDimension.filterFunction(ff); chart.redraw(); }); - it('should show the included points', function () { - var shownPoints = symbolsOfRadius(chart.symbolSize()); + it('should only contain the included points', () => { + const emptyPoints = symbolsMatching(() => true); + expect(emptyPoints.length).toBe(2); + }); + it('should show the included points', () => { + const shownPoints = symbolsOfRadius(10); // test symbolSize expect(shownPoints.length).toBe(2); expect(shownPoints[0].key).toEqual([22, -2]); expect(shownPoints[1].key).toEqual([33, 1]); }); - it('should hide the excluded points', function () { - var hiddenPoints = symbolsOfRadius(chart.hiddenSize()); - expect(hiddenPoints.length).toBe(7); + it('should update the titles', () => { + const titles = chart.selectAll('path.symbol title'); + const expected = ['22,-2: 1', '33,1: 2']; + expect(titles.size()).toBe(expected.length); + titles.each(function (d) { + expect(this.textContent).toBe(expected.shift()); + }); }); }); - describe('brushing', function () { - var otherDimension; + describe('brushing', () => { + let otherDimension; - beforeEach(function () { - otherDimension = data.dimension(function (d) { return [+d.value, +d.nvalue]; }); + beforeEach(() => { + otherDimension = data.dimension(d => [+d.value, +d.nvalue]); + + simulateChart2DBrushing(chart, [[22, -3], [44, 2]]); - chart.brush().extent([[22, -3], [44, 2]]); - chart.brush().on('brush')(); chart.redraw(); }); - it('should filter dimensions based on the same data', function () { + it('should not create brush handles', () => { + const selectAll = chart.select('g.brush').selectAll('path.custom-brush-handle'); + expect(selectAll.size()).toBe(0); + }); + + it('should filter dimensions based on the same data', () => { jasmine.clock().tick(100); expect(otherDimension.top(Infinity).length).toBe(3); }); + /* D3v4 - no easy replacement, dropping this case it('should set the height of the brush to the height implied by the extent', function () { expect(chart.select('g.brush rect.extent').attr('height')).toBe('46'); }); + */ - it('should not add handles to the brush', function () { + it('should not add handles to the brush', () => { expect(chart.select('.resize path').empty()).toBeTruthy(); }); - describe('excluded points', function () { - var selectedPoints; + describe('excluded points', () => { + let selectedPoints; - beforeEach(function () { + beforeEach(() => { jasmine.clock().tick(100); }); - var isOpaque = function () { - return +d3.select(this).attr('opacity') === 1; - }, isTranslucent = function () { - return +d3.select(this).attr('opacity') === 0.25; - }, isBlue = function () { + const isOpaque = function () { + return +d3.select(this).attr('opacity') === 0.9; // test nonemptyOpacity + }; + const isTranslucent = function () { + return +d3.select(this).attr('opacity') === 0.25; // test excludedOpacity + }; + const isBlue = function () { return d3.select(this).attr('fill') === '#1f77b4'; - }, isGrey = function () { - return d3.select(this).attr('fill') === '#ccc'; + }; + const isGrey = function () { + return d3.select(this).attr('fill') === '#ccc'; // test excludedColor }; - it('should not shrink the included points', function () { + it('should not shrink the included points', () => { selectedPoints = symbolsOfRadius(chart.symbolSize()); expect(selectedPoints.length).toBe(2); expect(selectedPoints[0].key).toEqual([22, -2]); expect(selectedPoints[1].key).toEqual([33, 1]); }); - it('should shrink the excluded points', function () { - selectedPoints = symbolsOfRadius(chart.excludedSize()); + it('should shrink the excluded points', () => { + selectedPoints = symbolsOfRadius(2); // test excludedSize expect(selectedPoints.length).toBe(7); expect(selectedPoints[0].key).toEqual([22, 10]); expect(selectedPoints[1].key).toEqual([44, -3]); }); - it('should keep the included points opaque', function () { + it('should keep the included points opaque', () => { selectedPoints = symbolsMatching(isOpaque); expect(selectedPoints.length).toBe(2); expect(selectedPoints[0].key).toEqual([22, -2]); expect(selectedPoints[1].key).toEqual([33, 1]); }); - it('should make the excluded points translucent', function () { + it('should make the excluded points translucent', () => { selectedPoints = symbolsMatching(isTranslucent); expect(selectedPoints.length).toBe(7); expect(selectedPoints[0].key).toEqual([22, 10]); expect(selectedPoints[1].key).toEqual([44, -3]); }); - it('should keep the included points blue', function () { + it('should keep the included points blue', () => { selectedPoints = symbolsMatching(isBlue); expect(selectedPoints.length).toBe(2); expect(selectedPoints[0].key).toEqual([22, -2]); expect(selectedPoints[1].key).toEqual([33, 1]); }); - it('should make the excluded points grey', function () { + it('should make the excluded points grey', () => { selectedPoints = symbolsMatching(isGrey); expect(selectedPoints.length).toBe(7); expect(selectedPoints[0].key).toEqual([22, 10]); expect(selectedPoints[1].key).toEqual([44, -3]); }); - it('should restore sizes, colors, and opacity when the brush is empty', function () { - chart.brush().extent([[22, 2], [22, -3]]); - chart.brush().on('brush')(); + it('should restore sizes, colors, and opacity when the brush is empty', () => { + simulateChart2DBrushing(chart, [[22, 2], [22, -3]]); + jasmine.clock().tick(100); selectedPoints = symbolsOfRadius(chart.symbolSize()); @@ -224,20 +388,29 @@ describe('dc.scatterPlot', function () { function matchSymbolSize (r) { return function () { - var symbol = d3.select(this); - var size = Math.pow(r, 2); - var path = d3.svg.symbol().size(size)(); - var result = comparePaths(symbol.attr('d'), path); + const symbol = d3.select(this); + const size = Math.pow(r, 2); + const path = d3.symbol().size(size)(); + const result = comparePaths(symbol.attr('d'), path); + return result.pass; + }; + } + + function matchSymbol (s, r) { + return function () { + const symbol = d3.select(this); + const size = Math.pow(r, 2); + const path = s.size(size)(); + const result = comparePaths(symbol.attr('d'), path); return result.pass; }; } function symbolsMatching (pred) { function getData (symbols) { - return symbols[0].map(function (symbol) { - return d3.select(symbol).datum(); - }); + return symbols.nodes().map(symbol => d3.select(symbol).datum()); } + return getData(chart.selectAll('path.symbol').filter(pred)); } @@ -245,69 +418,69 @@ describe('dc.scatterPlot', function () { return symbolsMatching(matchSymbolSize(r)); } - describe('legends', function () { - var compositeChart, id; - var subChart1, subChart2; - var firstItem; + describe('legends', () => { + let compositeChart; + let subChart1, subChart2; + let firstItem; - beforeEach(function () { + beforeEach(() => { id = 'scatter-plot-composite'; appendChartID(id); - compositeChart = dc.compositeChart('#' + id); + compositeChart = new dc.CompositeChart(`#${id}`); compositeChart .dimension(dimension) - .x(d3.time.scale.utc().domain([makeDate(2012, 0, 1), makeDate(2012, 11, 31)])) + .x(d3.scaleUtc().domain([makeDate(2012, 0, 1), makeDate(2012, 11, 31)])) .transitionDuration(0) - .legend(dc.legend()) + .legend(new dc.Legend()) .compose([ - subChart1 = dc.scatterPlot(compositeChart).colors('red').group(group, 'Scatter 1'), - subChart2 = dc.scatterPlot(compositeChart).colors('blue').group(group, 'Scatter 2') + subChart1 = new dc.ScatterPlot(compositeChart).colors('red').group(group, 'Scatter 1'), + subChart2 = new dc.ScatterPlot(compositeChart).colors('blue').group(group, 'Scatter 2') ]).render(); firstItem = compositeChart.select('g.dc-legend g.dc-legend-item'); }); - it('should provide a composite chart with corresponding legend data', function () { + it('should provide a composite chart with corresponding legend data', () => { expect(compositeChart.legendables()).toEqual([ {chart: subChart1, name: 'Scatter 1', color: 'red'}, {chart: subChart2, name: 'Scatter 2', color: 'blue'} ]); }); - describe('hovering', function () { - beforeEach(function () { - firstItem.on('mouseover')(firstItem.datum()); + describe('hovering', () => { + beforeEach(() => { + dc.d3compat.callHandler(firstItem.on('mouseover'), null, {}, firstItem.datum()); }); - describe('when a legend item is hovered over', function () { - it('should highlight corresponding plot', function () { - nthChart(0).expectPlotSymbolsToHaveSize(chart.highlightedSize()); + describe('when a legend item is hovered over', () => { + it('should highlight corresponding plot', () => { + nthChart(0).expectPlotSymbolsToHaveSize(subChart1.highlightedSize()); }); - it('should fade out non-corresponding lines and areas', function () { + it('should fade out non-corresponding lines and areas', () => { nthChart(1).expectPlotSymbolsToHaveClass('fadeout'); }); }); - describe('when a legend item is hovered out', function () { - beforeEach(function () { - firstItem.on('mouseout')(firstItem.datum()); + describe('when a legend item is hovered out', () => { + beforeEach(() => { + dc.d3compat.callHandler(firstItem.on('mouseout'), null, {}, firstItem.datum()); }); - it('should remove highlighting from corresponding lines and areas', function () { - nthChart(0).expectPlotSymbolsToHaveSize(chart.symbolSize()); + it('should remove highlighting from corresponding lines and areas', () => { + nthChart(0).expectPlotSymbolsToHaveSize(subChart1.symbolSize()); }); - it('should fade in non-corresponding lines and areas', function () { + it('should fade in non-corresponding lines and areas', () => { nthChart(1).expectPlotSymbolsNotToHaveClass('fadeout'); }); }); }); function nthChart (n) { - var subChart = d3.select(compositeChart.selectAll('g.sub')[0][n]); + const subChart = d3.select(compositeChart.selectAll('g.sub').nodes()[n]); subChart.expectPlotSymbolsToHaveClass = function (className) { subChart.selectAll('path.symbol').each(function () { @@ -316,10 +489,9 @@ describe('dc.scatterPlot', function () { }; subChart.expectPlotSymbolsToHaveSize = function (size) { - var highlightedSize = Math.pow(size, 2); - var highlightedPath = d3.svg.symbol().size(highlightedSize)(); + const match = matchSymbolSize(size); subChart.selectAll('path.symbol').each(function () { - expect(d3.select(this).attr('d')).toMatchPath(highlightedPath); + expect(match.apply(this)).toBeTruthy(); }); }; @@ -332,5 +504,57 @@ describe('dc.scatterPlot', function () { return subChart; } }); + describe('with ordinal axes', () => { + beforeEach(() => { + dimension = data.dimension(d => [d.state, d.region]); + group = dimension.group(); + chart + .margins({left: 50, top: 10, right: 0, bottom: 20}) + .dimension(dimension) + .group(group) + .x(d3.scaleBand()) + // ordinal axes work but you have to set the padding for both axes & give the y domain + .y(d3.scaleBand().paddingInner(1).domain(group.all().map(kv => kv.key[1]))) + .xUnits(dc.units.ordinal) + ._rangeBandPadding(1) + .render(); + }); + it('should correctly place the symbols', () => { + expect(nthSymbol(4).attr('transform')).toMatchTranslate(262.5, 75); + expect(nthSymbol(5).attr('transform')).toMatchTranslate(337.5, 37.5); + expect(nthSymbol(7).attr('transform')).toMatchTranslate(412.5, 0); + }); + describe('with grid lines', () => { + beforeEach(() => { + chart + .renderHorizontalGridLines(true) + .renderVerticalGridLines(true) + .render(); + }); + it('should draw the correct number of grid lines', () => { + expect(chart.selectAll('.grid-line.horizontal line').size()).toBe(5); + expect(chart.selectAll('.grid-line.vertical line').size()).toBe(6); + }); + }); + }); + + describe('accessibility scatter plot', () => { + + beforeEach(() => { + chart.keyboardAccessible(true); + }) + + it('internal elements are focusable by keyboard', () => { + chart.render(); + chart.selectAll('path.symbol').each(function () { + const dot = d3.select(this); + expect(dot.attr('tabindex')).toEqual('0'); + }); + }); + }); + + function nthSymbol (i) { + return d3.select(chart.selectAll('path.symbol').nodes()[i]); + } }); diff --git a/spec/select-menu-spec.js b/spec/select-menu-spec.js index 9d9bd0c4d9..a77c9f98df 100644 --- a/spec/select-menu-spec.js +++ b/spec/select-menu-spec.js @@ -1,202 +1,204 @@ /* global appendChartID, loadDateFixture */ -describe('dc.selectMenu', function () { - var id, chart; - var data, regionDimension, regionGroup; - var stateDimension, stateGroup; +describe('dc.selectMenu', () => { + let id, chart; + let data, regionDimension, regionGroup; + let stateDimension, stateGroup; - beforeEach(function () { + beforeEach(() => { data = crossfilter(loadDateFixture()); - regionDimension = data.dimension(function (d) { return d.region; }); - stateDimension = data.dimension(function (d) { return d.state; }); + regionDimension = data.dimension(d => d.region); + stateDimension = data.dimension(d => d.state); regionGroup = regionDimension.group(); stateGroup = stateDimension.group(); - id = 'seclect-menu'; + id = 'select-menu'; appendChartID(id); - chart = dc.selectMenu('#' + id); + chart = new dc.SelectMenu(`#${id}`); chart.dimension(stateDimension) .group(stateGroup) .transitionDuration(0); chart.render(); }); - describe('generation', function () { - it('we get something', function () { + describe('generation', () => { + it('we get something', () => { expect(chart).not.toBeNull(); }); - it('should be registered', function () { + it('should be registered', () => { expect(dc.hasChart(chart)).toBeTruthy(); }); - it('sets order', function () { + it('sets order', () => { expect(chart.order()).toBeDefined(); }); - it('sets prompt text', function () { + it('sets prompt text', () => { expect(chart.promptText()).toBe('Select all'); }); - it('creates select tag', function () { - expect(chart.selectAll('select').length).toEqual(1); + it('creates select tag', () => { + expect(chart.selectAll('select').nodes().length).toEqual(1); }); - it('select tag is not a multiple select by default', function () { + it('select tag is not a multiple select by default', () => { expect(chart.selectAll('select').attr('multiple')).toBeNull(); }); - it('can be made into a multiple', function () { + it('can be made into a multiple', () => { chart.multiple(true).redraw(); expect(chart.selectAll('select').attr('multiple')).toBeTruthy(); }); - it('select tag does not have size by default', function () { + it('select tag does not have size by default', () => { expect(chart.selectAll('select').attr('size')).toBeNull(); }); - it('can have size set', function () { - chart.size(10).redraw(); + it('can have numberVisible set', () => { + chart.numberVisible(10).redraw(); expect(chart.selectAll('select').attr('size')).toEqual('10'); }); - it('creates prompt option with empty value', function () { - var option = chart.selectAll('option')[0][0]; + it('treats size as synonym of numberVisible', () => { + chart.numberVisible(10); + expect(chart.size()).toEqual(chart.numberVisible()); + chart.size(20); + expect(chart.numberVisible()).toEqual(20); + }); + it('creates prompt option with empty value', () => { + const option = chart.selectAll('option').nodes()[0]; expect(option).not.toBeNull(); expect(option.value).toEqual(''); }); - it('creates prompt option with default prompt text', function () { - var option = chart.selectAll('option')[0][0]; + it('creates prompt option with default prompt text', () => { + const option = chart.selectAll('option').nodes()[0]; expect(option.text).toEqual('Select all'); }); - it('creates correct number of options', function () { - expect(chart.selectAll('option.dc-select-option')[0].length).toEqual(stateGroup.all().length); + it('creates correct number of options', () => { + expect(chart.selectAll('option.dc-select-option').nodes().length).toEqual(stateGroup.all().length); }); }); - describe('select options', function () { - var firstOption, lastOption, lastIndex; - beforeEach(function () { + describe('select options', () => { + let firstOption, lastOption, lastIndex; + beforeEach(() => { lastIndex = stateGroup.all().length - 1; - firstOption = getOption(chart,0); - lastOption = getOption(chart,lastIndex); + firstOption = getOption(chart, 0); + lastOption = getOption(chart, lastIndex); }); - it('display title as default option text', function () { + it('display title as default option text', () => { expect(firstOption.text).toEqual('California: 3'); }); - it('text property can be changed by changing title', function () { - chart.title(function (d) { return d.key; }).redraw(); - firstOption = getOption(chart,0); + it('text property can be changed by changing title', () => { + chart.title(d => d.key).redraw(); + firstOption = getOption(chart, 0); expect(firstOption.text).toEqual('California'); }); - it('are ordered by ascending group key by default', function () { + it('are ordered by ascending group key by default', () => { expect(firstOption.text).toEqual('California: 3'); expect(lastOption.text).toEqual('Ontario: 2'); }); - it('order can be changed by changing order function', function () { - chart.order(function (a, b) { return a.key.length - b.key.length; }); + it('order can be changed by changing order function', () => { + chart.order((a, b) => a.key.length - b.key.length); chart.redraw(); - lastOption = getOption(chart,lastIndex); + lastOption = getOption(chart, lastIndex); expect(lastOption.text).toEqual('Mississippi: 2'); }); }); - describe('regular single select', function () { - describe('selecting an option', function () { - it('filters dimension based on selected option\'s value', function () { + describe('regular single select', () => { + describe('selecting an option', () => { + it('filters dimension based on selected option\'s value', () => { chart.onChange(stateGroup.all()[0].key); expect(chart.filter()).toEqual('California'); }); - it('replaces filter on second selection', function () { + it('replaces filter on second selection', () => { chart.onChange(stateGroup.all()[0].key); chart.onChange(stateGroup.all()[1].key); expect(chart.filter()).toEqual('Colorado'); expect(chart.filters().length).toEqual(1); }); - it('actually filters dimension', function () { + it('actually filters dimension', () => { chart.onChange(stateGroup.all()[0].key); expect(regionGroup.all()[0].value).toEqual(0); expect(regionGroup.all()[3].value).toEqual(2); }); - it('removes filter when prompt option is selected', function () { + it('removes filter when prompt option is selected', () => { chart.onChange(null); expect(chart.hasFilter()).not.toBeTruthy(); expect(regionGroup.all()[0].value).toEqual(1); }); }); - describe('redraw with existing filter', function () { - it('selects option corresponding to active filter', function () { + describe('redraw with existing filter', () => { + it('selects option corresponding to active filter', () => { chart.onChange(stateGroup.all()[0].key); chart.redraw(); - expect(chart.selectAll('select')[0][0].value).toEqual('California'); + expect(chart.selectAll('select').nodes()[0].value).toEqual('California'); }); }); - afterEach(function () { + afterEach(() => { chart.onChange(null); }); }); - describe('multiple select', function () { - beforeEach(function () { + describe('multiple select', () => { + beforeEach(() => { chart.multiple(true); chart.onChange([stateGroup.all()[0].key, stateGroup.all()[1].key]); }); - it('adds filters based on selections', function () { + it('adds filters based on selections', () => { expect(chart.filters()).toEqual(['California', 'Colorado']); expect(chart.filters().length).toEqual(2); }); - it('actually filters dimension', function () { + it('actually filters dimension', () => { expect(regionGroup.all()[3].value).toEqual(2); expect(regionGroup.all()[4].value).toEqual(2); }); - it('removes all filters when prompt option is selected', function () { + it('removes all filters when prompt option is selected', () => { chart.onChange(null); expect(chart.hasFilter()).not.toBeTruthy(); expect(regionGroup.all()[0].value).toEqual(1); }); - it('selects all options corresponding to active filters on redraw', function () { - var selectedOptions = chart.selectAll('select').selectAll('option')[0].filter(function (d) { - // IE returns an extra option with value '', not sure what it means - return d.value && d.selected; - }); + it('selects all options corresponding to active filters on redraw', () => { + // IE returns an extra option with value '', not sure what it means + const selectedOptions = chart.selectAll('select').selectAll('option').nodes().filter(d => d.value && d.selected); expect(selectedOptions.length).toEqual(2); - expect(selectedOptions.map(function (d) { return d.value; })).toEqual(['California', 'Colorado']); + expect(selectedOptions.map(d => d.value)).toEqual(['California', 'Colorado']); }); - it('does not deselect previously filtered options when new option is added', function () { + it('does not deselect previously filtered options when new option is added', () => { chart.onChange([stateGroup.all()[0].key, stateGroup.all()[1].key, stateGroup.all()[5].key]); - var selectedOptions = chart.selectAll('select').selectAll('option')[0].filter(function (d) { - // IE returns an extra option with value '', not sure what it means - return d.value && d.selected; - }); + // IE returns an extra option with value '', not sure what it means + const selectedOptions = chart.selectAll('select').selectAll('option').nodes().filter(d => d.value && d.selected); expect(selectedOptions.length).toEqual(3); - expect(selectedOptions.map(function (d) { return d.value; })).toEqual(['California', 'Colorado', 'Ontario']); + expect(selectedOptions.map(d => d.value)).toEqual(['California', 'Colorado', 'Ontario']); }); - afterEach(function () { + afterEach(() => { chart.onChange(null); }); }); - describe('filterDisplayed', function () { - it('only displays options whose value > 0 by default', function () { + describe('filterDisplayed', () => { + it('only displays options whose value > 0 by default', () => { regionDimension.filter('South'); chart.redraw(); - expect(chart.selectAll('option.dc-select-option')[0].length).toEqual(1); - expect(getOption(chart,0).text).toEqual('California: 2'); + expect(chart.selectAll('option.dc-select-option').nodes().length).toEqual(1); + expect(getOption(chart, 0).text).toEqual('California: 2'); }); - it('can be overridden', function () { + it('can be overridden', () => { regionDimension.filter('South'); - chart.filterDisplayed(function (d) { return true; }).redraw(); - expect(chart.selectAll('option.dc-select-option')[0].length).toEqual(stateGroup.all().length); + chart.filterDisplayed(d => true).redraw(); + expect(chart.selectAll('option.dc-select-option').nodes().length).toEqual(stateGroup.all().length); expect(getOption(chart, stateGroup.all().length - 1).text).toEqual('Ontario: 0'); }); - it('retains order with filtered options', function () { + it('retains order with filtered options', () => { regionDimension.filter('Central'); chart.redraw(); - expect(getOption(chart,0).text).toEqual('Mississippi: 2'); - expect(getOption(chart,1).text).toEqual('Ontario: 1'); + expect(getOption(chart, 0).text).toEqual('Mississippi: 2'); + expect(getOption(chart, 1).text).toEqual('Ontario: 1'); }); - afterEach(function () { + afterEach(() => { regionDimension.filterAll(); }); }); - function getOption (chart, i) { - return chart.selectAll('option.dc-select-option')[0][i]; + function getOption (_chart, i) { + return _chart.selectAll('option.dc-select-option').nodes()[i]; } }); diff --git a/spec/series-chart-spec.js b/spec/series-chart-spec.js index cf6305d833..8a71a6bf21 100644 --- a/spec/series-chart-spec.js +++ b/spec/series-chart-spec.js @@ -1,105 +1,109 @@ /* global appendChartID */ -describe('dc.seriesChart', function () { +describe('dc.seriesChart', () => { - var chart; - var colorRows = [ + let chart; + const colorRows = [ {colData: 1, rowData: 1, colorData: 1}, {colData: 1, rowData: 2, colorData: 2}, {colData: 2, rowData: 1, colorData: 3}, {colData: 2, rowData: 2, colorData: 4} ]; - var colorData; + let colorData; - beforeEach(function () { + beforeEach(() => { colorData = crossfilter(colorRows); - var dimensionColorData = colorData.dimension(function (d) { return [+d.colData, +d.rowData]; }); - var groupColorData = dimensionColorData.group().reduceSum(function (d) { return +d.colorData; }); + const dimensionColorData = colorData.dimension(d => [+d.colData, +d.rowData]); + const groupColorData = dimensionColorData.group().reduceSum(d => +d.colorData); - var id = 'series-chart'; + const id = 'series-chart'; appendChartID(id); - chart = dc.seriesChart('#' + id); + chart = new dc.SeriesChart(`#${id}`); chart .width(210) .height(210) - .x(d3.scale.linear().domain([1,2])) + .x(d3.scaleLinear().domain([1,2])) .dimension(dimensionColorData) .group(groupColorData) .ordinalColors(['#000001', '#000002']) - .seriesAccessor(function (d) { return +d.key[0];}) - .keyAccessor(function (d) { return +d.key[1];}) - .valueAccessor(function (d) { return +d.value ;}) + .seriesAccessor(d => +d.key[0]) + .keyAccessor(d => +d.key[1]) + .valueAccessor(d => +d.value ) .childOptions({renderArea: true, dashStyle: [3, 1, 1]}) .transitionDuration(0); }); - describe('#render', function () { - beforeEach(function () { + describe('#render', () => { + beforeEach(() => { chart.render(); }); - it('should create the svg', function () { + it('should create the svg', () => { expect(chart.svg()).not.toBeNull(); }); - it('should position generated lineCharts using the data', function () { - var lines = chart.selectAll('path.line'); + it('should not allow calling compose', () => { + expect(chart.compose).toThrowError(); + }); + + it('should position generated lineCharts using the data', () => { + const lines = chart.selectAll('path.line'); - expect(d3.select(lines[0][0]).attr('d')).toMatchPath('M0,128L130,85'); - expect(d3.select(lines[0][1]).attr('d')).toMatchPath('M0,43L130,0'); + expect(d3.select(lines.nodes()[0]).attr('d')).toMatchPath('M0,128L130,85'); + expect(d3.select(lines.nodes()[1]).attr('d')).toMatchPath('M0,43L130,0'); }); - it('should color lines using the colors in the data', function () { - var lines = chart.selectAll('path.line'); + it('should color lines using the colors in the data', () => { + const lines = chart.selectAll('path.line'); - expect(d3.select(lines[0][0]).attr('stroke')).toBe('#000001'); - expect(d3.select(lines[0][1]).attr('stroke')).toBe('#000002'); + expect(d3.select(lines.nodes()[0]).attr('stroke')).toMatch(/#000001/i); + expect(d3.select(lines.nodes()[1]).attr('stroke')).toMatch(/#000002/i); }); - describe('with brush off', function () { - it('should create line chart dots', function () { + describe('with brush off', () => { + it('should create line chart dots', () => { chart.brushOn(false).render(); - var dots = chart.selectAll('circle.dot'); - expect(dots[0].length).toEqual(4); + const dots = chart.selectAll('circle.dot'); + expect(dots.nodes().length).toEqual(4); chart.brushOn(true); }); }); }); - describe('series sorting', function () { - beforeEach(function () { + describe('series sorting', () => { + beforeEach(() => { chart .seriesSort(d3.descending) .render(); }); - it('should order lineCharts in the order specified', function () { - var lines = chart.selectAll('path.line'); + it('should order lineCharts in the order specified', () => { + const lines = chart.selectAll('path.line'); - expect(d3.select(lines[0][1]).attr('d')).toMatchPath('M0,128L130,85'); - expect(d3.select(lines[0][0]).attr('d')).toMatchPath('M0,43L130,0'); + expect(d3.select(lines.nodes()[1]).attr('d')).toMatchPath('M0,128L130,85'); + expect(d3.select(lines.nodes()[0]).attr('d')).toMatchPath('M0,43L130,0'); }); }); - describe('chart options', function () { - beforeEach(function () { + describe('chart options', () => { + beforeEach(() => { chart.render(); }); - it('should apply options to all lines in the chart', function () { - var lines = chart.selectAll('path.line'); - var areas = chart.selectAll('path.area'); + it('should apply options to all lines in the chart', () => { + const lines = chart.selectAll('path.line'); + const areas = chart.selectAll('path.area'); - expect(d3.select(lines[0][0]).attr('stroke-dasharray')).toEqualIntList('3,1,1'); - expect(d3.select(lines[0][1]).attr('stroke-dasharray')).toEqualIntList('3,1,1'); + expect(d3.select(lines.nodes()[0]).attr('stroke-dasharray')).toEqualIntOrPixelList('3,1,1'); + expect(d3.select(lines.nodes()[1]).attr('stroke-dasharray')).toEqualIntOrPixelList('3,1,1'); - expect(d3.select(areas[0][0]).attr('fill')).toBe('#000001'); - expect(d3.select(areas[0][1]).attr('fill')).toBe('#000002'); + expect(d3.select(areas.nodes()[0]).attr('fill')).toMatch(/#000001/i); + expect(d3.select(areas.nodes()[1]).attr('fill')).toMatch(/#000002/i); }); }); - describe('#redraw', function () { - var colorRows2 = [ + describe('#redraw', () => { + const colorRows2 = [ {colData: 1, rowData: 1, colorData: 1}, {colData: 1, rowData: 2, colorData: 2}, {colData: 2, rowData: 1, colorData: 3}, @@ -107,27 +111,27 @@ describe('dc.seriesChart', function () { {colData: 3, rowData: 1, colorData: 5}, {colData: 3, rowData: 2, colorData: 6} ]; - var colorData2; - beforeEach(function () { + let colorData2; + beforeEach(() => { colorData2 = crossfilter(colorRows2); chart.brushOn(false); chart.render(); - var dimensionData = colorData2.dimension(function (d) { return [+d.colData, +d.rowData]; }); - var groupData = dimensionData.group().reduceSum(function (d) { return +d.colorData; }); + const dimensionData = colorData2.dimension(d => [+d.colData, +d.rowData]); + const groupData = dimensionData.group().reduceSum(d => +d.colorData); chart.dimension(dimensionData).group(groupData); chart.redraw(); }); - afterEach(function () { + afterEach(() => { chart.brushOn(true); }); - it('is redrawn with dots', function () { - var dots = chart.selectAll('circle.dot'); - expect(dots[0].length).toEqual(6); + it('is redrawn with dots', () => { + const dots = chart.selectAll('circle.dot'); + expect(dots.nodes().length).toEqual(6); }); }); }); diff --git a/spec/sunburst-chart-spec.js b/spec/sunburst-chart-spec.js new file mode 100644 index 0000000000..cae6bbd251 --- /dev/null +++ b/spec/sunburst-chart-spec.js @@ -0,0 +1,524 @@ +/* global appendChartID, loadDateFixture, makeDate, getSunburstDataOneRing3Segments, + loadSunburstData3CompleteRings, loadSunburstData10CompleteRings */ +describe('dc.sunburstChart', () => { + const width = 200; + const height = 200; + const radius = 100; + const defaultCenter = {x: width / 2, y: height / 2}; + const newCenter = {x: 101, y: 99}; + const innerRadius = 30; + let data, valueDimension, valueGroup; + let countryRegionStateDimension, countryRegionStateGroup; + let statusDimension; + let dateDimension; + + beforeEach(() => { + data = crossfilter(loadDateFixture()); + valueDimension = data.dimension(d => d.value); + valueGroup = valueDimension.group(); + + countryRegionStateDimension = data.dimension(d => [d.countrycode, d.region, d.state]); + + countryRegionStateGroup = countryRegionStateDimension.group(); + + statusDimension = data.dimension(d => d.status); + + dateDimension = data.dimension(d => d3.utcDay(d.dd)); + + }); + + function buildChart (id) { + const div = appendChartID(id); + div.append('a').attr('class', 'reset').style('display', 'none'); + div.append('span').attr('class', 'filter').style('display', 'none'); + const chart = new dc.SunburstChart(`#${id}`); + chart.dimension(countryRegionStateDimension).group(countryRegionStateGroup) + .width(width) + .height(height) + .transitionDuration(0); + chart.render(); + return chart; + } + + describe('generation', () => { + let chart; + beforeEach(() => { + chart = buildChart('pie-chart-age'); + chart.render(); + }); + it('we get something', () => { + expect(chart).not.toBeNull(); + }); + it('should be registered', () => { + expect(dc.hasChart(chart)).toBeTruthy(); + }); + it('dc-chart class should be turned on for parent div', () => { + expect(d3.select('#pie-chart-age').attr('class')).toEqual('dc-chart'); + }); + it('inner radius can be set', () => { + chart.innerRadius(innerRadius); + expect(chart.innerRadius()).toEqual(innerRadius); + }); + it('svg should be created', () => { + expect(chart.select('svg').empty()).toBeFalsy(); + }); + it('default color scheme should be created', () => { + expect(chart.colors().length > 0).toBeTruthy(); + }); + it('dimension should be set', () => { + expect(chart.dimension()).toBe(countryRegionStateDimension); + }); + it('group should be set', () => { + expect(chart.group()).toEqual(countryRegionStateGroup); + }); + it('width should be set', () => { + expect(chart.width()).toEqual(width); + }); + it('height should be set', () => { + expect(chart.height()).toEqual(height); + }); + it('radius should not be set', () => { + expect(chart.radius()).toBeFalsy(); + }); + it('cx should be set', () => { + expect(chart.cx()).toEqual(defaultCenter.x); + }); + it('cy should be set', () => { + expect(chart.cy()).toEqual(defaultCenter.y); + }); + it('height should be used for svg', () => { + expect(chart.select('svg').attr('height')).toEqual(String(height)); + }); + it('root g should be created', () => { + expect(chart.select('svg g').empty()).toBeFalsy(); + }); + it('root g should be translated to center', () => { + expect(chart.select('svg g').attr('transform')).toMatchTranslate(defaultCenter.x, defaultCenter.y); + }); + it('slice g should be created with class', () => { + expect(chart.selectAll('svg g g.pie-slice-level-1').data().length).toEqual(2); + }); + it('slice path should be created', () => { + expect(chart.selectAll('svg g g.pie-slice-level-1 path').data().length).toEqual(2); + }); + it('slice css class should be numbered with index', () => { + chart.selectAll('g.pie-slice').each(function (p, i) { + expect(d3.select(this).attr('class')).toContain(`pie-slice _${i}`); + }); + }); + it('slice path should be filled', () => { + chart.selectAll('svg g g.pie-slice path').each(function (p) { + expect(d3.select(this).attr('fill') !== '').toBeTruthy(); + }); + }); + it('slice path d should be created', () => { + chart.selectAll('svg g g.pie-slice path').each(function (p) { + expect(d3.select(this).attr('d') !== '').toBeTruthy(); + }); + }); + it('slice path fill should be set correctly', () => { + expect(d3.select(chart.selectAll('g.pie-slice path').nodes()[0]).attr('fill')).toEqual('#3182bd'); + expect(d3.select(chart.selectAll('g.pie-slice path').nodes()[1]).attr('fill')).toEqual('#6baed6'); + expect(d3.select(chart.selectAll('g.pie-slice path').nodes()[2]).attr('fill')).toEqual('#9ecae1'); + expect(d3.select(chart.selectAll('g.pie-slice path').nodes()[3]).attr('fill')).toEqual('#c6dbef'); + }); + it('slice label text should be set', () => { + chart.selectAll('svg g text.pie-slice').call(p => { + expect(p.text()).toEqual(p.datum().key); + }); + }); + it('slice label should be middle anchored', () => { + chart.selectAll('svg g text.pie-slice').each(function (p) { + expect(d3.select(this).attr('text-anchor')).toEqual('middle'); + }); + }); + it('reset link hidden after init rendering', () => { + expect(chart.select('a.reset').style('display')).toEqual('none'); + }); + it('filter info should be hidden after init rendering', () => { + expect(chart.select('span.filter').style('display')).toEqual('none'); + }); + describe('center positioning', () => { + beforeEach(() => { + chart + .cx(newCenter.x) + .cy(newCenter.y) + .render(); + return chart; + }); + afterEach(() => { + chart + .cx(defaultCenter.x) + .cy(defaultCenter.y) + .render(); + return chart; + }); + it(`root g should be translated to ${newCenter.x},${newCenter.y}`, () => { + expect(chart.select('svg g').attr('transform')).toMatchTranslate(newCenter.x, newCenter.y); + }); + }); + + describe('with radius', () => { + beforeEach(() => { + chart.radius(100) + .render(); + }); + it('should take', () => { + expect(chart.radius()).toEqual(radius); + }); + }); + + describe('re-render', () => { + beforeEach(() => { + chart.render(); + return chart; + }); + it('multiple invocation of render should update chart', () => { + expect(d3.selectAll('#pie-chart-age svg').nodes().length).toEqual(1); + }); + }); + + describe('n/a filter', () => { + beforeEach(() => { + statusDimension.filter('E'); + chart.render(); + return chart; + }); + it('should draw an empty chart', () => { + expect(chart.select('g').classed('empty-chart')).toBeTruthy(); + }); + it('should have one slice', () => { + expect(chart.selectAll('svg g text.pie-slice').nodes().length).toBe(1); + }); + afterEach(() => { + statusDimension.filterAll(); + }); + }); + describe('slice selection', () => { + it('on click function should be defined', () => { + expect(chart.selectAll('svg g g.pie-slice path').on('click') !== undefined).toBeTruthy(); + }); + it('by default no slice should be selected', () => { + expect(chart.hasFilter()).toBeFalsy(); + }); + it('be able to set selected slice', () => { + expect(chart.filter(['US', 'East', 'Ontario']).filter()).toEqual(['US', 'East', 'Ontario']); + expect(chart.hasFilter()).toBeTruthy(); + chart.filterAll(); + }); + it('should filter dimension by single selection', () => { + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + expect(valueGroup.all()[0]).toEqual({key: '22', value: 1}); + expect(valueGroup.all()[1].value).toEqual(0); + chart.filterAll(); + }); + it('should filter dimension by multiple selections', () => { + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + chart.filter(dc.filters.HierarchyFilter(['US', 'West', 'Colorado'])); + expect(valueGroup.all()[0]).toEqual({key: '22', value: 2}); + expect(valueGroup.all()[1].value).toEqual(0); + chart.filterAll(); + }); + it('should filter dimension with deselection', () => { + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + chart.filter(dc.filters.HierarchyFilter(['US', 'West', 'Colorado'])); + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + expect(valueGroup.all()[0]).toEqual({key: '22', value: 1}); + expect(valueGroup.all()[1].value).toEqual(0); + chart.filterAll(); + }); + it('should highlight selected slices', () => { + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + chart.filter(dc.filters.HierarchyFilter(['US', 'West', 'Colorado'])); + chart.render(); + chart.selectAll('g.pie-slice-level-3').each(function (d) { + if (d.path.toString() === ['CA', 'East', 'Ontario'].toString() || + d.path.toString() === ['US', 'West', 'Colorado'].toString() + ) { + expect(d3.select(this).attr('class').indexOf('selected') >= 0).toBeTruthy(); + } else { + expect(d3.select(this).attr('class').indexOf('deselected') >= 0).toBeTruthy(); + } + }); + chart.filterAll(); + }); + it('reset link generated after slice selection', () => { + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + expect(chart.select('a.reset').style('display')).not.toEqual('none'); + }); + it('filter info generated after slice selection', () => { + chart.filter(null); + chart.filter(dc.filters.HierarchyFilter(['CA', 'East', 'Ontario'])); + expect(chart.select('span.filter').style('display')).not.toEqual('none'); + }); + it('should remove highlight if no slice selected', () => { + chart.filterAll(); + chart.redraw(); + chart.selectAll('.pie-slice path').each(function (d) { + const cls = d3.select(this).attr('class'); + expect(cls === null || cls === '').toBeTruthy(); + }); + }); + }); + describe('filter through clicking', () => { + it('onClick should trigger filtering of according group', () => { + expect(chart.filters()).toEqual([]); + const d = chart.select('.pie-slice-level-3').datum(); + chart.onClick(d); + expect(chart.filter().slice(0)).toEqual(d.path); + }); + it('onClick should reset filter if clicked twice', () => { + expect(chart.filters()).toEqual([]); + const d = chart.select('.pie-slice-level-3').datum(); + chart.onClick(d); + chart.onClick(d); + expect(chart.filter()).toEqual(null); + }); + }); + }); + + describe('redraw after empty selection', () => { + let chart; + beforeEach(() => { + chart = buildChart('pie-chart2'); + dateDimension.filter([makeDate(2010, 0, 1), makeDate(2010, 0, 3)]); + chart.redraw(); + dateDimension.filter([makeDate(2012, 0, 1), makeDate(2012, 11, 30)]); + chart.redraw(); + }); + it('pie chart should be restored', () => { + chart.selectAll('g.pie-slice path').each(function (p) { + expect(d3.select(this).attr('d').indexOf('NaN') < 0).toBeTruthy(); + }); + }); + afterEach(() => { + dateDimension.filterAll(); + }); + }); + + describe('sunburst use baseMixin.ordering', () => { + function buildSunburstChartOneRingThreeSlices (id) { + data = crossfilter(getSunburstDataOneRing3Segments()); + const _valueDimension = data.dimension(d => [d.x]); + valueGroup = _valueDimension.group().reduceSum(d => +d.y); + appendChartID(id); + const chart = dc.sunburstChart(`#${id}`); + chart + .dimension(_valueDimension) + .group(valueGroup) + .width(width) + .height(height) + .transitionDuration(0); + return chart; + } + + function expectTextLabels (strings) { + strings.forEach((str,i) => { + expect(d3.select(`text.pie-slice._${i}`).text()).toEqual(str); + }); + } + + let chart; + beforeEach(() => { + chart = buildSunburstChartOneRingThreeSlices('sunburst_ordering_default_ordering'); + chart.render(); + }); + + describe('sunburst using default ordering', () => { + it('slices ordered by key', () => { + expectTextLabels(['a', 'b', 'c']); + }); + }); + + describe('sunburst using ordering by value ascending', () => { + it('slices ordered by value', () => { + chart.ordering(d => -d.value); + chart.render(); + expectTextLabels(['c', 'b', 'a']); + }); + }); + + }); + + describe('sunburst.relativeRingSizes', () => { + + function buildSunburstChart3CompleteRings (id) { + data = crossfilter(loadSunburstData3CompleteRings()); + const _valueDimension = data.dimension(d => [d.x1, d.x2, d.x3]); + return buildSunburst(_valueDimension, id); + } + + function buildSunburstChartNCompleteRings (N, id) { + data = crossfilter(loadSunburstData10CompleteRings()); + const _valueDimension = data.dimension(d => { + const ten = [d.x0, d.x1, d.x2, d.x3, d.x4, d.x5, d.x6 , d.x7, d.x8, d.x9 ]; + const key = Array.prototype.concat.apply(ten.slice(0, N%10), new Array(Math.floor(N/10)).fill(ten)); + expect(key.length).toEqual(N); + return key; + }); + return buildSunburst(_valueDimension, id); + } + + const buildSunburst = function (_valueDimension, id) { + const _valueGroup = _valueDimension.group().reduceSum(d => +d.y); + appendChartID(id); + const chart = dc.sunburstChart(`#${id}`); + chart + .dimension(_valueDimension) + .group(_valueGroup) + .width(width) + .height(height) + .transitionDuration(0); + return chart; + }; + + function getPieSliceBBoxY (chart, sliceNumber) { + return chart.select(`.pie-slice._${sliceNumber}`).node().getBBox().y; + } + + function getRingThicknessRounded (chart, ringNumber) { + if (ringNumber === 0) { + throw new Error('root ring 0 can not be checked this way.'); + } + const yInner = getPieSliceBBoxY(chart, ringNumber - 1); + const yOuter = getPieSliceBBoxY(chart, ringNumber); + return Math.round(Math.abs(yOuter - yInner)); + } + + describe('sunburst.defaultRingSizes: shrinking', () => { + let chart; + beforeEach(() => { + chart = buildSunburstChart3CompleteRings('sunburst_relativeRingSizes_regression'); + chart.render(); + }); + + it('rings should get narrower, farther away from the center', () => { + expect(getRingThicknessRounded(chart, 2)).toBeGreaterThan(0); + expect(getRingThicknessRounded(chart, 1)).toBeGreaterThan(getRingThicknessRounded(chart, 2)); + }); + }); + + describe('sunburst.relativeRingSizes: equal distribution', () => { + let chart; + beforeEach(() => { + chart = buildSunburstChart3CompleteRings('sunburst_relativeRingSizes_equal_distribution'); + chart.ringSizes(chart.equalRingSizes()); + chart.render(); + }); + it('rings should be equally wide', () => { + expect(getRingThicknessRounded(chart, 1)).toBeGreaterThan(0); + expect(getRingThicknessRounded(chart, 1)).toEqual(getRingThicknessRounded(chart, 2)); + }); + }); + + function testEqualRings (N) { + describe(`sunburst.relativeRingSizes: equal distribution - no rounding errors with ${N} rings`, () => { + let chart; + beforeEach(() => { + chart = buildSunburstChartNCompleteRings(N, 'sunburst_relativeRingSizes_equal_distribution_10rings'); + chart.ringSizes(chart.equalRingSizes()); + }); + it('chart renders without BadArgumentError caused by rounding issue in chart.relativeRingSizes() ' , () => { + expect(() => chart.render()).not.toThrow(); + }); + }); + } + for(let i=2; i<=27; ++i) {testEqualRings(i);} + + describe('sunburst.relativeRingSizes: specific percentages', () => { + let chart; + const specificPercentages = function (ringCount) { + return [.1, .3, .6]; + }; + beforeEach(() => { + chart = buildSunburstChart3CompleteRings('sunburst_relativeRingSizes_specific_percentages'); + chart.ringSizes(chart.relativeRingSizes(specificPercentages)); + expect(() => chart.render()).not.toThrow(); + }); + it('2nd ring should be half as wide as the 3rd ', () => { + expect(getRingThicknessRounded(chart, 1)).toBeGreaterThan(0); + expect(2 * getRingThicknessRounded(chart, 1)).toEqual(getRingThicknessRounded(chart, 2)); + }); + }); + + describe('sunburst.relativeRingSizes: invalid arguments', () => { + let chart; + + const functionReturnsNonArray = function (ringCount) { + return {}; + }; + + const tooManyPercentageValues = function (ringCount) { + return [.1, .1, .1, .1]; + }; + + const percentagesSumNot1 = function (ringCount) { + return [.5, .5, .5]; + }; + + beforeEach(() => { + chart = buildSunburstChart3CompleteRings('sunburst_relativeRingSizes_invalid_arguments'); + }); + + it('invalid arguments cause dc.errors.BadArgumentException, default function does not', () => { + chart.ringSizes(chart.relativeRingSizes(functionReturnsNonArray)); + expect(() => {chart.render()}).toThrowError(dc.BadArgumentException); + + chart.ringSizes(chart.relativeRingSizes(tooManyPercentageValues)); + expect(() => {chart.render()}).toThrowError(dc.BadArgumentException); + + chart.ringSizes(chart.relativeRingSizes(percentagesSumNot1)); + expect(() => {chart.render()}).toThrowError(dc.BadArgumentException); + + chart.ringSizes(chart.defaultRingSizes()); + chart.render(); + }); + }); + + }); + + + describe('accessibility sunburst', () => { + + let chart; + beforeEach(() => { + + const id = 'accessible-sunburst' + appendChartID(id); + chart = new dc.SunburstChart(`#${id}`); + chart + .dimension(countryRegionStateDimension) + .group(countryRegionStateGroup) + .width(width) + .height(height) + .transitionDuration(0) + .keyboardAccessible(true); + }) + + it('internal elements are focusable by keyboard', () => { + + chart.render(); + chart.selectAll('g.pie-slice path').each(function () { + const burst = d3.select(this); + expect(burst.attr('tabindex')).toEqual('0'); + }); + }); + + it('internal elements are clickable by pressing enter', () => { + + const clickHandlerSpy = jasmine.createSpy(); + chart.onClick = clickHandlerSpy; + chart.render(); + + const event = new Event('keydown'); + event.keyCode = 13; + + chart.selectAll('g.pie-slice path').each(function (d) { + this.dispatchEvent(event); + expect(clickHandlerSpy).toHaveBeenCalledWith(d); + clickHandlerSpy.calls.reset(); + }); + }); + }); + +}); diff --git a/spec/text-filter-widget-spec.js b/spec/text-filter-widget-spec.js new file mode 100644 index 0000000000..3191217621 --- /dev/null +++ b/spec/text-filter-widget-spec.js @@ -0,0 +1,83 @@ +/* global loadDateFixture, appendChartID */ +describe('dc.textFilterWidget', () => { + let dateFixture; + let id, chart, data; + let dimension, group; + + beforeEach(() => { + dateFixture = loadDateFixture(); + data = crossfilter(dateFixture); + dimension = data.dimension(d => `${d.countrycode} ${d.state}`); + group = dimension.group().reduceSum(d => 1); + + id = 'input-filter'; + appendChartID(id); + chart = new dc.TextFilterWidget(`#${id}`) + .dimension(dimension) + .group(group); + chart.render(); + }); + + describe('creation', () => { + it('generates something', () => { + expect(chart).not.toBeNull(); + }); + it('registers', () => { + expect(dc.hasChart(chart)).toBeTruthy(); + }); + it('sets an input field', () => { + expect(chart.selectAll('input').nodes().length).toEqual(1); + }); + it('doesn\'t filter by default', () => { + expect(chart.dimension().top(1000).length).toEqual(10); + }); + }); + + describe('default accessor functions', () => { + it('exists for normalize()', () => { + const normalize = chart.normalize(); + expect(typeof normalize).toBe('function'); + }); + it('exists for filterFunctionFactory()', () => { + const filterFunctionFactory = chart.filterFunctionFactory(); + expect(typeof filterFunctionFactory).toBe('function'); + }); + it('exists for placeHolder()', () => { + const placeHolder = chart.placeHolder(); + expect(typeof placeHolder).toBe('string'); + expect(placeHolder).toBe('search'); + }); + }); + + describe('filter when typing', () => { + const mockTyping = function (q) { + const i = d3.select('input'); + i.nodes()[0].value = q; + dc.d3compat.callHandler(i.on('input'), i.node(), {}, i.datum()); + }; + + beforeEach(() => { + chart.redraw(); + }); + + it('has a mock function that sets the value', () => { + mockTyping('42'); + expect(chart.selectAll('input').nodes()[0].value).toEqual('42'); + }); + + it('filters the dimension', () => { + mockTyping('lifo'); // Will match California + expect(chart.dimension().top(1000).length).toEqual(3); + }); + + it('filters the dimension in case insensitive way', () => { + mockTyping('LiFo'); // Will match California + expect(chart.dimension().top(1000).length).toEqual(3); + }); + + }); + + afterEach(() => { + dimension.filterAll(); + }); +}); diff --git a/spec/utils-spec.js b/spec/utils-spec.js index 46442da0ae..28720e661b 100644 --- a/spec/utils-spec.js +++ b/spec/utils-spec.js @@ -1,110 +1,198 @@ /* global makeDate */ -describe('dc utils', function () { - describe('dc.printer.filters', function () { - var printer; - beforeEach(function () { +describe('dc utils', () => { + describe('dc.printer.filters', () => { + let printer; + beforeEach(() => { printer = dc.printers.filters; }); - it('print simple string', function () { + it('print simple string', () => { expect(printer(['a'])).toEqual('a'); }); - it('print range', function () { + it('print range', () => { expect(printer([[10, 30]])).toEqual('[10 -> 30]'); }); - it('print simple string and a range', function () { + it('print simple string and a range', () => { expect(printer(['a', [10, 30]])).toEqual('a, [10 -> 30]'); }); }); - describe('dc.printer.filter', function () { - var printer; - beforeEach(function () { + describe('dc.printer.filter', () => { + let printer; + beforeEach(() => { printer = dc.printers.filter; - dc.dateFormat = d3.time.format.utc('%m/%d/%Y'); + dc.config.dateFormat = d3.utcFormat('%m/%d/%Y'); }); - it('print simple string', function () { + it('print simple string', () => { expect(printer('a')).toEqual('a'); }); - it('print date string', function () { + it('print date string', () => { expect(printer(makeDate(2012, 1, 1))).toEqual('02/01/2012'); }); - it('print int range', function () { + it('print int range', () => { expect(printer([10, 30])).toEqual('[10 -> 30]'); }); - it('print float range', function () { + it('print float range', () => { expect(printer([10.124244, 30.635623])).toEqual('[10.12 -> 30.64]'); }); - it('print date range', function () { + it('print date range', () => { expect(printer([makeDate(2012, 1, 1), makeDate(2012, 1, 15)])).toEqual('[02/01/2012 -> 02/15/2012]'); }); - it('print single element array', function () { + it('print single element array', () => { expect(printer([makeDate(2012, 1, 1)])).toEqual('02/01/2012'); }); - it('print null', function () { + it('print null', () => { expect(printer(null)).toEqual(''); }); - it('print zero', function () { + it('print zero', () => { expect(printer(0)).toEqual(0); }); + it('print a multi-element array', () => { + expect(printer(['this', 'that', 'and', 'the', 'other'])).toEqual('[this -> that -> and -> the -> other]'); + }); }); - describe('dc.utils.nameToId', function () { - it('id should be escaped properly', function () { + describe('dc.utils.nameToId', () => { + it('id should be escaped properly', () => { expect(dc.utils.nameToId('St. John\'s')).toEqual('st_johns'); }); }); - describe('dc.utils.add', function () { - var add; - beforeEach(function () { + describe('dc.utils.add', () => { + let add; + beforeEach(() => { add = dc.utils.add; }); - it('should be able to add days', function () { - var date = add(makeDate(2012, 0, 1), 10); + it('should be able to add days', () => { + const date = add(makeDate(2012, 0, 1), 10); expect(date.toString()).toEqual((makeDate(2012, 0, 11)).toString()); }); - it('should be able to add numbers', function () { - var num = add(10, 10); + it('should be able to add numbers', () => { + const num = add(10, 10); expect(num).toEqual(20); }); - it('should be able to add numbers w/ %', function () { - var num = add(10, '10%'); + it('should be able to add numbers w/ %', () => { + const num = add(10, '10%'); expect(num).toEqual(11); }); - it('should be able to add negative numbers w/ %', function () { - var num = add(-10, '10%'); + it('should be able to add negative numbers w/ %', () => { + const num = add(-10, '10%'); expect(num).toEqual(-9); }); - it('should ignore % when adding dates', function () { - var date = add(makeDate(2012, 0, 1), '10%'); + it('should ignore % when adding dates', () => { + const date = add(makeDate(2012, 0, 1), '10%'); expect(date.toString()).toEqual(makeDate(2012, 0, 11).toString()); }); + it('should be able to add hours to dates', () => { + const date = add(makeDate(2012, 0, 1), '24', 'hour'); + expect(date.toString()).toEqual(makeDate(2012, 0, 2).toString()); + }); + it('should be able to add weeks to dates', () => { + const date = add(makeDate(2012, 0, 1), '1', 'week'); + expect(date.toString()).toEqual(makeDate(2012, 0, 8).toString()); + }); + it('should be able to add month to dates', () => { + const date = add(makeDate(2012, 0, 1), '1', 'month'); + expect(date.toString()).toEqual(makeDate(2012, 1, 1).toString()); + }); }); - describe('dc.utils.subtract', function () { - var subtract; - beforeEach(function () { + describe('dc.utils.subtract', () => { + let subtract; + beforeEach(() => { subtract = dc.utils.subtract; }); - it('should be able to subtract dates', function () { - var date = subtract(makeDate(2012, 0, 11), 10); + it('should be able to subtract dates', () => { + const date = subtract(makeDate(2012, 0, 11), 10); expect(date.toString()).toEqual((makeDate(2012, 0, 1)).toString()); }); - it('should be able to subtract numbers', function () { - var num = subtract(10, 10); + it('should be able to subtract numbers', () => { + const num = subtract(10, 10); expect(num).toEqual(0); }); - it('should be able to subtract numbers w/ %', function () { - var num = subtract(10, '10%'); + it('should be able to subtract numbers w/ %', () => { + const num = subtract(10, '10%'); expect(num).toEqual(9); }); - it('should be able to subtract negative numbers w/ %', function () { - var num = subtract(-10, '10%'); + it('should be able to subtract negative numbers w/ %', () => { + const num = subtract(-10, '10%'); expect(num).toEqual(-11); }); - it('should ignore % when subtracting dates', function () { - var date = subtract(makeDate(2012, 0, 11), '10%'); + it('should ignore % when subtracting dates', () => { + const date = subtract(makeDate(2012, 0, 11), '10%'); + expect(date.toString()).toEqual(makeDate(2012, 0, 1).toString()); + }); + it('should be able to subtract hours from dates', () => { + const date = subtract(makeDate(2012, 0, 2), '24', 'hour'); + expect(date.toString()).toEqual(makeDate(2012, 0, 1).toString()); + }); + it('should be able to subtract week from dates', () => { + const date = subtract(makeDate(2012, 0, 8), '1', 'week'); + expect(date.toString()).toEqual(makeDate(2012, 0, 1).toString()); + }); + it('should be able to subtract month from dates', () => { + const date = subtract(makeDate(2012, 1, 1), '1', 'month'); expect(date.toString()).toEqual(makeDate(2012, 0, 1).toString()); }); }); + describe('dc.utils.arraysEqual', () => { + it('nulls should be equal', () => { + const a1 = null; + const a2 = null; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('null and undefined should be equal', () => { + const a1 = null; + let a2; // undefined + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('null should not be equal to any array', () => { + const a1 = null; + const a2 = []; + expect(dc.utils.arraysEqual(a1, a2)).toBe(false); + }); + it('any array should not be equal to null', () => { + const a1 = null; + const a2 = []; + expect(dc.utils.arraysEqual(a1, a2)).toBe(false); + }); + it('empty arrays should be', () => { + const a1 = []; + const a2 = []; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('should identify equal arrays - numbers', () => { + const a1 = [1, 2, 3]; + const a2 = [1, 2, 3]; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('should identify equal arrays - strings', () => { + const a1 = ['apple', 'mangoes', 'oranges', 'bananas']; + const a2 = ['apple', 'mangoes', 'oranges', 'bananas']; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('should identify equal arrays - dates', () => { + const a1 = [makeDate(2012, 1, 1), makeDate(2013, 10, 15)]; + const a2 = [makeDate(2012, 1, 1), makeDate(2013, 10, 15)]; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + it('should identify unequal arrays - numbers', () => { + const a1 = [4, 2, 3]; + const a2 = [1, 2, 3]; + expect(dc.utils.arraysEqual(a1, a2)).toBe(false); + }); + it('should identify unequal arrays - strings', () => { + const a1 = ['apple', 'cherries', 'oranges', 'bananas']; + const a2 = ['apple', 'mangoes', 'oranges', 'bananas']; + expect(dc.utils.arraysEqual(a1, a2)).toBe(false); + }); + it('should identify unequal arrays - dates', () => { + const a1 = [makeDate(2012, 1, 1), makeDate(2013, 10, 15)]; + const a2 = [makeDate(2012, 1, 1), makeDate(2013, 10, 16)]; + expect(dc.utils.arraysEqual(a1, a2)).toBe(false); + }); + it('should identify equal arrays with one of the elements as 0', () => { + const a1 = [0, 20]; + const a2 = [0, 20]; + expect(dc.utils.arraysEqual(a1, a2)).toBe(true); + }); + }); }); - diff --git a/src/banner.js b/src/banner.js deleted file mode 100644 index 59be0972f3..0000000000 --- a/src/banner.js +++ /dev/null @@ -1,2 +0,0 @@ -(function() { function _dc(d3, crossfilter) { -'use strict'; diff --git a/src/bar-chart.js b/src/bar-chart.js deleted file mode 100644 index 587ebf899f..0000000000 --- a/src/bar-chart.js +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Concrete bar chart/histogram implementation. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class barChart - * @memberof dc - * @mixes dc.stackMixin - * @mixes dc.coordinateGridMixin - * @example - * // create a bar chart under #chart-container1 element using the default global chart group - * var chart1 = dc.barChart('#chart-container1'); - * // create a bar chart under #chart-container2 element using chart group A - * var chart2 = dc.barChart('#chart-container2', 'chartGroupA'); - * // create a sub-chart under a composite parent chart - * var chart3 = dc.barChart(compositeChart); - * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} - * specifying a dom block element such as a div; or a dom element or d3 selection. If the bar - * chart is a sub-chart in a {@link dc.compositeChart Composite Chart} then pass in the parent - * composite chart instance instead. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.barChart} - */ -dc.barChart = function (parent, chartGroup) { - var MIN_BAR_WIDTH = 1; - var DEFAULT_GAP_BETWEEN_BARS = 2; - var LABEL_PADDING = 3; - - var _chart = dc.stackMixin(dc.coordinateGridMixin({})); - - var _gap = DEFAULT_GAP_BETWEEN_BARS; - var _centerBar = false; - var _alwaysUseRounding = false; - - var _barWidth; - - dc.override(_chart, 'rescale', function () { - _chart._rescale(); - _barWidth = undefined; - return _chart; - }); - - dc.override(_chart, 'render', function () { - if (_chart.round() && _centerBar && !_alwaysUseRounding) { - dc.logger.warn('By default, brush rounding is disabled if bars are centered. ' + - 'See dc.js bar chart API documentation for details.'); - } - - return _chart._render(); - }); - - _chart.label(function (d) { - return dc.utils.printSingleValue(d.y0 + d.y); - }, false); - - _chart.plotData = function () { - var layers = _chart.chartBodyG().selectAll('g.stack') - .data(_chart.data()); - - calculateBarWidth(); - - layers - .enter() - .append('g') - .attr('class', function (d, i) { - return 'stack ' + '_' + i; - }); - - var last = layers.size() - 1; - layers.each(function (d, i) { - var layer = d3.select(this); - - renderBars(layer, i, d); - - if (_chart.renderLabel() && last === i) { - renderLabels(layer, i, d); - } - }); - }; - - function barHeight (d) { - return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0))); - } - - function renderLabels (layer, layerIndex, d) { - var labels = layer.selectAll('text.barLabel') - .data(d.values, dc.pluck('x')); - - labels.enter() - .append('text') - .attr('class', 'barLabel') - .attr('text-anchor', 'middle'); - - if (_chart.isOrdinal()) { - labels.on('click', _chart.onClick); - labels.attr('cursor', 'pointer'); - } - - dc.transition(labels, _chart.transitionDuration()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - if (!_centerBar) { - x += _barWidth / 2; - } - return dc.utils.safeNumber(x); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0); - - if (d.y < 0) { - y -= barHeight(d); - } - - return dc.utils.safeNumber(y - LABEL_PADDING); - }) - .text(function (d) { - return _chart.label()(d); - }); - - dc.transition(labels.exit(), _chart.transitionDuration()) - .attr('height', 0) - .remove(); - } - - function renderBars (layer, layerIndex, d) { - var bars = layer.selectAll('rect.bar') - .data(d.values, dc.pluck('x')); - - var enter = bars.enter() - .append('rect') - .attr('class', 'bar') - .attr('fill', dc.pluck('data', _chart.getColor)) - .attr('y', _chart.yAxisHeight()) - .attr('height', 0); - - if (_chart.renderTitle()) { - enter.append('title').text(dc.pluck('data', _chart.title(d.name))); - } - - if (_chart.isOrdinal()) { - bars.on('click', _chart.onClick); - } - - dc.transition(bars, _chart.transitionDuration()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - if (_centerBar) { - x -= _barWidth / 2; - } - if (_chart.isOrdinal() && _gap !== undefined) { - x += _gap / 2; - } - return dc.utils.safeNumber(x); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0); - - if (d.y < 0) { - y -= barHeight(d); - } - - return dc.utils.safeNumber(y); - }) - .attr('width', _barWidth) - .attr('height', function (d) { - return barHeight(d); - }) - .attr('fill', dc.pluck('data', _chart.getColor)) - .select('title').text(dc.pluck('data', _chart.title(d.name))); - - dc.transition(bars.exit(), _chart.transitionDuration()) - .attr('x', function (d) { return _chart.x()(d.x); }) - .attr('width', _barWidth * 0.9) - .remove(); - } - - function calculateBarWidth () { - if (_barWidth === undefined) { - var numberOfBars = _chart.xUnitCount(); - - // please can't we always use rangeBands for bar charts? - if (_chart.isOrdinal() && _gap === undefined) { - _barWidth = Math.floor(_chart.x().rangeBand()); - } else if (_gap) { - _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); - } else { - _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); - } - - if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) { - _barWidth = MIN_BAR_WIDTH; - } - } - } - - _chart.fadeDeselectedArea = function () { - var bars = _chart.chartBodyG().selectAll('rect.bar'); - var extent = _chart.brush().extent(); - - if (_chart.isOrdinal()) { - if (_chart.hasFilter()) { - bars.classed(dc.constants.SELECTED_CLASS, function (d) { - return _chart.hasFilter(d.x); - }); - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return !_chart.hasFilter(d.x); - }); - } else { - bars.classed(dc.constants.SELECTED_CLASS, false); - bars.classed(dc.constants.DESELECTED_CLASS, false); - } - } else { - if (!_chart.brushIsEmpty(extent)) { - var start = extent[0]; - var end = extent[1]; - - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return d.x < start || d.x >= end; - }); - } else { - bars.classed(dc.constants.DESELECTED_CLASS, false); - } - } - }; - - /** - * Whether the bar chart will render each bar centered around the data position on the x-axis. - * @method centerBar - * @memberof dc.barChart - * @instance - * @param {Boolean} [centerBar=false] - * @return {Boolean} - * @return {dc.barChart} - */ - _chart.centerBar = function (centerBar) { - if (!arguments.length) { - return _centerBar; - } - _centerBar = centerBar; - return _chart; - }; - - dc.override(_chart, 'onClick', function (d) { - _chart._onClick(d.data); - }); - - /** - * Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1. - * Setting this value will also remove any previously set {@link dc.barChart#gap gap}. See the - * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs} - * for a visual description of how the padding is applied. - * @method barPadding - * @memberof dc.barChart - * @instance - * @param {Number} [barPadding=0] - * @return {Number} - * @return {dc.barChart} - */ - _chart.barPadding = function (barPadding) { - if (!arguments.length) { - return _chart._rangeBandPadding(); - } - _chart._rangeBandPadding(barPadding); - _gap = undefined; - return _chart; - }; - - _chart._useOuterPadding = function () { - return _gap === undefined; - }; - - /** - * Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts. - * Will pad the width by `padding * barWidth` on each side of the chart. - * @method outerPadding - * @memberof dc.barChart - * @instance - * @param {Number} [padding=0.5] - * @return {Number} - * @return {dc.barChart} - */ - _chart.outerPadding = _chart._outerRangeBandPadding; - - /** - * Manually set fixed gap (in px) between bars instead of relying on the default auto-generated - * gap. By default the bar chart implementation will calculate and set the gap automatically - * based on the number of data points and the length of the x axis. - * @method gap - * @memberof dc.barChart - * @instance - * @param {Number} [gap=2] - * @return {Number} - * @return {dc.barChart} - */ - _chart.gap = function (gap) { - if (!arguments.length) { - return _gap; - } - _gap = gap; - return _chart; - }; - - _chart.extendBrush = function () { - var extent = _chart.brush().extent(); - if (_chart.round() && (!_centerBar || _alwaysUseRounding)) { - extent[0] = extent.map(_chart.round())[0]; - extent[1] = extent.map(_chart.round())[1]; - - _chart.chartBodyG().select('.brush') - .call(_chart.brush().extent(extent)); - } - - return extent; - }; - - /** - * Set or get whether rounding is enabled when bars are centered. If false, using - * rounding with centered bars will result in a warning and rounding will be ignored. This flag - * has no effect if bars are not {@link dc.barChart#centerBar centered}. - * When using standard d3.js rounding methods, the brush often doesn't align correctly with - * centered bars since the bars are offset. The rounding function must add an offset to - * compensate, such as in the following example. - * @method alwaysUseRounding - * @memberof dc.barChart - * @instance - * @example - * chart.round(function(n) { return Math.floor(n) + 0.5; }); - * @param {Boolean} [alwaysUseRounding=false] - * @return {Boolean} - * @return {dc.barChart} - */ - _chart.alwaysUseRounding = function (alwaysUseRounding) { - if (!arguments.length) { - return _alwaysUseRounding; - } - _alwaysUseRounding = alwaysUseRounding; - return _chart; - }; - - function colorFilter (color, inv) { - return function () { - var item = d3.select(this); - var match = item.attr('fill') === color; - return inv ? !match : match; - }; - } - - _chart.legendHighlight = function (d) { - if (!_chart.isLegendableHidden(d)) { - _chart.g().selectAll('rect.bar') - .classed('highlight', colorFilter(d.color)) - .classed('fadeout', colorFilter(d.color, true)); - } - }; - - _chart.legendReset = function () { - _chart.g().selectAll('rect.bar') - .classed('highlight', false) - .classed('fadeout', false); - }; - - dc.override(_chart, 'xAxisMax', function () { - var max = this._xAxisMax(); - if ('resolution' in _chart.xUnits()) { - var res = _chart.xUnits().resolution; - max += res; - } - return max; - }); - - return _chart.anchor(parent, chartGroup); -}; diff --git a/src/base-mixin.js b/src/base-mixin.js deleted file mode 100644 index 0ec5fcdeab..0000000000 --- a/src/base-mixin.js +++ /dev/null @@ -1,1517 +0,0 @@ -/** - * `dc.baseMixin` is an abstract functional object representing a basic `dc` chart object - * for all chart and widget implementations. Methods from the {@link #dc.baseMixin dc.baseMixin} are inherited - * and available on all chart implementations in the `dc` library. - * @name baseMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.baseMixin} - */ -dc.baseMixin = function (_chart) { - _chart.__dcFlag__ = dc.utils.uniqueId(); - - var _dimension; - var _group; - - var _anchor; - var _root; - var _svg; - var _isChild; - - var _minWidth = 200; - var _defaultWidthCalc = function (element) { - var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; - return (width && width > _minWidth) ? width : _minWidth; - }; - var _widthCalc = _defaultWidthCalc; - - var _minHeight = 200; - var _defaultHeightCalc = function (element) { - var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; - return (height && height > _minHeight) ? height : _minHeight; - }; - var _heightCalc = _defaultHeightCalc; - var _width, _height; - - var _keyAccessor = dc.pluck('key'); - var _valueAccessor = dc.pluck('value'); - var _label = dc.pluck('key'); - - var _ordering = dc.pluck('key'); - var _orderSort; - - var _renderLabel = false; - - var _title = function (d) { - return _chart.keyAccessor()(d) + ': ' + _chart.valueAccessor()(d); - }; - var _renderTitle = true; - var _controlsUseVisibility = false; - - var _transitionDuration = 750; - - var _filterPrinter = dc.printers.filters; - - var _mandatoryAttributes = ['dimension', 'group']; - - var _chartGroup = dc.constants.DEFAULT_CHART_GROUP; - - var _listeners = d3.dispatch( - 'preRender', - 'postRender', - 'preRedraw', - 'postRedraw', - 'filtered', - 'zoomed', - 'renderlet', - 'pretransition'); - - var _legend; - var _commitHandler; - - var _filters = []; - var _filterHandler = function (dimension, filters) { - if (filters.length === 0) { - dimension.filter(null); - } else if (filters.length === 1 && !filters[0].isFiltered) { - // single value and not a function-based filter - dimension.filterExact(filters[0]); - } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { - // single range-based filter - dimension.filterRange(filters[0]); - } else { - dimension.filterFunction(function (d) { - for (var i = 0; i < filters.length; i++) { - var filter = filters[i]; - if (filter.isFiltered && filter.isFiltered(d)) { - return true; - } else if (filter <= d && filter >= d) { - return true; - } - } - return false; - }); - } - return filters; - }; - - var _data = function (group) { - return group.all(); - }; - - /** - * Set or get the height attribute of a chart. The height is applied to the SVGElement generated by - * the chart when rendered (or re-rendered). If a value is given, then it will be used to calculate - * the new height and the chart returned for method chaining. The value can either be a numeric, a - * function, or falsy. If no value is specified then the value of the current height attribute will - * be returned. - * - * By default, without an explicit height being given, the chart will select the width of its - * anchor element. If that isn't possible it defaults to 200 (provided by the - * {@link dc.baseMixin#minHeight minHeight} property). Setting the value falsy will return - * the chart to the default behavior. - * @method height - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#minHeight minHeight} - * @example - * // Default height - * chart.height(function (element) { - * var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; - * return (height && height > chart.minHeight()) ? height : chart.minHeight(); - * }); - * - * chart.height(250); // Set the chart's height to 250px; - * chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function - * chart.height(null); // reset the height to the default auto calculation - * @param {Number|Function} [height] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.height = function (height) { - if (!arguments.length) { - if (!dc.utils.isNumber(_height)) { - // only calculate once - _height = _heightCalc(_root.node()); - } - return _height; - } - _heightCalc = d3.functor(height || _defaultHeightCalc); - _height = undefined; - return _chart; - }; - - /** - * Set or get the width attribute of a chart. - * @method width - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#height height} - * @see {@link dc.baseMixin#minWidth minWidth} - * @example - * // Default width - * chart.width(function (element) { - * var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; - * return (width && width > chart.minWidth()) ? width : chart.minWidth(); - * }); - * @param {Number|Function} [width] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.width = function (width) { - if (!arguments.length) { - if (!dc.utils.isNumber(_width)) { - // only calculate once - _width = _widthCalc(_root.node()); - } - return _width; - } - _widthCalc = d3.functor(width || _defaultWidthCalc); - _width = undefined; - return _chart; - }; - - /** - * Set or get the minimum width attribute of a chart. This only has effect when used with the default - * {@link dc.baseMixin#width width} function. - * @method minWidth - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#width width} - * @param {Number} [minWidth=200] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.minWidth = function (minWidth) { - if (!arguments.length) { - return _minWidth; - } - _minWidth = minWidth; - return _chart; - }; - - /** - * Set or get the minimum height attribute of a chart. This only has effect when used with the default - * {@link dc.baseMixin#height height} function. - * @method minHeight - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#height height} - * @param {Number} [minHeight=200] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.minHeight = function (minHeight) { - if (!arguments.length) { - return _minHeight; - } - _minHeight = minHeight; - return _chart; - }; - - /** - * **mandatory** - * - * Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid [crossfilter - * dimension](https://github.com/square/crossfilter/wiki/API-Reference#wiki-dimension). - * - * If a value is given, then it will be used as the new dimension. If no value is specified then - * the current dimension will be returned. - * @method dimension - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension crossfilter.dimension} - * @example - * var index = crossfilter([]); - * var dimension = index.dimension(dc.pluck('key')); - * chart.dimension(dimension); - * @param {crossfilter.dimension} [dimension] - * @return {crossfilter.dimension} - * @return {dc.baseMixin} - */ - _chart.dimension = function (dimension) { - if (!arguments.length) { - return _dimension; - } - _dimension = dimension; - _chart.expireCache(); - return _chart; - }; - - /** - * Set the data callback or retrieve the chart's data set. The data callback is passed the chart's - * group and by default will return - * {@link https://github.com/square/crossfilter/wiki/API-Reference#group_all group.all}. - * This behavior may be modified to, for instance, return only the top 5 groups. - * @method data - * @memberof dc.baseMixin - * @instance - * @example - * // Default data function - * chart.data(function (group) { return group.all(); }); - * - * chart.data(function (group) { return group.top(5); }); - * @param {Function} [callback] - * @return {*} - * @return {dc.baseMixin} - */ - _chart.data = function (callback) { - if (!arguments.length) { - return _data.call(_chart, _group); - } - _data = d3.functor(callback); - _chart.expireCache(); - return _chart; - }; - - /** - * **mandatory** - * - * Set or get the group attribute of a chart. In `dc` a group is a - * {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter group}. - * Usually the group should be created from the particular dimension associated with the same chart. If a value is - * given, then it will be used as the new group. - * - * If no value specified then the current group will be returned. - * If `name` is specified then it will be used to generate legend label. - * @method group - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} - * @example - * var index = crossfilter([]); - * var dimension = index.dimension(dc.pluck('key')); - * chart.dimension(dimension); - * chart.group(dimension.group(crossfilter.reduceSum())); - * @param {crossfilter.group} [group] - * @param {String} [name] - * @return {crossfilter.group} - * @return {dc.baseMixin} - */ - _chart.group = function (group, name) { - if (!arguments.length) { - return _group; - } - _group = group; - _chart._groupName = name; - _chart.expireCache(); - return _chart; - }; - - /** - * Get or set an accessor to order ordinal dimensions. The chart uses - * {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by} - * to sort elements; this accessor returns the value to order on. - * @method ordering - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by} - * @example - * // Default ordering accessor - * _chart.ordering(dc.pluck('key')); - * @param {Function} [orderFunction] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.ordering = function (orderFunction) { - if (!arguments.length) { - return _ordering; - } - _ordering = orderFunction; - _orderSort = crossfilter.quicksort.by(_ordering); - _chart.expireCache(); - return _chart; - }; - - _chart._computeOrderedGroups = function (data) { - var dataCopy = data.slice(0); - - if (dataCopy.length <= 1) { - return dataCopy; - } - - if (!_orderSort) { - _orderSort = crossfilter.quicksort.by(_ordering); - } - - return _orderSort(dataCopy, 0, dataCopy.length); - }; - - /** - * Clear all filters associated with this chart - * - * The same can be achieved by calling {@link dc.baseMixin#filter chart.filter(null)}. - * @method filterAll - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.filterAll = function () { - return _chart.filter(null); - }; - - /** - * Execute d3 single selection in the chart's scope using the given selector and return the d3 - * selection. - * - * This function is **not chainable** since it does not return a chart instance; however the d3 - * selection result can be chained to d3 function calls. - * @method select - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection} - * @example - * // Similar to: - * d3.select('#chart-id').select(selector); - * @return {d3.selection} - */ - _chart.select = function (s) { - return _root.select(s); - }; - - /** - * Execute in scope d3 selectAll using the given selector and return d3 selection result. - * - * This function is **not chainable** since it does not return a chart instance; however the d3 - * selection result can be chained to d3 function calls. - * @method selectAll - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection} - * @example - * // Similar to: - * d3.select('#chart-id').selectAll(selector); - * @return {d3.selection} - */ - _chart.selectAll = function (s) { - return _root ? _root.selectAll(s) : null; - }; - - /** - * Set the root SVGElement to either be an existing chart's root; or any valid [d3 single - * selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom - * block element such as a div; or a dom element or d3 selection. Optionally registers the chart - * within the chartGroup. This class is called internally on chart initialization, but be called - * again to relocate the chart. However, it will orphan any previously created SVGElements. - * @method anchor - * @memberof dc.baseMixin - * @instance - * @param {anchorChart|anchorSelector|anchorNode} [parent] - * @param {String} [chartGroup] - * @return {String|node|d3.selection} - * @return {dc.baseMixin} - */ - _chart.anchor = function (parent, chartGroup) { - if (!arguments.length) { - return _anchor; - } - if (dc.instanceOfChart(parent)) { - _anchor = parent.anchor(); - _root = parent.root(); - _isChild = true; - } else if (parent) { - if (parent.select && parent.classed) { // detect d3 selection - _anchor = parent.node(); - } else { - _anchor = parent; - } - _root = d3.select(_anchor); - _root.classed(dc.constants.CHART_CLASS, true); - dc.registerChart(_chart, chartGroup); - _isChild = false; - } else { - throw new dc.errors.BadArgumentException('parent must be defined'); - } - _chartGroup = chartGroup; - return _chart; - }; - - /** - * Returns the DOM id for the chart's anchored location. - * @method anchorName - * @memberof dc.baseMixin - * @instance - * @return {String} - */ - _chart.anchorName = function () { - var a = _chart.anchor(); - if (a && a.id) { - return a.id; - } - if (a && a.replace) { - return a.replace('#', ''); - } - return 'dc-chart' + _chart.chartID(); - }; - - /** - * Returns the root element where a chart resides. Usually it will be the parent div element where - * the SVGElement was created. You can also pass in a new root element however this is usually handled by - * dc internally. Resetting the root element on a chart outside of dc internals may have - * unexpected consequences. - * @method root - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement HTMLElement} - * @param {HTMLElement} [rootElement] - * @return {HTMLElement} - * @return {dc.baseMixin} - */ - _chart.root = function (rootElement) { - if (!arguments.length) { - return _root; - } - _root = rootElement; - return _chart; - }; - - /** - * Returns the top SVGElement for this specific chart. You can also pass in a new SVGElement, - * however this is usually handled by dc internally. Resetting the SVGElement on a chart outside - * of dc internals may have unexpected consequences. - * @method svg - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} - * @param {SVGElement|d3.selection} [svgElement] - * @return {SVGElement|d3.selection} - * @return {dc.baseMixin} - */ - _chart.svg = function (svgElement) { - if (!arguments.length) { - return _svg; - } - _svg = svgElement; - return _chart; - }; - - /** - * Remove the chart's SVGElements from the dom and recreate the container SVGElement. - * @method resetSvg - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} - * @return {SVGElement} - */ - _chart.resetSvg = function () { - _chart.select('svg').remove(); - return generateSvg(); - }; - - function sizeSvg () { - if (_svg) { - _svg - .attr('width', _chart.width()) - .attr('height', _chart.height()); - } - } - - function generateSvg () { - _svg = _chart.root().append('svg'); - sizeSvg(); - return _svg; - } - - /** - * Set or get the filter printer function. The filter printer function is used to generate human - * friendly text for filter value(s) associated with the chart instance. By default dc charts use a - * default filter printer `dc.printers.filter` that provides simple printing support for both - * single value and ranged filters. - * @method filterPrinter - * @memberof dc.baseMixin - * @instance - * @param {Function} [filterPrinterFunction=dc.printers.filter] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.filterPrinter = function (filterPrinterFunction) { - if (!arguments.length) { - return _filterPrinter; - } - _filterPrinter = filterPrinterFunction; - return _chart; - }; - - /** - * If set, use the `visibility` attribute instead of the `display` attribute for showing/hiding - * chart reset and filter controls, for less disruption to the layout. - * @method controlsUseVisibility - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [controlsUseVisibility=false] - * @return {Boolean} - * @return {dc.baseMixin} - **/ - _chart.controlsUseVisibility = function (useVisibility) { - if (!arguments.length) { - return _controlsUseVisibility; - } - _controlsUseVisibility = useVisibility; - return _chart; - }; - - /** - * Turn on optional control elements within the root element. dc currently supports the - * following html control elements. - * * root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type - * of control element is usually used to store a reset link to allow user to reset filter on a - * certain chart. This element will be turned off automatically if the filter is cleared. - * * root.selectAll('.filter') elements are turned on if the chart has an active filter. The text - * content of this element is then replaced with the current filter value using the filter printer - * function. This type of element will be turned off automatically if the filter is cleared. - * @method turnOnControls - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.turnOnControls = function () { - if (_root) { - var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display'; - _chart.selectAll('.reset').style(attribute, null); - _chart.selectAll('.filter').text(_filterPrinter(_chart.filters())).style(attribute, null); - } - return _chart; - }; - - /** - * Turn off optional control elements within the root element. - * @method turnOffControls - * @memberof dc.baseMixin - * @see {@link dc.baseMixin#turnOnControls turnOnControls} - * @instance - * @return {dc.baseMixin} - */ - _chart.turnOffControls = function () { - if (_root) { - var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display'; - var value = _chart.controlsUseVisibility() ? 'hidden' : 'none'; - _chart.selectAll('.reset').style(attribute, value); - _chart.selectAll('.filter').style(attribute, value).text(_chart.filter()); - } - return _chart; - }; - - /** - * Set or get the animation transition duration (in milliseconds) for this chart instance. - * @method transitionDuration - * @memberof dc.baseMixin - * @instance - * @param {Number} [duration=750] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.transitionDuration = function (duration) { - if (!arguments.length) { - return _transitionDuration; - } - _transitionDuration = duration; - return _chart; - }; - - _chart._mandatoryAttributes = function (_) { - if (!arguments.length) { - return _mandatoryAttributes; - } - _mandatoryAttributes = _; - return _chart; - }; - - function checkForMandatoryAttributes (a) { - if (!_chart[a] || !_chart[a]()) { - throw new dc.errors.InvalidStateException('Mandatory attribute chart.' + a + - ' is missing on chart[#' + _chart.anchorName() + ']'); - } - } - - /** - * Invoking this method will force the chart to re-render everything from scratch. Generally it - * should only be used to render the chart for the first time on the page or if you want to make - * sure everything is redrawn from scratch instead of relying on the default incremental redrawing - * behaviour. - * @method render - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.render = function () { - _height = _width = undefined; // force recalculate - _listeners.preRender(_chart); - - if (_mandatoryAttributes) { - _mandatoryAttributes.forEach(checkForMandatoryAttributes); - } - - var result = _chart._doRender(); - - if (_legend) { - _legend.render(); - } - - _chart._activateRenderlets('postRender'); - - return result; - }; - - _chart._activateRenderlets = function (event) { - _listeners.pretransition(_chart); - if (_chart.transitionDuration() > 0 && _svg) { - _svg.transition().duration(_chart.transitionDuration()) - .each('end', function () { - _listeners.renderlet(_chart); - if (event) { - _listeners[event](_chart); - } - }); - } else { - _listeners.renderlet(_chart); - if (event) { - _listeners[event](_chart); - } - } - }; - - /** - * Calling redraw will cause the chart to re-render data changes incrementally. If there is no - * change in the underlying data dimension then calling this method will have no effect on the - * chart. Most chart interaction in dc will automatically trigger this method through internal - * events (in particular {@link dc.redrawAll dc.redrawAll}); therefore, you only need to - * manually invoke this function if data is manipulated outside of dc's control (for example if - * data is loaded in the background using - * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add}. - * @method redraw - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.redraw = function () { - sizeSvg(); - _listeners.preRedraw(_chart); - - var result = _chart._doRedraw(); - - if (_legend) { - _legend.render(); - } - - _chart._activateRenderlets('postRedraw'); - - return result; - }; - - /** - * Gets/sets the commit handler. If the chart has a commit handler, the handler will be called when - * the chart's filters have changed, in order to send the filter data asynchronously to a server. - * - * Unlike other functions in dc.js, the commit handler is asynchronous. It takes two arguments: - * a flag indicating whether this is a render (true) or a redraw (false), and a callback to be - * triggered once the commit is filtered. The callback has the standard node.js continuation signature - * with error first and result second. - * @method commitHandler - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.commitHandler = function (commitHandler) { - if (!arguments.length) { - return _commitHandler; - } - _commitHandler = commitHandler; - return _chart; - }; - - /** - * Redraws all charts in the same group as this chart, typically in reaction to a filter - * change. If the chart has a {@link dc.baseMixin.commitFilter commitHandler}, it will - * be executed and waited for. - * @method redrawGroup - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.redrawGroup = function () { - if (_commitHandler) { - _commitHandler(false, function (error, result) { - if (error) { - console.log(error); - } else { - dc.redrawAll(_chart.chartGroup()); - } - }); - } else { - dc.redrawAll(_chart.chartGroup()); - } - return _chart; - }; - - /** - * Renders all charts in the same group as this chart. If the chart has a - * {@link dc.baseMixin.commitFilter commitHandler}, it will be executed and waited for - * @method renderGroup - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.renderGroup = function () { - if (_commitHandler) { - _commitHandler(false, function (error, result) { - if (error) { - console.log(error); - } else { - dc.renderAll(_chart.chartGroup()); - } - }); - } else { - dc.renderAll(_chart.chartGroup()); - } - return _chart; - }; - - _chart._invokeFilteredListener = function (f) { - if (f !== undefined) { - _listeners.filtered(_chart, f); - } - }; - - _chart._invokeZoomedListener = function () { - _listeners.zoomed(_chart); - }; - - var _hasFilterHandler = function (filters, filter) { - if (filter === null || typeof(filter) === 'undefined') { - return filters.length > 0; - } - return filters.some(function (f) { - return filter <= f && filter >= f; - }); - }; - - /** - * Set or get the has-filter handler. The has-filter handler is a function that checks to see if - * the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows - * you to change the way filters are checked for and replaced. - * @method hasFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default has-filter handler - * chart.hasFilterHandler(function (filters, filter) { - * if (filter === null || typeof(filter) === 'undefined') { - * return filters.length > 0; - * } - * return filters.some(function (f) { - * return filter <= f && filter >= f; - * }); - * }); - * - * // custom filter handler (no-op) - * chart.hasFilterHandler(function(filters, filter) { - * return false; - * }); - * @param {Function} [hasFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.hasFilterHandler = function (hasFilterHandler) { - if (!arguments.length) { - return _hasFilterHandler; - } - _hasFilterHandler = hasFilterHandler; - return _chart; - }; - - /** - * Check whether any active filter or a specific filter is associated with particular chart instance. - * This function is **not chainable**. - * @method hasFilter - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#hasFilterHandler hasFilterHandler} - * @param {*} [filter] - * @return {Boolean} - */ - _chart.hasFilter = function (filter) { - return _hasFilterHandler(_filters, filter); - }; - - var _removeFilterHandler = function (filters, filter) { - for (var i = 0; i < filters.length; i++) { - if (filters[i] <= filter && filters[i] >= filter) { - filters.splice(i, 1); - break; - } - } - return filters; - }; - - /** - * Set or get the remove filter handler. The remove filter handler is a function that removes a - * filter from the chart's current filters. Using a custom remove filter handler allows you to - * change how filters are removed or perform additional work when removing a filter, e.g. when - * using a filter server other than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method removeFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default remove filter handler - * chart.removeFilterHandler(function (filters, filter) { - * for (var i = 0; i < filters.length; i++) { - * if (filters[i] <= filter && filters[i] >= filter) { - * filters.splice(i, 1); - * break; - * } - * } - * return filters; - * }); - * - * // custom filter handler (no-op) - * chart.removeFilterHandler(function(filters, filter) { - * return filters; - * }); - * @param {Function} [removeFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.removeFilterHandler = function (removeFilterHandler) { - if (!arguments.length) { - return _removeFilterHandler; - } - _removeFilterHandler = removeFilterHandler; - return _chart; - }; - - var _addFilterHandler = function (filters, filter) { - filters.push(filter); - return filters; - }; - - /** - * Set or get the add filter handler. The add filter handler is a function that adds a filter to - * the chart's filter list. Using a custom add filter handler allows you to change the way filters - * are added or perform additional work when adding a filter, e.g. when using a filter server other - * than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method addFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default add filter handler - * chart.addFilterHandler(function (filters, filter) { - * filters.push(filter); - * return filters; - * }); - * - * // custom filter handler (no-op) - * chart.addFilterHandler(function(filters, filter) { - * return filters; - * }); - * @param {Function} [addFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.addFilterHandler = function (addFilterHandler) { - if (!arguments.length) { - return _addFilterHandler; - } - _addFilterHandler = addFilterHandler; - return _chart; - }; - - var _resetFilterHandler = function (filters) { - return []; - }; - - /** - * Set or get the reset filter handler. The reset filter handler is a function that resets the - * chart's filter list by returning a new list. Using a custom reset filter handler allows you to - * change the way filters are reset, or perform additional work when resetting the filters, - * e.g. when using a filter server other than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method resetFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default remove filter handler - * function (filters) { - * return []; - * } - * - * // custom filter handler (no-op) - * chart.resetFilterHandler(function(filters) { - * return filters; - * }); - * @param {Function} [resetFilterHandler] - * @return {dc.baseMixin} - */ - _chart.resetFilterHandler = function (resetFilterHandler) { - if (!arguments.length) { - return _resetFilterHandler; - } - _resetFilterHandler = resetFilterHandler; - return _chart; - }; - - function applyFilters (filters) { - if (_chart.dimension() && _chart.dimension().filter) { - var fs = _filterHandler(_chart.dimension(), filters); - if (fs) { - filters = fs; - } - } - return filters; - } - - /** - * Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)` - * - * @method replaceFilter - * @memberof dc.baseMixin - * @instance - * @param {*} [filter] - * @return {dc.baseMixin} - **/ - _chart.replaceFilter = function (filter) { - _filters = _resetFilterHandler(_filters); - _chart.filter(filter); - }; - - /** - * Filter the chart by the given parameter, or return the current filter if no input parameter - * is given. - * - * The filter parameter can take one of these forms: - * * A single value: the value will be toggled (added if it is not present in the current - * filters, removed if it is present) - * * An array containing a single array of values (`[[value,value,value]]`): each value is - * toggled - * * When appropriate for the chart, a {@link dc.filters dc filter object} such as - * * {@link dc.filters.RangedFilter `dc.filters.RangedFilter`} for the - * {@link dc.coordinateGridMixin dc.coordinateGridMixin} charts - * * {@link dc.filters.TwoDimensionalFilter `dc.filters.TwoDimensionalFilter`} for the - * {@link dc.heatMap heat map} - * * {@link dc.filters.RangedTwoDimensionalFilter `dc.filters.RangedTwoDimensionalFilter`} - * for the {@link dc.scatterPlot scatter plot} - * * `null`: the filter will be reset using the - * {@link dc.baseMixin#resetFilterHandler resetFilterHandler} - * - * Note that this is always a toggle (even when it doesn't make sense for the filter type). If - * you wish to replace the current filter, either call `chart.filter(null)` first, or - * equivalently, call {@link dc.baseMixin#replaceFilter `chart.replaceFilter(filter)`} instead. - * - * Each toggle is executed by checking if the value is already present using the - * {@link dc.baseMixin#hasFilterHandler hasFilterHandler}; if it is not present, it is added - * using the {@link dc.baseMixin#addFilterHandler addFilterHandler}; if it is already present, - * it is removed using the {@link dc.baseMixin#removeFilterHandler removeFilterHandler}. - * - * Once the filters array has been updated, the filters are applied to the - * crossfilter dimension, using the {@link dc.baseMixin#filterHandler filterHandler}. - * - * Once you have set the filters, call {@link dc.baseMixin#redrawGroup `chart.redrawGroup()`} - * (or {@link dc.redrawAll `dc.redrawAll()`}) to redraw the chart's group. - * @method filter - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#addFilterHandler addFilterHandler} - * @see {@link dc.baseMixin#removeFilterHandler removeFilterHandler} - * @see {@link dc.baseMixin#resetFilterHandler resetFilterHandler} - * @see {@link dc.baseMixin#filterHandler filterHandler} - * @example - * // filter by a single string - * chart.filter('Sunday'); - * // filter by a single age - * chart.filter(18); - * // filter by a set of states - * chart.filter([['MA', 'TX', 'ND', 'WA']]); - * // filter by range -- note the use of dc.filters.RangedFilter, which is different - * // from the syntax for filtering a crossfilter dimension directly, dimension.filter([15,20]) - * chart.filter(dc.filters.RangedFilter(15,20)); - * @param {*} [filter] - * @return {dc.baseMixin} - */ - _chart.filter = function (filter) { - if (!arguments.length) { - return _filters.length > 0 ? _filters[0] : null; - } - var filters = _filters; - if (filter instanceof Array && filter[0] instanceof Array && !filter.isFiltered) { - // toggle each filter - filter[0].forEach(function (f) { - if (_hasFilterHandler(filters, f)) { - filters = _removeFilterHandler(filters, f); - } else { - filters = _addFilterHandler(filters, f); - } - }); - } else if (filter === null) { - filters = _resetFilterHandler(filters); - } else { - if (_hasFilterHandler(filters, filter)) { - filters = _removeFilterHandler(filters, filter); - } else { - filters = _addFilterHandler(filters, filter); - } - } - _filters = applyFilters(filters); - _chart._invokeFilteredListener(filter); - - if (_root !== null && _chart.hasFilter()) { - _chart.turnOnControls(); - } else { - _chart.turnOffControls(); - } - - return _chart; - }; - - /** - * Returns all current filters. This method does not perform defensive cloning of the internal - * filter array before returning, therefore any modification of the returned array will effect the - * chart's internal filter storage. - * @method filters - * @memberof dc.baseMixin - * @instance - * @return {Array<*>} - */ - _chart.filters = function () { - return _filters; - }; - - _chart.highlightSelected = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, true); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, false); - }; - - _chart.fadeDeselected = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, false); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, true); - }; - - _chart.resetHighlight = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, false); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, false); - }; - - /** - * This function is passed to d3 as the onClick handler for each chart. The default behavior is to - * filter on the clicked datum (passed to the callback) and redraw the chart group. - * @method onClick - * @memberof dc.baseMixin - * @instance - * @param {*} datum - */ - _chart.onClick = function (datum) { - var filter = _chart.keyAccessor()(datum); - dc.events.trigger(function () { - _chart.filter(filter); - _chart.redrawGroup(); - }); - }; - - /** - * Set or get the filter handler. The filter handler is a function that performs the filter action - * on a specific dimension. Using a custom filter handler allows you to perform additional logic - * before or after filtering. - * @method filterHandler - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension_filter crossfilter.dimension.filter} - * @example - * // default filter handler - * chart.filterHandler(function (dimension, filters) { - * dimension.filter(null); - * if (filters.length === 0) { - * dimension.filter(null); - * } else { - * dimension.filterFunction(function (d) { - * for (var i = 0; i < filters.length; i++) { - * var filter = filters[i]; - * if (filter.isFiltered && filter.isFiltered(d)) { - * return true; - * } else if (filter <= d && filter >= d) { - * return true; - * } - * } - * return false; - * }); - * } - * return filters; - * }); - * - * // custom filter handler - * chart.filterHandler(function(dimension, filter){ - * var newFilter = filter + 10; - * dimension.filter(newFilter); - * return newFilter; // set the actual filter value to the new value - * }); - * @param {Function} [filterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.filterHandler = function (filterHandler) { - if (!arguments.length) { - return _filterHandler; - } - _filterHandler = filterHandler; - return _chart; - }; - - // abstract function stub - _chart._doRender = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - _chart._doRedraw = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - _chart.legendables = function () { - // do nothing in base, should be overridden by sub-function - return []; - }; - - _chart.legendHighlight = function () { - // do nothing in base, should be overridden by sub-function - }; - - _chart.legendReset = function () { - // do nothing in base, should be overridden by sub-function - }; - - _chart.legendToggle = function () { - // do nothing in base, should be overriden by sub-function - }; - - _chart.isLegendableHidden = function () { - // do nothing in base, should be overridden by sub-function - return false; - }; - - /** - * Set or get the key accessor function. The key accessor function is used to retrieve the key - * value from the crossfilter group. Key values are used differently in different charts, for - * example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart. - * @method keyAccessor - * @memberof dc.baseMixin - * @instance - * @example - * // default key accessor - * chart.keyAccessor(function(d) { return d.key; }); - * // custom key accessor for a multi-value crossfilter reduction - * chart.keyAccessor(function(p) { return p.value.absGain; }); - * @param {Function} [keyAccessor] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.keyAccessor = function (keyAccessor) { - if (!arguments.length) { - return _keyAccessor; - } - _keyAccessor = keyAccessor; - return _chart; - }; - - /** - * Set or get the value accessor function. The value accessor function is used to retrieve the - * value from the crossfilter group. Group values are used differently in different charts, for - * example values correspond to slice sizes in a pie chart and y axis positions in a grid - * coordinate chart. - * @method valueAccessor - * @memberof dc.baseMixin - * @instance - * @example - * // default value accessor - * chart.valueAccessor(function(d) { return d.value; }); - * // custom value accessor for a multi-value crossfilter reduction - * chart.valueAccessor(function(p) { return p.value.percentageGain; }); - * @param {Function} [valueAccessor] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.valueAccessor = function (valueAccessor) { - if (!arguments.length) { - return _valueAccessor; - } - _valueAccessor = valueAccessor; - return _chart; - }; - - /** - * Set or get the label function. The chart class will use this function to render labels for each - * child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every - * chart supports the label function, for example line chart does not use this function - * at all. By default, enables labels; pass false for the second parameter if this is not desired. - * @method label - * @memberof dc.baseMixin - * @instance - * @example - * // default label function just return the key - * chart.label(function(d) { return d.key; }); - * // label function has access to the standard d3 data binding and can get quite complicated - * chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; }); - * @param {Function} [labelFunction] - * @param {Boolean} [enableLabels=true] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.label = function (labelFunction, enableLabels) { - if (!arguments.length) { - return _label; - } - _label = labelFunction; - if ((enableLabels === undefined) || enableLabels) { - _renderLabel = true; - } - return _chart; - }; - - /** - * Turn on/off label rendering - * @method renderLabel - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [renderLabel=false] - * @return {Boolean} - * @return {dc.baseMixin} - */ - _chart.renderLabel = function (renderLabel) { - if (!arguments.length) { - return _renderLabel; - } - _renderLabel = renderLabel; - return _chart; - }; - - /** - * Set or get the title function. The chart class will use this function to render the SVGElement title - * (usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice - * in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function; - * however in grid coordinate charts you need to turn off the brush in order to see titles, because - * otherwise the brush layer will block tooltip triggering. - * @method title - * @memberof dc.baseMixin - * @instance - * @example - * // default title function shows "key: value" - * chart.title(function(d) { return d.key + ': ' + d.value; }); - * // title function has access to the standard d3 data binding and can get quite complicated - * chart.title(function(p) { - * return p.key.getFullYear() - * + '\n' - * + 'Index Gain: ' + numberFormat(p.value.absGain) + '\n' - * + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\n' - * + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'; - * }); - * @param {Function} [titleFunction] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.title = function (titleFunction) { - if (!arguments.length) { - return _title; - } - _title = titleFunction; - return _chart; - }; - - /** - * Turn on/off title rendering, or return the state of the render title flag if no arguments are - * given. - * @method renderTitle - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [renderTitle=true] - * @return {Boolean} - * @return {dc.baseMixin} - */ - _chart.renderTitle = function (renderTitle) { - if (!arguments.length) { - return _renderTitle; - } - _renderTitle = renderTitle; - return _chart; - }; - - /** - * A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added - * to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked - * right after the chart finishes its transitions, giving you a way to modify the SVGElements. - * Renderlet functions take the chart instance as the only input parameter and you can - * use the dc API or use raw d3 to achieve pretty much any effect. - * - * Use {@link dc.baseMixin#on on} with a 'renderlet' prefix. - * Generates a random key for the renderlet, which makes it hard to remove. - * @method renderlet - * @memberof dc.baseMixin - * @instance - * @deprecated - * @example - * // do this instead of .renderlet(function(chart) { ... }) - * chart.on("renderlet", function(chart){ - * // mix of dc API and d3 manipulation - * chart.select('g.y').style('display', 'none'); - * // its a closure so you can also access other chart variable available in the closure scope - * moveChart.filter(chart.filter()); - * }); - * @param {Function} renderletFunction - * @return {dc.baseMixin} - */ - _chart.renderlet = dc.logger.deprecate(function (renderletFunction) { - _chart.on('renderlet.' + dc.utils.uniqueId(), renderletFunction); - return _chart; - }, 'chart.renderlet has been deprecated. Please use chart.on("renderlet.", renderletFunction)'); - - /** - * Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn - * together since it is expected they share the same underlying crossfilter data set. - * @method chartGroup - * @memberof dc.baseMixin - * @instance - * @param {String} [chartGroup] - * @return {String} - * @return {dc.baseMixin} - */ - _chart.chartGroup = function (chartGroup) { - if (!arguments.length) { - return _chartGroup; - } - if (!_isChild) { - dc.deregisterChart(_chart, _chartGroup); - } - _chartGroup = chartGroup; - if (!_isChild) { - dc.registerChart(_chart, _chartGroup); - } - return _chart; - }; - - /** - * Expire the internal chart cache. dc charts cache some data internally on a per chart basis to - * speed up rendering and avoid unnecessary calculation; however it might be useful to clear the - * cache if you have changed state which will affect rendering. For example if you invoke the - * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add} - * function or reset group or dimension after rendering it is a good idea to - * clear the cache to make sure charts are rendered properly. - * @method expireCache - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.expireCache = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - /** - * Attach a dc.legend widget to this chart. The legend widget will automatically draw legend labels - * based on the color setting and names associated with each group. - * @method legend - * @memberof dc.baseMixin - * @instance - * @example - * chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) - * @param {dc.legend} [legend] - * @return {dc.legend} - * @return {dc.baseMixin} - */ - _chart.legend = function (legend) { - if (!arguments.length) { - return _legend; - } - _legend = legend; - _legend.parent(_chart); - return _chart; - }; - - /** - * Returns the internal numeric ID of the chart. - * @method chartID - * @memberof dc.baseMixin - * @instance - * @return {String} - */ - _chart.chartID = function () { - return _chart.__dcFlag__; - }; - - /** - * Set chart options using a configuration object. Each key in the object will cause the method of - * the same name to be called with the value to set that attribute for the chart. - * @method options - * @memberof dc.baseMixin - * @instance - * @example - * chart.options({dimension: myDimension, group: myGroup}); - * @param {{}} opts - * @return {dc.baseMixin} - */ - _chart.options = function (opts) { - var applyOptions = [ - 'anchor', - 'group', - 'xAxisLabel', - 'yAxisLabel', - 'stack', - 'title', - 'point', - 'getColor', - 'overlayGeoJson' - ]; - - for (var o in opts) { - if (typeof(_chart[o]) === 'function') { - if (opts[o] instanceof Array && applyOptions.indexOf(o) !== -1) { - _chart[o].apply(_chart, opts[o]); - } else { - _chart[o].call(_chart, opts[o]); - } - } else { - dc.logger.debug('Not a valid option setter name: ' + o); - } - } - return _chart; - }; - - /** - * All dc chart instance supports the following listeners. - * Supports the following events: - * * `renderlet` - This listener function will be invoked after transitions after redraw and render. Replaces the - * deprecated {@link dc.baseMixin#renderlet renderlet} method. - * * `pretransition` - Like `.on('renderlet', ...)` but the event is fired before transitions start. - * * `preRender` - This listener function will be invoked before chart rendering. - * * `postRender` - This listener function will be invoked after chart finish rendering including - * all renderlets' logic. - * * `preRedraw` - This listener function will be invoked before chart redrawing. - * * `postRedraw` - This listener function will be invoked after chart finish redrawing - * including all renderlets' logic. - * * `filtered` - This listener function will be invoked after a filter is applied, added or removed. - * * `zoomed` - This listener function will be invoked after a zoom is triggered. - * @method on - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Internals#dispatch_on d3.dispatch.on} - * @example - * .on('renderlet', function(chart, filter){...}) - * .on('pretransition', function(chart, filter){...}) - * .on('preRender', function(chart){...}) - * .on('postRender', function(chart){...}) - * .on('preRedraw', function(chart){...}) - * .on('postRedraw', function(chart){...}) - * .on('filtered', function(chart, filter){...}) - * .on('zoomed', function(chart, filter){...}) - * @param {String} event - * @param {Function} listener - * @return {dc.baseMixin} - */ - _chart.on = function (event, listener) { - _listeners.on(event, listener); - return _chart; - }; - - return _chart; -}; diff --git a/src/base/base-mixin.js b/src/base/base-mixin.js new file mode 100644 index 0000000000..95262d26f8 --- /dev/null +++ b/src/base/base-mixin.js @@ -0,0 +1,1500 @@ +import {select} from 'd3-selection'; +import {dispatch} from 'd3-dispatch'; +import {ascending} from 'd3-array'; + +import {pluck, utils} from '../core/utils'; +import {instanceOfChart} from '../core/core'; +import {deregisterChart, redrawAll, registerChart, renderAll} from '../core/chart-registry'; +import {constants} from '../core/constants'; +import {events} from '../core/events'; +import {logger} from '../core/logger'; +import {printers} from '../core/printers'; +import {InvalidStateException} from '../core/invalid-state-exception'; +import {BadArgumentException} from '../core/bad-argument-exception'; +import {d3compat} from '../core/config'; + +const _defaultFilterHandler = (dimension, filters) => { + if (filters.length === 0) { + dimension.filter(null); + } else if (filters.length === 1 && !filters[0].isFiltered) { + // single value and not a function-based filter + dimension.filterExact(filters[0]); + } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { + // single range-based filter + dimension.filterRange(filters[0]); + } else { + dimension.filterFunction(d => { + for (let i = 0; i < filters.length; i++) { + const filter = filters[i]; + if (filter.isFiltered) { + if(filter.isFiltered(d)) { + return true; + } + } else if (filter <= d && filter >= d) { + return true; + } + } + return false; + }); + } + return filters; +}; + +const _defaultHasFilterHandler = (filters, filter) => { + if (filter === null || typeof (filter) === 'undefined') { + return filters.length > 0; + } + return filters.some(f => filter <= f && filter >= f); +}; + +const _defaultRemoveFilterHandler = (filters, filter) => { + for (let i = 0; i < filters.length; i++) { + if (filters[i] <= filter && filters[i] >= filter) { + filters.splice(i, 1); + break; + } + } + return filters; +}; + +const _defaultAddFilterHandler = (filters, filter) => { + filters.push(filter); + return filters; +}; + +const _defaultResetFilterHandler = filters => []; + +/** + * `BaseMixin` is an abstract functional object representing a basic `dc` chart object + * for all chart and widget implementations. Methods from the {@link #BaseMixin BaseMixin} are inherited + * and available on all chart implementations in the `dc` library. + * @mixin BaseMixin + */ +export class BaseMixin { + constructor () { + this.__dcFlag__ = utils.uniqueId(); + this._svgDescription = null + this._keyboardAccessible = false; + + this._dimension = undefined; + this._group = undefined; + + this._anchor = undefined; + this._root = undefined; + this._svg = undefined; + this._isChild = undefined; + + this._minWidth = 200; + this._defaultWidthCalc = element => { + const width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; + return (width && width > this._minWidth) ? width : this._minWidth; + }; + this._widthCalc = this._defaultWidthCalc; + + this._minHeight = 200; + this._defaultHeightCalc = element => { + const height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; + return (height && height > this._minHeight) ? height : this._minHeight; + }; + this._heightCalc = this._defaultHeightCalc; + this._width = undefined; + this._height = undefined; + this._useViewBoxResizing = false; + + this._keyAccessor = pluck('key'); + this._valueAccessor = pluck('value'); + this._label = pluck('key'); + + this._ordering = pluck('key'); + + this._renderLabel = false; + + this._title = d => `${this.keyAccessor()(d)}: ${this.valueAccessor()(d)}`; + this._renderTitle = true; + this._controlsUseVisibility = false; + + this._transitionDuration = 750; + + this._transitionDelay = 0; + + this._filterPrinter = printers.filters; + + this._mandatoryAttributesList = ['dimension', 'group']; + + this._chartGroup = constants.DEFAULT_CHART_GROUP; + + this._listeners = dispatch( + 'preRender', + 'postRender', + 'preRedraw', + 'postRedraw', + 'filtered', + 'zoomed', + 'renderlet', + 'pretransition'); + + this._legend = undefined; + this._commitHandler = undefined; + + this._defaultData = group => group.all(); + this._data = this._defaultData; + + this._filters = []; + + this._filterHandler = _defaultFilterHandler; + this._hasFilterHandler = _defaultHasFilterHandler; + this._removeFilterHandler = _defaultRemoveFilterHandler; + this._addFilterHandler = _defaultAddFilterHandler; + this._resetFilterHandler = _defaultResetFilterHandler; + } + + /** + * Set or get the height attribute of a chart. The height is applied to the SVGElement generated by + * the chart when rendered (or re-rendered). If a value is given, then it will be used to calculate + * the new height and the chart returned for method chaining. The value can either be a numeric, a + * function, or falsy. If no value is specified then the value of the current height attribute will + * be returned. + * + * By default, without an explicit height being given, the chart will select the width of its + * anchor element. If that isn't possible it defaults to 200 (provided by the + * {@link BaseMixin#minHeight minHeight} property). Setting the value falsy will return + * the chart to the default behavior. + * @see {@link BaseMixin#minHeight minHeight} + * @example + * // Default height + * chart.height(function (element) { + * var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; + * return (height && height > chart.minHeight()) ? height : chart.minHeight(); + * }); + * + * chart.height(250); // Set the chart's height to 250px; + * chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function + * chart.height(null); // reset the height to the default auto calculation + * @param {Number|Function} [height] + * @returns {Number|BaseMixin} + */ + height (height) { + if (!arguments.length) { + if (!utils.isNumber(this._height)) { + // only calculate once + this._height = this._heightCalc(this._root.node()); + } + return this._height; + } + this._heightCalc = height ? (typeof height === 'function' ? height : utils.constant(height)) : this._defaultHeightCalc; + this._height = undefined; + return this; + } + + /** + * Set or get the width attribute of a chart. + * @see {@link BaseMixin#height height} + * @see {@link BaseMixin#minWidth minWidth} + * @example + * // Default width + * chart.width(function (element) { + * var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; + * return (width && width > chart.minWidth()) ? width : chart.minWidth(); + * }); + * @param {Number|Function} [width] + * @returns {Number|BaseMixin} + */ + width (width) { + if (!arguments.length) { + if (!utils.isNumber(this._width)) { + // only calculate once + this._width = this._widthCalc(this._root.node()); + } + return this._width; + } + this._widthCalc = width ? (typeof width === 'function' ? width : utils.constant(width)) : this._defaultWidthCalc; + this._width = undefined; + return this; + } + + /** + * Set or get the minimum width attribute of a chart. This only has effect when used with the default + * {@link BaseMixin#width width} function. + * @see {@link BaseMixin#width width} + * @param {Number} [minWidth=200] + * @returns {Number|BaseMixin} + */ + minWidth (minWidth) { + if (!arguments.length) { + return this._minWidth; + } + this._minWidth = minWidth; + return this; + } + + /** + * Set or get the minimum height attribute of a chart. This only has effect when used with the default + * {@link BaseMixin#height height} function. + * @see {@link BaseMixin#height height} + * @param {Number} [minHeight=200] + * @returns {Number|BaseMixin} + */ + minHeight (minHeight) { + if (!arguments.length) { + return this._minHeight; + } + this._minHeight = minHeight; + return this; + } + + /** + * Turn on/off using the SVG + * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox `viewBox` attribute}. + * When enabled, `viewBox` will be set on the svg root element instead of `width` and `height`. + * Requires that the chart aspect ratio be defined using chart.width(w) and chart.height(h). + * + * This will maintain the aspect ratio while enabling the chart to resize responsively to the + * space given to the chart using CSS. For example, the chart can use `width: 100%; height: + * 100%` or absolute positioning to resize to its parent div. + * + * Since the text will be sized as if the chart is drawn according to the width and height, and + * will be resized if the chart is any other size, you need to set the chart width and height so + * that the text looks good. In practice, 600x400 seems to work pretty well for most charts. + * + * You can see examples of this resizing strategy in the [Chart Resizing + * Examples](http://dc-js.github.io/dc.js/resizing/); just add `?resize=viewbox` to any of the + * one-chart examples to enable `useViewBoxResizing`. + * @param {Boolean} [useViewBoxResizing=false] + * @returns {Boolean|BaseMixin} + */ + useViewBoxResizing (useViewBoxResizing) { + if (!arguments.length) { + return this._useViewBoxResizing; + } + this._useViewBoxResizing = useViewBoxResizing; + return this; + } + + /** + * **mandatory** + * + * Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension crossfilter dimension} + * + * If a value is given, then it will be used as the new dimension. If no value is specified then + * the current dimension will be returned. + * @see {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension crossfilter.dimension} + * @example + * var index = crossfilter([]); + * var dimension = index.dimension(pluck('key')); + * chart.dimension(dimension); + * @param {crossfilter.dimension} [dimension] + * @returns {crossfilter.dimension|BaseMixin} + */ + dimension (dimension) { + if (!arguments.length) { + return this._dimension; + } + this._dimension = dimension; + this.expireCache(); + return this; + } + + /** + * Set the data callback or retrieve the chart's data set. The data callback is passed the chart's + * group and by default will return + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all group.all}. + * This behavior may be modified to, for instance, return only the top 5 groups. + * @example + * // Default data function + * chart.data(function (group) { return group.all(); }); + * + * chart.data(function (group) { return group.top(5); }); + * @param {Function} [callback] + * @returns {*|BaseMixin} + */ + data (callback) { + if (!arguments.length) { + return this._data(this._group); + } + this._data = typeof callback === 'function' ? callback : utils.constant(callback); + this.expireCache(); + return this; + } + + /** + * **mandatory** + * + * Set or get the group attribute of a chart. In `dc` a group is a + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce crossfilter group}. + * Usually the group should be created from the particular dimension associated with the same chart. If a value is + * given, then it will be used as the new group. + * + * If no value specified then the current group will be returned. + * If `name` is specified then it will be used to generate legend label. + * @see {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} + * @example + * var index = crossfilter([]); + * var dimension = index.dimension(pluck('key')); + * chart.dimension(dimension); + * chart.group(dimension.group().reduceSum()); + * @param {crossfilter.group} [group] + * @param {String} [name] + * @returns {crossfilter.group|BaseMixin} + */ + group (group, name) { + if (!arguments.length) { + return this._group; + } + this._group = group; + this._groupName = name; + this.expireCache(); + return this; + } + + /** + * Get or set an accessor to order ordinal dimensions. The chart uses + * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort Array.sort} + * to sort elements; this accessor returns the value to order on. + * @example + * // Default ordering accessor + * _chart.ordering(pluck('key')); + * @param {Function} [orderFunction] + * @returns {Function|BaseMixin} + */ + ordering (orderFunction) { + if (!arguments.length) { + return this._ordering; + } + this._ordering = orderFunction; + this.expireCache(); + return this; + } + + _computeOrderedGroups (data) { + // clone the array before sorting, otherwise Array.sort sorts in-place + return Array.from(data).sort((a, b) => ascending(this._ordering(a), this._ordering(b))); + } + + /** + * Clear all filters associated with this chart. The same effect can be achieved by calling + * {@link BaseMixin#filter chart.filter(null)}. + * @returns {BaseMixin} + */ + filterAll () { + return this.filter(null); + } + + /** + * Execute d3 single selection in the chart's scope using the given selector and return the d3 + * selection. + * + * This function is **not chainable** since it does not return a chart instance; however the d3 + * selection result can be chained to d3 function calls. + * @see {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3.select} + * @example + * // Has the same effect as d3.select('#chart-id').select(selector) + * chart.select(selector) + * @param {String} sel CSS selector string + * @returns {d3.selection} + */ + select (sel) { + return this._root.select(sel); + } + + /** + * Execute in scope d3 selectAll using the given selector and return d3 selection result. + * + * This function is **not chainable** since it does not return a chart instance; however the d3 + * selection result can be chained to d3 function calls. + * @see {@link https://github.com/d3/d3-selection/blob/master/README.md#selectAll d3.selectAll} + * @example + * // Has the same effect as d3.select('#chart-id').selectAll(selector) + * chart.selectAll(selector) + * @param {String} sel CSS selector string + * @returns {d3.selection} + */ + selectAll (sel) { + return this._root ? this._root.selectAll(sel) : null; + } + + /** + * Set the root SVGElement to either be an existing chart's root; or any valid [d3 single + * selector](https://github.com/d3/d3-selection/blob/master/README.md#selecting-elements) specifying a dom + * block element such as a div; or a dom element or d3 selection. Optionally registers the chart + * within the chartGroup. This class is called internally on chart initialization, but be called + * again to relocate the chart. However, it will orphan any previously created SVGElements. + * @param {anchorChart|anchorSelector|anchorNode} [parent] + * @param {String} [chartGroup] + * @returns {String|node|d3.selection|BaseMixin} + */ + anchor (parent, chartGroup) { + if (!arguments.length) { + return this._anchor; + } + if (instanceOfChart(parent)) { + this._anchor = parent.anchor(); + if (this._anchor.children) { // is _anchor a div? + this._anchor = `#${parent.anchorName()}`; + } + this._root = parent.root(); + this._isChild = true; + } else if (parent) { + if (parent.select && parent.classed) { // detect d3 selection + this._anchor = parent.node(); + } else { + this._anchor = parent; + } + this._root = select(this._anchor); + this._root.classed(constants.CHART_CLASS, true); + registerChart(this, chartGroup); + this._isChild = false; + } else { + throw new BadArgumentException('parent must be defined'); + } + this._chartGroup = chartGroup; + return this; + } + + /** + * Returns the DOM id for the chart's anchored location. + * @returns {String} + */ + anchorName () { + const a = this.anchor(); + if (a && a.id) { + return a.id; + } + if (a && a.replace) { + return a.replace('#', ''); + } + return `dc-chart${this.chartID()}`; + } + + /** + * Returns the root element where a chart resides. Usually it will be the parent div element where + * the SVGElement was created. You can also pass in a new root element however this is usually handled by + * dc internally. Resetting the root element on a chart outside of dc internals may have + * unexpected consequences. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement HTMLElement} + * @param {HTMLElement} [rootElement] + * @returns {HTMLElement|BaseMixin} + */ + root (rootElement) { + if (!arguments.length) { + return this._root; + } + this._root = rootElement; + return this; + } + + /** + * Returns the top SVGElement for this specific chart. You can also pass in a new SVGElement, + * however this is usually handled by dc internally. Resetting the SVGElement on a chart outside + * of dc internals may have unexpected consequences. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} + * @param {SVGElement|d3.selection} [svgElement] + * @returns {SVGElement|d3.selection|BaseMixin} + */ + svg (svgElement) { + if (!arguments.length) { + return this._svg; + } + this._svg = svgElement; + return this; + } + + /** + * Remove the chart's SVGElements from the dom and recreate the container SVGElement. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} + * @returns {SVGElement} + */ + resetSvg () { + this.select('svg').remove(); + return this.generateSvg(); + } + + sizeSvg () { + if (this._svg) { + if (!this._useViewBoxResizing) { + this._svg + .attr('width', this.width()) + .attr('height', this.height()); + } else if (!this._svg.attr('viewBox')) { + this._svg + .attr('viewBox', `0 0 ${this.width()} ${this.height()}`); + } + } + } + + generateSvg () { + this._svg = this.root().append('svg'); + + if (this._svgDescription || this._keyboardAccessible) { + + this._svg.append('desc') + .attr('id', `desc-id-${this.__dcFlag__}`) + .html(`${this.svgDescription()}`); + + this._svg + .attr('tabindex', '0') + .attr('role', 'img') + .attr('aria-labelledby', `desc-id-${this.__dcFlag__}`); + } + + this.sizeSvg(); + return this._svg; + } + + /** + * Set or get description text for the entire SVG graphic. If set, will create a `` element as the first + * child of the SVG with the description text and also make the SVG focusable from keyboard. + * @param {String} [description] + * @returns {String|BaseMixin} + */ + svgDescription (description) { + if (!arguments.length) { + return this._svgDescription || this.constructor.name; + } + + this._svgDescription = description; + return this; + } + + /** + * If set, interactive chart elements like individual bars in a bar chart or symbols in a scatter plot + * will be focusable from keyboard and on pressing Enter or Space will behave as if clicked on. + * + * If `svgDescription` has not been explicitly set, will also set SVG description text to the class + * constructor name, like BarChart or HeatMap, and make the entire SVG focusable. + * @param {Boolean} [keyboardAccessible=false] + * @returns {Boolean|BarChart} + */ + keyboardAccessible (keyboardAccessible) { + if (!arguments.length) { + return this._keyboardAccessible; + } + this._keyboardAccessible = keyboardAccessible; + return this; + } + + /** + * Set or get the filter printer function. The filter printer function is used to generate human + * friendly text for filter value(s) associated with the chart instance. The text will get shown + * in the `.filter element; see {@link BaseMixin#turnOnControls turnOnControls}. + * + * By default dc charts use a default filter printer {@link printers.filters printers.filters} + * that provides simple printing support for both single value and ranged filters. + * @example + * // for a chart with an ordinal brush, print the filters in upper case + * chart.filterPrinter(function(filters) { + * return filters.map(function(f) { return f.toUpperCase(); }).join(', '); + * }); + * // for a chart with a range brush, print the filter as start and extent + * chart.filterPrinter(function(filters) { + * return 'start ' + utils.printSingleValue(filters[0][0]) + + * ' extent ' + utils.printSingleValue(filters[0][1] - filters[0][0]); + * }); + * @param {Function} [filterPrinterFunction=printers.filters] + * @returns {Function|BaseMixin} + */ + filterPrinter (filterPrinterFunction) { + if (!arguments.length) { + return this._filterPrinter; + } + this._filterPrinter = filterPrinterFunction; + return this; + } + + /** + * If set, use the `visibility` attribute instead of the `display` attribute for showing/hiding + * chart reset and filter controls, for less disruption to the layout. + * @param {Boolean} [controlsUseVisibility=false] + * @returns {Boolean|BaseMixin} + */ + controlsUseVisibility (controlsUseVisibility) { + if (!arguments.length) { + return this._controlsUseVisibility; + } + this._controlsUseVisibility = controlsUseVisibility; + return this; + } + + /** + * Turn on optional control elements within the root element. dc currently supports the + * following html control elements. + * * root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type + * of control element is usually used to store a reset link to allow user to reset filter on a + * certain chart. This element will be turned off automatically if the filter is cleared. + * * root.selectAll('.filter') elements are turned on if the chart has an active filter. The text + * content of this element is then replaced with the current filter value using the filter printer + * function. This type of element will be turned off automatically if the filter is cleared. + * @returns {BaseMixin} + */ + turnOnControls () { + if (this._root) { + const attribute = this.controlsUseVisibility() ? 'visibility' : 'display'; + this.selectAll('.reset').style(attribute, null); + this.selectAll('.filter').text(this._filterPrinter(this.filters())).style(attribute, null); + } + return this; + } + + /** + * Turn off optional control elements within the root element. + * @see {@link BaseMixin#turnOnControls turnOnControls} + * @returns {BaseMixin} + */ + turnOffControls () { + if (this._root) { + const attribute = this.controlsUseVisibility() ? 'visibility' : 'display'; + const value = this.controlsUseVisibility() ? 'hidden' : 'none'; + this.selectAll('.reset').style(attribute, value); + this.selectAll('.filter').style(attribute, value).text(this.filter()); + } + return this; + } + + /** + * Set or get the animation transition duration (in milliseconds) for this chart instance. + * @param {Number} [duration=750] + * @returns {Number|BaseMixin} + */ + transitionDuration (duration) { + if (!arguments.length) { + return this._transitionDuration; + } + this._transitionDuration = duration; + return this; + } + + /** + * Set or get the animation transition delay (in milliseconds) for this chart instance. + * @param {Number} [delay=0] + * @returns {Number|BaseMixin} + */ + transitionDelay (delay) { + if (!arguments.length) { + return this._transitionDelay; + } + this._transitionDelay = delay; + return this; + } + + _mandatoryAttributes (_) { + if (!arguments.length) { + return this._mandatoryAttributesList; + } + this._mandatoryAttributesList = _; + return this; + } + + checkForMandatoryAttributes (a) { + if (!this[a] || !this[a]()) { + throw new InvalidStateException(`Mandatory attribute chart.${a} is missing on chart[#${this.anchorName()}]`); + } + } + + /** + * Invoking this method will force the chart to re-render everything from scratch. Generally it + * should only be used to render the chart for the first time on the page or if you want to make + * sure everything is redrawn from scratch instead of relying on the default incremental redrawing + * behaviour. + * @returns {BaseMixin} + */ + render () { + this._height = this._width = undefined; // force recalculate + this._listeners.call('preRender', this, this); + + if (this._mandatoryAttributesList) { + this._mandatoryAttributesList.forEach(e => this.checkForMandatoryAttributes(e)); + } + + const result = this._doRender(); + + if (this._legend) { + this._legend.render(); + } + + this._activateRenderlets('postRender'); + + return result; + } + + _makeKeyboardAccessible (onClickFunction, ...onClickArgs) { + // called from each chart module's render and redraw methods + const tabElements = this._svg + .selectAll('.dc-tabbable') + .attr('tabindex', 0); + + if (onClickFunction) { + tabElements.on('keydown', d3compat.eventHandler((d, event) => { + // trigger only if d is an object undestood by KeyAccessor() + if (event.keyCode === 13 && typeof d === 'object') { + onClickFunction.call(this, d, ...onClickArgs) + } + // special case for space key press - prevent scrolling + if (event.keyCode === 32 && typeof d === 'object') { + onClickFunction.call(this, d, ...onClickArgs) + event.preventDefault(); + } + + })); + } + } + + _activateRenderlets (event) { + this._listeners.call('pretransition', this, this); + if (this.transitionDuration() > 0 && this._svg) { + this._svg.transition().duration(this.transitionDuration()).delay(this.transitionDelay()) + .on('end', () => { + this._listeners.call('renderlet', this, this); + if (event) { + this._listeners.call(event, this, this); + } + }); + } else { + this._listeners.call('renderlet', this, this); + if (event) { + this._listeners.call(event, this, this); + } + } + } + + /** + * Calling redraw will cause the chart to re-render data changes incrementally. If there is no + * change in the underlying data dimension then calling this method will have no effect on the + * chart. Most chart interaction in dc will automatically trigger this method through internal + * events (in particular {@link redrawAll redrawAll}); therefore, you only need to + * manually invoke this function if data is manipulated outside of dc's control (for example if + * data is loaded in the background using + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add}). + * @returns {BaseMixin} + */ + redraw () { + this.sizeSvg(); + this._listeners.call('preRedraw', this, this); + + const result = this._doRedraw(); + + if (this._legend) { + this._legend.render(); + } + + this._activateRenderlets('postRedraw'); + + return result; + } + + /** + * Gets/sets the commit handler. If the chart has a commit handler, the handler will be called when + * the chart's filters have changed, in order to send the filter data asynchronously to a server. + * + * Unlike other functions in dc.js, the commit handler is asynchronous. It takes two arguments: + * a flag indicating whether this is a render (true) or a redraw (false), and a callback to be + * triggered once the commit is done. The callback has the standard node.js continuation signature + * with error first and result second. + * @param {Function} commitHandler + * @returns {BaseMixin} + */ + commitHandler (commitHandler) { + if (!arguments.length) { + return this._commitHandler; + } + this._commitHandler = commitHandler; + return this; + } + + /** + * Redraws all charts in the same group as this chart, typically in reaction to a filter + * change. If the chart has a {@link BaseMixin.commitFilter commitHandler}, it will + * be executed and waited for. + * @returns {BaseMixin} + */ + redrawGroup () { + if (this._commitHandler) { + this._commitHandler(false, (error, result) => { + if (error) { + console.log(error); + } else { + redrawAll(this.chartGroup()); + } + }); + } else { + redrawAll(this.chartGroup()); + } + return this; + } + + /** + * Renders all charts in the same group as this chart. If the chart has a + * {@link BaseMixin.commitFilter commitHandler}, it will be executed and waited for + * @returns {BaseMixin} + */ + renderGroup () { + if (this._commitHandler) { + this._commitHandler(false, (error, result) => { + if (error) { + console.log(error); + } else { + renderAll(this.chartGroup()); + } + }); + } else { + renderAll(this.chartGroup()); + } + return this; + } + + _invokeFilteredListener (f) { + if (f !== undefined) { + this._listeners.call('filtered', this, this, f); + } + } + + _invokeZoomedListener () { + this._listeners.call('zoomed', this, this); + } + + /** + * Set or get the has-filter handler. The has-filter handler is a function that checks to see if + * the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows + * you to change the way filters are checked for and replaced. + * @example + * // default has-filter handler + * chart.hasFilterHandler(function (filters, filter) { + * if (filter === null || typeof(filter) === 'undefined') { + * return filters.length > 0; + * } + * return filters.some(function (f) { + * return filter <= f && filter >= f; + * }); + * }); + * + * // custom filter handler (no-op) + * chart.hasFilterHandler(function(filters, filter) { + * return false; + * }); + * @param {Function} [hasFilterHandler] + * @returns {Function|BaseMixin} + */ + hasFilterHandler (hasFilterHandler) { + if (!arguments.length) { + return this._hasFilterHandler; + } + this._hasFilterHandler = hasFilterHandler; + return this; + } + + /** + * Check whether any active filter or a specific filter is associated with particular chart instance. + * This function is **not chainable**. + * @see {@link BaseMixin#hasFilterHandler hasFilterHandler} + * @param {*} [filter] + * @returns {Boolean} + */ + hasFilter (filter) { + return this._hasFilterHandler(this._filters, filter); + } + + /** + * Set or get the remove filter handler. The remove filter handler is a function that removes a + * filter from the chart's current filters. Using a custom remove filter handler allows you to + * change how filters are removed or perform additional work when removing a filter, e.g. when + * using a filter server other than crossfilter. + * + * The handler should return a new or modified array as the result. + * @example + * // default remove filter handler + * chart.removeFilterHandler(function (filters, filter) { + * for (var i = 0; i < filters.length; i++) { + * if (filters[i] <= filter && filters[i] >= filter) { + * filters.splice(i, 1); + * break; + * } + * } + * return filters; + * }); + * + * // custom filter handler (no-op) + * chart.removeFilterHandler(function(filters, filter) { + * return filters; + * }); + * @param {Function} [removeFilterHandler] + * @returns {Function|BaseMixin} + */ + removeFilterHandler (removeFilterHandler) { + if (!arguments.length) { + return this._removeFilterHandler; + } + this._removeFilterHandler = removeFilterHandler; + return this; + } + + /** + * Set or get the add filter handler. The add filter handler is a function that adds a filter to + * the chart's filter list. Using a custom add filter handler allows you to change the way filters + * are added or perform additional work when adding a filter, e.g. when using a filter server other + * than crossfilter. + * + * The handler should return a new or modified array as the result. + * @example + * // default add filter handler + * chart.addFilterHandler(function (filters, filter) { + * filters.push(filter); + * return filters; + * }); + * + * // custom filter handler (no-op) + * chart.addFilterHandler(function(filters, filter) { + * return filters; + * }); + * @param {Function} [addFilterHandler] + * @returns {Function|BaseMixin} + */ + addFilterHandler (addFilterHandler) { + if (!arguments.length) { + return this._addFilterHandler; + } + this._addFilterHandler = addFilterHandler; + return this; + } + + /** + * Set or get the reset filter handler. The reset filter handler is a function that resets the + * chart's filter list by returning a new list. Using a custom reset filter handler allows you to + * change the way filters are reset, or perform additional work when resetting the filters, + * e.g. when using a filter server other than crossfilter. + * + * The handler should return a new or modified array as the result. + * @example + * // default remove filter handler + * function (filters) { + * return []; + * } + * + * // custom filter handler (no-op) + * chart.resetFilterHandler(function(filters) { + * return filters; + * }); + * @param {Function} [resetFilterHandler] + * @returns {BaseMixin} + */ + resetFilterHandler (resetFilterHandler) { + if (!arguments.length) { + return this._resetFilterHandler; + } + this._resetFilterHandler = resetFilterHandler; + return this; + } + + applyFilters (filters) { + if (this.dimension() && this.dimension().filter) { + const fs = this._filterHandler(this.dimension(), filters); + if (fs) { + filters = fs; + } + } + return filters; + } + + /** + * Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)` + * but more efficient because the filter is only applied once. + * + * @param {*} [filter] + * @returns {BaseMixin} + */ + replaceFilter (filter) { + this._filters = this._resetFilterHandler(this._filters); + this.filter(filter); + return this; + } + + /** + * Filter the chart by the given parameter, or return the current filter if no input parameter + * is given. + * + * The filter parameter can take one of these forms: + * * A single value: the value will be toggled (added if it is not present in the current + * filters, removed if it is present) + * * An array containing a single array of values (`[[value,value,value]]`): each value is + * toggled + * * When appropriate for the chart, a {@link filters dc filter object} such as + * * {@link filters.RangedFilter `filters.RangedFilter`} for the + * {@link CoordinateGridMixin CoordinateGridMixin} charts + * * {@link filters.TwoDimensionalFilter `filters.TwoDimensionalFilter`} for the + * {@link HeatMap heat map} + * * {@link filters.RangedTwoDimensionalFilter `filters.RangedTwoDimensionalFilter`} + * for the {@link ScatterPlot scatter plot} + * * `null`: the filter will be reset using the + * {@link BaseMixin#resetFilterHandler resetFilterHandler} + * + * Note that this is always a toggle (even when it doesn't make sense for the filter type). If + * you wish to replace the current filter, either call `chart.filter(null)` first - or it's more + * efficient to call {@link BaseMixin#replaceFilter `chart.replaceFilter(filter)`} instead. + * + * Each toggle is executed by checking if the value is already present using the + * {@link BaseMixin#hasFilterHandler hasFilterHandler}; if it is not present, it is added + * using the {@link BaseMixin#addFilterHandler addFilterHandler}; if it is already present, + * it is removed using the {@link BaseMixin#removeFilterHandler removeFilterHandler}. + * + * Once the filters array has been updated, the filters are applied to the + * crossfilter dimension, using the {@link BaseMixin#filterHandler filterHandler}. + * + * Once you have set the filters, call {@link BaseMixin#redrawGroup `chart.redrawGroup()`} + * (or {@link redrawAll `redrawAll()`}) to redraw the chart's group. + * @see {@link BaseMixin#addFilterHandler addFilterHandler} + * @see {@link BaseMixin#removeFilterHandler removeFilterHandler} + * @see {@link BaseMixin#resetFilterHandler resetFilterHandler} + * @see {@link BaseMixin#filterHandler filterHandler} + * @example + * // filter by a single string + * chart.filter('Sunday'); + * // filter by a single age + * chart.filter(18); + * // filter by a set of states + * chart.filter([['MA', 'TX', 'ND', 'WA']]); + * // filter by range -- note the use of filters.RangedFilter, which is different + * // from the syntax for filtering a crossfilter dimension directly, dimension.filter([15,20]) + * chart.filter(filters.RangedFilter(15,20)); + * @param {*} [filter] + * @returns {BaseMixin} + */ + filter (filter) { + if (!arguments.length) { + return this._filters.length > 0 ? this._filters[0] : null; + } + let filters = this._filters; + if (filter instanceof Array && filter[0] instanceof Array && !filter.isFiltered) { + // toggle each filter + filter[0].forEach(f => { + if (this._hasFilterHandler(filters, f)) { + filters = this._removeFilterHandler(filters, f); + } else { + filters = this._addFilterHandler(filters, f); + } + }); + } else if (filter === null) { + filters = this._resetFilterHandler(filters); + } else { + if (this._hasFilterHandler(filters, filter)) { + filters = this._removeFilterHandler(filters, filter); + } else { + filters = this._addFilterHandler(filters, filter); + } + } + this._filters = this.applyFilters(filters); + this._invokeFilteredListener(filter); + + if (this._root !== null && this.hasFilter()) { + this.turnOnControls(); + } else { + this.turnOffControls(); + } + + return this; + } + + /** + * Returns all current filters. This method does not perform defensive cloning of the internal + * filter array before returning, therefore any modification of the returned array will effect the + * chart's internal filter storage. + * @returns {Array<*>} + */ + filters () { + return this._filters; + } + + highlightSelected (e) { + select(e).classed(constants.SELECTED_CLASS, true); + select(e).classed(constants.DESELECTED_CLASS, false); + } + + fadeDeselected (e) { + select(e).classed(constants.SELECTED_CLASS, false); + select(e).classed(constants.DESELECTED_CLASS, true); + } + + resetHighlight (e) { + select(e).classed(constants.SELECTED_CLASS, false); + select(e).classed(constants.DESELECTED_CLASS, false); + } + + /** + * This function is passed to d3 as the onClick handler for each chart. The default behavior is to + * filter on the clicked datum (passed to the callback) and redraw the chart group. + * + * This function can be replaced in order to change the click behavior (but first look at + * @example + * var oldHandler = chart.onClick; + * chart.onClick = function(datum) { + * // use datum. + * @param {*} datum + * @return {undefined} + */ + onClick (datum) { + const filter = this.keyAccessor()(datum); + events.trigger(() => { + this.filter(filter); + this.redrawGroup(); + }); + } + + /** + * Set or get the filter handler. The filter handler is a function that performs the filter action + * on a specific dimension. Using a custom filter handler allows you to perform additional logic + * before or after filtering. + * @see {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter crossfilter.dimension.filter} + * @example + * // the default filter handler handles all possible cases for the charts in dc.js + * // you can replace it with something more specialized for your own chart + * chart.filterHandler(function (dimension, filters) { + * if (filters.length === 0) { + * // the empty case (no filtering) + * dimension.filter(null); + * } else if (filters.length === 1 && !filters[0].isFiltered) { + * // single value and not a function-based filter + * dimension.filterExact(filters[0]); + * } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { + * // single range-based filter + * dimension.filterRange(filters[0]); + * } else { + * // an array of values, or an array of filter objects + * dimension.filterFunction(function (d) { + * for (var i = 0; i < filters.length; i++) { + * var filter = filters[i]; + * if (filter.isFiltered && filter.isFiltered(d)) { + * return true; + * } else if (filter <= d && filter >= d) { + * return true; + * } + * } + * return false; + * }); + * } + * return filters; + * }); + * + * // custom filter handler + * chart.filterHandler(function(dimension, filter){ + * var newFilter = filter + 10; + * dimension.filter(newFilter); + * return newFilter; // set the actual filter value to the new value + * }); + * @param {Function} [filterHandler] + * @returns {Function|BaseMixin} + */ + filterHandler (filterHandler) { + if (!arguments.length) { + return this._filterHandler; + } + this._filterHandler = filterHandler; + return this; + } + + // abstract function stub + _doRender () { + // do nothing in base, should be overridden by sub-function + return this; + } + + _doRedraw () { + // do nothing in base, should be overridden by sub-function + return this; + } + + legendables () { + // do nothing in base, should be overridden by sub-function + return []; + } + + legendHighlight () { + // do nothing in base, should be overridden by sub-function + } + + legendReset () { + // do nothing in base, should be overridden by sub-function + } + + legendToggle () { + // do nothing in base, should be overriden by sub-function + } + + isLegendableHidden () { + // do nothing in base, should be overridden by sub-function + return false; + } + + /** + * Set or get the key accessor function. The key accessor function is used to retrieve the key + * value from the crossfilter group. Key values are used differently in different charts, for + * example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart. + * @example + * // default key accessor + * chart.keyAccessor(function(d) { return d.key; }); + * // custom key accessor for a multi-value crossfilter reduction + * chart.keyAccessor(function(p) { return p.value.absGain; }); + * @param {Function} [keyAccessor] + * @returns {Function|BaseMixin} + */ + keyAccessor (keyAccessor) { + if (!arguments.length) { + return this._keyAccessor; + } + this._keyAccessor = keyAccessor; + return this; + } + + /** + * Set or get the value accessor function. The value accessor function is used to retrieve the + * value from the crossfilter group. Group values are used differently in different charts, for + * example values correspond to slice sizes in a pie chart and y axis positions in a grid + * coordinate chart. + * @example + * // default value accessor + * chart.valueAccessor(function(d) { return d.value; }); + * // custom value accessor for a multi-value crossfilter reduction + * chart.valueAccessor(function(p) { return p.value.percentageGain; }); + * @param {Function} [valueAccessor] + * @returns {Function|BaseMixin} + */ + valueAccessor (valueAccessor) { + if (!arguments.length) { + return this._valueAccessor; + } + this._valueAccessor = valueAccessor; + return this; + } + + /** + * Set or get the label function. The chart class will use this function to render labels for each + * child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every + * chart supports the label function, for example line chart does not use this function + * at all. By default, enables labels; pass false for the second parameter if this is not desired. + * @example + * // default label function just return the key + * chart.label(function(d) { return d.key; }); + * // label function has access to the standard d3 data binding and can get quite complicated + * chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; }); + * @param {Function} [labelFunction] + * @param {Boolean} [enableLabels=true] + * @returns {Function|BaseMixin} + */ + label (labelFunction, enableLabels) { + if (!arguments.length) { + return this._label; + } + this._label = labelFunction; + if ((enableLabels === undefined) || enableLabels) { + this._renderLabel = true; + } + return this; + } + + /** + * Turn on/off label rendering + * @param {Boolean} [renderLabel=false] + * @returns {Boolean|BaseMixin} + */ + renderLabel (renderLabel) { + if (!arguments.length) { + return this._renderLabel; + } + this._renderLabel = renderLabel; + return this; + } + + /** + * Set or get the title function. The chart class will use this function to render the SVGElement title + * (usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice + * in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function; + * however in grid coordinate charts you need to turn off the brush in order to see titles, because + * otherwise the brush layer will block tooltip triggering. + * @example + * // default title function shows "key: value" + * chart.title(function(d) { return d.key + ': ' + d.value; }); + * // title function has access to the standard d3 data binding and can get quite complicated + * chart.title(function(p) { + * return p.key.getFullYear() + * + '\n' + * + 'Index Gain: ' + numberFormat(p.value.absGain) + '\n' + * + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\n' + * + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'; + * }); + * @param {Function} [titleFunction] + * @returns {Function|BaseMixin} + */ + title (titleFunction) { + if (!arguments.length) { + return this._title; + } + this._title = titleFunction; + return this; + } + + /** + * Turn on/off title rendering, or return the state of the render title flag if no arguments are + * given. + * @param {Boolean} [renderTitle=true] + * @returns {Boolean|BaseMixin} + */ + renderTitle (renderTitle) { + if (!arguments.length) { + return this._renderTitle; + } + this._renderTitle = renderTitle; + return this; + } + + /** + * Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn + * together since it is expected they share the same underlying crossfilter data set. + * @param {String} [chartGroup] + * @returns {String|BaseMixin} + */ + chartGroup (chartGroup) { + if (!arguments.length) { + return this._chartGroup; + } + if (!this._isChild) { + deregisterChart(this, this._chartGroup); + } + this._chartGroup = chartGroup; + if (!this._isChild) { + registerChart(this, this._chartGroup); + } + return this; + } + + /** + * Expire the internal chart cache. dc charts cache some data internally on a per chart basis to + * speed up rendering and avoid unnecessary calculation; however it might be useful to clear the + * cache if you have changed state which will affect rendering. For example, if you invoke + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add} + * function or reset group or dimension after rendering, it is a good idea to + * clear the cache to make sure charts are rendered properly. + * @returns {BaseMixin} + */ + expireCache () { + // do nothing in base, should be overridden by sub-function + return this; + } + + /** + * Attach a Legend widget to this chart. The legend widget will automatically draw legend labels + * based on the color setting and names associated with each group. + * @example + * chart.legend(new Legend().x(400).y(10).itemHeight(13).gap(5)) + * @param {Legend} [legend] + * @returns {Legend|BaseMixin} + */ + legend (legend) { + if (!arguments.length) { + return this._legend; + } + this._legend = legend; + this._legend.parent(this); + return this; + } + + /** + * Returns the internal numeric ID of the chart. + * @returns {String} + */ + chartID () { + return this.__dcFlag__; + } + + /** + * Set chart options using a configuration object. Each key in the object will cause the method of + * the same name to be called with the value to set that attribute for the chart. + * @example + * chart.options({dimension: myDimension, group: myGroup}); + * @param {{}} opts + * @returns {BaseMixin} + */ + options (opts) { + const applyOptions = [ + 'anchor', + 'group', + 'xAxisLabel', + 'yAxisLabel', + 'stack', + 'title', + 'point', + 'getColor', + 'overlayGeoJson' + ]; + + for (const o in opts) { + if (typeof (this[o]) === 'function') { + if (opts[o] instanceof Array && applyOptions.indexOf(o) !== -1) { + this[o].apply(this, opts[o]); + } else { + this[o].call(this, opts[o]); + } + } else { + logger.debug(`Not a valid option setter name: ${o}`); + } + } + return this; + } + + /** + * All dc chart instance supports the following listeners. + * Supports the following events: + * * `renderlet` - This listener function will be invoked after transitions after redraw and render. Replaces the + * deprecated {@link BaseMixin#renderlet renderlet} method. + * * `pretransition` - Like `.on('renderlet', ...)` but the event is fired before transitions start. + * * `preRender` - This listener function will be invoked before chart rendering. + * * `postRender` - This listener function will be invoked after chart finish rendering including + * all renderlets' logic. + * * `preRedraw` - This listener function will be invoked before chart redrawing. + * * `postRedraw` - This listener function will be invoked after chart finish redrawing + * including all renderlets' logic. + * * `filtered` - This listener function will be invoked after a filter is applied, added or removed. + * * `zoomed` - This listener function will be invoked after a zoom is triggered. + * @see {@link https://github.com/d3/d3-dispatch/blob/master/README.md#dispatch_on d3.dispatch.on} + * @example + * .on('renderlet', function(chart, filter){...}) + * .on('pretransition', function(chart, filter){...}) + * .on('preRender', function(chart){...}) + * .on('postRender', function(chart){...}) + * .on('preRedraw', function(chart){...}) + * .on('postRedraw', function(chart){...}) + * .on('filtered', function(chart, filter){...}) + * .on('zoomed', function(chart, filter){...}) + * @param {String} event + * @param {Function} listener + * @returns {BaseMixin} + */ + on (event, listener) { + this._listeners.on(event, listener); + return this; + } + + /** + * A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added + * to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked + * right after the chart finishes its transitions, giving you a way to modify the SVGElements. + * Renderlet functions take the chart instance as the only input parameter and you can + * use the dc API or use raw d3 to achieve pretty much any effect. + * + * Use {@link BaseMixin#on on} with a 'renderlet' prefix. + * Generates a random key for the renderlet, which makes it hard to remove. + * @deprecated chart.renderlet has been deprecated. Please use chart.on("renderlet.", renderletFunction) + * @example + * // do this instead of .renderlet(function(chart) { ... }) + * chart.on("renderlet", function(chart){ + * // mix of dc API and d3 manipulation + * chart.select('g.y').style('display', 'none'); + * // its a closure so you can also access other chart variable available in the closure scope + * moveChart.filter(chart.filter()); + * }); + * @param {Function} renderletFunction + * @returns {BaseMixin} + */ + renderlet (renderletFunction) { + logger.warnOnce('chart.renderlet has been deprecated. Please use chart.on("renderlet.", renderletFunction)'); + this.on(`renderlet.${utils.uniqueId()}`, renderletFunction); + return this; + } +} + +export const baseMixin = () => new BaseMixin(); diff --git a/src/base/bubble-mixin.js b/src/base/bubble-mixin.js new file mode 100644 index 0000000000..d1d688bc73 --- /dev/null +++ b/src/base/bubble-mixin.js @@ -0,0 +1,309 @@ +import { ascending, descending, min, max } from 'd3-array'; +import { scaleLinear } from 'd3-scale'; + +import {ColorMixin} from './color-mixin'; +import {transition} from '../core/core'; +import {events} from '../core/events'; +import {d3compat} from '../core/config'; + +/** + * This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles. + * @mixin BubbleMixin + * @mixes ColorMixin + * @param {Object} Base + * @returns {BubbleMixin} + */ +export const BubbleMixin = Base => class extends ColorMixin(Base) { + constructor () { + super(); + + this._maxBubbleRelativeSize = 0.3; + this._minRadiusWithLabel = 10; + this._sortBubbleSize = false; + this._elasticRadius = false; + this._excludeElasticZero = true; + + // These cane be used by derived classes as well, so member status + this.BUBBLE_NODE_CLASS = 'node'; + this.BUBBLE_CLASS = 'bubble'; + this.MIN_RADIUS = 10; + + this.renderLabel(true); + + this.data(group => { + const data = group.all(); + + if (this._keyboardAccessible) { + // sort based on the x value (key) + data.sort((a, b) => ascending(this.keyAccessor()(a), this.keyAccessor()(b))); + } + + if (this._sortBubbleSize) { + // sort descending so smaller bubbles are on top + const radiusAccessor = this.radiusValueAccessor(); + data.sort((a, b) => descending(radiusAccessor(a), radiusAccessor(b))); + } + return data; + }); + + this._r = scaleLinear().domain([0, 100]); + } + + _rValueAccessor (d) { + return d.r; + } + + /** + * Get or set the bubble radius scale. By default the bubble chart uses + * {@link https://github.com/d3/d3-scale/blob/master/README.md#scaleLinear d3.scaleLinear().domain([0, 100])} + * as its radius scale. + * @memberof BubbleMixin + * @instance + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @param {d3.scale} [bubbleRadiusScale=d3.scaleLinear().domain([0, 100])] + * @returns {d3.scale|BubbleMixin} + */ + r (bubbleRadiusScale) { + if (!arguments.length) { + return this._r; + } + this._r = bubbleRadiusScale; + return this; + } + + /** + * Turn on or off the elastic bubble radius feature, or return the value of the flag. If this + * feature is turned on, then bubble radii will be automatically rescaled to fit the chart better. + * @memberof BubbleMixin + * @instance + * @param {Boolean} [elasticRadius=false] + * @returns {Boolean|BubbleChart} + */ + elasticRadius (elasticRadius) { + if (!arguments.length) { + return this._elasticRadius; + } + this._elasticRadius = elasticRadius; + return this; + } + + calculateRadiusDomain () { + if (this._elasticRadius) { + this.r().domain([this.rMin(), this.rMax()]); + } + } + + /** + * Get or set the radius value accessor function. If set, the radius value accessor function will + * be used to retrieve a data value for each bubble. The data retrieved then will be mapped using + * the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble + * size. + * @memberof BubbleMixin + * @instance + * @param {Function} [radiusValueAccessor] + * @returns {Function|BubbleMixin} + */ + radiusValueAccessor (radiusValueAccessor) { + if (!arguments.length) { + return this._rValueAccessor; + } + this._rValueAccessor = radiusValueAccessor; + return this; + } + + rMin () { + let values = this.data().map(this.radiusValueAccessor()); + if(this._excludeElasticZero) { + values = values.filter(value => value > 0); + } + return min(values); + } + + rMax () { + return max(this.data(), e => this.radiusValueAccessor()(e)); + } + + bubbleR (d) { + const value = this.radiusValueAccessor()(d); + let r = this.r()(value); + if (isNaN(r) || value <= 0) { + r = 0; + } + return r; + } + + _labelFunction (d) { + return this.label()(d); + } + + _shouldLabel (d) { + return (this.bubbleR(d) > this._minRadiusWithLabel); + } + + _labelOpacity (d) { + return this._shouldLabel(d) ? 1 : 0; + } + + _labelPointerEvent (d) { + return this._shouldLabel(d) ? 'all' : 'none'; + } + + _doRenderLabel (bubbleGEnter) { + if (this.renderLabel()) { + let label = bubbleGEnter.select('text'); + + if (label.empty()) { + label = bubbleGEnter.append('text') + .attr('text-anchor', 'middle') + .attr('dy', '.3em') + .on('click', d3compat.eventHandler(d => this.onClick(d))); + } + + label + .attr('opacity', 0) + .attr('pointer-events', d => this._labelPointerEvent(d)) + .text(d => this._labelFunction(d)); + transition(label, this.transitionDuration(), this.transitionDelay()) + .attr('opacity', d => this._labelOpacity(d)); + } + } + + doUpdateLabels (bubbleGEnter) { + if (this.renderLabel()) { + const labels = bubbleGEnter.select('text') + .attr('pointer-events', d => this._labelPointerEvent(d)) + .text(d => this._labelFunction(d)); + transition(labels, this.transitionDuration(), this.transitionDelay()) + .attr('opacity', d => this._labelOpacity(d)); + } + } + + _titleFunction (d) { + return this.title()(d); + } + + _doRenderTitles (g) { + if (this.renderTitle()) { + const title = g.select('title'); + + if (title.empty()) { + g.append('title').text(d => this._titleFunction(d)); + } + } + } + + doUpdateTitles (g) { + if (this.renderTitle()) { + g.select('title').text(d => this._titleFunction(d)); + } + } + + /** + * Turn on or off the bubble sorting feature, or return the value of the flag. If enabled, + * bubbles will be sorted by their radius, with smaller bubbles in front. + * @memberof BubbleChart + * @instance + * @param {Boolean} [sortBubbleSize=false] + * @returns {Boolean|BubbleChart} + */ + sortBubbleSize (sortBubbleSize) { + if (!arguments.length) { + return this._sortBubbleSize; + } + this._sortBubbleSize = sortBubbleSize; + return this; + } + + /** + * Get or set the minimum radius. This will be used to initialize the radius scale's range. + * @memberof BubbleMixin + * @instance + * @param {Number} [radius=10] + * @returns {Number|BubbleMixin} + */ + minRadius (radius) { + if (!arguments.length) { + return this.MIN_RADIUS; + } + this.MIN_RADIUS = radius; + return this; + } + + /** + * Get or set the minimum radius for label rendering. If a bubble's radius is less than this value + * then no label will be rendered. + * @memberof BubbleMixin + * @instance + * @param {Number} [radius=10] + * @returns {Number|BubbleMixin} + */ + + minRadiusWithLabel (radius) { + if (!arguments.length) { + return this._minRadiusWithLabel; + } + this._minRadiusWithLabel = radius; + return this; + } + + /** + * Get or set the maximum relative size of a bubble to the length of x axis. This value is useful + * when the difference in radius between bubbles is too great. + * @memberof BubbleMixin + * @instance + * @param {Number} [relativeSize=0.3] + * @returns {Number|BubbleMixin} + */ + maxBubbleRelativeSize (relativeSize) { + if (!arguments.length) { + return this._maxBubbleRelativeSize; + } + this._maxBubbleRelativeSize = relativeSize; + return this; + } + + /** + * Should the chart exclude zero when calculating elastic bubble radius? + * @memberof BubbleMixin + * @instance + * @param {Boolean} [excludeZero=true] + * @returns {Boolean|BubbleMixin} + */ + excludeElasticZero (excludeZero) { + if (!arguments.length) { + return this._excludeElasticZero; + } + this._excludeElasticZero = excludeZero; + return this; + } + + fadeDeselectedArea (selection) { + if (this.hasFilter()) { + const chart = this; + this.selectAll(`g.${chart.BUBBLE_NODE_CLASS}`).each(function (d) { + if (chart.isSelectedNode(d)) { + chart.highlightSelected(this); + } else { + chart.fadeDeselected(this); + } + }); + } else { + const chart = this; + this.selectAll(`g.${chart.BUBBLE_NODE_CLASS}`).each(function () { + chart.resetHighlight(this); + }); + } + } + + isSelectedNode (d) { + return this.hasFilter(d.key); + } + + onClick (d) { + const filter = d.key; + events.trigger(() => { + this.filter(filter); + this.redrawGroup(); + }); + } +}; diff --git a/src/base/cap-mixin.js b/src/base/cap-mixin.js new file mode 100644 index 0000000000..c306fd2dc2 --- /dev/null +++ b/src/base/cap-mixin.js @@ -0,0 +1,192 @@ +import {sum} from 'd3-array'; + +/** + * Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the + * Row and Pie Charts. + * + * The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest + * will be replaced with an *others* element, with value equal to the sum of the replaced values. The + * keys of the elements below the cap limit are recorded in order to filter by those keys when the + * others* element is clicked. + * @mixin CapMixin + * @param {Object} Base + * @returns {CapMixin} + */ +export const CapMixin = Base => class extends Base { + constructor () { + super(); + + this._cap = Infinity; + this._takeFront = true; + this._othersLabel = 'Others'; + + this._othersGrouper = (topItems, restItems) => { + const restItemsSum = sum(restItems, this.valueAccessor()), + restKeys = restItems.map(this.keyAccessor()); + if (restItemsSum > 0) { + return topItems.concat([{ + others: restKeys, + key: this.othersLabel(), + value: restItemsSum + }]); + } + return topItems; + }; + + // emulate old group.top(N) ordering + this.ordering(kv => -kv.value); + + // return N "top" groups, where N is the cap, sorted by baseMixin.ordering + // whether top means front or back depends on takeFront + this.data(group => { + if (this._cap === Infinity) { + return this._computeOrderedGroups(group.all()); + } else { + let items = group.all(), rest; + items = this._computeOrderedGroups(items); // sort by baseMixin.ordering + + if (this._cap) { + if (this._takeFront) { + rest = items.slice(this._cap); + items = items.slice(0, this._cap); + } else { + const start = Math.max(0, items.length - this._cap); + rest = items.slice(0, start); + items = items.slice(start); + } + } + + if (this._othersGrouper) { + return this._othersGrouper(items, rest); + } + return items; + } + }); + } + + cappedKeyAccessor (d, i) { + if (d.others) { + return d.key; + } + return this.keyAccessor()(d, i); + } + + cappedValueAccessor (d, i) { + if (d.others) { + return d.value; + } + return this.valueAccessor()(d, i); + } + + /** + * Get or set the count of elements to that will be included in the cap. If there is an + * {@link CapMixin#othersGrouper othersGrouper}, any further elements will be combined in an + * extra element with its name determined by {@link CapMixin#othersLabel othersLabel}. + * + * As of dc.js 2.1 and onward, the capped charts use + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_all group.all()} + * and {@link BaseMixin#ordering BaseMixin.ordering()} to determine the order of + * elements. Then `cap` and {@link CapMixin#takeFront takeFront} determine how many elements + * to keep, from which end of the resulting array. + * + * **Migration note:** Up through dc.js 2.0.*, capping used + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_top group.top(N)}, + * which selects the largest items according to + * {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group_order group.order()}. + * The chart then sorted the items according to {@link BaseMixin#ordering baseMixin.ordering()}. + * So the two values essentially had to agree, but if the `group.order()` was incorrect (it's + * easy to forget about), the wrong rows or slices would be displayed, in the correct order. + * + * If your chart previously relied on `group.order()`, use `chart.ordering()` instead. As of + * 2.1.5, the ordering defaults to sorting from greatest to least like `group.top(N)` did. + * + * If you want to cap by one ordering but sort by another, you can still do this by + * specifying your own {@link BaseMixin#data `.data()`} callback. For details, see the example + * {@link https://dc-js.github.io/dc.js/examples/cap-and-sort-differently.html Cap and Sort Differently}. + * @memberof CapMixin + * @instance + * @param {Number} [count=Infinity] + * @returns {Number|CapMixin} + */ + cap (count) { + if (!arguments.length) { + return this._cap; + } + this._cap = count; + return this; + } + + /** + * Get or set the direction of capping. If set, the chart takes the first + * {@link CapMixin#cap cap} elements from the sorted array of elements; otherwise + * it takes the last `cap` elements. + * @memberof CapMixin + * @instance + * @param {Boolean} [takeFront=true] + * @returns {Boolean|CapMixin} + */ + takeFront (takeFront) { + if (!arguments.length) { + return this._takeFront; + } + this._takeFront = takeFront; + return this; + } + + /** + * Get or set the label for *Others* slice when slices cap is specified. + * @memberof CapMixin + * @instance + * @param {String} [label="Others"] + * @returns {String|CapMixin} + */ + othersLabel (label) { + if (!arguments.length) { + return this._othersLabel; + } + this._othersLabel = label; + return this; + } + + /** + * Get or set the grouper function that will perform the insertion of data for the *Others* slice + * if the slices cap is specified. If set to a falsy value, no others will be added. + * + * The grouper function takes an array of included ("top") items, and an array of the rest of + * the items. By default the grouper function computes the sum of the rest. + * @memberof CapMixin + * @instance + * @example + * // Do not show others + * chart.othersGrouper(null); + * // Default others grouper + * chart.othersGrouper(function (topItems, restItems) { + * var restItemsSum = d3.sum(restItems, _chart.valueAccessor()), + * restKeys = restItems.map(_chart.keyAccessor()); + * if (restItemsSum > 0) { + * return topItems.concat([{ + * others: restKeys, + * key: _chart.othersLabel(), + * value: restItemsSum + * }]); + * } + * return topItems; + * }); + * @param {Function} [grouperFunction] + * @returns {Function|CapMixin} + */ + othersGrouper (grouperFunction) { + if (!arguments.length) { + return this._othersGrouper; + } + this._othersGrouper = grouperFunction; + return this; + } + + onClick (d) { + if (d.others) { + this.filter([d.others]); + } + super.onClick(d); + } +}; diff --git a/src/base/color-mixin.js b/src/base/color-mixin.js new file mode 100644 index 0000000000..39a3d80c67 --- /dev/null +++ b/src/base/color-mixin.js @@ -0,0 +1,177 @@ +import {scaleLinear, scaleOrdinal, scaleQuantize} from 'd3-scale'; +import {interpolateHcl} from 'd3-interpolate'; +import {max, min} from 'd3-array'; + +import {config} from '../core/config'; +import {utils} from '../core/utils'; + +/** + * The Color Mixin is an abstract chart functional class providing universal coloring support + * as a mix-in for any concrete chart implementation. + * @mixin ColorMixin + * @param {Object} Base + * @returns {ColorMixin} + */ +export const ColorMixin = Base => class extends Base { + constructor () { + super(); + + this._colors = scaleOrdinal(config.defaultColors()); + + this._colorAccessor = d => this.keyAccessor()(d); + this._colorCalculator = undefined; + + { + const chart = this; + // ES6: this method is called very differently from stack-mixin and derived charts + // Removing and placing it as a member method is tricky + + /** + * Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. + * @method getColor + * @memberof ColorMixin + * @instance + * @param {*} d + * @param {Number} [i] + * @returns {String} + */ + chart.getColor = function (d, i) { + return chart._colorCalculator ? + chart._colorCalculator.call(this, d, i) : + chart._colors(chart._colorAccessor.call(this, d, i)); + }; + } + } + + /** + * Set the domain by determining the min and max values as retrieved by + * {@link ColorMixin#colorAccessor .colorAccessor} over the chart's dataset. + * @memberof ColorMixin + * @instance + * @returns {ColorMixin} + */ + calculateColorDomain () { + const newDomain = [min(this.data(), this.colorAccessor()), + max(this.data(), this.colorAccessor())]; + this._colors.domain(newDomain); + return this; + } + + /** + * Retrieve current color scale or set a new color scale. This methods accepts any function that + * operates like a d3 scale. + * @memberof ColorMixin + * @instance + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @example + * // alternate categorical scale + * chart.colors(d3.scale.category20b()); + * // ordinal scale + * chart.colors(d3.scaleOrdinal().range(['red','green','blue'])); + * // convenience method, the same as above + * chart.ordinalColors(['red','green','blue']); + * // set a linear scale + * chart.linearColors(["#4575b4", "#ffffbf", "#a50026"]); + * @param {d3.scale} [colorScale=d3.scaleOrdinal(d3.schemeCategory20c)] + * @returns {d3.scale|ColorMixin} + */ + colors (colorScale) { + if (!arguments.length) { + return this._colors; + } + if (colorScale instanceof Array) { + this._colors = scaleQuantize().range(colorScale); // deprecated legacy support, note: this fails for ordinal domains + } else { + this._colors = typeof colorScale === 'function' ? colorScale : utils.constant(colorScale); + } + return this; + } + + /** + * Convenience method to set the color scale to + * {@link https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales d3.scaleOrdinal} with + * range `r`. + * @memberof ColorMixin + * @instance + * @param {Array} r + * @returns {ColorMixin} + */ + ordinalColors (r) { + return this.colors(scaleOrdinal().range(r)); + } + + /** + * Convenience method to set the color scale to an Hcl interpolated linear scale with range `r`. + * @memberof ColorMixin + * @instance + * @param {Array} r + * @returns {ColorMixin} + */ + linearColors (r) { + return this.colors(scaleLinear() + .range(r) + .interpolate(interpolateHcl)); + } + + /** + * Set or the get color accessor function. This function will be used to map a data point in a + * crossfilter group to a color value on the color scale. The default function uses the key + * accessor. + * @memberof ColorMixin + * @instance + * @example + * // default index based color accessor + * .colorAccessor(function (d, i){return i;}) + * // color accessor for a multi-value crossfilter reduction + * .colorAccessor(function (d){return d.value.absGain;}) + * @param {Function} [colorAccessor] + * @returns {Function|ColorMixin} + */ + colorAccessor (colorAccessor) { + if (!arguments.length) { + return this._colorAccessor; + } + this._colorAccessor = colorAccessor; + return this; + } + + /** + * Set or get the current domain for the color mapping function. The domain must be supplied as an + * array. + * + * Note: previously this method accepted a callback function. Instead you may use a custom scale + * set by {@link ColorMixin#colors .colors}. + * @memberof ColorMixin + * @instance + * @param {Array} [domain] + * @returns {Array|ColorMixin} + */ + colorDomain (domain) { + if (!arguments.length) { + return this._colors.domain(); + } + this._colors.domain(domain); + return this; + } + + /** + * Overrides the color selection algorithm, replacing it with a simple function. + * + * Normally colors will be determined by calling the `colorAccessor` to get a value, and then passing that + * value through the `colorScale`. + * + * But sometimes it is difficult to get a color scale to produce the desired effect. The `colorCalculator` + * takes the datum and index and returns a color directly. + * @memberof ColorMixin + * @instance + * @param {*} [colorCalculator] + * @returns {Function|ColorMixin} + */ + colorCalculator (colorCalculator) { + if (!arguments.length) { + return this._colorCalculator || this.getColor; + } + this._colorCalculator = colorCalculator; + return this; + } +}; diff --git a/src/base/coordinate-grid-mixin.js b/src/base/coordinate-grid-mixin.js new file mode 100644 index 0000000000..78e95a112f --- /dev/null +++ b/src/base/coordinate-grid-mixin.js @@ -0,0 +1,1423 @@ +import {schemeCategory10} from 'd3-scale-chromatic'; +import {timeDay} from 'd3-time'; +import {max, min} from 'd3-array'; +import {scaleBand, scaleLinear, scaleOrdinal} from 'd3-scale'; +import {axisTop, axisBottom, axisLeft, axisRight} from 'd3-axis'; +import {zoom, zoomIdentity} from 'd3-zoom'; +import {brushX} from 'd3-brush'; + +import {ColorMixin} from './color-mixin'; +import {MarginMixin} from './margin-mixin'; +import {optionalTransition, transition} from '../core/core'; +import {units} from '../core/units'; +import {constants} from '../core/constants'; +import {utils} from '../core/utils'; +import {d3compat} from '../core/config'; +import {logger} from '../core/logger'; +import {filters} from '../core/filters'; +import {events} from '../core/events'; + +const GRID_LINE_CLASS = 'grid-line'; +const HORIZONTAL_CLASS = 'horizontal'; +const VERTICAL_CLASS = 'vertical'; +const Y_AXIS_LABEL_CLASS = 'y-axis-label'; +const X_AXIS_LABEL_CLASS = 'x-axis-label'; +const CUSTOM_BRUSH_HANDLE_CLASS = 'custom-brush-handle'; +const DEFAULT_AXIS_LABEL_PADDING = 12; + +/** + * Coordinate Grid is an abstract base chart designed to support a number of coordinate grid based + * concrete chart types, e.g. bar chart, line chart, and bubble chart. + * @mixin CoordinateGridMixin + * @mixes ColorMixin + * @mixes MarginMixin + */ +export class CoordinateGridMixin extends ColorMixin(MarginMixin) { + constructor () { + super(); + + this.colors(scaleOrdinal(schemeCategory10)); + this._mandatoryAttributes().push('x'); + this._parent = undefined; + this._g = undefined; + this._chartBodyG = undefined; + + this._x = undefined; + this._origX = undefined; // Will hold original scale in case of zoom + this._xOriginalDomain = undefined; + this._xAxis = null; + this._xUnits = units.integers; + this._xAxisPadding = 0; + this._xAxisPaddingUnit = timeDay; + this._xElasticity = false; + this._xAxisLabel = undefined; + this._xAxisLabelPadding = 0; + this._lastXDomain = undefined; + + this._y = undefined; + this._yAxis = null; + this._yAxisPadding = 0; + this._yElasticity = false; + this._yAxisLabel = undefined; + this._yAxisLabelPadding = 0; + + this._brush = brushX(); + + this._gBrush = undefined; + this._brushOn = true; + this._parentBrushOn = false; + this._round = undefined; + this._ignoreBrushEvents = false; // ignore when carrying out programmatic brush operations + + this._renderHorizontalGridLine = false; + this._renderVerticalGridLine = false; + + this._resizing = false; + this._unitCount = undefined; + + this._zoomScale = [1, Infinity]; + this._zoomOutRestrict = true; + + this._zoom = zoom().on('zoom', d3compat.eventHandler((d, evt) => this._onZoom(evt))); + this._nullZoom = zoom().on('zoom', null); + this._hasBeenMouseZoomable = false; + this._ignoreZoomEvents = false; // ignore when carrying out programmatic zoom operations + + this._rangeChart = undefined; + this._focusChart = undefined; + + this._mouseZoomable = false; + this._clipPadding = 0; + + this._fOuterRangeBandPadding = 0.5; + this._fRangeBandPadding = 0; + + this._useRightYAxis = false; + this._useTopXAxis = false; + } + + /** + * When changing the domain of the x or y scale, it is necessary to tell the chart to recalculate + * and redraw the axes. (`.rescale()` is called automatically when the x or y scale is replaced + * with {@link CoordinateGridMixin+x .x()} or {@link CoordinateGridMixin#y .y()}, and has + * no effect on elastic scales.) + * @returns {CoordinateGridMixin} + */ + rescale () { + this._unitCount = undefined; + this._resizing = true; + return this; + } + + resizing (resizing) { + if (!arguments.length) { + return this._resizing; + } + this._resizing = resizing; + return this; + } + + /** + * Get or set the range selection chart associated with this instance. Setting the range selection + * chart using this function will automatically update its selection brush when the current chart + * zooms in. In return the given range chart will also automatically attach this chart as its focus + * chart hence zoom in when range brush updates. + * + * Usually the range and focus charts will share a dimension. The range chart will set the zoom + * boundaries for the focus chart, so its dimension values must be compatible with the domain of + * the focus chart. + * + * See the [Nasdaq 100 Index](https://dc-js.github.io/dc.js/) example for this effect in action. + * @param {CoordinateGridMixin} [rangeChart] + * @returns {CoordinateGridMixin} + */ + rangeChart (rangeChart) { + if (!arguments.length) { + return this._rangeChart; + } + this._rangeChart = rangeChart; + this._rangeChart.focusChart(this); + return this; + } + + /** + * Get or set the scale extent for mouse zooms. + * @param {Array} [extent=[1, Infinity]] + * @returns {Array|CoordinateGridMixin} + */ + zoomScale (extent) { + if (!arguments.length) { + return this._zoomScale; + } + this._zoomScale = extent; + return this; + } + + /** + * Get or set the zoom restriction for the chart. If true limits the zoom to origional domain of the chart. + * @param {Boolean} [zoomOutRestrict=true] + * @returns {Boolean|CoordinateGridMixin} + */ + zoomOutRestrict (zoomOutRestrict) { + if (!arguments.length) { + return this._zoomOutRestrict; + } + this._zoomOutRestrict = zoomOutRestrict; + return this; + } + + _generateG (parent) { + if (parent === undefined) { + this._parent = this.svg(); + } else { + this._parent = parent; + } + + const href = window.location.href.split('#')[0]; + + this._g = this._parent.append('g'); + + this._chartBodyG = this._g.append('g').attr('class', 'chart-body') + .attr('transform', `translate(${this.margins().left}, ${this.margins().top})`) + .attr('clip-path', `url(http://github.com/$%7Bhref%7D#${this._getClipPathId()})`); + + return this._g; + } + + /** + * Get or set the root g element. This method is usually used to retrieve the g element in order to + * overlay custom svg drawing programatically. **Caution**: The root g element is usually generated + * by dc.js internals, and resetting it might produce unpredictable result. + * @param {SVGElement} [gElement] + * @returns {SVGElement|CoordinateGridMixin} + */ + g (gElement) { + if (!arguments.length) { + return this._g; + } + this._g = gElement; + return this; + } + + /** + * Set or get mouse zoom capability flag (default: false). When turned on the chart will be + * zoomable using the mouse wheel. If the range selector chart is attached zooming will also update + * the range selection brush on the associated range selector chart. + * @param {Boolean} [mouseZoomable=false] + * @returns {Boolean|CoordinateGridMixin} + */ + mouseZoomable (mouseZoomable) { + if (!arguments.length) { + return this._mouseZoomable; + } + this._mouseZoomable = mouseZoomable; + return this; + } + + /** + * Retrieve the svg group for the chart body. + * @param {SVGElement} [chartBodyG] + * @returns {SVGElement} + */ + chartBodyG (chartBodyG) { + if (!arguments.length) { + return this._chartBodyG; + } + this._chartBodyG = chartBodyG; + return this; + } + + /** + * **mandatory** + * + * Get or set the x scale. The x scale can be any d3 + * {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} or + * {@link https://github.com/d3/d3-scale/blob/master/README.md#ordinal-scales ordinal scale} + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @example + * // set x to a linear scale + * chart.x(d3.scaleLinear().domain([-2500, 2500])) + * // set x to a time scale to generate histogram + * chart.x(d3.scaleTime().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) + * @param {d3.scale} [xScale] + * @returns {d3.scale|CoordinateGridMixin} + */ + x (xScale) { + if (!arguments.length) { + return this._x; + } + this._x = xScale; + this._xOriginalDomain = this._x.domain(); + this.rescale(); + return this; + } + + xOriginalDomain () { + return this._xOriginalDomain; + } + + /** + * Set or get the xUnits function. The coordinate grid chart uses the xUnits function to calculate + * the number of data projections on the x axis such as the number of bars for a bar chart or the + * number of dots for a line chart. + * + * This function is expected to return a Javascript array of all data points on the x axis, or + * the number of points on the axis. d3 time range functions [d3.timeDays, d3.timeMonths, and + * d3.timeYears](https://github.com/d3/d3-time/blob/master/README.md#intervals) are all valid + * xUnits functions. + * + * dc.js also provides a few units function, see the {@link units Units Namespace} for + * a list of built-in units functions. + * + * Note that as of dc.js 3.0, `units.ordinal` is not a real function, because it is not + * possible to define this function compliant with the d3 range functions. It was already a + * magic value which caused charts to behave differently, and now it is completely so. + * @example + * // set x units to count days + * chart.xUnits(d3.timeDays); + * // set x units to count months + * chart.xUnits(d3.timeMonths); + * + * // A custom xUnits function can be used as long as it follows the following interface: + * // units in integer + * function(start, end) { + * // simply calculates how many integers in the domain + * return Math.abs(end - start); + * } + * + * // fixed units + * function(start, end) { + * // be aware using fixed units will disable the focus/zoom ability on the chart + * return 1000; + * } + * @param {Function} [xUnits=units.integers] + * @returns {Function|CoordinateGridMixin} + */ + xUnits (xUnits) { + if (!arguments.length) { + return this._xUnits; + } + this._xUnits = xUnits; + return this; + } + + /** + * Set or get the x axis used by a particular coordinate grid chart instance. This function is most + * useful when x axis customization is required. The x axis in dc.js is an instance of a + * {@link https://github.com/d3/d3-axis/blob/master/README.md#axisBottom d3 bottom axis object}; + * therefore it supports any valid d3 axisBottom manipulation. + * + * **Caution**: The x axis is usually generated internally by dc; resetting it may cause + * unexpected results. Note also that when used as a getter, this function is not chainable: + * it returns the axis, not the chart, + * {@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis + * so attempting to call chart functions after calling `.xAxis()` will fail}. + * @see {@link https://github.com/d3/d3-axis/blob/master/README.md#axisBottom d3.axisBottom} + * @example + * // customize x axis tick format + * chart.xAxis().tickFormat(function(v) {return v + '%';}); + * // customize x axis tick values + * chart.xAxis().tickValues([0, 100, 200, 300]); + * @param {d3.axis} [xAxis=d3.axisBottom()] + * @returns {d3.axis|CoordinateGridMixin} + */ + xAxis (xAxis) { + if (!arguments.length) { + if (!this._xAxis) { + this._xAxis = this._createXAxis(); + } + return this._xAxis; + } + this._xAxis = xAxis; + return this; + } + + /** + * Turn on/off elastic x axis behavior. If x axis elasticity is turned on, then the grid chart will + * attempt to recalculate the x axis range whenever a redraw event is triggered. + * @param {Boolean} [elasticX=false] + * @returns {Boolean|CoordinateGridMixin} + */ + elasticX (elasticX) { + if (!arguments.length) { + return this._xElasticity; + } + this._xElasticity = elasticX; + return this; + } + + /** + * Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x + * axis if elasticX is turned on; otherwise it is ignored. + * + * Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to + * number or date x axes. When padding a date axis, an integer represents number of units being padded + * and a percentage string will be treated the same as an integer. The unit will be determined by the + * xAxisPaddingUnit variable. + * @param {Number|String} [padding=0] + * @returns {Number|String|CoordinateGridMixin} + */ + xAxisPadding (padding) { + if (!arguments.length) { + return this._xAxisPadding; + } + this._xAxisPadding = padding; + return this; + } + + /** + * Set or get x axis padding unit for the elastic x axis. The padding unit will determine which unit to + * use when applying xAxis padding if elasticX is turned on and if x-axis uses a time dimension; + * otherwise it is ignored. + * + * The padding unit should be a + * [d3 time interval](https://github.com/d3/d3-time/blob/master/README.md#self._interval). + * For backward compatibility with dc.js 2.0, it can also be the name of a d3 time interval + * ('day', 'hour', etc). Available arguments are the + * [d3 time intervals](https://github.com/d3/d3-time/blob/master/README.md#intervals d3.timeInterval). + * @param {String} [unit=d3.timeDay] + * @returns {String|CoordinateGridMixin} + */ + xAxisPaddingUnit (unit) { + if (!arguments.length) { + return this._xAxisPaddingUnit; + } + this._xAxisPaddingUnit = unit; + return this; + } + + /** + * Returns the number of units displayed on the x axis. If the x axis is ordinal (`xUnits` is + * `units.ordinal`), this is the number of items in the domain of the x scale. Otherwise, the + * x unit count is calculated using the {@link CoordinateGridMixin#xUnits xUnits} function. + * @returns {Number} + */ + xUnitCount () { + if (this._unitCount === undefined) { + if (this.isOrdinal()) { + // In this case it number of items in domain + this._unitCount = this.x().domain().length; + } else { + this._unitCount = this.xUnits()(this.x().domain()[0], this.x().domain()[1]); + + // Sometimes xUnits() may return an array while sometimes directly the count + if (this._unitCount instanceof Array) { + this._unitCount = this._unitCount.length; + } + } + } + + return this._unitCount; + } + + /** + * Gets or sets whether the chart should be drawn with a right axis instead of a left axis. When + * used with a chart in a composite chart, allows both left and right Y axes to be shown on a + * chart. + * @param {Boolean} [useRightYAxis=false] + * @returns {Boolean|CoordinateGridMixin} + */ + useRightYAxis (useRightYAxis) { + if (!arguments.length) { + return this._useRightYAxis; + } + + // We need to warn if value is changing after self._yAxis was created + if (this._useRightYAxis !== useRightYAxis && this._yAxis) { + logger.warn('Value of useRightYAxis has been altered, after yAxis was created. ' + + 'You might get unexpected yAxis behavior. ' + + 'Make calls to useRightYAxis sooner in your chart creation process.'); + } + + this._useRightYAxis = useRightYAxis; + return this; + } + + /** + * Gets or sets whether the chart should be drawn with a top axis instead of a bottom axis. When + * used with a chart in a composite chart, allows both top and bottom X axes to be shown on a + * chart. + * @param {Boolean} [useTopXAxis=false] + * @returns {Boolean|CoordinateGridMixin} + */ + useTopXAxis (useTopXAxis) { + if (!arguments.length) { + return this._useTopXAxis; + } + + // We need to warn if value is changing after self._yAxis was created + if (this._useTopXAxis !== useTopXAxis && this._xAxis) { + logger.warn('Value of useTopXAxis has been altered, after xAxis was created. ' + + 'You might get unexpected yAxis behavior. ' + + 'Make calls to useTopXAxis sooner in your chart creation process.'); + } + + this._useTopXAxis = useTopXAxis; + return this; + } + + /** + * Returns true if the chart is using ordinal xUnits ({@link units.ordinal units.ordinal}, or false + * otherwise. Most charts behave differently with ordinal data and use the result of this method to + * trigger the appropriate logic. + * @returns {Boolean} + */ + isOrdinal () { + return this.xUnits() === units.ordinal; + } + + _useOuterPadding () { + return true; + } + + _ordinalXDomain () { + const groups = this._computeOrderedGroups(this.data()); + return groups.map(this.keyAccessor()); + } + + _createXAxis () { + return this._useTopXAxis ? axisTop() : axisBottom(); + } + + // eslint-disable-next-line complexity + _prepareXAxis (g, render) { + if (!this.isOrdinal()) { + if (this.elasticX()) { + this._x.domain([this.xAxisMin(), this.xAxisMax()]); + } + } else { // self._chart.isOrdinal() + // D3v4 - Ordinal charts would need scaleBand + // bandwidth is a method in scaleBand + // (https://github.com/d3/d3-scale/blob/master/README.md#scaleBand) + if (!this._x.bandwidth) { + // If self._x is not a scaleBand create a new scale and + // copy the original domain to the new scale + logger.warn('For compatibility with d3v4+, dc.js d3.0 ordinal bar/line/bubble charts need ' + + 'd3.scaleBand() for the x scale, instead of d3.scaleOrdinal(). ' + + 'Replacing .x() with a d3.scaleBand with the same domain - ' + + 'make the same change in your code to avoid this warning!'); + this._x = scaleBand().domain(this._x.domain()); + } + + if (this.elasticX() || this._x.domain().length === 0) { + this._x.domain(this._ordinalXDomain()); + } + } + + // has the domain changed? + const xdom = this._x.domain(); + if (render || !utils.arraysEqual(this._lastXDomain, xdom)) { + this.rescale(); + } + this._lastXDomain = xdom; + + // please can't we always use rangeBands for bar charts? + if (this.isOrdinal()) { + this._x.range([0, this.xAxisLength()]) + .paddingInner(this._fRangeBandPadding) + .paddingOuter(this._useOuterPadding() ? this._fOuterRangeBandPadding : 0); + } else { + this._x.range([0, this.xAxisLength()]); + } + + if (!this._xAxis) { + this._xAxis = this._createXAxis() + } + + this._xAxis = this._xAxis.scale(this.x()); + + this._renderVerticalGridLines(g); + } + + renderXAxis (g) { + let axisXG = g.select('g.x'); + + if (axisXG.empty()) { + axisXG = g.append('g') + .attr('class', 'axis x') + .attr('transform', `translate(${this.margins().left},${this._xAxisY()})`); + } + + let axisXLab = g.select(`text.${X_AXIS_LABEL_CLASS}`); + const axisXLabY = this._useTopXAxis ? this._xAxisLabelPadding : (this.height() - this._xAxisLabelPadding); + if (axisXLab.empty() && this.xAxisLabel()) { + axisXLab = g.append('text') + .attr('class', X_AXIS_LABEL_CLASS) + .attr('transform', `translate(${this.margins().left + this.xAxisLength() / 2},${axisXLabY})`) + .attr('text-anchor', 'middle'); + } + if (this.xAxisLabel() && axisXLab.text() !== this.xAxisLabel()) { + axisXLab.text(this.xAxisLabel()); + } + + transition(axisXG, this.transitionDuration(), this.transitionDelay()) + .attr('transform', `translate(${this.margins().left},${this._xAxisY()})`) + .call(this._xAxis); + transition(axisXLab, this.transitionDuration(), this.transitionDelay()) + .attr('transform', `translate(${this.margins().left + this.xAxisLength() / 2},${axisXLabY})`); + } + + _renderVerticalGridLines (g) { + let gridLineG = g.select(`g.${VERTICAL_CLASS}`); + + if (this._renderVerticalGridLine) { + if (gridLineG.empty()) { + gridLineG = g.insert('g', ':first-child') + .attr('class', `${GRID_LINE_CLASS} ${VERTICAL_CLASS}`) + .attr('transform', `translate(${this.margins().left},${this.margins().top})`); + } + + const ticks = this._xAxis.tickValues() ? this._xAxis.tickValues() : + (typeof this._x.ticks === 'function' ? this._x.ticks.apply(this._x, this._xAxis.tickArguments()) : this._x.domain()); + + const lines = gridLineG.selectAll('line') + .data(ticks); + + // enter + const linesGEnter = lines.enter() + .append('line') + .attr('x1', d => this._x(d)) + .attr('y1', this._xAxisY() - this.margins().top) + .attr('x2', d => this._x(d)) + .attr('y2', 0) + .attr('opacity', 0); + transition(linesGEnter, this.transitionDuration(), this.transitionDelay()) + .attr('opacity', 0.5); + + // update + transition(lines, this.transitionDuration(), this.transitionDelay()) + .attr('x1', d => this._x(d)) + .attr('y1', this._xAxisY() - this.margins().top) + .attr('x2', d => this._x(d)) + .attr('y2', 0); + + // exit + lines.exit().remove(); + } else { + gridLineG.selectAll('line').remove(); + } + } + + _xAxisY () { + return this._useTopXAxis ? this.margins().top : this.height() - this.margins().bottom; + } + + xAxisLength () { + return this.effectiveWidth(); + } + + /** + * Set or get the x axis label. If setting the label, you may optionally include additional padding to + * the margin to make room for the label. By default the padded is set to 12 to accomodate the text height. + * @param {String} [labelText] + * @param {Number} [padding=12] + * @returns {String} + */ + xAxisLabel (labelText, padding) { + if (!arguments.length) { + return this._xAxisLabel; + } + this._xAxisLabel = labelText; + this.margins().bottom -= this._xAxisLabelPadding; + this._xAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding; + this.margins().bottom += this._xAxisLabelPadding; + return this; + } + + _createYAxis () { + return this._useRightYAxis ? axisRight() : axisLeft(); + } + + _prepareYAxis (g) { + if (this._y === undefined || this.elasticY()) { + if (this._y === undefined) { + this._y = scaleLinear(); + } + const _min = this.yAxisMin() || 0; + const _max = this.yAxisMax() || 0; + this._y.domain([_min, _max]).rangeRound([this.yAxisHeight(), 0]); + } + + this._y.range([this.yAxisHeight(), 0]); + + if (!this._yAxis) { + this._yAxis = this._createYAxis(); + } + + this._yAxis.scale(this._y); + + this._renderHorizontalGridLinesForAxis(g, this._y, this._yAxis); + } + + renderYAxisLabel (axisClass, text, rotation, labelXPosition) { + labelXPosition = labelXPosition || this._yAxisLabelPadding; + + let axisYLab = this.g().select(`text.${Y_AXIS_LABEL_CLASS}.${axisClass}-label`); + const labelYPosition = (this.margins().top + this.yAxisHeight() / 2); + if (axisYLab.empty() && text) { + axisYLab = this.g().append('text') + .attr('transform', `translate(${labelXPosition},${labelYPosition}),rotate(${rotation})`) + .attr('class', `${Y_AXIS_LABEL_CLASS} ${axisClass}-label`) + .attr('text-anchor', 'middle') + .text(text); + } + if (text && axisYLab.text() !== text) { + axisYLab.text(text); + } + transition(axisYLab, this.transitionDuration(), this.transitionDelay()) + .attr('transform', `translate(${labelXPosition},${labelYPosition}),rotate(${rotation})`); + } + + renderYAxisAt (axisClass, axis, position) { + let axisYG = this.g().select(`g.${axisClass}`); + if (axisYG.empty()) { + axisYG = this.g().append('g') + .attr('class', `axis ${axisClass}`) + .attr('transform', `translate(${position},${this.margins().top})`); + } + + transition(axisYG, this.transitionDuration(), this.transitionDelay()) + .attr('transform', `translate(${position},${this.margins().top})`) + .call(axis); + } + + renderYAxis () { + const axisPosition = this._useRightYAxis ? (this.width() - this.margins().right) : this._yAxisX(); + this.renderYAxisAt('y', this._yAxis, axisPosition); + const labelPosition = this._useRightYAxis ? (this.width() - this._yAxisLabelPadding) : this._yAxisLabelPadding; + const rotation = this._useRightYAxis ? 90 : -90; + this.renderYAxisLabel('y', this.yAxisLabel(), rotation, labelPosition); + } + + _renderHorizontalGridLinesForAxis (g, scale, axis) { + let gridLineG = g.select(`g.${HORIZONTAL_CLASS}`); + + if (this._renderHorizontalGridLine) { + // see https://github.com/d3/d3-axis/blob/master/src/axis.js#L48 + const ticks = axis.tickValues() ? axis.tickValues() : + (scale.ticks ? scale.ticks.apply(scale, axis.tickArguments()) : scale.domain()); + + if (gridLineG.empty()) { + gridLineG = g.insert('g', ':first-child') + .attr('class', `${GRID_LINE_CLASS} ${HORIZONTAL_CLASS}`) + .attr('transform', `translate(${this.margins().left},${this.margins().top})`); + } + + const lines = gridLineG.selectAll('line') + .data(ticks); + + // enter + const linesGEnter = lines.enter() + .append('line') + .attr('x1', 1) + .attr('y1', d => scale(d)) + .attr('x2', this.xAxisLength()) + .attr('y2', d => scale(d)) + .attr('opacity', 0); + transition(linesGEnter, this.transitionDuration(), this.transitionDelay()) + .attr('opacity', 0.5); + + // update + transition(lines, this.transitionDuration(), this.transitionDelay()) + .attr('x1', 1) + .attr('y1', d => scale(d)) + .attr('x2', this.xAxisLength()) + .attr('y2', d => scale(d)); + + // exit + lines.exit().remove(); + } else { + gridLineG.selectAll('line').remove(); + } + } + + _yAxisX () { + return this.useRightYAxis() ? this.width() - this.margins().right : this.margins().left; + } + + /** + * Set or get the y axis label. If setting the label, you may optionally include additional padding + * to the margin to make room for the label. By default the padding is set to 12 to accommodate the + * text height. + * @param {String} [labelText] + * @param {Number} [padding=12] + * @returns {String|CoordinateGridMixin} + */ + yAxisLabel (labelText, padding) { + if (!arguments.length) { + return this._yAxisLabel; + } + this._yAxisLabel = labelText; + this.margins().left -= this._yAxisLabelPadding; + this._yAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding; + this.margins().left += this._yAxisLabelPadding; + return this; + } + + /** + * Get or set the y scale. The y scale is typically automatically determined by the chart implementation. + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @param {d3.scale} [yScale] + * @returns {d3.scale|CoordinateGridMixin} + */ + y (yScale) { + if (!arguments.length) { + return this._y; + } + this._y = yScale; + this.rescale(); + return this; + } + + /** + * Set or get the y axis used by the coordinate grid chart instance. This function is most useful + * when y axis customization is required. Depending on `useRightYAxis` the y axis in dc.js is an instance of + * either [d3.axisLeft](https://github.com/d3/d3-axis/blob/master/README.md#axisLeft) or + * [d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight); therefore it supports any + * valid d3 axis manipulation. + * + * **Caution**: The y axis is usually generated internally by dc; resetting it may cause + * unexpected results. Note also that when used as a getter, this function is not chainable: it + * returns the axis, not the chart, + * {@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis + * so attempting to call chart functions after calling `.yAxis()` will fail}. + * In addition, depending on whether you are going to use the axis on left or right + * you need to appropriately pass [d3.axisLeft](https://github.com/d3/d3-axis/blob/master/README.md#axisLeft) + * or [d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight) + * @see {@link https://github.com/d3/d3-axis/blob/master/README.md d3.axis} + * @example + * // customize y axis tick format + * chart.yAxis().tickFormat(function(v) {return v + '%';}); + * // customize y axis tick values + * chart.yAxis().tickValues([0, 100, 200, 300]); + * @param {d3.axisLeft|d3.axisRight} [yAxis] + * @returns {d3.axisLeft|d3.axisRight|CoordinateGridMixin} + */ + yAxis (yAxis) { + if (!arguments.length) { + if (!this._yAxis) { + this._yAxis = this._createYAxis(); + } + return this._yAxis; + } + this._yAxis = yAxis; + return this; + } + + /** + * Turn on/off elastic y axis behavior. If y axis elasticity is turned on, then the grid chart will + * attempt to recalculate the y axis range whenever a redraw event is triggered. + * @param {Boolean} [elasticY=false] + * @returns {Boolean|CoordinateGridMixin} + */ + elasticY (elasticY) { + if (!arguments.length) { + return this._yElasticity; + } + this._yElasticity = elasticY; + return this; + } + + /** + * Turn on/off horizontal grid lines. + * @param {Boolean} [renderHorizontalGridLines=false] + * @returns {Boolean|CoordinateGridMixin} + */ + renderHorizontalGridLines (renderHorizontalGridLines) { + if (!arguments.length) { + return this._renderHorizontalGridLine; + } + this._renderHorizontalGridLine = renderHorizontalGridLines; + return this; + } + + /** + * Turn on/off vertical grid lines. + * @param {Boolean} [renderVerticalGridLines=false] + * @returns {Boolean|CoordinateGridMixin} + */ + renderVerticalGridLines (renderVerticalGridLines) { + if (!arguments.length) { + return this._renderVerticalGridLine; + } + this._renderVerticalGridLine = renderVerticalGridLines; + return this; + } + + /** + * Calculates the minimum x value to display in the chart. Includes xAxisPadding if set. + * @returns {*} + */ + xAxisMin () { + const m = min(this.data(), e => this.keyAccessor()(e)); + return utils.subtract(m, this._xAxisPadding, this._xAxisPaddingUnit); + } + + /** + * Calculates the maximum x value to display in the chart. Includes xAxisPadding if set. + * @returns {*} + */ + xAxisMax () { + const m = max(this.data(), e => this.keyAccessor()(e)); + return utils.add(m, this._xAxisPadding, this._xAxisPaddingUnit); + } + + /** + * Calculates the minimum y value to display in the chart. Includes yAxisPadding if set. + * @returns {*} + */ + yAxisMin () { + const m = min(this.data(), e => this.valueAccessor()(e)); + return utils.subtract(m, this._yAxisPadding); + } + + /** + * Calculates the maximum y value to display in the chart. Includes yAxisPadding if set. + * @returns {*} + */ + yAxisMax () { + const m = max(this.data(), e => this.valueAccessor()(e)); + return utils.add(m, this._yAxisPadding); + } + + /** + * Set or get y axis padding for the elastic y axis. The padding will be added to the top and + * bottom of the y axis if elasticY is turned on; otherwise it is ignored. + * + * Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to + * number or date axes. When padding a date axis, an integer represents number of days being padded + * and a percentage string will be treated the same as an integer. + * @param {Number|String} [padding=0] + * @returns {Number|CoordinateGridMixin} + */ + yAxisPadding (padding) { + if (!arguments.length) { + return this._yAxisPadding; + } + this._yAxisPadding = padding; + return this; + } + + yAxisHeight () { + return this.effectiveHeight(); + } + + /** + * Set or get the rounding function used to quantize the selection when brushing is enabled. + * @example + * // set x unit round to by month, this will make sure range selection brush will + * // select whole months + * chart.round(d3.timeMonth.round); + * @param {Function} [round] + * @returns {Function|CoordinateGridMixin} + */ + round (round) { + if (!arguments.length) { + return this._round; + } + this._round = round; + return this; + } + + _rangeBandPadding (_) { + if (!arguments.length) { + return this._fRangeBandPadding; + } + this._fRangeBandPadding = _; + return this; + } + + _outerRangeBandPadding (_) { + if (!arguments.length) { + return this._fOuterRangeBandPadding; + } + this._fOuterRangeBandPadding = _; + return this; + } + + filter (_) { + if (!arguments.length) { + return super.filter(); + } + + super.filter(_); + + this.redrawBrush(_, false); + + return this; + } + + /** + * Get or set the brush. Brush must be an instance of d3 brushes + * https://github.com/d3/d3-brush/blob/master/README.md + * You will use this only if you are writing a new chart type that supports brushing. + * + * **Caution**: dc creates and manages brushes internally. Go through and understand the source code + * if you want to pass a new brush object. Even if you are only using the getter, + * the brush object may not behave the way you expect. + * + * @param {d3.brush} [_] + * @returns {d3.brush|CoordinateGridMixin} + */ + brush (_) { + if (!arguments.length) { + return this._brush; + } + this._brush = _; + return this; + } + + renderBrush (g, doTransition) { + if (this._brushOn) { + this._brush.on('start brush end', d3compat.eventHandler((d, evt) => this._brushing(evt))); + + // To retrieve selection we need self._gBrush + this._gBrush = g.append('g') + .attr('class', 'brush') + .attr('transform', `translate(${this.margins().left},${this.margins().top})`); + + this.setBrushExtents(); + + this.createBrushHandlePaths(this._gBrush, doTransition); + + this.redrawBrush(this.filter(), doTransition); + } + } + + createBrushHandlePaths (gBrush) { + let brushHandles = gBrush.selectAll(`path.${CUSTOM_BRUSH_HANDLE_CLASS}`).data([{type: 'w'}, {type: 'e'}]); + + brushHandles = brushHandles + .enter() + .append('path') + .attr('class', CUSTOM_BRUSH_HANDLE_CLASS) + .merge(brushHandles); + + brushHandles + .attr('d', d => this.resizeHandlePath(d)); + } + + extendBrush (brushSelection) { + if (brushSelection && this.round()) { + brushSelection[0] = this.round()(brushSelection[0]); + brushSelection[1] = this.round()(brushSelection[1]); + } + return brushSelection; + } + + brushIsEmpty (brushSelection) { + return !brushSelection || brushSelection[1] <= brushSelection[0]; + } + + _brushing (evt) { + if (this._ignoreBrushEvents) { + return; + } + + let brushSelection = evt.selection; + if (brushSelection) { + brushSelection = brushSelection.map(this.x().invert); + } + + brushSelection = this.extendBrush(brushSelection); + + this.redrawBrush(brushSelection, false); + + const rangedFilter = this.brushIsEmpty(brushSelection) ? null : filters.RangedFilter(brushSelection[0], brushSelection[1]); + + events.trigger(() => { + this.applyBrushSelection(rangedFilter); + }, constants.EVENT_DELAY); + } + + // This can be overridden in a derived chart. For example Composite chart overrides it + applyBrushSelection (rangedFilter) { + this.replaceFilter(rangedFilter); + this.redrawGroup(); + } + + _withoutBrushEvents (closure) { + const oldValue = this._ignoreBrushEvents; + this._ignoreBrushEvents = true; + + try { + closure(); + } finally { + this._ignoreBrushEvents = oldValue; + } + } + + setBrushExtents (doTransition) { + this._withoutBrushEvents(() => { + // Set boundaries of the brush, must set it before applying to self._gBrush + this._brush.extent([[0, 0], [this.effectiveWidth(), this.effectiveHeight()]]); + }); + + this._gBrush + .call(this._brush); + } + + redrawBrush (brushSelection, doTransition) { + if (this._brushOn && this._gBrush) { + if (this._resizing) { + this.setBrushExtents(doTransition); + } + + if (!brushSelection) { + this._withoutBrushEvents(() => { + this._gBrush + .call(this._brush.move, null); + }) + + this._gBrush.selectAll(`path.${CUSTOM_BRUSH_HANDLE_CLASS}`) + .attr('display', 'none'); + } else { + const scaledSelection = [this._x(brushSelection[0]), this._x(brushSelection[1])]; + + const gBrush = + optionalTransition(doTransition, this.transitionDuration(), this.transitionDelay())(this._gBrush); + + this._withoutBrushEvents(() => { + gBrush + .call(this._brush.move, scaledSelection); + }); + + gBrush.selectAll(`path.${CUSTOM_BRUSH_HANDLE_CLASS}`) + .attr('display', null) + .attr('transform', (d, i) => `translate(${this._x(brushSelection[i])}, 0)`) + .attr('d', d => this.resizeHandlePath(d)); + } + } + this.fadeDeselectedArea(brushSelection); + } + + fadeDeselectedArea (brushSelection) { + // do nothing, sub-chart should override this function + } + + // borrowed from Crossfilter example + resizeHandlePath (d) { + d = d.type; + const e = +(d === 'e'), x = e ? 1 : -1, y = this.effectiveHeight() / 3; + return `M${0.5 * x},${y + }A6,6 0 0 ${e} ${6.5 * x},${y + 6 + }V${2 * y - 6 + }A6,6 0 0 ${e} ${0.5 * x},${2 * y + }Z` + + `M${2.5 * x},${y + 8 + }V${2 * y - 8 + }M${4.5 * x},${y + 8 + }V${2 * y - 8}`; + } + + _getClipPathId () { + return `${this.anchorName().replace(/[ .#=\[\]"]/g, '-')}-clip`; + } + + /** + * Get or set the padding in pixels for the clip path. Once set padding will be applied evenly to + * the top, left, right, and bottom when the clip path is generated. If set to zero, the clip area + * will be exactly the chart body area minus the margins. + * @param {Number} [padding=5] + * @returns {Number|CoordinateGridMixin} + */ + clipPadding (padding) { + if (!arguments.length) { + return this._clipPadding; + } + this._clipPadding = padding; + return this; + } + + _generateClipPath () { + const defs = utils.appendOrSelect(this._parent, 'defs'); + // cannot select elements; bug in WebKit, must select by id + // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I + const id = this._getClipPathId(); + const chartBodyClip = utils.appendOrSelect(defs, `#${id}`, 'clipPath').attr('id', id); + + const padding = this._clipPadding * 2; + + utils.appendOrSelect(chartBodyClip, 'rect') + .attr('width', this.xAxisLength() + padding) + .attr('height', this.yAxisHeight() + padding) + .attr('transform', `translate(-${this._clipPadding}, -${this._clipPadding})`); + } + + _preprocessData () { + } + + _doRender () { + this.resetSvg(); + + this._preprocessData(); + + this._generateG(); + this._generateClipPath(); + + this._drawChart(true); + + this._configureMouseZoom(); + + return this; + } + + _doRedraw () { + this._preprocessData(); + + this._drawChart(false); + this._generateClipPath(); + + return this; + } + + _drawChart (render) { + if (this.isOrdinal()) { + this._brushOn = false; + } + + this._prepareXAxis(this.g(), render); + this._prepareYAxis(this.g()); + + this.plotData(); + + if (this.elasticX() || this._resizing || render) { + this.renderXAxis(this.g()); + } + + if (this.elasticY() || this._resizing || render) { + this.renderYAxis(this.g()); + } + + if (render) { + this.renderBrush(this.g(), false); + } else { + // Animate the brush only while resizing + this.redrawBrush(this.filter(), this._resizing); + } + this.fadeDeselectedArea(this.filter()); + this.resizing(false); + } + + _configureMouseZoom () { + // Save a copy of original x scale + this._origX = this._x.copy(); + + if (this._mouseZoomable) { + this._enableMouseZoom(); + } else if (this._hasBeenMouseZoomable) { + this._disableMouseZoom(); + } + } + + _enableMouseZoom () { + this._hasBeenMouseZoomable = true; + + const extent = [[0, 0], [this.effectiveWidth(), this.effectiveHeight()]]; + + this._zoom + .scaleExtent(this._zoomScale) + .extent(extent) + .duration(this.transitionDuration()); + + if (this._zoomOutRestrict) { + // Ensure minimum zoomScale is at least 1 + const zoomScaleMin = Math.max(this._zoomScale[0], 1); + this._zoom + .translateExtent(extent) + .scaleExtent([zoomScaleMin, this._zoomScale[1]]); + } + + this.root().call(this._zoom); + + // Tell D3 zoom our current zoom/pan status + this._updateD3zoomTransform(); + } + + _disableMouseZoom () { + this.root().call(this._nullZoom); + } + + _zoomHandler (newDomain, noRaiseEvents) { + let domFilter; + + if (this._hasRangeSelected(newDomain)) { + this.x().domain(newDomain); + domFilter = filters.RangedFilter(newDomain[0], newDomain[1]); + } else { + this.x().domain(this._xOriginalDomain); + domFilter = null; + } + + this.replaceFilter(domFilter); + this.rescale(); + this.redraw(); + + if (!noRaiseEvents) { + if (this._rangeChart && !utils.arraysEqual(this.filter(), this._rangeChart.filter())) { + events.trigger(() => { + this._rangeChart.replaceFilter(domFilter); + this._rangeChart.redraw(); + }); + } + + this._invokeZoomedListener(); + events.trigger(() => { + this.redrawGroup(); + }, constants.EVENT_DELAY); + } + } + + // event.transform.rescaleX(self._origX).domain() should give back newDomain + _domainToZoomTransform (newDomain, origDomain, xScale) { + const k = (origDomain[1] - origDomain[0]) / (newDomain[1] - newDomain[0]); + const xt = -1 * xScale(newDomain[0]); + + return zoomIdentity.scale(k).translate(xt, 0); + } + + // If we changing zoom status (for example by calling focus), tell D3 zoom about it + _updateD3zoomTransform () { + if (this._zoom) { + this._withoutZoomEvents(() => { + this._zoom.transform(this.root(), this._domainToZoomTransform(this.x().domain(), this._xOriginalDomain, this._origX)); + }); + } + } + + _withoutZoomEvents (closure) { + const oldValue = this._ignoreZoomEvents; + this._ignoreZoomEvents = true; + + try { + closure(); + } finally { + this._ignoreZoomEvents = oldValue; + } + } + + _onZoom (evt) { + // ignore zoom events if it was caused by a programmatic change + if (this._ignoreZoomEvents) { + return; + } + + const newDomain = evt.transform.rescaleX(this._origX).domain(); + this.focus(newDomain, false); + } + + _checkExtents (ext, outerLimits) { + if (!ext || ext.length !== 2 || !outerLimits || outerLimits.length !== 2) { + return ext; + } + + if (ext[0] > outerLimits[1] || ext[1] < outerLimits[0]) { + console.warn('Could not intersect extents, will reset'); + } + // Math.max does not work (as the values may be dates as well) + return [ext[0] > outerLimits[0] ? ext[0] : outerLimits[0], ext[1] < outerLimits[1] ? ext[1] : outerLimits[1]]; + } + + /** + * Zoom this chart to focus on the given range. The given range should be an array containing only + * 2 elements (`[start, end]`) defining a range in the x domain. If the range is not given or set + * to null, then the zoom will be reset. _For focus to work elasticX has to be turned off; + * otherwise focus will be ignored. + * + * To avoid ping-pong volley of events between a pair of range and focus charts please set + * `noRaiseEvents` to `true`. In that case it will update this chart but will not fire `zoom` event + * and not try to update back the associated range chart. + * If you are calling it manually - typically you will leave it to `false` (the default). + * + * @example + * chart.on('renderlet', function(chart) { + * // smooth the rendering through event throttling + * events.trigger(function(){ + * // focus some other chart to the range selected by user on this chart + * someOtherChart.focus(chart.filter()); + * }); + * }) + * @param {Array} [range] + * @param {Boolean} [noRaiseEvents = false] + * @return {undefined} + */ + focus (range, noRaiseEvents) { + if (this._zoomOutRestrict) { + // ensure range is within self._xOriginalDomain + range = this._checkExtents(range, this._xOriginalDomain); + + // If it has an associated range chart ensure range is within domain of that rangeChart + if (this._rangeChart) { + range = this._checkExtents(range, this._rangeChart.x().domain()); + } + } + + this._zoomHandler(range, noRaiseEvents); + this._updateD3zoomTransform(); + } + + refocused () { + return !utils.arraysEqual(this.x().domain(), this._xOriginalDomain); + } + + focusChart (c) { + if (!arguments.length) { + return this._focusChart; + } + this._focusChart = c; + this.on('filtered.dcjs-range-chart', chart => { + if (!chart.filter()) { + events.trigger(() => { + this._focusChart.x().domain(this._focusChart.xOriginalDomain(), true); + }); + } else if (!utils.arraysEqual(chart.filter(), this._focusChart.filter())) { + events.trigger(() => { + this._focusChart.focus(chart.filter(), true); + }); + } + }); + return this; + } + + /** + * Turn on/off the brush-based range filter. When brushing is on then user can drag the mouse + * across a chart with a quantitative scale to perform range filtering based on the extent of the + * brush, or click on the bars of an ordinal bar chart or slices of a pie chart to filter and + * un-filter them. However turning on the brush filter will disable other interactive elements on + * the chart such as highlighting, tool tips, and reference lines. Zooming will still be possible + * if enabled, but only via scrolling (panning will be disabled.) + * @param {Boolean} [brushOn=true] + * @returns {Boolean|CoordinateGridMixin} + */ + brushOn (brushOn) { + if (!arguments.length) { + return this._brushOn; + } + this._brushOn = brushOn; + return this; + } + + /** + * This will be internally used by composite chart onto children. Please go not invoke directly. + * + * @protected + * @param {Boolean} [brushOn=false] + * @returns {Boolean|CoordinateGridMixin} + */ + parentBrushOn (brushOn) { + if (!arguments.length) { + return this._parentBrushOn; + } + this._parentBrushOn = brushOn; + return this; + } + + // Get the SVG rendered brush + gBrush () { + return this._gBrush; + } + + _hasRangeSelected (range) { + return range instanceof Array && range.length > 1; + } +} diff --git a/src/base/d3.box.js b/src/base/d3.box.js new file mode 100644 index 0000000000..3c976c2b18 --- /dev/null +++ b/src/base/d3.box.js @@ -0,0 +1,517 @@ +// https://github.com/d3/d3-plugins/blob/master/box/box.js +// * Original source March 22, 2013 +// * Enhancements integrated on May 13, 2018 for dc.js library only + +// https://github.com/d3/d3-plugins/blob/master/LICENSE +// Copyright (c) 2012-2015, Michael Bostock +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name Michael Bostock may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/*eslint complexity: 0*/ + +// Inspired by http://informationandvisualization.de/blog/box-plot + +import {ascending, quantile, range} from 'd3-array'; +import {select} from 'd3-selection'; +import {scaleLinear} from 'd3-scale'; +import {timerFlush} from 'd3-timer'; + +import {utils} from '../core/utils'; + +export const d3Box = function () { + let width = 1; + let height = 1; + let duration = 0; + const delay = 0; + let domain = null; + let value = Number; + let whiskers = boxWhiskers; + let quartiles = boxQuartiles; + let tickFormat = null; + + // Enhanced attributes + let renderDataPoints = false; + const dataRadius = 3; + let dataOpacity = 0.3; + let dataWidthPortion = 0.8; + let renderTitle = false; + let showOutliers = true; + let boldOutlier = false; + + + // For each small multiple… + function box (g) { + g.each(function (data, index) { + data = data.map(value).sort(ascending); + const _g = select(this); + const n = data.length; + let min; + let max; + + // Leave if there are no items. + if (n === 0) {return;} + + // Compute quartiles. Must return exactly 3 elements. + const quartileData = data.quartiles = quartiles(data); + + // Compute whiskers. Must return exactly 2 elements, or null. + const whiskerIndices = whiskers && whiskers.call(this, data, index), + whiskerData = whiskerIndices && whiskerIndices.map(_i => data[_i]); + + // Compute outliers. If no whiskers are specified, all data are 'outliers'. + // We compute the outliers as indices, so that we can join across transitions! + const outlierIndices = whiskerIndices ? + range(0, whiskerIndices[0]).concat(range(whiskerIndices[1] + 1, n)) : range(n); + + // Determine the maximum value based on if outliers are shown + if (showOutliers) { + min = data[0]; + max = data[n - 1]; + } else { + min = data[whiskerIndices[0]]; + max = data[whiskerIndices[1]]; + } + const pointIndices = range(whiskerIndices[0], whiskerIndices[1] + 1); + + // Compute the new x-scale. + const x1 = scaleLinear() + .domain(domain && domain.call(this, data, index) || [min, max]) + .range([height, 0]); + + // Retrieve the old x-scale, if this is an update. + const x0 = this.__chart__ || scaleLinear() + .domain([0, Infinity]) + .range(x1.range()); + + // Stash the new scale. + this.__chart__ = x1; + + // Note: the box, median, and box tick elements are fixed in number, + // so we only have to handle enter and update. In contrast, the outliers + // and other elements are variable, so we need to exit them! Variable + // elements also fade in and out. + + // Update center line: the vertical line spanning the whiskers. + const center = _g.selectAll('line.center') + .data(whiskerData ? [whiskerData] : []); + + center.enter().insert('line', 'rect') + .attr('class', 'center') + .attr('x1', width / 2) + .attr('y1', d => x0(d[0])) + .attr('x2', width / 2) + .attr('y2', d => x0(d[1])) + .style('opacity', 1e-6) + .transition() + .duration(duration) + .delay(delay) + .style('opacity', 1) + .attr('y1', d => x1(d[0])) + .attr('y2', d => x1(d[1])); + + center.transition() + .duration(duration) + .delay(delay) + .style('opacity', 1) + .attr('x1', width / 2) + .attr('x2', width / 2) + .attr('y1', d => x1(d[0])) + .attr('y2', d => x1(d[1])); + + center.exit().transition() + .duration(duration) + .delay(delay) + .style('opacity', 1e-6) + .attr('y1', d => x1(d[0])) + .attr('y2', d => x1(d[1])) + .remove(); + + // Update innerquartile box. + const _box = _g.selectAll('rect.box') + .data([quartileData]); + + _box.enter().append('rect') + .attr('class', 'box') + .attr('x', 0) + .attr('y', d => x0(d[2])) + .attr('width', width) + .attr('height', d => x0(d[0]) - x0(d[2])) + .style('fill-opacity', (renderDataPoints) ? 0.1 : 1) + .transition() + .duration(duration) + .delay(delay) + .attr('y', d => x1(d[2])) + .attr('height', d => x1(d[0]) - x1(d[2])); + + _box.transition() + .duration(duration) + .delay(delay) + .attr('width', width) + .attr('y', d => x1(d[2])) + .attr('height', d => x1(d[0]) - x1(d[2])); + + // Update median line. + const medianLine = _g.selectAll('line.median') + .data([quartileData[1]]); + + medianLine.enter().append('line') + .attr('class', 'median') + .attr('x1', 0) + .attr('y1', x0) + .attr('x2', width) + .attr('y2', x0) + .transition() + .duration(duration) + .delay(delay) + .attr('y1', x1) + .attr('y2', x1); + + medianLine.transition() + .duration(duration) + .delay(delay) + .attr('x1', 0) + .attr('x2', width) + .attr('y1', x1) + .attr('y2', x1); + + // Update whiskers. + const whisker = _g.selectAll('line.whisker') + .data(whiskerData || []); + + whisker.enter().insert('line', 'circle, text') + .attr('class', 'whisker') + .attr('x1', 0) + .attr('y1', x0) + .attr('x2', width) + .attr('y2', x0) + .style('opacity', 1e-6) + .transition() + .duration(duration) + .delay(delay) + .attr('y1', x1) + .attr('y2', x1) + .style('opacity', 1); + + whisker.transition() + .duration(duration) + .delay(delay) + .attr('x1', 0) + .attr('x2', width) + .attr('y1', x1) + .attr('y2', x1) + .style('opacity', 1); + + whisker.exit().transition() + .duration(duration) + .delay(delay) + .attr('y1', x1) + .attr('y2', x1) + .style('opacity', 1e-6) + .remove(); + + // Update outliers. + if (showOutliers) { + const outlierClass = boldOutlier ? 'outlierBold' : 'outlier'; + const outlierSize = boldOutlier ? 3 : 5; + const outlierX = boldOutlier ? + function () { + return Math.floor(Math.random() * + (width * dataWidthPortion) + + 1 + ((width - (width * dataWidthPortion)) / 2)); + } : + function () { + return width / 2; + }; + + const outlier = _g.selectAll(`circle.${outlierClass}`) + .data(outlierIndices, Number); + + outlier.enter().insert('circle', 'text') + .attr('class', outlierClass) + .attr('r', outlierSize) + .attr('cx', outlierX) + .attr('cy', i => x0(data[i])) + .style('opacity', 1e-6) + .transition() + .duration(duration) + .delay(delay) + .attr('cy', i => x1(data[i])) + .style('opacity', 0.6); + + if (renderTitle) { + outlier.selectAll('title').remove(); + outlier.append('title').text(i => data[i]); + } + + outlier.transition() + .duration(duration) + .delay(delay) + .attr('cx', outlierX) + .attr('cy', i => x1(data[i])) + .style('opacity', 0.6); + + outlier.exit().transition() + .duration(duration) + .delay(delay) + .attr('cy', 0) //function (i) { return x1(d[i]); }) + .style('opacity', 1e-6) + .remove(); + } + + // Update Values + if (renderDataPoints) { + const point = _g.selectAll('circle.data') + .data(pointIndices); + + point.enter().insert('circle', 'text') + .attr('class', 'data') + .attr('r', dataRadius) + .attr('cx', () => Math.floor(Math.random() * + (width * dataWidthPortion) + + 1 + ((width - (width * dataWidthPortion)) / 2))) + .attr('cy', i => x0(data[i])) + .style('opacity', 1e-6) + .transition() + .duration(duration) + .delay(delay) + .attr('cy', i => x1(data[i])) + .style('opacity', dataOpacity); + + if (renderTitle) { + point.selectAll('title').remove(); + point.append('title').text(i => data[i]); + } + + point.transition() + .duration(duration) + .delay(delay) + .attr('cx', () => Math.floor(Math.random() * + (width * dataWidthPortion) + + 1 + ((width - (width * dataWidthPortion)) / 2))) + .attr('cy', i => x1(data[i])) + .style('opacity', dataOpacity); + + point.exit().transition() + .duration(duration) + .delay(delay) + .attr('cy', 0) + .style('opacity', 1e-6) + .remove(); + } + + // Compute the tick format. + const format = tickFormat || x1.tickFormat(8); + + // Update box ticks. + const boxTick = _g.selectAll('text.box') + .data(quartileData); + + boxTick.enter().append('text') + .attr('class', 'box') + .attr('dy', '.3em') + .attr('dx', (d, i) => i & 1 ? 6 : -6) + .attr('x', (d, i) => i & 1 ? width : 0) + .attr('y', x0) + .attr('text-anchor', (d, i) => i & 1 ? 'start' : 'end') + .text(format) + .transition() + .duration(duration) + .delay(delay) + .attr('y', x1); + + boxTick.transition() + .duration(duration) + .delay(delay) + .text(format) + .attr('x', (d, i) => i & 1 ? width : 0) + .attr('y', x1); + + // Update whisker ticks. These are handled separately from the box + // ticks because they may or may not exist, and we want don't want + // to join box ticks pre-transition with whisker ticks post-. + const whiskerTick = _g.selectAll('text.whisker') + .data(whiskerData || []); + + whiskerTick.enter().append('text') + .attr('class', 'whisker') + .attr('dy', '.3em') + .attr('dx', 6) + .attr('x', width) + .attr('y', x0) + .text(format) + .style('opacity', 1e-6) + .transition() + .duration(duration) + .delay(delay) + .attr('y', x1) + .style('opacity', 1); + + whiskerTick.transition() + .duration(duration) + .delay(delay) + .text(format) + .attr('x', width) + .attr('y', x1) + .style('opacity', 1); + + whiskerTick.exit().transition() + .duration(duration) + .delay(delay) + .attr('y', x1) + .style('opacity', 1e-6) + .remove(); + + // Remove temporary quartiles element from within data array. + delete data.quartiles; + }); + timerFlush(); + } + + box.width = function (x) { + if (!arguments.length) { + return width; + } + width = x; + return box; + }; + + box.height = function (x) { + if (!arguments.length) { + return height; + } + height = x; + return box; + }; + + box.tickFormat = function (x) { + if (!arguments.length) { + return tickFormat; + } + tickFormat = x; + return box; + }; + + box.showOutliers = function (x) { + if (!arguments.length) { + return showOutliers; + } + showOutliers = x; + return box; + }; + + box.boldOutlier = function (x) { + if (!arguments.length) { + return boldOutlier; + } + boldOutlier = x; + return box; + }; + + box.renderDataPoints = function (x) { + if (!arguments.length) { + return renderDataPoints; + } + renderDataPoints = x; + return box; + }; + + box.renderTitle = function (x) { + if (!arguments.length) { + return renderTitle; + } + renderTitle = x; + return box; + }; + + box.dataOpacity = function (x) { + if (!arguments.length) { + return dataOpacity; + } + dataOpacity = x; + return box; + }; + + box.dataWidthPortion = function (x) { + if (!arguments.length) { + return dataWidthPortion; + } + dataWidthPortion = x; + return box; + }; + + box.duration = function (x) { + if (!arguments.length) { + return duration; + } + duration = x; + return box; + }; + + box.domain = function (x) { + if (!arguments.length) { + return domain; + } + domain = x === null ? x : typeof x === 'function' ? x : utils.constant(x); + return box; + }; + + box.value = function (x) { + if (!arguments.length) { + return value; + } + value = x; + return box; + }; + + box.whiskers = function (x) { + if (!arguments.length) { + return whiskers; + } + whiskers = x; + return box; + }; + + box.quartiles = function (x) { + if (!arguments.length) { + return quartiles; + } + quartiles = x; + return box; + }; + + return box; +}; + +function boxWhiskers (d) { + return [0, d.length - 1]; +} + +function boxQuartiles (d) { + return [ + quantile(d, 0.25), + quantile(d, 0.5), + quantile(d, 0.75) + ]; +} diff --git a/src/base/margin-mixin.js b/src/base/margin-mixin.js new file mode 100644 index 0000000000..fc7f7757a3 --- /dev/null +++ b/src/base/margin-mixin.js @@ -0,0 +1,54 @@ +import {BaseMixin} from './base-mixin'; + +/** + * Margin is a mixin that provides margin utility functions for both the Row Chart and Coordinate Grid + * Charts. + * @mixin MarginMixin + * @param {Object} Base + * @returns {MarginMixin} + */ +export class MarginMixin extends BaseMixin { + constructor () { + super(); + + this._margin = {top: 10, right: 50, bottom: 30, left: 30}; + } + + /** + * Get or set the margins for a particular coordinate grid chart instance. The margins is stored as + * an associative Javascript array. + * @memberof MarginMixin + * @instance + * @example + * var leftMargin = chart.margins().left; // 30 by default + * chart.margins().left = 50; + * leftMargin = chart.margins().left; // now 50 + * @param {{top: Number, right: Number, left: Number, bottom: Number}} [margins={top: 10, right: 50, bottom: 30, left: 30}] + * @returns {{top: Number, right: Number, left: Number, bottom: Number}|MarginMixin} + */ + margins (margins) { + if (!arguments.length) { + return this._margin; + } + this._margin = margins; + return this; + } + + /** + * Effective width of the chart excluding margins (in pixels). + * + * @returns {number} + */ + effectiveWidth () { + return this.width() - this.margins().left - this.margins().right; + } + + /** + * Effective height of the chart excluding margins (in pixels). + * + * @returns {number} + */ + effectiveHeight () { + return this.height() - this.margins().top - this.margins().bottom; + } +} diff --git a/src/base/stack-mixin.js b/src/base/stack-mixin.js new file mode 100644 index 0000000000..e124c54a97 --- /dev/null +++ b/src/base/stack-mixin.js @@ -0,0 +1,324 @@ +import {stack} from 'd3-shape'; +import {max, min} from 'd3-array'; + +import {pluck, utils} from '../core/utils'; +import {CoordinateGridMixin} from './coordinate-grid-mixin'; + +/** + * Stack Mixin is an mixin that provides cross-chart support of stackability using d3.stack. + * @mixin StackMixin + * @mixes CoordinateGridMixin + */ +export class StackMixin extends CoordinateGridMixin { + constructor () { + super(); + + this._stackLayout = stack(); + + this._stack = []; + this._titles = {}; + + this._hidableStacks = false; + this._evadeDomainFilter = false; + + this.data(() => { + const layers = this._stack.filter(this._visibility); + if (!layers.length) { + return []; + } + layers.forEach((l, i) => this._prepareValues(l, i)); + const v4data = layers[0].values.map((v, i) => { + const col = {x: v.x}; + layers.forEach(layer => { + col[layer.name] = layer.values[i].y; + }); + return col; + }); + const keys = layers.map(layer => layer.name); + const v4result = this.stackLayout().keys(keys)(v4data); + v4result.forEach((series, i) => { + series.forEach((ys, j) => { + layers[i].values[j].y0 = ys[0]; + layers[i].values[j].y1 = ys[1]; + }); + }); + return layers; + }); + + this.colorAccessor(function (d) { + return this.layer || this.name || d.name || d.layer; + }); + } + + _prepareValues (layer, layerIdx) { + const valAccessor = layer.accessor || this.valueAccessor(); + layer.name = String(layer.name || layerIdx); + const allValues = layer.group.all().map((d, i) => ({ + x: this.keyAccessor()(d, i), + y: layer.hidden ? null : valAccessor(d, i), + data: d, + layer: layer.name, + hidden: layer.hidden + })); + + layer.domainValues = allValues.filter(l => this._domainFilter()(l)); + layer.values = this.evadeDomainFilter() ? allValues : layer.domainValues; + } + + _domainFilter () { + if (!this.x()) { + return utils.constant(true); + } + const xDomain = this.x().domain(); + if (this.isOrdinal()) { + // TODO #416 + //var domainSet = d3.set(xDomain); + return () => true //domainSet.has(p.x); + ; + } + if (this.elasticX()) { + return () => true; + } + return p => p.x >= xDomain[0] && p.x <= xDomain[xDomain.length - 1]; + } + + /** + * Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks + * in the same chart will share the same key accessor and therefore the same set of keys. + * + * For example, in a stacked bar chart, the bars of each stack will be positioned using the same set + * of keys on the x axis, while stacked vertically. If name is specified then it will be used to + * generate the legend label. + * @see {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} + * @example + * // stack group using default accessor + * chart.stack(valueSumGroup) + * // stack group using custom accessor + * .stack(avgByDayGroup, function(d){return d.value.avgByDay;}); + * @param {crossfilter.group} group + * @param {String} [name] + * @param {Function} [accessor] + * @returns {Array<{group: crossfilter.group, name: String, accessor: Function}>|StackMixin} + */ + stack (group, name, accessor) { + if (!arguments.length) { + return this._stack; + } + + if (arguments.length <= 2) { + accessor = name; + } + + const layer = {group: group}; + if (typeof name === 'string') { + layer.name = name; + } + if (typeof accessor === 'function') { + layer.accessor = accessor; + } + this._stack.push(layer); + + return this; + } + + group (g, n, f) { + if (!arguments.length) { + return super.group(); + } + this._stack = []; + this._titles = {}; + this.stack(g, n); + if (f) { + this.valueAccessor(f); + } + return super.group(g, n); + } + + /** + * Allow named stacks to be hidden or shown by clicking on legend items. + * This does not affect the behavior of hideStack or showStack. + * @param {Boolean} [hidableStacks=false] + * @returns {Boolean|StackMixin} + */ + hidableStacks (hidableStacks) { + if (!arguments.length) { + return this._hidableStacks; + } + this._hidableStacks = hidableStacks; + return this; + } + + _findLayerByName (n) { + const i = this._stack.map(pluck('name')).indexOf(n); + return this._stack[i]; + } + + /** + * Hide all stacks on the chart with the given name. + * The chart must be re-rendered for this change to appear. + * @param {String} stackName + * @returns {StackMixin} + */ + hideStack (stackName) { + const layer = this._findLayerByName(stackName); + if (layer) { + layer.hidden = true; + } + return this; + } + + /** + * Show all stacks on the chart with the given name. + * The chart must be re-rendered for this change to appear. + * @param {String} stackName + * @returns {StackMixin} + */ + showStack (stackName) { + const layer = this._findLayerByName(stackName); + if (layer) { + layer.hidden = false; + } + return this; + } + + getValueAccessorByIndex (index) { + return this._stack[index].accessor || this.valueAccessor(); + } + + yAxisMin () { + const m = min(this._flattenStack(), p => (p.y < 0) ? (p.y + p.y0) : p.y0); + return utils.subtract(m, this.yAxisPadding()); + } + + yAxisMax () { + const m = max(this._flattenStack(), p => (p.y > 0) ? (p.y + p.y0) : p.y0); + return utils.add(m, this.yAxisPadding()); + } + + _flattenStack () { + // A round about way to achieve flatMap + // When target browsers support flatMap, just replace map -> flatMap, no concat needed + const values = this.data().map(layer => layer.domainValues); + return [].concat(...values); + } + + xAxisMin () { + const m = min(this._flattenStack(), pluck('x')); + return utils.subtract(m, this.xAxisPadding(), this.xAxisPaddingUnit()); + } + + xAxisMax () { + const m = max(this._flattenStack(), pluck('x')); + return utils.add(m, this.xAxisPadding(), this.xAxisPaddingUnit()); + } + + /** + * Set or get the title function. Chart class will use this function to render svg title (usually interpreted by + * browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart. + * Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to + * use title otherwise the brush layer will block tooltip trigger. + * + * If the first argument is a stack name, the title function will get or set the title for that stack. If stackName + * is not provided, the first stack is implied. + * @example + * // set a title function on 'first stack' + * chart.title('first stack', function(d) { return d.key + ': ' + d.value; }); + * // get a title function from 'second stack' + * var secondTitleFunction = chart.title('second stack'); + * @param {String} [stackName] + * @param {Function} [titleAccessor] + * @returns {String|StackMixin} + */ + title (stackName, titleAccessor) { + if (!stackName) { + return super.title(); + } + + if (typeof stackName === 'function') { + return super.title(stackName); + } + if (stackName === this._groupName && typeof titleAccessor === 'function') { + return super.title(titleAccessor); + } + + if (typeof titleAccessor !== 'function') { + return this._titles[stackName] || super.title(); + } + + this._titles[stackName] = titleAccessor; + + return this; + } + + /** + * Gets or sets the stack layout algorithm, which computes a baseline for each stack and + * propagates it to the next. + * @see {@link https://github.com/d3/d3-3.x-api-reference/blob/master/Stack-Layout.md d3.stackD3v3} + * @param {Function} [_stack=d3.stackD3v3] + * @returns {Function|StackMixin} + */ + stackLayout (_stack) { + if (!arguments.length) { + return this._stackLayout; + } + this._stackLayout = _stack; + return this; + } + + /** + * Since dc.js 2.0, there has been {@link https://github.com/dc-js/dc.js/issues/949 an issue} + * where points are filtered to the current domain. While this is a useful optimization, it is + * incorrectly implemented: the next point outside the domain is required in order to draw lines + * that are clipped to the bounds, as well as bars that are partly clipped. + * + * A fix will be included in dc.js 2.1.x, but a workaround is needed for dc.js 2.0 and until + * that fix is published, so set this flag to skip any filtering of points. + * + * Once the bug is fixed, this flag will have no effect, and it will be deprecated. + * @param {Boolean} [evadeDomainFilter=false] + * @returns {Boolean|StackMixin} + */ + evadeDomainFilter (evadeDomainFilter) { + if (!arguments.length) { + return this._evadeDomainFilter; + } + this._evadeDomainFilter = evadeDomainFilter; + return this; + } + + _visibility (l) { + return !l.hidden; + } + + _ordinalXDomain () { + const flat = this._flattenStack().map(pluck('data')); + const ordered = this._computeOrderedGroups(flat); + return ordered.map(this.keyAccessor()); + } + + legendables () { + return this._stack.map((layer, i) => ({ + chart: this, + name: layer.name, + hidden: layer.hidden || false, + color: this.getColor.call(layer, layer.values, i) + })); + } + + isLegendableHidden (d) { + const layer = this._findLayerByName(d.name); + return layer ? layer.hidden : false; + } + + legendToggle (d) { + if (this._hidableStacks) { + if (this.isLegendableHidden(d)) { + this.showStack(d.name); + } else { + this.hideStack(d.name); + } + //_chart.redraw(); + this.renderGroup(); + } + } +} diff --git a/src/box-plot.js b/src/box-plot.js deleted file mode 100644 index ddd5a52adc..0000000000 --- a/src/box-plot.js +++ /dev/null @@ -1,240 +0,0 @@ -/** - * A box plot is a chart that depicts numerical data via their quartile ranges. - * - * Examples: - * - {@link http://dc-js.github.io/dc.js/examples/box-plot-time.html Box plot time example} - * - {@link http://dc-js.github.io/dc.js/examples/box-plot.html Box plot example} - * @class boxPlot - * @memberof dc - * @mixes dc.coordinateGridMixin - * @example - * // create a box plot under #chart-container1 element using the default global chart group - * var boxPlot1 = dc.boxPlot('#chart-container1'); - * // create a box plot under #chart-container2 element using chart group A - * var boxPlot2 = dc.boxPlot('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.boxPlot} - */ -dc.boxPlot = function (parent, chartGroup) { - var _chart = dc.coordinateGridMixin({}); - - // Returns a function to compute the interquartile range. - function DEFAULT_WHISKERS_IQR (k) { - return function (d) { - var q1 = d.quartiles[0], - q3 = d.quartiles[2], - iqr = (q3 - q1) * k, - i = -1, - j = d.length; - do { ++i; } while (d[i] < q1 - iqr); - do { --j; } while (d[j] > q3 + iqr); - return [i, j]; - }; - } - - var _whiskerIqrFactor = 1.5; - var _whiskersIqr = DEFAULT_WHISKERS_IQR; - var _whiskers = _whiskersIqr(_whiskerIqrFactor); - - var _box = d3.box(); - var _tickFormat = null; - - var _boxWidth = function (innerChartWidth, xUnits) { - if (_chart.isOrdinal()) { - return _chart.x().rangeBand(); - } else { - return innerChartWidth / (1 + _chart.boxPadding()) / xUnits; - } - }; - - // default padding to handle min/max whisker text - _chart.yAxisPadding(12); - - // default to ordinal - _chart.x(d3.scale.ordinal()); - _chart.xUnits(dc.units.ordinal); - - // valueAccessor should return an array of values that can be coerced into numbers - // or if data is overloaded for a static array of arrays, it should be `Number`. - // Empty arrays are not included. - _chart.data(function (group) { - return group.all().map(function (d) { - d.map = function (accessor) { return accessor.call(d, d); }; - return d; - }).filter(function (d) { - var values = _chart.valueAccessor()(d); - return values.length !== 0; - }); - }); - - /** - * Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1. - * See the {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs} - * for a visual description of how the padding is applied. - * @method boxPadding - * @memberof dc.boxPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3.scale.ordinal.rangeBands} - * @param {Number} [padding=0.8] - * @return {Number} - * @return {dc.boxPlot} - */ - _chart.boxPadding = _chart._rangeBandPadding; - _chart.boxPadding(0.8); - - /** - * Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts - * or on charts with a custom {@link dc.boxPlot#boxWidth .boxWidth}. Will pad the width by - * `padding * barWidth` on each side of the chart. - * @method outerPadding - * @memberof dc.boxPlot - * @instance - * @param {Number} [padding=0.5] - * @return {Number} - * @return {dc.boxPlot} - */ - _chart.outerPadding = _chart._outerRangeBandPadding; - _chart.outerPadding(0.5); - - /** - * Get or set the numerical width of the boxplot box. The width may also be a function taking as - * parameters the chart width excluding the right and left margins, as well as the number of x - * units. - * @example - * // Using numerical parameter - * chart.boxWidth(10); - * // Using function - * chart.boxWidth((innerChartWidth, xUnits) { ... }); - * @method boxWidth - * @memberof dc.boxPlot - * @instance - * @param {Number|Function} [boxWidth=0.5] - * @return {Number|Function} - * @return {dc.boxPlot} - */ - _chart.boxWidth = function (boxWidth) { - if (!arguments.length) { - return _boxWidth; - } - _boxWidth = d3.functor(boxWidth); - return _chart; - }; - - var boxTransform = function (d, i) { - var xOffset = _chart.x()(_chart.keyAccessor()(d, i)); - return 'translate(' + xOffset + ', 0)'; - }; - - _chart._preprocessData = function () { - if (_chart.elasticX()) { - _chart.x().domain([]); - } - }; - - _chart.plotData = function () { - var _calculatedBoxWidth = _boxWidth(_chart.effectiveWidth(), _chart.xUnitCount()); - - _box.whiskers(_whiskers) - .width(_calculatedBoxWidth) - .height(_chart.effectiveHeight()) - .value(_chart.valueAccessor()) - .domain(_chart.y().domain()) - .duration(_chart.transitionDuration()) - .tickFormat(_tickFormat); - - var boxesG = _chart.chartBodyG().selectAll('g.box').data(_chart.data(), function (d) { return d.key; }); - - renderBoxes(boxesG); - updateBoxes(boxesG); - removeBoxes(boxesG); - - _chart.fadeDeselectedArea(); - }; - - function renderBoxes (boxesG) { - var boxesGEnter = boxesG.enter().append('g'); - - boxesGEnter - .attr('class', 'box') - .attr('transform', boxTransform) - .call(_box) - .on('click', function (d) { - _chart.filter(d.key); - _chart.redrawGroup(); - }); - } - - function updateBoxes (boxesG) { - dc.transition(boxesG, _chart.transitionDuration()) - .attr('transform', boxTransform) - .call(_box) - .each(function () { - d3.select(this).select('rect.box').attr('fill', _chart.getColor); - }); - } - - function removeBoxes (boxesG) { - boxesG.exit().remove().call(_box); - } - - _chart.fadeDeselectedArea = function () { - if (_chart.hasFilter()) { - _chart.g().selectAll('g.box').each(function (d) { - if (_chart.isSelectedNode(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.g().selectAll('g.box').each(function () { - _chart.resetHighlight(this); - }); - } - }; - - _chart.isSelectedNode = function (d) { - return _chart.hasFilter(d.key); - }; - - _chart.yAxisMin = function () { - var min = d3.min(_chart.data(), function (e) { - return d3.min(_chart.valueAccessor()(e)); - }); - return dc.utils.subtract(min, _chart.yAxisPadding()); - }; - - _chart.yAxisMax = function () { - var max = d3.max(_chart.data(), function (e) { - return d3.max(_chart.valueAccessor()(e)); - }); - return dc.utils.add(max, _chart.yAxisPadding()); - }; - - /** - * Set the numerical format of the boxplot median, whiskers and quartile labels. Defaults to - * integer formatting. - * @example - * // format ticks to 2 decimal places - * chart.tickFormat(d3.format('.2f')); - * @method tickFormat - * @memberof dc.boxPlot - * @instance - * @param {Function} [tickFormat] - * @return {Number|Function} - * @return {dc.boxPlot} - */ - _chart.tickFormat = function (tickFormat) { - if (!arguments.length) { - return _tickFormat; - } - _tickFormat = tickFormat; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; diff --git a/src/bubble-chart.js b/src/bubble-chart.js deleted file mode 100644 index e4b82e20d5..0000000000 --- a/src/bubble-chart.js +++ /dev/null @@ -1,177 +0,0 @@ -/** - * A concrete implementation of a general purpose bubble chart that allows data visualization using the - * following dimensions: - * - x axis position - * - y axis position - * - bubble radius - * - color - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/vc/index.html US Venture Capital Landscape 2011} - * @class bubbleChart - * @memberof dc - * @mixes dc.bubbleMixin - * @mixes dc.coordinateGridMixin - * @example - * // create a bubble chart under #chart-container1 element using the default global chart group - * var bubbleChart1 = dc.bubbleChart('#chart-container1'); - * // create a bubble chart under #chart-container2 element using chart group A - * var bubbleChart2 = dc.bubbleChart('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.bubbleChart} - */ -dc.bubbleChart = function (parent, chartGroup) { - var _chart = dc.bubbleMixin(dc.coordinateGridMixin({})); - - var _elasticRadius = false; - var _sortBubbleSize = false; - - _chart.transitionDuration(750); - - var bubbleLocator = function (d) { - return 'translate(' + (bubbleX(d)) + ',' + (bubbleY(d)) + ')'; - }; - - /** - * Turn on or off the elastic bubble radius feature, or return the value of the flag. If this - * feature is turned on, then bubble radii will be automatically rescaled to fit the chart better. - * @method elasticRadius - * @memberof dc.bubbleChart - * @instance - * @param {Boolean} [elasticRadius=false] - * @return {Boolean} - * @return {dc.bubbleChart} - */ - _chart.elasticRadius = function (elasticRadius) { - if (!arguments.length) { - return _elasticRadius; - } - _elasticRadius = elasticRadius; - return _chart; - }; - - /** - * Turn on or off the bubble sorting feature, or return the value of the flag. If enabled, - * bubbles will be sorted by their radius, with smaller bubbles in front. - * @method sortBubbleSize - * @memberof dc.bubbleChart - * @instance - * @param {Boolean} [sortBubbleSize=false] - * @return {Boolean} - * @return {dc.bubbleChart} - */ - _chart.sortBubbleSize = function (sortBubbleSize) { - if (!arguments.length) { - return _sortBubbleSize; - } - _sortBubbleSize = sortBubbleSize; - return _chart; - }; - - _chart.plotData = function () { - if (_elasticRadius) { - _chart.r().domain([_chart.rMin(), _chart.rMax()]); - } - - _chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]); - - var data = _chart.data(); - if (_sortBubbleSize) { - // sort descending so smaller bubbles are on top - var radiusAccessor = _chart.radiusValueAccessor(); - data.sort(function (a, b) { return d3.descending(radiusAccessor(a), radiusAccessor(b)); }); - } - var bubbleG = _chart.chartBodyG().selectAll('g.' + _chart.BUBBLE_NODE_CLASS) - .data(data, function (d) { return d.key; }); - if (_sortBubbleSize) { - // Call order here to update dom order based on sort - bubbleG.order(); - } - - renderNodes(bubbleG); - - updateNodes(bubbleG); - - removeNodes(bubbleG); - - _chart.fadeDeselectedArea(); - }; - - function renderNodes (bubbleG) { - var bubbleGEnter = bubbleG.enter().append('g'); - - bubbleGEnter - .attr('class', _chart.BUBBLE_NODE_CLASS) - .attr('transform', bubbleLocator) - .append('circle').attr('class', function (d, i) { - return _chart.BUBBLE_CLASS + ' _' + i; - }) - .on('click', _chart.onClick) - .attr('fill', _chart.getColor) - .attr('r', 0); - dc.transition(bubbleG, _chart.transitionDuration()) - .selectAll('circle.' + _chart.BUBBLE_CLASS) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('opacity', function (d) { - return (_chart.bubbleR(d) > 0) ? 1 : 0; - }); - - _chart._doRenderLabel(bubbleGEnter); - - _chart._doRenderTitles(bubbleGEnter); - } - - function updateNodes (bubbleG) { - dc.transition(bubbleG, _chart.transitionDuration()) - .attr('transform', bubbleLocator) - .selectAll('circle.' + _chart.BUBBLE_CLASS) - .attr('fill', _chart.getColor) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('opacity', function (d) { - return (_chart.bubbleR(d) > 0) ? 1 : 0; - }); - - _chart.doUpdateLabels(bubbleG); - _chart.doUpdateTitles(bubbleG); - } - - function removeNodes (bubbleG) { - bubbleG.exit().remove(); - } - - function bubbleX (d) { - var x = _chart.x()(_chart.keyAccessor()(d)); - if (isNaN(x)) { - x = 0; - } - return x; - } - - function bubbleY (d) { - var y = _chart.y()(_chart.valueAccessor()(d)); - if (isNaN(y)) { - y = 0; - } - return y; - } - - _chart.renderBrush = function () { - // override default x axis brush from parent chart - }; - - _chart.redrawBrush = function () { - // override default x axis brush from parent chart - _chart.fadeDeselectedArea(); - }; - - return _chart.anchor(parent, chartGroup); -}; diff --git a/src/bubble-mixin.js b/src/bubble-mixin.js deleted file mode 100644 index 1e30490fb2..0000000000 --- a/src/bubble-mixin.js +++ /dev/null @@ -1,244 +0,0 @@ -/** - * This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles. - * @name bubbleMixin - * @memberof dc - * @mixin - * @mixes dc.colorMixin - * @param {Object} _chart - * @return {dc.bubbleMixin} - */ -dc.bubbleMixin = function (_chart) { - var _maxBubbleRelativeSize = 0.3; - var _minRadiusWithLabel = 10; - - _chart.BUBBLE_NODE_CLASS = 'node'; - _chart.BUBBLE_CLASS = 'bubble'; - _chart.MIN_RADIUS = 10; - - _chart = dc.colorMixin(_chart); - - _chart.renderLabel(true); - - _chart.data(function (group) { - return group.top(Infinity); - }); - - var _r = d3.scale.linear().domain([0, 100]); - - var _rValueAccessor = function (d) { - return d.r; - }; - - /** - * Get or set the bubble radius scale. By default the bubble chart uses - * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales#linear d3.scale.linear().domain([0, 100])} - * as its radius scale. - * @method r - * @memberof dc.bubbleMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale} - * @param {d3.scale} [bubbleRadiusScale=d3.scale.linear().domain([0, 100])] - * @return {d3.scale} - * @return {dc.bubbleMixin} - */ - _chart.r = function (bubbleRadiusScale) { - if (!arguments.length) { - return _r; - } - _r = bubbleRadiusScale; - return _chart; - }; - - /** - * Get or set the radius value accessor function. If set, the radius value accessor function will - * be used to retrieve a data value for each bubble. The data retrieved then will be mapped using - * the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble - * size. - * @method radiusValueAccessor - * @memberof dc.bubbleMixin - * @instance - * @param {Function} [radiusValueAccessor] - * @return {Function} - * @return {dc.bubbleMixin} - */ - _chart.radiusValueAccessor = function (radiusValueAccessor) { - if (!arguments.length) { - return _rValueAccessor; - } - _rValueAccessor = radiusValueAccessor; - return _chart; - }; - - _chart.rMin = function () { - var min = d3.min(_chart.data(), function (e) { - return _chart.radiusValueAccessor()(e); - }); - return min; - }; - - _chart.rMax = function () { - var max = d3.max(_chart.data(), function (e) { - return _chart.radiusValueAccessor()(e); - }); - return max; - }; - - _chart.bubbleR = function (d) { - var value = _chart.radiusValueAccessor()(d); - var r = _chart.r()(value); - if (isNaN(r) || value <= 0) { - r = 0; - } - return r; - }; - - var labelFunction = function (d) { - return _chart.label()(d); - }; - - var shouldLabel = function (d) { - return (_chart.bubbleR(d) > _minRadiusWithLabel); - }; - - var labelOpacity = function (d) { - return shouldLabel(d) ? 1 : 0; - }; - - var labelPointerEvent = function (d) { - return shouldLabel(d) ? 'all' : 'none'; - }; - - _chart._doRenderLabel = function (bubbleGEnter) { - if (_chart.renderLabel()) { - var label = bubbleGEnter.select('text'); - - if (label.empty()) { - label = bubbleGEnter.append('text') - .attr('text-anchor', 'middle') - .attr('dy', '.3em') - .on('click', _chart.onClick); - } - - label - .attr('opacity', 0) - .attr('pointer-events', labelPointerEvent) - .text(labelFunction); - dc.transition(label, _chart.transitionDuration()) - .attr('opacity', labelOpacity); - } - }; - - _chart.doUpdateLabels = function (bubbleGEnter) { - if (_chart.renderLabel()) { - var labels = bubbleGEnter.selectAll('text') - .attr('pointer-events', labelPointerEvent) - .text(labelFunction); - dc.transition(labels, _chart.transitionDuration()) - .attr('opacity', labelOpacity); - } - }; - - var titleFunction = function (d) { - return _chart.title()(d); - }; - - _chart._doRenderTitles = function (g) { - if (_chart.renderTitle()) { - var title = g.select('title'); - - if (title.empty()) { - g.append('title').text(titleFunction); - } - } - }; - - _chart.doUpdateTitles = function (g) { - if (_chart.renderTitle()) { - g.selectAll('title').text(titleFunction); - } - }; - - /** - * Get or set the minimum radius. This will be used to initialize the radius scale's range. - * @method minRadius - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [radius=10] - * @return {Number} - * @return {dc.bubbleMixin} - */ - _chart.minRadius = function (radius) { - if (!arguments.length) { - return _chart.MIN_RADIUS; - } - _chart.MIN_RADIUS = radius; - return _chart; - }; - - /** - * Get or set the minimum radius for label rendering. If a bubble's radius is less than this value - * then no label will be rendered. - * @method minRadiusWithLabel - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [radius=10] - * @return {Number} - * @return {dc.bubbleMixin} - */ - - _chart.minRadiusWithLabel = function (radius) { - if (!arguments.length) { - return _minRadiusWithLabel; - } - _minRadiusWithLabel = radius; - return _chart; - }; - - /** - * Get or set the maximum relative size of a bubble to the length of x axis. This value is useful - * when the difference in radius between bubbles is too great. - * @method maxBubbleRelativeSize - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [relativeSize=0.3] - * @return {Number} - * @return {dc.bubbleMixin} - */ - _chart.maxBubbleRelativeSize = function (relativeSize) { - if (!arguments.length) { - return _maxBubbleRelativeSize; - } - _maxBubbleRelativeSize = relativeSize; - return _chart; - }; - - _chart.fadeDeselectedArea = function () { - if (_chart.hasFilter()) { - _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function (d) { - if (_chart.isSelectedNode(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function () { - _chart.resetHighlight(this); - }); - } - }; - - _chart.isSelectedNode = function (d) { - return _chart.hasFilter(d.key); - }; - - _chart.onClick = function (d) { - var filter = d.key; - dc.events.trigger(function () { - _chart.filter(filter); - _chart.redrawGroup(); - }); - }; - - return _chart; -}; diff --git a/src/bubble-overlay.js b/src/bubble-overlay.js deleted file mode 100644 index 901afb0f57..0000000000 --- a/src/bubble-overlay.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay - * chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the - * typical x and y positioning while retaining the capability to visualize data using bubble radius - * and coloring. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class bubbleOverlay - * @memberof dc - * @mixes dc.bubbleMixin - * @mixes dc.baseMixin - * @example - * // create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group - * var bubbleChart1 = dc.bubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg')); - * // create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A - * var bubbleChart2 = dc.compositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg')); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.bubbleOverlay} - */ -dc.bubbleOverlay = function (parent, chartGroup) { - var BUBBLE_OVERLAY_CLASS = 'bubble-overlay'; - var BUBBLE_NODE_CLASS = 'node'; - var BUBBLE_CLASS = 'bubble'; - - /** - * **mandatory** - * - * Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg - * element; therefore the bubble overlay chart will not work if this function is not invoked. If the - * underlying image is a bitmap, then an empty svg will need to be created on top of the image. - * @method svg - * @memberof dc.bubbleOverlay - * @instance - * @example - * // set up underlying svg element - * chart.svg(d3.select('#chart svg')); - * @param {SVGElement|d3.selection} [imageElement] - * @return {dc.bubbleOverlay} - */ - var _chart = dc.bubbleMixin(dc.baseMixin({})); - var _g; - var _points = []; - - _chart.transitionDuration(750); - - _chart.radiusValueAccessor(function (d) { - return d.value; - }); - - /** - * **mandatory** - * - * Set up a data point on the overlay. The name of a data point should match a specific 'key' among - * data groups generated using keyAccessor. If a match is found (point name <-> data group key) - * then a bubble will be generated at the position specified by the function. x and y - * value specified here are relative to the underlying svg. - * @method point - * @memberof dc.bubbleOverlay - * @instance - * @param {String} name - * @param {Number} x - * @param {Number} y - * @return {dc.bubbleOverlay} - */ - _chart.point = function (name, x, y) { - _points.push({name: name, x: x, y: y}); - return _chart; - }; - - _chart._doRender = function () { - _g = initOverlayG(); - - _chart.r().range([_chart.MIN_RADIUS, _chart.width() * _chart.maxBubbleRelativeSize()]); - - initializeBubbles(); - - _chart.fadeDeselectedArea(); - - return _chart; - }; - - function initOverlayG () { - _g = _chart.select('g.' + BUBBLE_OVERLAY_CLASS); - if (_g.empty()) { - _g = _chart.svg().append('g').attr('class', BUBBLE_OVERLAY_CLASS); - } - return _g; - } - - function initializeBubbles () { - var data = mapData(); - - _points.forEach(function (point) { - var nodeG = getNodeG(point, data); - - var circle = nodeG.select('circle.' + BUBBLE_CLASS); - - if (circle.empty()) { - circle = nodeG.append('circle') - .attr('class', BUBBLE_CLASS) - .attr('r', 0) - .attr('fill', _chart.getColor) - .on('click', _chart.onClick); - } - - dc.transition(circle, _chart.transitionDuration()) - .attr('r', function (d) { - return _chart.bubbleR(d); - }); - - _chart._doRenderLabel(nodeG); - - _chart._doRenderTitles(nodeG); - }); - } - - function mapData () { - var data = {}; - _chart.data().forEach(function (datum) { - data[_chart.keyAccessor()(datum)] = datum; - }); - return data; - } - - function getNodeG (point, data) { - var bubbleNodeClass = BUBBLE_NODE_CLASS + ' ' + dc.utils.nameToId(point.name); - - var nodeG = _g.select('g.' + dc.utils.nameToId(point.name)); - - if (nodeG.empty()) { - nodeG = _g.append('g') - .attr('class', bubbleNodeClass) - .attr('transform', 'translate(' + point.x + ',' + point.y + ')'); - } - - nodeG.datum(data[point.name]); - - return nodeG; - } - - _chart._doRedraw = function () { - updateBubbles(); - - _chart.fadeDeselectedArea(); - - return _chart; - }; - - function updateBubbles () { - var data = mapData(); - - _points.forEach(function (point) { - var nodeG = getNodeG(point, data); - - var circle = nodeG.select('circle.' + BUBBLE_CLASS); - - dc.transition(circle, _chart.transitionDuration()) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('fill', _chart.getColor); - - _chart.doUpdateLabels(nodeG); - - _chart.doUpdateTitles(nodeG); - }); - } - - _chart.debug = function (flag) { - if (flag) { - var debugG = _chart.select('g.' + dc.constants.DEBUG_GROUP_CLASS); - - if (debugG.empty()) { - debugG = _chart.svg() - .append('g') - .attr('class', dc.constants.DEBUG_GROUP_CLASS); - } - - var debugText = debugG.append('text') - .attr('x', 10) - .attr('y', 20); - - debugG - .append('rect') - .attr('width', _chart.width()) - .attr('height', _chart.height()) - .on('mousemove', function () { - var position = d3.mouse(debugG.node()); - var msg = position[0] + ', ' + position[1]; - debugText.text(msg); - }); - } else { - _chart.selectAll('.debug').remove(); - } - - return _chart; - }; - - _chart.anchor(parent, chartGroup); - - return _chart; -}; diff --git a/src/cap-mixin.js b/src/cap-mixin.js deleted file mode 100644 index ae0e2a65a5..0000000000 --- a/src/cap-mixin.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the - * Row and Pie Charts. - * - * The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest - * will be replaced with an *others* element, with value equal to the sum of the replaced values. The - * keys of the elements below the cap limit are recorded in order to filter by those keys when the - * others* element is clicked. - * @name capMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.capMixin} - */ -dc.capMixin = function (_chart) { - - var _cap = Infinity; - - var _othersLabel = 'Others'; - - var _othersGrouper = function (topRows) { - var topRowsSum = d3.sum(topRows, _chart.valueAccessor()), - allRows = _chart.group().all(), - allRowsSum = d3.sum(allRows, _chart.valueAccessor()), - topKeys = topRows.map(_chart.keyAccessor()), - allKeys = allRows.map(_chart.keyAccessor()), - topSet = d3.set(topKeys), - others = allKeys.filter(function (d) {return !topSet.has(d);}); - if (allRowsSum > topRowsSum) { - return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]); - } - return topRows; - }; - - _chart.cappedKeyAccessor = function (d, i) { - if (d.others) { - return d.key; - } - return _chart.keyAccessor()(d, i); - }; - - _chart.cappedValueAccessor = function (d, i) { - if (d.others) { - return d.value; - } - return _chart.valueAccessor()(d, i); - }; - - _chart.data(function (group) { - if (_cap === Infinity) { - return _chart._computeOrderedGroups(group.all()); - } else { - var topRows = group.top(_cap); // ordered by crossfilter group order (default value) - topRows = _chart._computeOrderedGroups(topRows); // re-order using ordering (default key) - if (_othersGrouper) { - return _othersGrouper(topRows); - } - return topRows; - } - }); - - /** - * Get or set the count of elements to that will be included in the cap. - * @method cap - * @memberof dc.capMixin - * @instance - * @param {Number} [count=Infinity] - * @return {Number} - * @return {dc.capMixin} - */ - _chart.cap = function (count) { - if (!arguments.length) { - return _cap; - } - _cap = count; - return _chart; - }; - - /** - * Get or set the label for *Others* slice when slices cap is specified - * @method othersLabel - * @memberof dc.capMixin - * @instance - * @param {String} [label="Others"] - * @return {String} - * @return {dc.capMixin} - */ - _chart.othersLabel = function (label) { - if (!arguments.length) { - return _othersLabel; - } - _othersLabel = label; - return _chart; - }; - - /** - * Get or set the grouper function that will perform the insertion of data for the *Others* slice - * if the slices cap is specified. If set to a falsy value, no others will be added. By default the - * grouper function computes the sum of all values below the cap. - * @method othersGrouper - * @memberof dc.capMixin - * @instance - * @example - * // Default others grouper - * chart.othersGrouper(function (topRows) { - * var topRowsSum = d3.sum(topRows, _chart.valueAccessor()), - * allRows = _chart.group().all(), - * allRowsSum = d3.sum(allRows, _chart.valueAccessor()), - * topKeys = topRows.map(_chart.keyAccessor()), - * allKeys = allRows.map(_chart.keyAccessor()), - * topSet = d3.set(topKeys), - * others = allKeys.filter(function (d) {return !topSet.has(d);}); - * if (allRowsSum > topRowsSum) { - * return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]); - * } - * return topRows; - * }); - * // Custom others grouper - * chart.othersGrouper(function (data) { - * // compute the value for others, presumably the sum of all values below the cap - * var othersSum = yourComputeOthersValueLogic(data) - * - * // the keys are needed to properly filter when the others element is clicked - * var othersKeys = yourComputeOthersKeysArrayLogic(data); - * - * // add the others row to the dataset - * data.push({'key': 'Others', 'value': othersSum, 'others': othersKeys }); - * - * return data; - * }); - * @param {Function} [grouperFunction] - * @return {Function} - * @return {dc.capMixin} - */ - _chart.othersGrouper = function (grouperFunction) { - if (!arguments.length) { - return _othersGrouper; - } - _othersGrouper = grouperFunction; - return _chart; - }; - - dc.override(_chart, 'onClick', function (d) { - if (d.others) { - _chart.filter([d.others]); - } - _chart._onClick(d); - }); - - return _chart; -}; diff --git a/src/charts/bar-chart.js b/src/charts/bar-chart.js new file mode 100644 index 0000000000..be5617e7fd --- /dev/null +++ b/src/charts/bar-chart.js @@ -0,0 +1,375 @@ +import {select} from 'd3-selection'; + +import {StackMixin} from '../base/stack-mixin'; +import {transition} from '../core/core'; +import {constants} from '../core/constants'; +import {logger} from '../core/logger'; +import {pluck, utils} from '../core/utils'; +import {d3compat} from '../core/config'; + +const MIN_BAR_WIDTH = 1; +const DEFAULT_GAP_BETWEEN_BARS = 2; +const LABEL_PADDING = 3; + +/** + * Concrete bar chart/histogram implementation. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * - {@link https://dc-js.github.io/dc.js/crime/index.html Canadian City Crime Stats} + * @mixes StackMixin + */ +export class BarChart extends StackMixin { + /** + * Create a Bar Chart + * @example + * // create a bar chart under #chart-container1 element using the default global chart group + * var chart1 = new BarChart('#chart-container1'); + * // create a bar chart under #chart-container2 element using chart group A + * var chart2 = new BarChart('#chart-container2', 'chartGroupA'); + * // create a sub-chart under a composite parent chart + * var chart3 = new BarChart(compositeChart); + * @param {String|node|d3.selection|CompositeChart} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} + * specifying a dom block element such as a div; or a dom element or d3 selection. If the bar + * chart is a sub-chart in a {@link CompositeChart Composite Chart} then pass in the parent + * composite chart instance instead. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._gap = DEFAULT_GAP_BETWEEN_BARS; + this._centerBar = false; + this._alwaysUseRounding = false; + + this._barWidth = undefined; + + this.label(d => utils.printSingleValue(d.y0 + d.y), false); + + this.anchor(parent, chartGroup); + } + + /** + * Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts. + * Will pad the width by `padding * barWidth` on each side of the chart. + * @param {Number} [padding=0.5] + * @returns {Number|BarChart} + */ + outerPadding (padding) { + if (!arguments.length) { + return this._outerRangeBandPadding(); + } + return this._outerRangeBandPadding(padding); + } + + rescale () { + super.rescale(); + this._barWidth = undefined; + return this; + } + + render () { + if (this.round() && this._centerBar && !this._alwaysUseRounding) { + logger.warn('By default, brush rounding is disabled if bars are centered. ' + + 'See dc.js bar chart API documentation for details.'); + } + + return super.render(); + } + + plotData () { + let layers = this.chartBodyG().selectAll('g.stack') + .data(this.data()); + + this._calculateBarWidth(); + + layers = layers + .enter() + .append('g') + .attr('class', (d, i) => `stack _${i}`) + .merge(layers); + + const last = layers.size() - 1; + { + const chart = this; + layers.each(function (d, i) { + const layer = select(this); + + chart._renderBars(layer, i, d); + + if (chart.renderLabel() && last === i) { + chart._renderLabels(layer, i, d); + } + }); + } + } + + _barHeight (d) { + return utils.safeNumber(Math.abs(this.y()(d.y + d.y0) - this.y()(d.y0))); + } + + _labelXPos (d) { + let x = this.x()(d.x); + if (!this._centerBar) { + x += this._barWidth / 2; + } + if (this.isOrdinal() && this._gap !== undefined) { + x += this._gap / 2; + } + return utils.safeNumber(x); + } + + _labelYPos (d) { + let y = this.y()(d.y + d.y0); + + if (d.y < 0) { + y -= this._barHeight(d); + } + + return utils.safeNumber(y - LABEL_PADDING); + } + + _renderLabels (layer, layerIndex, data) { + const labels = layer.selectAll('text.barLabel') + .data(data.values, pluck('x')); + + const labelsEnterUpdate = labels + .enter() + .append('text') + .attr('class', 'barLabel') + .attr('text-anchor', 'middle') + .attr('x', d => this._labelXPos(d)) + .attr('y', d => this._labelYPos(d)) + .merge(labels); + + if (this.isOrdinal()) { + labelsEnterUpdate.on('click', d3compat.eventHandler(d => this.onClick(d))); + labelsEnterUpdate.attr('cursor', 'pointer'); + } + + transition(labelsEnterUpdate, this.transitionDuration(), this.transitionDelay()) + .attr('x', d => this._labelXPos(d)) + .attr('y', d => this._labelYPos(d)) + .text(d => this.label()(d)); + + transition(labels.exit(), this.transitionDuration(), this.transitionDelay()) + .attr('height', 0) + .remove(); + } + + _barXPos (d) { + let x = this.x()(d.x); + if (this._centerBar) { + x -= this._barWidth / 2; + } + if (this.isOrdinal() && this._gap !== undefined) { + x += this._gap / 2; + } + return utils.safeNumber(x); + } + + _renderBars (layer, layerIndex, data) { + const bars = layer.selectAll('rect.bar') + .data(data.values, pluck('x')); + + const enter = bars.enter() + .append('rect') + .attr('class', 'bar') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('fill', pluck('data', this.getColor)) + .attr('x', d => this._barXPos(d)) + .attr('y', this.yAxisHeight()) + .attr('height', 0); + + const barsEnterUpdate = enter.merge(bars); + + if (this.renderTitle()) { + enter.append('title').text(pluck('data', this.title(data.name))); + } + + if (this.isOrdinal()) { + barsEnterUpdate.on('click', d3compat.eventHandler(d => this.onClick(d))); + } + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.onClick); + } + + transition(barsEnterUpdate, this.transitionDuration(), this.transitionDelay()) + .attr('x', d => this._barXPos(d)) + .attr('y', d => { + let y = this.y()(d.y + d.y0); + + if (d.y < 0) { + y -= this._barHeight(d); + } + + return utils.safeNumber(y); + }) + .attr('width', this._barWidth) + .attr('height', d => this._barHeight(d)) + .attr('fill', pluck('data', this.getColor)) + .select('title').text(pluck('data', this.title(data.name))); + + transition(bars.exit(), this.transitionDuration(), this.transitionDelay()) + .attr('x', d => this.x()(d.x)) + .attr('width', this._barWidth * 0.9) + .remove(); + } + + _calculateBarWidth () { + if (this._barWidth === undefined) { + const numberOfBars = this.xUnitCount(); + + // please can't we always use rangeBands for bar charts? + if (this.isOrdinal() && this._gap === undefined) { + this._barWidth = Math.floor(this.x().bandwidth()); + } else if (this._gap) { + this._barWidth = Math.floor((this.xAxisLength() - (numberOfBars - 1) * this._gap) / numberOfBars); + } else { + this._barWidth = Math.floor(this.xAxisLength() / (1 + this.barPadding()) / numberOfBars); + } + + if (this._barWidth === Infinity || isNaN(this._barWidth) || this._barWidth < MIN_BAR_WIDTH) { + this._barWidth = MIN_BAR_WIDTH; + } + } + } + + fadeDeselectedArea (brushSelection) { + const bars = this.chartBodyG().selectAll('rect.bar'); + + if (this.isOrdinal()) { + if (this.hasFilter()) { + bars.classed(constants.SELECTED_CLASS, d => this.hasFilter(d.x)); + bars.classed(constants.DESELECTED_CLASS, d => !this.hasFilter(d.x)); + } else { + bars.classed(constants.SELECTED_CLASS, false); + bars.classed(constants.DESELECTED_CLASS, false); + } + } else if (this.brushOn() || this.parentBrushOn()) { + if (!this.brushIsEmpty(brushSelection)) { + const start = brushSelection[0]; + const end = brushSelection[1]; + + bars.classed(constants.DESELECTED_CLASS, d => d.x < start || d.x >= end); + } else { + bars.classed(constants.DESELECTED_CLASS, false); + } + } + } + + /** + * Whether the bar chart will render each bar centered around the data position on the x-axis. + * @param {Boolean} [centerBar=false] + * @returns {Boolean|BarChart} + */ + centerBar (centerBar) { + if (!arguments.length) { + return this._centerBar; + } + this._centerBar = centerBar; + return this; + } + + onClick (d) { + super.onClick(d.data); + } + + /** + * Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1. + * Setting this value will also remove any previously set {@link BarChart#gap gap}. See the + * {@link https://github.com/d3/d3-scale/blob/master/README.md#scaleBand d3 docs} + * for a visual description of how the padding is applied. + * @param {Number} [barPadding=0] + * @returns {Number|BarChart} + */ + barPadding (barPadding) { + if (!arguments.length) { + return this._rangeBandPadding(); + } + this._rangeBandPadding(barPadding); + this._gap = undefined; + return this; + } + + _useOuterPadding () { + return this._gap === undefined; + } + + /** + * Manually set fixed gap (in px) between bars instead of relying on the default auto-generated + * gap. By default the bar chart implementation will calculate and set the gap automatically + * based on the number of data points and the length of the x axis. + * @param {Number} [gap=2] + * @returns {Number|BarChart} + */ + gap (gap) { + if (!arguments.length) { + return this._gap; + } + this._gap = gap; + return this; + } + + extendBrush (brushSelection) { + if (brushSelection && this.round() && (!this._centerBar || this._alwaysUseRounding)) { + brushSelection[0] = this.round()(brushSelection[0]); + brushSelection[1] = this.round()(brushSelection[1]); + } + return brushSelection; + } + + /** + * Set or get whether rounding is enabled when bars are centered. If false, using + * rounding with centered bars will result in a warning and rounding will be ignored. This flag + * has no effect if bars are not {@link BarChart#centerBar centered}. + * When using standard d3.js rounding methods, the brush often doesn't align correctly with + * centered bars since the bars are offset. The rounding function must add an offset to + * compensate, such as in the following example. + * @example + * chart.round(function(n) { return Math.floor(n) + 0.5; }); + * @param {Boolean} [alwaysUseRounding=false] + * @returns {Boolean|BarChart} + */ + alwaysUseRounding (alwaysUseRounding) { + if (!arguments.length) { + return this._alwaysUseRounding; + } + this._alwaysUseRounding = alwaysUseRounding; + return this; + } + + legendHighlight (d) { + const colorFilter = (color, inv) => function () { + const item = select(this); + const match = item.attr('fill') === color; + return inv ? !match : match; + }; + + if (!this.isLegendableHidden(d)) { + this.g().selectAll('rect.bar') + .classed('highlight', colorFilter(d.color)) + .classed('fadeout', colorFilter(d.color, true)); + } + } + + legendReset () { + this.g().selectAll('rect.bar') + .classed('highlight', false) + .classed('fadeout', false); + } + + xAxisMax () { + let max = super.xAxisMax(); + if ('resolution' in this.xUnits()) { + const res = this.xUnits().resolution; + max += res; + } + return max; + } +} + +export const barChart = (parent, chartGroup) => new BarChart(parent, chartGroup); diff --git a/src/charts/box-plot.js b/src/charts/box-plot.js new file mode 100644 index 0000000000..8d737c454d --- /dev/null +++ b/src/charts/box-plot.js @@ -0,0 +1,410 @@ +import {scaleBand} from 'd3-scale'; +import {select} from 'd3-selection'; +import {min, max} from 'd3-array'; + +import {d3Box} from '../base/d3.box' +import {CoordinateGridMixin} from '../base/coordinate-grid-mixin'; +import {transition} from '../core/core'; +import {units} from '../core/units'; +import {utils} from '../core/utils'; +import {d3compat} from '../core/config'; + +// Returns a function to compute the interquartile range. +function defaultWhiskersIQR (k) { + return d => { + const q1 = d.quartiles[0]; + const q3 = d.quartiles[2]; + const iqr = (q3 - q1) * k; + + let i = -1; + let j = d.length; + + do { + ++i; + } while (d[i] < q1 - iqr); + + do { + --j; + } while (d[j] > q3 + iqr); + + return [i, j]; + }; +} + +/** + * A box plot is a chart that depicts numerical data via their quartile ranges. + * + * Examples: + * - {@link http://dc-js.github.io/dc.js/examples/boxplot-basic.html Boxplot Basic example} + * - {@link http://dc-js.github.io/dc.js/examples/boxplot-enhanced.html Boxplot Enhanced example} + * - {@link http://dc-js.github.io/dc.js/examples/boxplot-render-data.html Boxplot Render Data example} + * - {@link http://dc-js.github.io/dc.js/examples/boxplot-time.html Boxplot time example} + * @mixes CoordinateGridMixin + */ +export class BoxPlot extends CoordinateGridMixin { + /** + * Create a Box Plot. + * + * @example + * // create a box plot under #chart-container1 element using the default global chart group + * var boxPlot1 = new BoxPlot('#chart-container1'); + * // create a box plot under #chart-container2 element using chart group A + * var boxPlot2 = new BoxPlot('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._whiskerIqrFactor = 1.5; + this._whiskersIqr = defaultWhiskersIQR; + this._whiskers = this._whiskersIqr(this._whiskerIqrFactor); + + this._box = d3Box(); + this._tickFormat = null; + this._renderDataPoints = false; + this._dataOpacity = 0.3; + this._dataWidthPortion = 0.8; + this._showOutliers = true; + this._boldOutlier = false; + + // Used in yAxisMin and yAxisMax to add padding in pixel coordinates + // so the min and max data points/whiskers are within the chart + this._yRangePadding = 8; + + this._boxWidth = (innerChartWidth, xUnits) => { + if (this.isOrdinal()) { + return this.x().bandwidth(); + } else { + return innerChartWidth / (1 + this.boxPadding()) / xUnits; + } + }; + + // default to ordinal + this.x(scaleBand()); + this.xUnits(units.ordinal); + + // valueAccessor should return an array of values that can be coerced into numbers + // or if data is overloaded for a static array of arrays, it should be `Number`. + // Empty arrays are not included. + this.data(group => group.all().map(d => { + d.map = accessor => accessor.call(d, d); + return d; + }).filter(d => { + const values = this.valueAccessor()(d); + return values.length !== 0; + })); + + this.boxPadding(0.8); + this.outerPadding(0.5); + + this.anchor(parent, chartGroup); + } + + /** + * Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1. + * See the {@link https://github.com/d3/d3-scale/blob/master/README.md#scaleBand d3 docs} + * for a visual description of how the padding is applied. + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md#scaleBand d3.scaleBand} + * @param {Number} [padding=0.8] + * @returns {Number|BoxPlot} + */ + boxPadding (padding) { + if (!arguments.length) { + return this._rangeBandPadding(); + } + return this._rangeBandPadding(padding); + } + + /** + * Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts + * or on charts with a custom {@link BoxPlot#boxWidth .boxWidth}. Will pad the width by + * `padding * barWidth` on each side of the chart. + * @param {Number} [padding=0.5] + * @returns {Number|BoxPlot} + */ + outerPadding (padding) { + if (!arguments.length) { + return this._outerRangeBandPadding(); + } + return this._outerRangeBandPadding(padding); + } + + /** + * Get or set the numerical width of the boxplot box. The width may also be a function taking as + * parameters the chart width excluding the right and left margins, as well as the number of x + * units. + * @example + * // Using numerical parameter + * chart.boxWidth(10); + * // Using function + * chart.boxWidth((innerChartWidth, xUnits) { ... }); + * @param {Number|Function} [boxWidth=0.5] + * @returns {Number|Function|BoxPlot} + */ + boxWidth (boxWidth) { + if (!arguments.length) { + return this._boxWidth; + } + this._boxWidth = typeof boxWidth === 'function' ? boxWidth : utils.constant(boxWidth); + return this; + } + + _boxTransform (d, i) { + const xOffset = this.x()(this.keyAccessor()(d, i)); + return `translate(${xOffset}, 0)`; + } + + _preprocessData () { + if (this.elasticX()) { + this.x().domain([]); + } + } + + plotData () { + this._calculatedBoxWidth = this._boxWidth(this.effectiveWidth(), this.xUnitCount()); + + this._box.whiskers(this._whiskers) + .width(this._calculatedBoxWidth) + .height(this.effectiveHeight()) + .value(this.valueAccessor()) + .domain(this.y().domain()) + .duration(this.transitionDuration()) + .tickFormat(this._tickFormat) + .renderDataPoints(this._renderDataPoints) + .dataOpacity(this._dataOpacity) + .dataWidthPortion(this._dataWidthPortion) + .renderTitle(this.renderTitle()) + .showOutliers(this._showOutliers) + .boldOutlier(this._boldOutlier); + + const boxesG = this.chartBodyG().selectAll('g.box').data(this.data(), this.keyAccessor()); + + const boxesGEnterUpdate = this._renderBoxes(boxesG); + this._updateBoxes(boxesGEnterUpdate); + this._removeBoxes(boxesG); + + this.fadeDeselectedArea(this.filter()); + } + + _renderBoxes (boxesG) { + const boxesGEnter = boxesG.enter().append('g'); + + boxesGEnter + .attr('class', 'box') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('transform', (d, i) => this._boxTransform(d, i)) + .call(this._box) + .on('click', d3compat.eventHandler(d => { + this.filter(this.keyAccessor()(d)); + this.redrawGroup(); + })) + .selectAll('circle') + .classed('dc-tabbable', this._keyboardAccessible); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.onClick); + } + + return boxesGEnter.merge(boxesG); + } + + _updateBoxes (boxesG) { + const chart = this; + transition(boxesG, this.transitionDuration(), this.transitionDelay()) + .attr('transform', (d, i) => this._boxTransform(d, i)) + .call(this._box) + .each(function (d) { + const color = chart.getColor(d, 0); + select(this).select('rect.box').attr('fill', color); + select(this).selectAll('circle.data').attr('fill', color); + }); + } + + _removeBoxes (boxesG) { + boxesG.exit().remove().call(this._box); + } + + _minDataValue () { + return min(this.data(), e => min(this.valueAccessor()(e))); + } + + _maxDataValue () { + return max(this.data(), e => max(this.valueAccessor()(e))); + } + + _yAxisRangeRatio () { + return ((this._maxDataValue() - this._minDataValue()) / this.effectiveHeight()); + } + + onClick (d) { + this.filter(this.keyAccessor()(d)); + this.redrawGroup(); + } + + fadeDeselectedArea (brushSelection) { + const chart = this; + if (this.hasFilter()) { + if (this.isOrdinal()) { + this.g().selectAll('g.box').each(function (d) { + if (chart.isSelectedNode(d)) { + chart.highlightSelected(this); + } else { + chart.fadeDeselected(this); + } + }); + } else { + if (!(this.brushOn() || this.parentBrushOn())) { + return; + } + const start = brushSelection[0]; + const end = brushSelection[1]; + this.g().selectAll('g.box').each(function (d) { + const key = chart.keyAccessor()(d); + if (key < start || key >= end) { + chart.fadeDeselected(this); + } else { + chart.highlightSelected(this); + } + }); + } + } else { + this.g().selectAll('g.box').each(function () { + chart.resetHighlight(this); + }); + } + } + + isSelectedNode (d) { + return this.hasFilter(this.keyAccessor()(d)); + } + + yAxisMin () { + const padding = this._yRangePadding * this._yAxisRangeRatio(); + return utils.subtract(this._minDataValue() - padding, this.yAxisPadding()); + } + + yAxisMax () { + const padding = this._yRangePadding * this._yAxisRangeRatio(); + return utils.add(this._maxDataValue() + padding, this.yAxisPadding()); + } + + /** + * Get or set the numerical format of the boxplot median, whiskers and quartile labels. Defaults + * to integer formatting. + * @example + * // format ticks to 2 decimal places + * chart.tickFormat(d3.format('.2f')); + * @param {Function} [tickFormat] + * @returns {Number|Function|BoxPlot} + */ + tickFormat (tickFormat) { + if (!arguments.length) { + return this._tickFormat; + } + this._tickFormat = tickFormat; + return this; + } + + /** + * Get or set the amount of padding to add, in pixel coordinates, to the top and + * bottom of the chart to accommodate box/whisker labels. + * @example + * // allow more space for a bigger whisker font + * chart.yRangePadding(12); + * @param {Function} [yRangePadding = 8] + * @returns {Number|Function|BoxPlot} + */ + yRangePadding (yRangePadding) { + if (!arguments.length) { + return this._yRangePadding; + } + this._yRangePadding = yRangePadding; + return this; + } + + /** + * Get or set whether individual data points will be rendered. + * @example + * // Enable rendering of individual data points + * chart.renderDataPoints(true); + * @param {Boolean} [show=false] + * @returns {Boolean|BoxPlot} + */ + renderDataPoints (show) { + if (!arguments.length) { + return this._renderDataPoints; + } + this._renderDataPoints = show; + return this; + } + + /** + * Get or set the opacity when rendering data. + * @example + * // If individual data points are rendered increase the opacity. + * chart.dataOpacity(0.7); + * @param {Number} [opacity=0.3] + * @returns {Number|BoxPlot} + */ + dataOpacity (opacity) { + if (!arguments.length) { + return this._dataOpacity; + } + this._dataOpacity = opacity; + return this; + } + + /** + * Get or set the portion of the width of the box to show data points. + * @example + * // If individual data points are rendered increase the data box. + * chart.dataWidthPortion(0.9); + * @param {Number} [percentage=0.8] + * @returns {Number|BoxPlot} + */ + dataWidthPortion (percentage) { + if (!arguments.length) { + return this._dataWidthPortion; + } + this._dataWidthPortion = percentage; + return this; + } + + /** + * Get or set whether outliers will be rendered. + * @example + * // Disable rendering of outliers + * chart.showOutliers(false); + * @param {Boolean} [show=true] + * @returns {Boolean|BoxPlot} + */ + showOutliers (show) { + if (!arguments.length) { + return this._showOutliers; + } + this._showOutliers = show; + return this; + } + + /** + * Get or set whether outliers will be drawn bold. + * @example + * // If outliers are rendered display as bold + * chart.boldOutlier(true); + * @param {Boolean} [show=false] + * @returns {Boolean|BoxPlot} + */ + boldOutlier (show) { + if (!arguments.length) { + return this._boldOutlier; + } + this._boldOutlier = show; + return this; + } +} + +export const boxPlot = (parent, chartGroup) => new BoxPlot(parent, chartGroup); diff --git a/src/charts/bubble-chart.js b/src/charts/bubble-chart.js new file mode 100644 index 0000000000..d7624baa24 --- /dev/null +++ b/src/charts/bubble-chart.js @@ -0,0 +1,142 @@ +import {BubbleMixin} from '../base/bubble-mixin'; +import {CoordinateGridMixin} from '../base/coordinate-grid-mixin'; +import {transition} from '../core/core'; +import {d3compat} from '../core/config'; + +/** + * A concrete implementation of a general purpose bubble chart that allows data visualization using the + * following dimensions: + * - x axis position + * - y axis position + * - bubble radius + * - color + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * - {@link https://dc-js.github.io/dc.js/vc/index.html US Venture Capital Landscape 2011} + * @mixes BubbleMixin + * @mixes CoordinateGridMixin + */ +export class BubbleChart extends BubbleMixin(CoordinateGridMixin) { + /** + * Create a Bubble Chart. + * + * @example + * // create a bubble chart under #chart-container1 element using the default global chart group + * var bubbleChart1 = new BubbleChart('#chart-container1'); + * // create a bubble chart under #chart-container2 element using chart group A + * var bubbleChart2 = new BubbleChart('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this.transitionDuration(750); + + this.transitionDelay(0); + + this.anchor(parent, chartGroup); + } + + _bubbleLocator (d) { + return `translate(${this._bubbleX(d)},${this._bubbleY(d)})`; + } + + plotData () { + this.calculateRadiusDomain(); + this.r().range([this.MIN_RADIUS, this.xAxisLength() * this.maxBubbleRelativeSize()]); + + const data = this.data(); + let bubbleG = this.chartBodyG().selectAll(`g.${this.BUBBLE_NODE_CLASS}`) + .data(data, d => d.key); + if (this.sortBubbleSize() || this.keyboardAccessible()) { + // update dom order based on sort + bubbleG.order(); + } + + this._removeNodes(bubbleG); + + bubbleG = this._renderNodes(bubbleG); + + this._updateNodes(bubbleG); + + this.fadeDeselectedArea(this.filter()); + } + + _renderNodes (bubbleG) { + const bubbleGEnter = bubbleG.enter().append('g'); + + bubbleGEnter + .attr('class', this.BUBBLE_NODE_CLASS) + .attr('transform', d => this._bubbleLocator(d)) + .append('circle').attr('class', (d, i) => `${this.BUBBLE_CLASS} _${i}`) + .on('click', d3compat.eventHandler(d => this.onClick(d))) + .classed('dc-tabbable', this._keyboardAccessible) + .attr('fill', this.getColor) + .attr('r', 0); + + bubbleG = bubbleGEnter.merge(bubbleG); + + transition(bubbleG, this.transitionDuration(), this.transitionDelay()) + .select(`circle.${this.BUBBLE_CLASS}`) + .attr('r', d => this.bubbleR(d)) + .attr('opacity', d => (this.bubbleR(d) > 0) ? 1 : 0); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.onClick); + } + + this._doRenderLabel(bubbleGEnter); + + this._doRenderTitles(bubbleGEnter); + + return bubbleG; + } + + _updateNodes (bubbleG) { + transition(bubbleG, this.transitionDuration(), this.transitionDelay()) + .attr('transform', d => this._bubbleLocator(d)) + .select(`circle.${this.BUBBLE_CLASS}`) + .attr('fill', this.getColor) + .attr('r', d => this.bubbleR(d)) + .attr('opacity', d => (this.bubbleR(d) > 0) ? 1 : 0); + + this.doUpdateLabels(bubbleG); + this.doUpdateTitles(bubbleG); + } + + _removeNodes (bubbleG) { + bubbleG.exit().remove(); + } + + _bubbleX (d) { + let x = this.x()(this.keyAccessor()(d)); + if (isNaN(x) || !isFinite(x)) { + x = 0; + } + return x; + } + + _bubbleY (d) { + let y = this.y()(this.valueAccessor()(d)); + if (isNaN(y) || !isFinite(y)) { + y = 0; + } + return y; + } + + renderBrush () { + // override default x axis brush from parent chart + } + + redrawBrush (brushSelection, doTransition) { + // override default x axis brush from parent chart + this.fadeDeselectedArea(brushSelection); + } +} + +export const bubbleChart = (parent, chartGroup) => new BubbleChart(parent, chartGroup); diff --git a/src/charts/bubble-overlay.js b/src/charts/bubble-overlay.js new file mode 100644 index 0000000000..0b44267361 --- /dev/null +++ b/src/charts/bubble-overlay.js @@ -0,0 +1,217 @@ +import {BaseMixin} from '../base/base-mixin'; +import {BubbleMixin} from '../base/bubble-mixin'; +import {transition} from '../core/core'; +import {constants} from '../core/constants'; +import {utils} from '../core/utils'; +import {d3compat} from '../core/config'; + +const BUBBLE_OVERLAY_CLASS = 'bubble-overlay'; +const BUBBLE_NODE_CLASS = 'node'; +const BUBBLE_CLASS = 'bubble'; + +/** + * The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay + * chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the + * typical x and y positioning while retaining the capability to visualize data using bubble radius + * and coloring. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/crime/index.html Canadian City Crime Stats} + * @mixes BubbleMixin + * @mixes BaseMixin + */ +export class BubbleOverlay extends BubbleMixin(BaseMixin) { + /** + * Create a Bubble Overlay. + * + * @example + * // create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group + * var bubbleChart1 = BubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg')); + * // create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A + * var bubbleChart2 = new CompositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg')); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + /** + * **mandatory** + * + * Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg + * element; therefore the bubble overlay chart will not work if this function is not invoked. If the + * underlying image is a bitmap, then an empty svg will need to be created on top of the image. + * @example + * // set up underlying svg element + * chart.svg(d3.select('#chart svg')); + * @param {SVGElement|d3.selection} [imageElement] + * @returns {BubbleOverlay} + */ + this._g = undefined; + this._points = []; + this._keyboardAccessible = false; + + this.transitionDuration(750); + + this.transitionDelay(0); + + this.radiusValueAccessor(d => d.value); + + this.anchor(parent, chartGroup); + } + + /** + * **mandatory** + * + * Set up a data point on the overlay. The name of a data point should match a specific 'key' among + * data groups generated using keyAccessor. If a match is found (point name <-> data group key) + * then a bubble will be generated at the position specified by the function. x and y + * value specified here are relative to the underlying svg. + * @param {String} name + * @param {Number} x + * @param {Number} y + * @returns {BubbleOverlay} + */ + point (name, x, y) { + this._points.push({name: name, x: x, y: y}); + return this; + } + + _doRender () { + this._g = this._initOverlayG(); + + this.r().range([this.MIN_RADIUS, this.width() * this.maxBubbleRelativeSize()]); + + this._initializeBubbles(); + + this.fadeDeselectedArea(this.filter()); + + return this; + } + + _initOverlayG () { + this._g = this.select(`g.${BUBBLE_OVERLAY_CLASS}`); + if (this._g.empty()) { + this._g = this.svg().append('g').attr('class', BUBBLE_OVERLAY_CLASS); + } + return this._g; + } + + _initializeBubbles () { + const data = this._mapData(); + this.calculateRadiusDomain(); + + this._points.forEach(point => { + const nodeG = this._getNodeG(point, data); + + let circle = nodeG.select(`circle.${BUBBLE_CLASS}`); + + if (circle.empty()) { + circle = nodeG.append('circle') + .attr('class', BUBBLE_CLASS) + .classed('dc-tabbable', this._keyboardAccessible) + .attr('r', 0) + .attr('fill', this.getColor) + .on('click', d3compat.eventHandler(d => this.onClick(d))); + } + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.onClick); + } + + transition(circle, this.transitionDuration(), this.transitionDelay()) + .attr('r', d => this.bubbleR(d)); + + this._doRenderLabel(nodeG); + + this._doRenderTitles(nodeG); + }); + } + + _mapData () { + const data = {}; + this.data().forEach(datum => { + data[this.keyAccessor()(datum)] = datum; + }); + return data; + } + + _getNodeG (point, data) { + const bubbleNodeClass = `${BUBBLE_NODE_CLASS} ${utils.nameToId(point.name)}`; + + let nodeG = this._g.select(`g.${utils.nameToId(point.name)}`); + + if (nodeG.empty()) { + nodeG = this._g.append('g') + .attr('class', bubbleNodeClass) + .attr('transform', `translate(${point.x},${point.y})`); + } + + nodeG.datum(data[point.name]); + + return nodeG; + } + + _doRedraw () { + this._updateBubbles(); + + this.fadeDeselectedArea(this.filter()); + + return this; + } + + _updateBubbles () { + const data = this._mapData(); + this.calculateRadiusDomain(); + + this._points.forEach(point => { + const nodeG = this._getNodeG(point, data); + + const circle = nodeG.select(`circle.${BUBBLE_CLASS}`); + + transition(circle, this.transitionDuration(), this.transitionDelay()) + .attr('r', d => this.bubbleR(d)) + .attr('fill', this.getColor); + + this.doUpdateLabels(nodeG); + + this.doUpdateTitles(nodeG); + }); + } + + debug (flag) { + if (flag) { + let debugG = this.select(`g.${constants.DEBUG_GROUP_CLASS}`); + + if (debugG.empty()) { + debugG = this.svg() + .append('g') + .attr('class', constants.DEBUG_GROUP_CLASS); + } + + const debugText = debugG.append('text') + .attr('x', 10) + .attr('y', 20); + + debugG + .append('rect') + .attr('width', this.width()) + .attr('height', this.height()) + .on('mousemove', d3compat.eventHandler((d, evt) => { + const position = d3compat.pointer(evt, debugG.node()); + const msg = `${position[0]}, ${position[1]}`; + debugText.text(msg); + })); + } else { + this.selectAll('.debug').remove(); + } + + return this; + } + +} + +export const bubbleOverlay = (parent, chartGroup) => new BubbleOverlay(parent, chartGroup); diff --git a/src/charts/cbox-menu.js b/src/charts/cbox-menu.js new file mode 100644 index 0000000000..e49f75c183 --- /dev/null +++ b/src/charts/cbox-menu.js @@ -0,0 +1,280 @@ +import {select} from 'd3-selection'; + +import {events} from '../core/events'; +import {BaseMixin} from '../base/base-mixin'; +import {utils} from '../core/utils' +import {d3compat} from '../core/config'; + +const GROUP_CSS_CLASS = 'dc-cbox-group'; +const ITEM_CSS_CLASS = 'dc-cbox-item'; + +/** + * The CboxMenu is a simple widget designed to filter a dimension by + * selecting option(s) from a set of HTML `` elements. The menu can be + * made into a set of radio buttons (single select) or checkboxes (multiple). + * @mixes BaseMixin + */ +export class CboxMenu extends BaseMixin { + /** + * Create a Cbox Menu. + * + * @example + * // create a cboxMenu under #cbox-container using the default global chart group + * var cbox = new CboxMenu('#cbox-container') + * .dimension(states) + * .group(stateGroup); + * // the option text can be set via the title() function + * // by default the option text is '`key`: `value`' + * cbox.title(function (d){ + * return 'STATE: ' + d.key; + * }) + * @param {String|node|d3.selection|CompositeChart} parent - Any valid + * [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this widget should be placed in. + * Interaction with the widget will only trigger events and redraws within its group. + */ + constructor (parent, chartGroup) { + super(); + + this._cbox = undefined; + this._promptText = 'Select all'; + this._multiple = false; + this._inputType = 'radio'; + this._promptValue = null; + + this._uniqueId = utils.uniqueId(); + + this.data(group => group.all().filter(this._filterDisplayed)); + + // There is an accessor for this attribute, initialized with default value + this._filterDisplayed = d => this.valueAccessor()(d) > 0; + + this._order = (a, b) => { + if (this.keyAccessor()(a) > this.keyAccessor()(b)) { + return 1; + } + if (this.keyAccessor()(a) < this.keyAccessor()(b)) { + return -1; + } + return 0; + }; + + this.anchor(parent, chartGroup); + } + + _doRender () { + return this._doRedraw(); + } + + _doRedraw () { + this.select('ul').remove(); + this._cbox = this.root() + .append('ul') + .classed(GROUP_CSS_CLASS, true); + this._renderOptions(); + + if (this.hasFilter() && this._multiple) { + this._cbox.selectAll('input') + // adding `false` avoids failing test cases in phantomjs + .property('checked', d => d && this.filters().indexOf(String(this.keyAccessor()(d))) >= 0 || false); + } else if (this.hasFilter()) { + this._cbox.selectAll('input') + .property('checked', d => { + if (!d) { + return false; + } + return this.keyAccessor()(d) === this.filter(); + }); + } + return this; + } + + _renderOptions () { + let options = this._cbox + .selectAll(`li.${ITEM_CSS_CLASS}`) + .data(this.data(), d => this.keyAccessor()(d)); + + options.exit().remove(); + + options = options.enter() + .append('li') + .classed(ITEM_CSS_CLASS, true) + .merge(options); + + options + .append('input') + .attr('type', this._inputType) + .attr('value', d => this.keyAccessor()(d)) + .attr('name', `domain_${this._uniqueId}`) + .attr('id', (d, i) => `input_${this._uniqueId}_${i}`); + options + .append('label') + .attr('for', (d, i) => `input_${this._uniqueId}_${i}`) + .text(this.title()); + + const chart = this; + // 'all' option + if (this._multiple) { + this._cbox + .append('li') + .append('input') + .attr('type', 'reset') + .text(this._promptText) + .on('click', d3compat.eventHandler(function (d, evt) { + return chart._onChange(d, evt, this); + })); + } else { + const li = this._cbox.append('li'); + li.append('input') + .attr('type', this._inputType) + .attr('value', this._promptValue) + .attr('name', `domain_${this._uniqueId}`) + .attr('id', (d, i) => `input_${this._uniqueId}_all`) + .property('checked', true); + li.append('label') + .attr('for', (d, i) => `input_${this._uniqueId}_all`) + .text(this._promptText); + } + + this._cbox + .selectAll(`li.${ITEM_CSS_CLASS}`) + .sort(this._order); + + this._cbox.on('change', d3compat.eventHandler(function (d, evt) { + return chart._onChange(d, evt, this); + })); + return options; + } + + _onChange (d, evt, element) { + let values; + + const target = select(evt.target); + let options; + + if (!target.datum()) { + values = this._promptValue || null; + } else { + options = select(element).selectAll('input') + .filter(function (o) { + if (o) { + return this.checked; + } + }); + values = options.nodes().map(option => option.value); + // check if only prompt option is selected + if (!this._multiple && values.length === 1) { + values = values[0]; + } + } + this.onChange(values); + } + + onChange (val) { + if (val && this._multiple) { + this.replaceFilter([val]); + } else if (val) { + this.replaceFilter(val); + } else { + this.filterAll(); + } + events.trigger(() => { + this.redrawGroup(); + }); + } + + /** + * Get or set the function that controls the ordering of option tags in the + * cbox menu. By default options are ordered by the group key in ascending + * order. + * @param {Function} [order] + * @returns {Function|CboxMenu} + * @example + * // order by the group's value + * chart.order(function (a,b) { + * return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; + * }); + */ + order (order) { + if (!arguments.length) { + return this._order; + } + this._order = order; + return this; + } + + /** + * Get or set the text displayed in the options used to prompt selection. + * @param {String} [promptText='Select all'] + * @returns {String|CboxMenu} + * @example + * chart.promptText('All states'); + */ + promptText (promptText) { + if (!arguments.length) { + return this._promptText; + } + this._promptText = promptText; + return this; + } + + /** + * Get or set the function that filters options prior to display. By default options + * with a value of < 1 are not displayed. + * @param {function} [filterDisplayed] + * @returns {Function|CboxMenu} + * @example + * // display all options override the `filterDisplayed` function: + * chart.filterDisplayed(function () { + * return true; + * }); + */ + filterDisplayed (filterDisplayed) { + if (!arguments.length) { + return this._filterDisplayed; + } + this._filterDisplayed = filterDisplayed; + return this; + } + + /** + * Controls the type of input element. Setting it to true converts + * the HTML `input` tags from radio buttons to checkboxes. + * @param {boolean} [multiple=false] + * @returns {Boolean|CboxMenu} + * @example + * chart.multiple(true); + */ + multiple (multiple) { + if (!arguments.length) { + return this._multiple; + } + this._multiple = multiple; + if (this._multiple) { + this._inputType = 'checkbox'; + } else { + this._inputType = 'radio'; + } + return this; + } + + /** + * Controls the default value to be used for + * [dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) + * when only the prompt value is selected. If `null` (the default), no filtering will occur when + * just the prompt is selected. + * @param {?*} [promptValue=null] + * @returns {*|CboxMenu} + */ + promptValue (promptValue) { + if (!arguments.length) { + return this._promptValue; + } + this._promptValue = promptValue; + + return this; + } +} + +export const cboxMenu = (parent, chartGroup) => new CboxMenu(parent, chartGroup); diff --git a/src/charts/composite-chart.js b/src/charts/composite-chart.js new file mode 100644 index 0000000000..f0b8744f80 --- /dev/null +++ b/src/charts/composite-chart.js @@ -0,0 +1,584 @@ +import {min, max} from 'd3-array'; +import {scaleLinear} from 'd3-scale'; +import {axisRight} from 'd3-axis'; + +import {utils} from '../core/utils'; +import {CoordinateGridMixin} from '../base/coordinate-grid-mixin'; + +const SUB_CHART_CLASS = 'sub'; +const DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING = 12; + +/** + * Composite charts are a special kind of chart that render multiple charts on the same Coordinate + * Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to + * achieve some quite flexible charting effects. + * @mixes CoordinateGridMixin + */ +export class CompositeChart extends CoordinateGridMixin { + /** + * Create a Composite Chart. + * @example + * // create a composite chart under #chart-container1 element using the default global chart group + * var compositeChart1 = new CompositeChart('#chart-container1'); + * // create a composite chart under #chart-container2 element using chart group A + * var compositeChart2 = new CompositeChart('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._children = []; + + this._childOptions = {}; + + this._shareColors = false; + this._shareTitle = true; + this._alignYAxes = false; + + this._rightYAxis = axisRight(); + this._rightYAxisLabel = 0; + this._rightYAxisLabelPadding = DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING; + this._rightY = undefined; + this._rightAxisGridLines = false; + + this._mandatoryAttributes([]); + this.transitionDuration(500); + this.transitionDelay(0); + + this.on('filtered.dcjs-composite-chart', chart => { + // Propagate the filters onto the children + // Notice that on children the call is .replaceFilter and not .filter + // the reason is that _chart.filter() returns the entire current set of filters not just the last added one + for (let i = 0; i < this._children.length; ++i) { + this._children[i].replaceFilter(this.filter()); + } + }); + + this.anchor(parent, chartGroup); + } + + _generateG () { + const g = super._generateG(); + + for (let i = 0; i < this._children.length; ++i) { + const child = this._children[i]; + + this._generateChildG(child, i); + + if (!child.dimension()) { + child.dimension(this.dimension()); + } + if (!child.group()) { + child.group(this.group()); + } + + child.chartGroup(this.chartGroup()); + child.svg(this.svg()); + child.xUnits(this.xUnits()); + child.transitionDuration(this.transitionDuration(), this.transitionDelay()); + child.parentBrushOn(this.brushOn()); + child.brushOn(false); + child.renderTitle(this.renderTitle()); + child.elasticX(this.elasticX()); + } + + return g; + } + + rescale () { + super.rescale(); + + this._children.forEach(child => { + child.rescale(); + }); + + return this; + } + + resizing (resizing) { + if (!arguments.length) { + return super.resizing(); + } + super.resizing(resizing); + + this._children.forEach(child => { + child.resizing(resizing); + }); + + return this; + } + + _prepareYAxis () { + const left = (this._leftYAxisChildren().length !== 0); + const right = (this._rightYAxisChildren().length !== 0); + const ranges = this._calculateYAxisRanges(left, right); + + if (left) { + this._prepareLeftYAxis(ranges); + } + if (right) { + this._prepareRightYAxis(ranges); + } + + if (this._leftYAxisChildren().length > 0 && !this._rightAxisGridLines) { + this._renderHorizontalGridLinesForAxis(this.g(), this.y(), this.yAxis()); + } else if (this._rightYAxisChildren().length > 0) { + this._renderHorizontalGridLinesForAxis(this.g(), this._rightY, this._rightYAxis); + } + } + + renderYAxis () { + if (this._leftYAxisChildren().length !== 0) { + this.renderYAxisAt('y', this.yAxis(), this.margins().left); + this.renderYAxisLabel('y', this.yAxisLabel(), -90); + } + + if (this._rightYAxisChildren().length !== 0) { + this.renderYAxisAt('yr', this.rightYAxis(), this.width() - this.margins().right); + this.renderYAxisLabel('yr', this.rightYAxisLabel(), 90, this.width() - this._rightYAxisLabelPadding); + } + } + + _calculateYAxisRanges (left, right) { + let lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax; + let ranges; + + if (left) { + lyAxisMin = this._yAxisMin(); + lyAxisMax = this._yAxisMax(); + } + + if (right) { + ryAxisMin = this._rightYAxisMin(); + ryAxisMax = this._rightYAxisMax(); + } + + if (this.alignYAxes() && left && right) { + ranges = this._alignYAxisRanges(lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax); + } + + return ranges || { + lyAxisMin: lyAxisMin, + lyAxisMax: lyAxisMax, + ryAxisMin: ryAxisMin, + ryAxisMax: ryAxisMax + }; + } + + _alignYAxisRanges (lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax) { + // since the two series will share a zero, each Y is just a multiple + // of the other. and the ratio should be the ratio of the ranges of the + // input data, so that they come out the same height. so we just min/max + + // note: both ranges already include zero due to the stack mixin (#667) + // if #667 changes, we can reconsider whether we want data height or + // height from zero to be equal. and it will be possible for the axes + // to be aligned but not visible. + const extentRatio = (ryAxisMax - ryAxisMin) / (lyAxisMax - lyAxisMin); + + return { + lyAxisMin: Math.min(lyAxisMin, ryAxisMin / extentRatio), + lyAxisMax: Math.max(lyAxisMax, ryAxisMax / extentRatio), + ryAxisMin: Math.min(ryAxisMin, lyAxisMin * extentRatio), + ryAxisMax: Math.max(ryAxisMax, lyAxisMax * extentRatio) + }; + } + + _prepareRightYAxis (ranges) { + const needDomain = this.rightY() === undefined || this.elasticY(), + needRange = needDomain || this.resizing(); + if (this.rightY() === undefined) { + this.rightY(scaleLinear()); + } + if (needDomain) { + this.rightY().domain([ranges.ryAxisMin, ranges.ryAxisMax]); + } + if (needRange) { + this.rightY().rangeRound([this.yAxisHeight(), 0]); + } + + this.rightY().range([this.yAxisHeight(), 0]); + this.rightYAxis(this.rightYAxis().scale(this.rightY())); + + // In D3v4 create a RightAxis + // _chart.rightYAxis().orient('right'); + } + + _prepareLeftYAxis (ranges) { + const needDomain = this.y() === undefined || this.elasticY(), + needRange = needDomain || this.resizing(); + if (this.y() === undefined) { + this.y(scaleLinear()); + } + if (needDomain) { + this.y().domain([ranges.lyAxisMin, ranges.lyAxisMax]); + } + if (needRange) { + this.y().rangeRound([this.yAxisHeight(), 0]); + } + + this.y().range([this.yAxisHeight(), 0]); + this.yAxis(this.yAxis().scale(this.y())); + + // In D3v4 create a LeftAxis + // _chart.yAxis().orient('left'); + } + + _generateChildG (child, i) { + child._generateG(this.g()); + child.g().attr('class', `${SUB_CHART_CLASS} _${i}`); + } + + plotData () { + for (let i = 0; i < this._children.length; ++i) { + const child = this._children[i]; + + if (!child.g()) { + this._generateChildG(child, i); + } + + if (this._shareColors) { + child.colors(this.colors()); + } + + child.x(this.x()); + + child.xAxis(this.xAxis()); + + if (child.useRightYAxis()) { + child.y(this.rightY()); + child.yAxis(this.rightYAxis()); + } else { + child.y(this.y()); + child.yAxis(this.yAxis()); + } + + child.plotData(); + + child._activateRenderlets(); + } + } + + /** + * Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the + * default behavior. This option is only respected when subcharts with both left and right y-axes + * are present. + * @param {Boolean} [useRightAxisGridLines=false] + * @returns {Boolean|CompositeChart} + */ + useRightAxisGridLines (useRightAxisGridLines) { + if (!arguments) { + return this._rightAxisGridLines; + } + + this._rightAxisGridLines = useRightAxisGridLines; + return this; + } + + /** + * Get or set chart-specific options for all child charts. This is equivalent to calling + * {@link BaseMixin#options .options} on each child chart. + * @param {Object} [childOptions] + * @returns {Object|CompositeChart} + */ + childOptions (childOptions) { + if (!arguments.length) { + return this._childOptions; + } + this._childOptions = childOptions; + this._children.forEach(child => { + child.options(this._childOptions); + }); + return this; + } + + fadeDeselectedArea (brushSelection) { + if (this.brushOn()) { + for (let i = 0; i < this._children.length; ++i) { + const child = this._children[i]; + child.fadeDeselectedArea(brushSelection); + } + } + } + + /** + * Set or get the right y axis label. + * @param {String} [rightYAxisLabel] + * @param {Number} [padding] + * @returns {String|CompositeChart} + */ + rightYAxisLabel (rightYAxisLabel, padding) { + if (!arguments.length) { + return this._rightYAxisLabel; + } + this._rightYAxisLabel = rightYAxisLabel; + this.margins().right -= this._rightYAxisLabelPadding; + this._rightYAxisLabelPadding = (padding === undefined) ? DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING : padding; + this.margins().right += this._rightYAxisLabelPadding; + return this; + } + + /** + * Combine the given charts into one single composite coordinate grid chart. + * @example + * moveChart.compose([ + * // when creating sub-chart you need to pass in the parent chart + * new LineChart(moveChart) + * .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used + * .valueAccessor(function (d){return d.value.avg;}) + * // most of the normal functions will continue to work in a composed chart + * .renderArea(true) + * .stack(monthlyMoveGroup, function (d){return d.value;}) + * .title(function (d){ + * var value = d.value.avg?d.value.avg:d.value; + * if(isNaN(value)) value = 0; + * return dateFormat(d.key) + '\n' + numberFormat(value); + * }), + * new BarChart(moveChart) + * .group(volumeByMonthGroup) + * .centerBar(true) + * ]); + * @param {Array} [subChartArray] + * @returns {CompositeChart} + */ + compose (subChartArray) { + this._children = subChartArray; + this._children.forEach(child => { + child.height(this.height()); + child.width(this.width()); + child.margins(this.margins()); + + if (this._shareTitle) { + child.title(this.title()); + } + + child.options(this._childOptions); + }); + this.rescale(); + return this; + } + + _setChildrenProperty (prop, value) { + this._children.forEach(child => { + child[prop](value); + }); + } + + // properties passed through in compose() + height (height) { + if(!arguments.length) { + return super.height(); + } + super.height(height); + this._setChildrenProperty('height', height); + return this; + } + + width (width) { + if(!arguments.length) { + return super.width(); + } + super.width(width); + this._setChildrenProperty('width', width); + return this; + } + + margins (margins) { + if(!arguments.length) { + return super.margins(); + } + super.margins(margins); + this._setChildrenProperty('margins', margins); + return this; + } + + /** + * Returns the child charts which are composed into the composite chart. + * @returns {Array} + */ + children () { + return this._children; + } + + /** + * Get or set color sharing for the chart. If set, the {@link ColorMixin#colors .colors()} value from this chart + * will be shared with composed children. Additionally if the child chart implements + * Stackable and has not set a custom .colorAccessor, then it will generate a color + * specific to its order in the composition. + * @param {Boolean} [shareColors=false] + * @returns {Boolean|CompositeChart} + */ + shareColors (shareColors) { + if (!arguments.length) { + return this._shareColors; + } + this._shareColors = shareColors; + return this; + } + + /** + * Get or set title sharing for the chart. If set, the {@link BaseMixin#title .title()} value from + * this chart will be shared with composed children. + * + * Note: currently you must call this before `compose` or the child will still get the parent's + * `title` function! + * @param {Boolean} [shareTitle=true] + * @returns {Boolean|CompositeChart} + */ + shareTitle (shareTitle) { + if (!arguments.length) { + return this._shareTitle; + } + this._shareTitle = shareTitle; + return this; + } + + /** + * Get or set the y scale for the right axis. The right y scale is typically automatically + * generated by the chart implementation. + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @param {d3.scale} [yScale] + * @returns {d3.scale|CompositeChart} + */ + rightY (yScale) { + if (!arguments.length) { + return this._rightY; + } + this._rightY = yScale; + this.rescale(); + return this; + } + + /** + * Get or set alignment between left and right y axes. A line connecting '0' on both y axis + * will be parallel to x axis. This only has effect when {@link CoordinateGridMixin#elasticY elasticY} is true. + * @param {Boolean} [alignYAxes=false] + * @returns {Chart} + */ + alignYAxes (alignYAxes) { + if (!arguments.length) { + return this._alignYAxes; + } + this._alignYAxes = alignYAxes; + this.rescale(); + return this; + } + + _leftYAxisChildren () { + return this._children.filter(child => !child.useRightYAxis()); + } + + _rightYAxisChildren () { + return this._children.filter(child => child.useRightYAxis()); + } + + _getYAxisMin (charts) { + return charts.map(c => c.yAxisMin()); + } + + _yAxisMin () { + return min(this._getYAxisMin(this._leftYAxisChildren())); + } + + _rightYAxisMin () { + return min(this._getYAxisMin(this._rightYAxisChildren())); + } + + _getYAxisMax (charts) { + return charts.map(c => c.yAxisMax()); + } + + _yAxisMax () { + return utils.add(max(this._getYAxisMax(this._leftYAxisChildren())), this.yAxisPadding()); + } + + _rightYAxisMax () { + return utils.add(max(this._getYAxisMax(this._rightYAxisChildren())), this.yAxisPadding()); + } + + _getAllXAxisMinFromChildCharts () { + return this._children.map(c => c.xAxisMin()); + } + + xAxisMin () { + return utils.subtract(min(this._getAllXAxisMinFromChildCharts()), this.xAxisPadding(), this.xAxisPaddingUnit()); + } + + _getAllXAxisMaxFromChildCharts () { + return this._children.map(c => c.xAxisMax()); + } + + xAxisMax () { + return utils.add(max(this._getAllXAxisMaxFromChildCharts()), this.xAxisPadding(), this.xAxisPaddingUnit()); + } + + legendables () { + return this._children.reduce((items, child) => { + if (this._shareColors) { + child.colors(this.colors()); + } + items.push.apply(items, child.legendables()); + return items; + }, []); + } + + legendHighlight (d) { + for (let j = 0; j < this._children.length; ++j) { + const child = this._children[j]; + child.legendHighlight(d); + } + } + + legendReset (d) { + for (let j = 0; j < this._children.length; ++j) { + const child = this._children[j]; + child.legendReset(d); + } + } + + legendToggle () { + console.log('composite should not be getting legendToggle itself'); + } + + /** + * Set or get the right y axis used by the composite chart. This function is most useful when y + * axis customization is required. The y axis in dc.js is an instance of a + * [d3.axisRight](https://github.com/d3/d3-axis/blob/master/README.md#axisRight) therefore it supports any valid + * d3 axis manipulation. + * + * **Caution**: The right y axis is usually generated internally by dc; resetting it may cause + * unexpected results. Note also that when used as a getter, this function is not chainable: it + * returns the axis, not the chart, + * {@link https://github.com/dc-js/dc.js/wiki/FAQ#why-does-everything-break-after-a-call-to-xaxis-or-yaxis + * so attempting to call chart functions after calling `.yAxis()` will fail}. + * @see {@link https://github.com/d3/d3-axis/blob/master/README.md#axisRight} + * @example + * // customize y axis tick format + * chart.rightYAxis().tickFormat(function (v) {return v + '%';}); + * // customize y axis tick values + * chart.rightYAxis().tickValues([0, 100, 200, 300]); + * @param {d3.axisRight} [rightYAxis] + * @returns {d3.axisRight|CompositeChart} + */ + rightYAxis (rightYAxis) { + if (!arguments.length) { + return this._rightYAxis; + } + this._rightYAxis = rightYAxis; + return this; + } + + yAxisMin () { + throw new Error('Not supported for this chart type'); + } + + yAxisMax () { + throw new Error('Not supported for this chart type'); + } +} + +export const compositeChart = (parent, chartGroup) => new CompositeChart(parent, chartGroup); diff --git a/src/charts/data-count.js b/src/charts/data-count.js new file mode 100644 index 0000000000..e1aacea861 --- /dev/null +++ b/src/charts/data-count.js @@ -0,0 +1,148 @@ +import {format} from 'd3-format'; + +import {logger} from '../core/logger'; +import {BaseMixin} from '../base/base-mixin'; + +/** + * The data count widget is a simple widget designed to display the number of records selected by the + * current filters out of the total number of records in the data set. Once created the data count widget + * will automatically update the text content of child elements with the following classes: + * + * * `.total-count` - total number of records + * * `.filter-count` - number of records matched by the current filters + * + * Note: this widget works best for the specific case of showing the number of records out of a + * total. If you want a more general-purpose numeric display, please use the + * {@link NumberDisplay} widget instead. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * @mixes BaseMixin + */ +export class DataCount extends BaseMixin { + /** + * Create a Data Count widget. + * @example + * var ndx = crossfilter(data); + * var all = ndx.groupAll(); + * + * new DataCount('.dc-data-count') + * .crossfilter(ndx) + * .groupAll(all); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._formatNumber = format(',d'); + this._crossfilter = null; + this._groupAll = null; + this._html = {some: '', all: ''}; + + this._mandatoryAttributes(['crossfilter', 'groupAll']); + + this.anchor(parent, chartGroup); + } + + /** + * Gets or sets an optional object specifying HTML templates to use depending how many items are + * selected. The text `%total-count` will replaced with the total number of records, and the text + * `%filter-count` will be replaced with the number of selected records. + * - all: HTML template to use if all items are selected + * - some: HTML template to use if not all items are selected + * @example + * counter.html({ + * some: '%filter-count out of %total-count records selected', + * all: 'All records selected. Click on charts to apply filters' + * }) + * @param {{some:String, all: String}} [options] + * @returns {{some:String, all: String}|DataCount} + */ + html (options) { + if (!arguments.length) { + return this._html; + } + if (options.all) { + this._html.all = options.all; + } + if (options.some) { + this._html.some = options.some; + } + return this; + } + + /** + * Gets or sets an optional function to format the filter count and total count. + * @see {@link https://github.com/d3/d3-format/blob/master/README.md#format d3.format} + * @example + * counter.formatNumber(d3.format('.2g')) + * @param {Function} [formatter=d3.format('.2g')] + * @returns {Function|DataCount} + */ + formatNumber (formatter) { + if (!arguments.length) { + return this._formatNumber; + } + this._formatNumber = formatter; + return this; + } + + _doRender () { + const tot = this.crossfilter().size(), + val = this.groupAll().value(); + const all = this._formatNumber(tot); + const selected = this._formatNumber(val); + + if ((tot === val) && (this._html.all !== '')) { + this.root().html(this._html.all.replace('%total-count', all).replace('%filter-count', selected)); + } else if (this._html.some !== '') { + this.root().html(this._html.some.replace('%total-count', all).replace('%filter-count', selected)); + } else { + this.selectAll('.total-count').text(all); + this.selectAll('.filter-count').text(selected); + } + return this; + } + + _doRedraw () { + return this._doRender(); + } + + crossfilter (cf) { + if (!arguments.length) { + return this._crossfilter; + } + this._crossfilter = cf; + return this; + } + + dimension (cf) { + logger.warnOnce('consider using dataCount.crossfilter instead of dataCount.dimension for clarity'); + if (!arguments.length) { + return this.crossfilter(); + } + return this.crossfilter(cf); + } + + groupAll (groupAll) { + if (!arguments.length) { + return this._groupAll; + } + this._groupAll = groupAll; + return this; + } + + group (groupAll) { + logger.warnOnce('consider using dataCount.groupAll instead of dataCount.group for clarity'); + if (!arguments.length) { + return this.groupAll(); + } + return this.groupAll(groupAll); + } +} + +export const dataCount = (parent, chartGroup) => new DataCount(parent, chartGroup); diff --git a/src/charts/data-grid.js b/src/charts/data-grid.js new file mode 100644 index 0000000000..b7a9d3123a --- /dev/null +++ b/src/charts/data-grid.js @@ -0,0 +1,274 @@ +import {ascending} from 'd3-array'; + +import {logger} from '../core/logger'; +import {BaseMixin} from '../base/base-mixin'; +import {d3compat} from '../core/config'; + +const LABEL_CSS_CLASS = 'dc-grid-label'; +const ITEM_CSS_CLASS = 'dc-grid-item'; +const SECTION_CSS_CLASS = 'dc-grid-section dc-grid-group'; +const GRID_CSS_CLASS = 'dc-grid-top'; + +/** + * Data grid is a simple widget designed to list the filtered records, providing + * a simple way to define how the items are displayed. + * + * Note: Formerly the data grid chart (and data table) used the {@link DataGrid#group group} attribute as a + * keying function for {@link https://github.com/d3/d3-collection/blob/master/README.md#nest nesting} the data + * together in sections. This was confusing so it has been renamed to `section`, although `group` still works. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ep/ List of members of the european parliament} + * @mixes BaseMixin + */ +export class DataGrid extends BaseMixin { + /** + * Create a Data Grid. + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._section = null; + this._size = 999; // shouldn't be needed, but you might + this._html = function (d) { + return `you need to provide an html() handling param: ${JSON.stringify(d)}`; + }; + this._sortBy = function (d) { + return d; + }; + this._order = ascending; + this._beginSlice = 0; + this._endSlice = undefined; + + this._htmlSection = d => `

${ + this.keyAccessor()(d)}

`; + + this._mandatoryAttributes(['dimension', 'section']); + + this.anchor(parent, chartGroup); + } + + _doRender () { + this.selectAll(`div.${GRID_CSS_CLASS}`).remove(); + + this._renderItems(this._renderSections()); + + return this; + } + + _renderSections () { + const sections = this.root().selectAll(`div.${GRID_CSS_CLASS}`) + .data(this._nestEntries(), d => this.keyAccessor()(d)); + + const itemSection = sections + .enter() + .append('div') + .attr('class', GRID_CSS_CLASS); + + if (this._htmlSection) { + itemSection + .html(d => this._htmlSection(d)); + } + + sections.exit().remove(); + return itemSection; + } + + _nestEntries () { + let entries = this.dimension().top(this._size); + + entries = entries + .sort((a, b) => this._order(this._sortBy(a), this._sortBy(b))) + .slice(this._beginSlice, this._endSlice) + + return d3compat.nester({ + key: this.section(), + sortKeys: this._order, + entries + }); + } + + _renderItems (sections) { + let items = sections.order() + .selectAll(`div.${ITEM_CSS_CLASS}`) + .data(d => d.values); + + items.exit().remove(); + + items = items + .enter() + .append('div') + .attr('class', ITEM_CSS_CLASS) + .html(d => this._html(d)) + .merge(items); + + return items; + } + + _doRedraw () { + return this._doRender(); + } + + /** + * Get or set the section function for the data grid. The section function takes a data row and + * returns the key to specify to {@link https://github.com/d3/d3-collection/blob/master/README.md#nest d3.nest} + * to split rows into sections. + * + * Do not pass in a crossfilter section as this will not work. + * @example + * // section rows by the value of their field + * chart + * .section(function(d) { return d.field; }) + * @param {Function} section Function taking a row of data and returning the nest key. + * @returns {Function|DataGrid} + */ + section (section) { + if (!arguments.length) { + return this._section; + } + this._section = section; + return this; + } + + /** + * Backward-compatible synonym for {@link DataGrid#section section}. + * + * @param {Function} section Function taking a row of data and returning the nest key. + * @returns {Function|DataGrid} + */ + group (section) { + logger.warnOnce('consider using dataGrid.section instead of dataGrid.group for clarity'); + if (!arguments.length) { + return this.section(); + } + return this.section(section); + } + + /** + * Get or set the index of the beginning slice which determines which entries get displayed by the widget. + * Useful when implementing pagination. + * @param {Number} [beginSlice=0] + * @returns {Number|DataGrid} + */ + beginSlice (beginSlice) { + if (!arguments.length) { + return this._beginSlice; + } + this._beginSlice = beginSlice; + return this; + } + + /** + * Get or set the index of the end slice which determines which entries get displayed by the widget. + * Useful when implementing pagination. + * @param {Number} [endSlice] + * @returns {Number|DataGrid} + */ + endSlice (endSlice) { + if (!arguments.length) { + return this._endSlice; + } + this._endSlice = endSlice; + return this; + } + + /** + * Get or set the grid size which determines the number of items displayed by the widget. + * @param {Number} [size=999] + * @returns {Number|DataGrid} + */ + size (size) { + if (!arguments.length) { + return this._size; + } + this._size = size; + return this; + } + + /** + * Get or set the function that formats an item. The data grid widget uses a + * function to generate dynamic html. Use your favourite templating engine or + * generate the string directly. + * @example + * chart.html(function (d) { return '
'+data.exampleString+'
';}); + * @param {Function} [html] + * @returns {Function|DataGrid} + */ + html (html) { + if (!arguments.length) { + return this._html; + } + this._html = html; + return this; + } + + /** + * Get or set the function that formats a section label. + * @example + * chart.htmlSection (function (d) { return '

'.d.key . 'with ' . d.values.length .' items

'}); + * @param {Function} [htmlSection] + * @returns {Function|DataGrid} + */ + htmlSection (htmlSection) { + if (!arguments.length) { + return this._htmlSection; + } + this._htmlSection = htmlSection; + return this; + } + + /** + * Backward-compatible synonym for {@link DataGrid#htmlSection htmlSection}. + * @param {Function} [htmlSection] + * @returns {Function|DataGrid} + */ + htmlGroup (htmlSection) { + logger.warnOnce('consider using dataGrid.htmlSection instead of dataGrid.htmlGroup for clarity'); + if (!arguments.length) { + return this.htmlSection(); + } + return this.htmlSection(htmlSection); + } + + /** + * Get or set sort-by function. This function works as a value accessor at the item + * level and returns a particular field to be sorted. + * @example + * chart.sortBy(function(d) { + * return d.date; + * }); + * @param {Function} [sortByFunction] + * @returns {Function|DataGrid} + */ + sortBy (sortByFunction) { + if (!arguments.length) { + return this._sortBy; + } + this._sortBy = sortByFunction; + return this; + } + + /** + * Get or set sort the order function. + * @see {@link https://github.com/d3/d3-array/blob/master/README.md#ascending d3.ascending} + * @see {@link https://github.com/d3/d3-array/blob/master/README.md#descending d3.descending} + * @example + * chart.order(d3.descending); + * @param {Function} [order=d3.ascending] + * @returns {Function|DataGrid} + */ + order (order) { + if (!arguments.length) { + return this._order; + } + this._order = order; + return this; + } +} + +export const dataGrid = (parent, chartGroup) => new DataGrid(parent, chartGroup); diff --git a/src/charts/data-table.js b/src/charts/data-table.js new file mode 100644 index 0000000000..b630e77076 --- /dev/null +++ b/src/charts/data-table.js @@ -0,0 +1,443 @@ +import {ascending} from 'd3-array'; + +import {logger} from '../core/logger'; +import {BaseMixin} from '../base/base-mixin'; +import {d3compat} from '../core/config'; + +const LABEL_CSS_CLASS = 'dc-table-label'; +const ROW_CSS_CLASS = 'dc-table-row'; +const COLUMN_CSS_CLASS = 'dc-table-column'; +const SECTION_CSS_CLASS = 'dc-table-section dc-table-group'; +const HEAD_CSS_CLASS = 'dc-table-head'; + +/** + * The data table is a simple widget designed to list crossfilter focused data set (rows being + * filtered) in a good old tabular fashion. + * + * An interesting feature of the data table is that you can pass a crossfilter group to the + * `dimension`, if you want to show aggregated data instead of raw data rows. This requires no + * special code as long as you specify the {@link DataTable#order order} as `d3.descending`, + * since the data table will use `dimension.top()` to fetch the data in that case, and the method is + * equally supported on the crossfilter group as the crossfilter dimension. + * + * If you want to display aggregated data in ascending order, you will need to wrap the group + * in a [fake dimension](https://github.com/dc-js/dc.js/wiki/FAQ#fake-dimensions) to support the + * `.bottom()` method. See the example linked below for more details. + * + * Note: Formerly the data table (and data grid chart) used the {@link DataTable#group group} attribute as a + * keying function for {@link https://github.com/d3/d3-collection/blob/master/README.md#nest nesting} the data + * together in sections. This was confusing so it has been renamed to `section`, although `group` still works. + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * - {@link http://dc-js.github.io/dc.js/examples/table-on-aggregated-data.html dataTable on a crossfilter group} + * ({@link https://github.com/dc-js/dc.js/blob/master/web-src/examples/table-on-aggregated-data.html source}) + * + * @mixes BaseMixin + */ +export class DataTable extends BaseMixin { + /** + * Create a Data Table. + * + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._size = 25; + this._columns = []; + this._sortBy = d => d; + this._order = ascending; + this._beginSlice = 0; + this._endSlice = undefined; + this._showSections = true; + this._section = () => ''; // all in one section + + this._mandatoryAttributes(['dimension']); + + this.anchor(parent, chartGroup); + } + + _doRender () { + this.selectAll('tbody').remove(); + + this._renderRows(this._renderSections()); + + return this; + } + + _doColumnValueFormat (v, d) { + return (typeof v === 'function') ? v(d) : // v as function + (typeof v === 'string') ? d[v] : // v is field name string + v.format(d); // v is Object, use fn (element 2) + } + + _doColumnHeaderFormat (d) { + // if 'function', convert to string representation + // show a string capitalized + // if an object then display its label string as-is. + return (typeof d === 'function') ? this._doColumnHeaderFnToString(d) : + (typeof d === 'string') ? this._doColumnHeaderCapitalize(d) : + String(d.label); + } + + _doColumnHeaderCapitalize (s) { + // capitalize + return s.charAt(0).toUpperCase() + s.slice(1); + } + + _doColumnHeaderFnToString (f) { + // columnString(f) { + let s = String(f); + const i1 = s.indexOf('return '); + if (i1 >= 0) { + const i2 = s.lastIndexOf(';'); + if (i2 >= 0) { + s = s.substring(i1 + 7, i2); + const i3 = s.indexOf('numberFormat'); + if (i3 >= 0) { + s = s.replace('numberFormat', ''); + } + } + } + return s; + } + + _renderSections () { + // The 'original' example uses all 'functions'. + // If all 'functions' are used, then don't remove/add a header, and leave + // the html alone. This preserves the functionality of earlier releases. + // A 2nd option is a string representing a field in the data. + // A third option is to supply an Object such as an array of 'information', and + // supply your own _doColumnHeaderFormat and _doColumnValueFormat functions to + // create what you need. + let bAllFunctions = true; + this._columns.forEach(f => { + bAllFunctions = bAllFunctions & (typeof f === 'function'); + }); + + if (!bAllFunctions) { + // ensure one thead + let thead = this.selectAll('thead').data([0]); + thead.exit().remove(); + thead = thead.enter() + .append('thead') + .merge(thead); + + // with one tr + let headrow = thead.selectAll('tr').data([0]); + headrow.exit().remove(); + headrow = headrow.enter() + .append('tr') + .merge(headrow); + + // with a th for each column + const headcols = headrow.selectAll('th') + .data(this._columns); + headcols.exit().remove(); + headcols.enter().append('th') + .merge(headcols) + .attr('class', HEAD_CSS_CLASS) + .html(d => (this._doColumnHeaderFormat(d))); + } + + const sections = this.root().selectAll('tbody') + .data(this._nestEntries(), d => this.keyAccessor()(d)); + + const rowSection = sections + .enter() + .append('tbody'); + + if (this._showSections === true) { + rowSection + .append('tr') + .attr('class', SECTION_CSS_CLASS) + .append('td') + .attr('class', LABEL_CSS_CLASS) + .attr('colspan', this._columns.length) + .html(d => this.keyAccessor()(d)); + } + + sections.exit().remove(); + + return rowSection; + } + + _nestEntries () { + let entries; + if (this._order === ascending) { + entries = this.dimension().bottom(this._size); + } else { + entries = this.dimension().top(this._size); + } + + entries = entries.sort((a, b) => this._order(this._sortBy(a), this._sortBy(b))).slice(this._beginSlice, this._endSlice) + + return d3compat.nester({ + key: this.section(), + sortKeys: this._order, + entries + }); + } + + _renderRows (sections) { + const rows = sections.order() + .selectAll(`tr.${ROW_CSS_CLASS}`) + .data(d => d.values); + + const rowEnter = rows.enter() + .append('tr') + .attr('class', ROW_CSS_CLASS); + + this._columns.forEach((v, i) => { + rowEnter.append('td') + .attr('class', `${COLUMN_CSS_CLASS} _${i}`) + .html(d => this._doColumnValueFormat(v, d)); + }); + + rows.exit().remove(); + + return rows; + } + + _doRedraw () { + return this._doRender(); + } + + /** + * Get or set the section function for the data table. The section function takes a data row and + * returns the key to specify to {@link https://github.com/d3/d3-collection/blob/master/README.md#nest d3.nest} + * to split rows into sections. By default there will be only one section with no name. + * + * Set {@link DataTable#showSections showSections} to false to hide the section headers + * + * @example + * // section rows by the value of their field + * chart + * .section(function(d) { return d.field; }) + * @param {Function} section Function taking a row of data and returning the nest key. + * @returns {Function|DataTable} + */ + section (section) { + if (!arguments.length) { + return this._section; + } + this._section = section; + return this; + } + + /** + * Backward-compatible synonym for {@link DataTable#section section}. + * + * @param {Function} section Function taking a row of data and returning the nest key. + * @returns {Function|DataTable} + */ + group (section) { + logger.warnOnce('consider using dataTable.section instead of dataTable.group for clarity'); + if (!arguments.length) { + return this.section(); + } + return this.section(section); + } + + /** + * Get or set the table size which determines the number of rows displayed by the widget. + * @param {Number} [size=25] + * @returns {Number|DataTable} + */ + size (size) { + if (!arguments.length) { + return this._size; + } + this._size = size; + return this; + } + + /** + * Get or set the index of the beginning slice which determines which entries get displayed + * by the widget. Useful when implementing pagination. + * + * Note: the sortBy function will determine how the rows are ordered for pagination purposes. + + * See the {@link http://dc-js.github.io/dc.js/examples/table-pagination.html table pagination example} + * to see how to implement the pagination user interface using `beginSlice` and `endSlice`. + * @param {Number} [beginSlice=0] + * @returns {Number|DataTable} + */ + beginSlice (beginSlice) { + if (!arguments.length) { + return this._beginSlice; + } + this._beginSlice = beginSlice; + return this; + } + + /** + * Get or set the index of the end slice which determines which entries get displayed by the + * widget. Useful when implementing pagination. See {@link DataTable#beginSlice `beginSlice`} for more information. + * @param {Number|undefined} [endSlice=undefined] + * @returns {Number|DataTable} + */ + endSlice (endSlice) { + if (!arguments.length) { + return this._endSlice; + } + this._endSlice = endSlice; + return this; + } + + /** + * Get or set column functions. The data table widget supports several methods of specifying the + * columns to display. + * + * The original method uses an array of functions to generate dynamic columns. Column functions + * are simple javascript functions with only one input argument `d` which represents a row in + * the data set. The return value of these functions will be used to generate the content for + * each cell. However, this method requires the HTML for the table to have a fixed set of column + * headers. + * + *
chart.columns([
+     *     function(d) { return d.date; },
+     *     function(d) { return d.open; },
+     *     function(d) { return d.close; },
+     *     function(d) { return numberFormat(d.close - d.open); },
+     *     function(d) { return d.volume; }
+     * ]);
+     * 
+ * + * In the second method, you can list the columns to read from the data without specifying it as + * a function, except where necessary (ie, computed columns). Note the data element name is + * capitalized when displayed in the table header. You can also mix in functions as necessary, + * using the third `{label, format}` form, as shown below. + * + *
chart.columns([
+     *     "date",    // d["date"], ie, a field accessor; capitalized automatically
+     *     "open",    // ...
+     *     "close",   // ...
+     *     {
+     *         label: "Change",
+     *         format: function (d) {
+     *             return numberFormat(d.close - d.open);
+     *         }
+     *     },
+     *     "volume"   // d["volume"], ie, a field accessor; capitalized automatically
+     * ]);
+     * 
+ * + * In the third example, we specify all fields using the `{label, format}` method: + *
chart.columns([
+     *     {
+     *         label: "Date",
+     *         format: function (d) { return d.date; }
+     *     },
+     *     {
+     *         label: "Open",
+     *         format: function (d) { return numberFormat(d.open); }
+     *     },
+     *     {
+     *         label: "Close",
+     *         format: function (d) { return numberFormat(d.close); }
+     *     },
+     *     {
+     *         label: "Change",
+     *         format: function (d) { return numberFormat(d.close - d.open); }
+     *     },
+     *     {
+     *         label: "Volume",
+     *         format: function (d) { return d.volume; }
+     *     }
+     * ]);
+     * 
+ * + * You may wish to override the dataTable functions `_doColumnHeaderCapitalize` and + * `_doColumnHeaderFnToString`, which are used internally to translate the column information or + * function into a displayed header. The first one is used on the "string" column specifier; the + * second is used to transform a stringified function into something displayable. For the Stock + * example, the function for Change becomes the table header **d.close - d.open**. + * + * Finally, you can even specify a completely different form of column definition. To do this, + * override `_chart._doColumnHeaderFormat` and `_chart._doColumnValueFormat` Be aware that + * fields without numberFormat specification will be displayed just as they are stored in the + * data, unformatted. + * @param {Array} [columns=[]] + * @returns {Array}|DataTable} + */ + columns (columns) { + if (!arguments.length) { + return this._columns; + } + this._columns = columns; + return this; + } + + /** + * Get or set sort-by function. This function works as a value accessor at row level and returns a + * particular field to be sorted by. + * @example + * chart.sortBy(function(d) { + * return d.date; + * }); + * @param {Function} [sortBy=identity function] + * @returns {Function|DataTable} + */ + sortBy (sortBy) { + if (!arguments.length) { + return this._sortBy; + } + this._sortBy = sortBy; + return this; + } + + /** + * Get or set sort order. If the order is `d3.ascending`, the data table will use + * `dimension().bottom()` to fetch the data; otherwise it will use `dimension().top()` + * @see {@link https://github.com/d3/d3-array/blob/master/README.md#ascending d3.ascending} + * @see {@link https://github.com/d3/d3-array/blob/master/README.md#descending d3.descending} + * @example + * chart.order(d3.descending); + * @param {Function} [order=d3.ascending] + * @returns {Function|DataTable} + */ + order (order) { + if (!arguments.length) { + return this._order; + } + this._order = order; + return this; + } + + /** + * Get or set if section header rows will be shown. + * @example + * chart + * .section([value], [name]) + * .showSections(true|false); + * @param {Boolean} [showSections=true] + * @returns {Boolean|DataTable} + */ + showSections (showSections) { + if (!arguments.length) { + return this._showSections; + } + this._showSections = showSections; + return this; + } + + /** + * Backward-compatible synonym for {@link DataTable#showSections showSections}. + * @param {Boolean} [showSections=true] + * @returns {Boolean|DataTable} + */ + showGroups (showSections) { + logger.warnOnce('consider using dataTable.showSections instead of dataTable.showGroups for clarity'); + if (!arguments.length) { + return this.showSections(); + } + return this.showSections(showSections); + } +} + +export const dataTable = (parent, chartGroup) => new DataTable(parent, chartGroup); diff --git a/src/charts/geo-choropleth-chart.js b/src/charts/geo-choropleth-chart.js new file mode 100644 index 0000000000..c899ed55c4 --- /dev/null +++ b/src/charts/geo-choropleth-chart.js @@ -0,0 +1,298 @@ +import {geoPath, geoAlbersUsa} from 'd3-geo'; +import {select} from 'd3-selection'; + +import {BaseMixin} from '../base/base-mixin'; +import {ColorMixin} from '../base/color-mixin'; +import {transition} from '../core/core'; +import {logger} from '../core/logger'; +import {events} from '../core/events'; +import {utils} from '../core/utils'; +import {d3compat} from '../core/config'; + +/** + * The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map + * from GeoJson data. This chart implementation was inspired by + * {@link http://bl.ocks.org/4060606 the great d3 choropleth example}. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/vc/index.html US Venture Capital Landscape 2011} + * @mixes ColorMixin + * @mixes BaseMixin + */ +export class GeoChoroplethChart extends ColorMixin(BaseMixin) { + /** + * Create a Geo Choropleth Chart. + * @example + * // create a choropleth chart under '#us-chart' element using the default global chart group + * var chart1 = new GeoChoroplethChart('#us-chart'); + * // create a choropleth chart under '#us-chart2' element using chart group A + * var chart2 = new CompositeChart('#us-chart2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this.colorAccessor(d => d || 0); + + this._geoPath = geoPath(); + this._projectionFlag = undefined; + this._projection = undefined; + + this._geoJsons = []; + + this.anchor(parent, chartGroup); + } + + _doRender () { + this.resetSvg(); + for (let layerIndex = 0; layerIndex < this._geoJsons.length; ++layerIndex) { + const states = this.svg().append('g') + .attr('class', `layer${layerIndex}`); + + let regionG = states.selectAll(`g.${this._geoJson(layerIndex).name}`) + .data(this._geoJson(layerIndex).data); + + regionG = regionG.enter() + .append('g') + .attr('class', this._geoJson(layerIndex).name) + .merge(regionG); + + regionG + .append('path') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('fill', 'white') + .attr('d', this._getGeoPath()); + + regionG.append('title'); + + this._plotData(layerIndex); + } + this._projectionFlag = false; + } + + _plotData (layerIndex) { + const data = this._generateLayeredData(); + + if (this._isDataLayer(layerIndex)) { + const regionG = this._renderRegionG(layerIndex); + + this._renderPaths(regionG, layerIndex, data); + + this._renderTitles(regionG, layerIndex, data); + } + } + + _generateLayeredData () { + const data = {}; + const groupAll = this.data(); + for (let i = 0; i < groupAll.length; ++i) { + data[this.keyAccessor()(groupAll[i])] = this.valueAccessor()(groupAll[i]); + } + return data; + } + + _isDataLayer (layerIndex) { + return this._geoJson(layerIndex).keyAccessor; + } + + _renderRegionG (layerIndex) { + const regionG = this.svg() + .selectAll(this._layerSelector(layerIndex)) + .classed('selected', d => this._isSelected(layerIndex, d)) + .classed('deselected', d => this._isDeselected(layerIndex, d)) + .attr('class', d => { + const layerNameClass = this._geoJson(layerIndex).name; + const regionClass = utils.nameToId(this._geoJson(layerIndex).keyAccessor(d)); + let baseClasses = `${layerNameClass} ${regionClass}`; + if (this._isSelected(layerIndex, d)) { + baseClasses += ' selected'; + } + if (this._isDeselected(layerIndex, d)) { + baseClasses += ' deselected'; + } + return baseClasses; + }); + return regionG; + } + + _layerSelector (layerIndex) { + return `g.layer${layerIndex} g.${this._geoJson(layerIndex).name}`; + } + + _isSelected (layerIndex, d) { + return this.hasFilter() && this.hasFilter(this._getKey(layerIndex, d)); + } + + _isDeselected (layerIndex, d) { + return this.hasFilter() && !this.hasFilter(this._getKey(layerIndex, d)); + } + + _getKey (layerIndex, d) { + return this._geoJson(layerIndex).keyAccessor(d); + } + + _geoJson (index) { + return this._geoJsons[index]; + } + + _renderPaths (regionG, layerIndex, data) { + const paths = regionG + .select('path') + .attr('fill', function () { + const currentFill = select(this).attr('fill'); + if (currentFill) { + return currentFill; + } + return 'none'; + }) + .on('click', d3compat.eventHandler(d => this.onClick(d, layerIndex))); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.onClick, layerIndex); + } + + transition(paths, this.transitionDuration(), + this.transitionDelay()).attr('fill', (d, i) => this.getColor(data[this._geoJson(layerIndex).keyAccessor(d)], i)); + } + + onClick (d, layerIndex) { + const selectedRegion = this._geoJson(layerIndex).keyAccessor(d); + events.trigger(() => { + this.filter(selectedRegion); + this.redrawGroup(); + }); + } + + _renderTitles (regionG, layerIndex, data) { + if (this.renderTitle()) { + regionG.selectAll('title').text(d => { + const key = this._getKey(layerIndex, d); + const value = data[key]; + return this.title()({key: key, value: value}); + }); + } + } + + _doRedraw () { + for (let layerIndex = 0; layerIndex < this._geoJsons.length; ++layerIndex) { + this._plotData(layerIndex); + if (this._projectionFlag) { + this.svg().selectAll(`g.${this._geoJson(layerIndex).name} path`).attr('d', this._getGeoPath()); + } + } + this._projectionFlag = false; + } + + /** + * **mandatory** + * + * Use this function to insert a new GeoJson map layer. This function can be invoked multiple times + * if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple + * layers with the same name the new overlay will override the existing one. + * @see {@link http://geojson.org/ GeoJSON} + * @see {@link https://github.com/topojson/topojson/wiki TopoJSON} + * @see {@link https://github.com/topojson/topojson-1.x-api-reference/blob/master/API-Reference.md#wiki-feature topojson.feature} + * @example + * // insert a layer for rendering US states + * chart.overlayGeoJson(statesJson.features, 'state', function(d) { + * return d.properties.name; + * }); + * @param {_geoJson} json - a geojson feed + * @param {String} name - name of the layer + * @param {Function} keyAccessor - accessor function used to extract 'key' from the GeoJson data. The key extracted by + * this function should match the keys returned by the crossfilter groups. + * @returns {GeoChoroplethChart} + */ + overlayGeoJson (json, name, keyAccessor) { + for (let i = 0; i < this._geoJsons.length; ++i) { + if (this._geoJsons[i].name === name) { + this._geoJsons[i].data = json; + this._geoJsons[i].keyAccessor = keyAccessor; + return this; + } + } + this._geoJsons.push({name: name, data: json, keyAccessor: keyAccessor}); + return this; + } + + /** + * Gets or sets a custom geo projection function. See the available + * {@link https://github.com/d3/d3-geo/blob/master/README.md#projections d3 geo projection functions}. + * + * Starting version 3.0 it has been deprecated to rely on the default projection being + * {@link https://github.com/d3/d3-geo/blob/master/README.md#geoAlbersUsa d3.geoAlbersUsa()}. Please + * set it explicitly. {@link https://bl.ocks.org/mbostock/5557726 + * Considering that `null` is also a valid value for projection}, if you need + * projection to be `null` please set it explicitly to `null`. + * @see {@link https://github.com/d3/d3-geo/blob/master/README.md#projections d3.projection} + * @see {@link https://github.com/d3/d3-geo-projection d3-geo-projection} + * @param {d3.projection} [projection=d3.geoAlbersUsa()] + * @returns {d3.projection|GeoChoroplethChart} + */ + projection (projection) { + if (!arguments.length) { + return this._projection; + } + + this._projection = projection; + this._projectionFlag = true; + return this; + } + + _getGeoPath () { + if (this._projection === undefined) { + logger.warn('choropleth projection default of geoAlbers is deprecated,' + + ' in next version projection will need to be set explicitly'); + return this._geoPath.projection(geoAlbersUsa()); + } + + return this._geoPath.projection(this._projection); + } + + /** + * Returns all GeoJson layers currently registered with this chart. The returned array is a + * reference to this chart's internal data structure, so any modification to this array will also + * modify this chart's internal registration. + * @returns {Array<{name:String, data: Object, accessor: Function}>} + */ + geoJsons () { + return this._geoJsons; + } + + /** + * Returns the {@link https://github.com/d3/d3-geo/blob/master/README.md#paths d3.geoPath} object used to + * render the projection and features. Can be useful for figuring out the bounding box of the + * feature set and thus a way to calculate scale and translation for the projection. + * @see {@link https://github.com/d3/d3-geo/blob/master/README.md#paths d3.geoPath} + * @returns {d3.geoPath} + */ + geoPath () { + return this._geoPath; + } + + /** + * Remove a GeoJson layer from this chart by name + * @param {String} name + * @returns {GeoChoroplethChart} + */ + removeGeoJson (name) { + const geoJsons = []; + + for (let i = 0; i < this._geoJsons.length; ++i) { + const layer = this._geoJsons[i]; + if (layer.name !== name) { + geoJsons.push(layer); + } + } + + this._geoJsons = geoJsons; + + return this; + } +} + +export const geoChoroplethChart = (parent, chartGroup) => new GeoChoroplethChart(parent, chartGroup); diff --git a/src/charts/heatmap.js b/src/charts/heatmap.js new file mode 100644 index 0000000000..8149d741df --- /dev/null +++ b/src/charts/heatmap.js @@ -0,0 +1,409 @@ +import {ascending} from 'd3-array'; +import {scaleBand} from 'd3-scale'; + +import {transition} from '../core/core'; +import {logger} from '../core/logger'; +import {filters} from '../core/filters'; +import {events} from '../core/events'; +import {ColorMixin} from '../base/color-mixin'; +import {MarginMixin} from '../base/margin-mixin'; +import {d3compat} from '../core/config'; + +const DEFAULT_BORDER_RADIUS = 6.75; + +/** + * A heat map is matrix that represents the values of two dimensions of data using colors. + * @mixes ColorMixin + * @mixes MarginMixin + * @mixes BaseMixin + */ +export class HeatMap extends ColorMixin(MarginMixin) { + /** + * Create a Heat Map + * @example + * // create a heat map under #chart-container1 element using the default global chart group + * var heatMap1 = new HeatMap('#chart-container1'); + * // create a heat map under #chart-container2 element using chart group A + * var heatMap2 = new HeatMap('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._chartBody = undefined; + + this._cols = undefined; + this._rows = undefined; + this._colOrdering = ascending; + this._rowOrdering = ascending; + this._colScale = scaleBand(); + this._rowScale = scaleBand(); + + this._xBorderRadius = DEFAULT_BORDER_RADIUS; + this._yBorderRadius = DEFAULT_BORDER_RADIUS; + + this._mandatoryAttributes(['group']); + this.title(this.colorAccessor()); + + this._colsLabel = d => d; + this._rowsLabel = d => d; + + this._xAxisOnClick = d => { + this._filterAxis(0, d); + }; + this._yAxisOnClick = d => { + this._filterAxis(1, d); + }; + this._boxOnClick = d => { + const filter = d.key; + events.trigger(() => { + this.filter(filters.TwoDimensionalFilter(filter)); + this.redrawGroup(); + }); + }; + + this.anchor(parent, chartGroup); + } + + /** + * Set or get the column label function. The chart class uses this function to render + * column labels on the X axis. It is passed the column name. + * @example + * // the default label function just returns the name + * chart.colsLabel(function(d) { return d; }); + * @param {Function} [labelFunction=function(d) { return d; }] + * @returns {Function|HeatMap} + */ + colsLabel (labelFunction) { + if (!arguments.length) { + return this._colsLabel; + } + this._colsLabel = labelFunction; + return this; + } + + /** + * Set or get the row label function. The chart class uses this function to render + * row labels on the Y axis. It is passed the row name. + * @example + * // the default label function just returns the name + * chart.rowsLabel(function(d) { return d; }); + * @param {Function} [labelFunction=function(d) { return d; }] + * @returns {Function|HeatMap} + */ + rowsLabel (labelFunction) { + if (!arguments.length) { + return this._rowsLabel; + } + this._rowsLabel = labelFunction; + return this; + } + + _filterAxis (axis, value) { + const cellsOnAxis = this.selectAll('.box-group').filter(d => d.key[axis] === value); + const unfilteredCellsOnAxis = cellsOnAxis.filter(d => !this.hasFilter(d.key)); + events.trigger(() => { + const selection = unfilteredCellsOnAxis.empty() ? cellsOnAxis : unfilteredCellsOnAxis; + const filtersList = selection.data().map(kv => filters.TwoDimensionalFilter(kv.key)); + this.filter([filtersList]); + this.redrawGroup(); + }); + } + + filter (filter) { + const nonstandardFilter = f => { + logger.warnOnce('heatmap.filter taking a coordinate is deprecated - please pass dc.filters.TwoDimensionalFilter instead'); + return this._filter(filters.TwoDimensionalFilter(f)); + }; + + if (!arguments.length) { + return super.filter(); + } + if (filter !== null && filter.filterType !== 'TwoDimensionalFilter' && + !(Array.isArray(filter) && Array.isArray(filter[0]) && filter[0][0].filterType === 'TwoDimensionalFilter')) { + return nonstandardFilter(filter); + } + return super.filter(filter); + } + + /** + * Gets or sets the values used to create the rows of the heatmap, as an array. By default, all + * the values will be fetched from the data using the value accessor. + * @param {Array} [rows] + * @returns {Array|HeatMap} + */ + + rows (rows) { + if (!arguments.length) { + return this._rows; + } + this._rows = rows; + return this; + } + + /** + * Get or set a comparator to order the rows. + * Default is {@link https://github.com/d3/d3-array#ascending d3.ascending}. + * @param {Function} [rowOrdering] + * @returns {Function|HeatMap} + */ + rowOrdering (rowOrdering) { + if (!arguments.length) { + return this._rowOrdering; + } + this._rowOrdering = rowOrdering; + return this; + } + + /** + * Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all + * the values will be fetched from the data using the key accessor. + * @param {Array} [cols] + * @returns {Array|HeatMap} + */ + cols (cols) { + if (!arguments.length) { + return this._cols; + } + this._cols = cols; + return this; + } + + /** + * Get or set a comparator to order the columns. + * Default is {@link https://github.com/d3/d3-array#ascending d3.ascending}. + * @param {Function} [colOrdering] + * @returns {Function|HeatMap} + */ + colOrdering (colOrdering) { + if (!arguments.length) { + return this._colOrdering; + } + this._colOrdering = colOrdering; + return this; + } + + _doRender () { + this.resetSvg(); + + this._chartBody = this.svg() + .append('g') + .attr('class', 'heatmap') + .attr('transform', `translate(${this.margins().left},${this.margins().top})`); + + return this._doRedraw(); + } + + _doRedraw () { + const data = this.data(); + let rows = this.rows() || data.map(this.valueAccessor()), + cols = this.cols() || data.map(this.keyAccessor()); + if (this._rowOrdering) { + rows = rows.sort(this._rowOrdering); + } + if (this._colOrdering) { + cols = cols.sort(this._colOrdering); + } + rows = this._rowScale.domain(rows); + cols = this._colScale.domain(cols); + + const rowCount = rows.domain().length, + colCount = cols.domain().length, + boxWidth = Math.floor(this.effectiveWidth() / colCount), + boxHeight = Math.floor(this.effectiveHeight() / rowCount); + + cols.rangeRound([0, this.effectiveWidth()]); + rows.rangeRound([this.effectiveHeight(), 0]); + + let boxes = this._chartBody.selectAll('g.box-group').data(this.data(), + (d, i) => `${this.keyAccessor()(d, i)}\0${this.valueAccessor()(d, i)}`); + + boxes.exit().remove(); + + const gEnter = boxes.enter().append('g') + .attr('class', 'box-group'); + + gEnter.append('rect') + .attr('class', 'heat-box') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('fill', 'white') + .attr('x', (d, i) => cols(this.keyAccessor()(d, i))) + .attr('y', (d, i) => rows(this.valueAccessor()(d, i))) + .on('click', d3compat.eventHandler(this.boxOnClick())); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this.boxOnClick); + } + + boxes = gEnter.merge(boxes); + + if (this.renderTitle()) { + gEnter.append('title'); + boxes.select('title').text(this.title()); + } + + transition(boxes.select('rect'), this.transitionDuration(), this.transitionDelay()) + .attr('x', (d, i) => cols(this.keyAccessor()(d, i))) + .attr('y', (d, i) => rows(this.valueAccessor()(d, i))) + .attr('rx', this._xBorderRadius) + .attr('ry', this._yBorderRadius) + .attr('fill', this.getColor) + .attr('width', boxWidth) + .attr('height', boxHeight); + + let gCols = this._chartBody.select('g.cols'); + if (gCols.empty()) { + gCols = this._chartBody.append('g').attr('class', 'cols axis'); + } + let gColsText = gCols.selectAll('text').data(cols.domain()); + + gColsText.exit().remove(); + + gColsText = gColsText + .enter() + .append('text') + .attr('x', d => cols(d) + boxWidth / 2) + .style('text-anchor', 'middle') + .attr('y', this.effectiveHeight()) + .attr('dy', 12) + .on('click', d3compat.eventHandler(this.xAxisOnClick())) + .text(this.colsLabel()) + .merge(gColsText); + + transition(gColsText, this.transitionDuration(), this.transitionDelay()) + .text(this.colsLabel()) + .attr('x', d => cols(d) + boxWidth / 2) + .attr('y', this.effectiveHeight()); + + let gRows = this._chartBody.select('g.rows'); + if (gRows.empty()) { + gRows = this._chartBody.append('g').attr('class', 'rows axis'); + } + + let gRowsText = gRows.selectAll('text').data(rows.domain()); + + gRowsText.exit().remove(); + + gRowsText = gRowsText + .enter() + .append('text') + .style('text-anchor', 'end') + .attr('x', 0) + .attr('dx', -2) + .attr('y', d => rows(d) + boxHeight / 2) + .attr('dy', 6) + .on('click', d3compat.eventHandler(this.yAxisOnClick())) + .text(this.rowsLabel()) + .merge(gRowsText); + + transition(gRowsText, this.transitionDuration(), this.transitionDelay()) + .text(this.rowsLabel()) + .attr('y', d => rows(d) + boxHeight / 2); + + if (this.hasFilter()) { + const chart = this; + this.selectAll('g.box-group').each(function (d) { + if (chart.isSelectedNode(d)) { + chart.highlightSelected(this); + } else { + chart.fadeDeselected(this); + } + }); + } else { + const chart = this; + this.selectAll('g.box-group').each(function () { + chart.resetHighlight(this); + }); + } + return this; + } + + /** + * Gets or sets the handler that fires when an individual cell is clicked in the heatmap. + * By default, filtering of the cell will be toggled. + * @example + * // default box on click handler + * chart.boxOnClick(function (d) { + * var filter = d.key; + * events.trigger(function () { + * _chart.filter(filter); + * _chart.redrawGroup(); + * }); + * }); + * @param {Function} [handler] + * @returns {Function|HeatMap} + */ + boxOnClick (handler) { + if (!arguments.length) { + return this._boxOnClick; + } + this._boxOnClick = handler; + return this; + } + + /** + * Gets or sets the handler that fires when a column tick is clicked in the x axis. + * By default, if any cells in the column are unselected, the whole column will be selected, + * otherwise the whole column will be unselected. + * @param {Function} [handler] + * @returns {Function|HeatMap} + */ + xAxisOnClick (handler) { + if (!arguments.length) { + return this._xAxisOnClick; + } + this._xAxisOnClick = handler; + return this; + } + + /** + * Gets or sets the handler that fires when a row tick is clicked in the y axis. + * By default, if any cells in the row are unselected, the whole row will be selected, + * otherwise the whole row will be unselected. + * @param {Function} [handler] + * @returns {Function|HeatMap} + */ + yAxisOnClick (handler) { + if (!arguments.length) { + return this._yAxisOnClick; + } + this._yAxisOnClick = handler; + return this; + } + + /** + * Gets or sets the X border radius. Set to 0 to get full rectangles. + * @param {Number} [xBorderRadius=6.75] + * @returns {Number|HeatMap} + */ + xBorderRadius (xBorderRadius) { + if (!arguments.length) { + return this._xBorderRadius; + } + this._xBorderRadius = xBorderRadius; + return this; + } + + /** + * Gets or sets the Y border radius. Set to 0 to get full rectangles. + * @param {Number} [yBorderRadius=6.75] + * @returns {Number|HeatMap} + */ + yBorderRadius (yBorderRadius) { + if (!arguments.length) { + return this._yBorderRadius; + } + this._yBorderRadius = yBorderRadius; + return this; + } + + isSelectedNode (d) { + return this.hasFilter(d.key); + } +} + +export const heatMap = (parent, chartGroup) => new HeatMap(parent, chartGroup); diff --git a/src/charts/html-legend.js b/src/charts/html-legend.js new file mode 100644 index 0000000000..bb0fcdf411 --- /dev/null +++ b/src/charts/html-legend.js @@ -0,0 +1,231 @@ +import {select} from 'd3-selection'; + +import {pluck, utils} from '../core/utils'; +import {d3compat} from '../core/config'; +import {constants} from '../core/constants'; + +/** + * htmlLegend is a attachable widget that can be added to other dc charts to render horizontal/vertical legend + * labels. + * @example + * chart.legend(HtmlLegend().container(legendContainerElement).horizontal(false)) + * @returns {HtmlLegend} + */ +export class HtmlLegend { + constructor () { + this._htmlLegendDivCssClass = 'dc-html-legend'; + this._legendItemCssClassHorizontal = 'dc-legend-item-horizontal'; + this._legendItemCssClassVertical = 'dc-legend-item-vertical'; + this._parent = undefined; + this._container = undefined; + this._legendText = pluck('name'); + this._maxItems = undefined; + this._horizontal = false; + this._legendItemClass = undefined; + this._highlightSelected = false; + this._keyboardAccessible = false; + } + + parent (p) { + if (!arguments.length) { + return this._parent; + } + this._parent = p; + return this; + } + + render () { + this._defaultLegendItemCssClass = this._horizontal ? this._legendItemCssClassHorizontal : this._legendItemCssClassVertical; + this._container.select(`div.${this._htmlLegendDivCssClass}`).remove(); + + const container = this._container.append('div').attr('class', this._htmlLegendDivCssClass); + container.attr('style', `max-width:${this._container.nodes()[0].style.width}`); + + let legendables = this._parent.legendables(); + const filters = this._parent.filters(); + + if (this._maxItems !== undefined) { + legendables = legendables.slice(0, this._maxItems); + } + + const legendItemClassName = this._legendItemClass ? this._legendItemClass : this._defaultLegendItemCssClass; + + const itemEnter = container.selectAll(`div.${legendItemClassName}`) + .data(legendables).enter() + .append('div') + .classed(legendItemClassName, true) + .on('mouseover', d3compat.eventHandler(d => this._parent.legendHighlight(d))) + .on('mouseout', d3compat.eventHandler(d => this._parent.legendReset(d))) + .on('click', d3compat.eventHandler(d => this._parent.legendToggle(d))); + + if (this._highlightSelected) { + itemEnter.classed(constants.SELECTED_CLASS, d => filters.indexOf(d.name) !== -1); + } + + itemEnter.append('span') + .attr('class', 'dc-legend-item-color') + .style('background-color', pluck('color')); + + itemEnter.append('span') + .attr('class', 'dc-legend-item-label') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('title', this._legendText) + .text(this._legendText); + + if (this._keyboardAccessible) { + this._makeLegendKeyboardAccessible(); + } + } + + /** + * Set the container selector for the legend widget. Required. + * @param {String} [container] + * @return {String|HtmlLegend} + */ + container (container) { + if (!arguments.length) { + return this._container; + } + this._container = select(container); + return this; + } + + /** + * This can be optionally used to override class for legenditem and just use this class style. + * This is helpful for overriding the style of a particular chart rather than overriding + * the style for all charts. + * + * Setting this will disable the highlighting of selected items also. + * @param {String} [legendItemClass] + * @return {String|HtmlLegend} + */ + legendItemClass (legendItemClass) { + if (!arguments.length) { + return this._legendItemClass; + } + this._legendItemClass = legendItemClass; + return this; + } + + /** + * This can be optionally used to enable highlighting legends for the selections/filters for the + * chart. + * @param {String} [highlightSelected] + * @return {String|HtmlLegend} + */ + highlightSelected (highlightSelected) { + if (!arguments.length) { + return this._highlightSelected; + } + this._highlightSelected = highlightSelected; + return this; + } + + /** + * Display the legend horizontally instead of vertically + * @param {String} [horizontal] + * @return {String|HtmlLegend} + */ + horizontal (horizontal) { + if (!arguments.length) { + return this._horizontal; + } + this._horizontal = horizontal; + return this; + } + + /** + * Set or get the legend text function. The legend widget uses this function to render the legend + * text for each item. If no function is specified the legend widget will display the names + * associated with each group. + * @param {Function} [legendText] + * @returns {Function|HtmlLegend} + * @example + * // default legendText + * legend.legendText(pluck('name')) + * + * // create numbered legend items + * chart.legend(new HtmlLegend().legendText(function(d, i) { return i + '. ' + d.name; })) + * + * // create legend displaying group counts + * chart.legend(new HtmlLegend().legendText(function(d) { return d.name + ': ' d.data; })) + */ + legendText (legendText) { + if (!arguments.length) { + return this._legendText; + } + this._legendText = legendText; + return this; + } + + /** + * Maximum number of legend items to display + * @param {Number} [maxItems] + * @return {HtmlLegend} + */ + maxItems (maxItems) { + if (!arguments.length) { + return this._maxItems; + } + this._maxItems = utils.isNumber(maxItems) ? maxItems : undefined; + return this; + } + + /** + * If set, individual legend items will be focusable from keyboard and on pressing Enter or Space + * will behave as if clicked on. + * + * If `svgDescription` on the parent chart has not been explicitly set, will also set the default + * SVG description text to the class constructor name, like BarChart or HeatMap, and make the entire + * SVG focusable. + * @param {Boolean} [keyboardAccessible=false] + * @returns {Boolean|HtmlLegend} + */ + keyboardAccessible (keyboardAccessible) { + if (!arguments.length) { + return this._keyboardAccessible; + } + this._keyboardAccessible = keyboardAccessible; + return this; + } + + _makeLegendKeyboardAccessible () { + + if (!this._parent._svgDescription) { + + this._parent.svg().append('desc') + .attr('id', `desc-id-${this._parent.__dcFlag__}`) + .html(`${this._parent.svgDescription()}`); + + this._parent.svg() + .attr('tabindex', '0') + .attr('role', 'img') + .attr('aria-labelledby', `desc-id-${this._parent.__dcFlag__}`); + } + + const tabElements = this.container() + .selectAll('.dc-legend-item-label.dc-tabbable') + .attr('tabindex', 0); + + tabElements + .on('keydown', d3compat.eventHandler((d, event) => { + // trigger only if d is an object + if (event.keyCode === 13 && typeof d === 'object') { + d.chart.legendToggle(d) + } + // special case for space key press - prevent scrolling + if (event.keyCode === 32 && typeof d === 'object') { + d.chart.legendToggle(d) + event.preventDefault(); + } + })) + .on('focus', d3compat.eventHandler(d => { + this._parent.legendHighlight(d); + })) + .on('blur', d3compat.eventHandler(d => { + this._parent.legendReset(d); + })); + } +} + +export const htmlLegend = () => new HtmlLegend(); diff --git a/src/charts/legend.js b/src/charts/legend.js new file mode 100644 index 0000000000..6daa0cc601 --- /dev/null +++ b/src/charts/legend.js @@ -0,0 +1,358 @@ +import {pluck, utils} from '../core/utils'; +import {d3compat} from '../core/config'; +import {constants} from '../core/constants'; + +const LABEL_GAP = 2; + +/** + * Legend is a attachable widget that can be added to other dc charts to render horizontal legend + * labels. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * - {@link https://dc-js.github.io/dc.js/crime/index.html Canadian City Crime Stats} + * @example + * chart.legend(new Legend().x(400).y(10).itemHeight(13).gap(5)) + * @returns {Legend} + */ +export class Legend { + constructor () { + this._parent = undefined; + this._x = 0; + this._y = 0; + this._itemHeight = 12; + this._gap = 5; + this._horizontal = false; + this._legendWidth = 560; + this._itemWidth = 70; + this._autoItemWidth = false; + this._legendText = pluck('name'); + this._maxItems = undefined; + this._highlightSelected = false; + this._keyboardAccessible = false; + + this._g = undefined; + } + + parent (p) { + if (!arguments.length) { + return this._parent; + } + this._parent = p; + return this; + } + + /** + * Set or get x coordinate for legend widget. + * @param {Number} [x=0] + * @returns {Number|Legend} + */ + x (x) { + if (!arguments.length) { + return this._x; + } + this._x = x; + return this; + } + + /** + * Set or get y coordinate for legend widget. + * @param {Number} [y=0] + * @returns {Number|Legend} + */ + y (y) { + if (!arguments.length) { + return this._y; + } + this._y = y; + return this; + } + + /** + * Set or get gap between legend items. + * @param {Number} [gap=5] + * @returns {Number|Legend} + */ + gap (gap) { + if (!arguments.length) { + return this._gap; + } + this._gap = gap; + return this; + } + + /** + * This can be optionally used to enable highlighting legends for the selections/filters for the + * chart. + * @param {String} [highlightSelected] + * @return {String|dc.legend} + **/ + highlightSelected (highlightSelected) { + if (!arguments.length) { + return this._highlightSelected; + } + this._highlightSelected = highlightSelected; + return this; + } + + /** + * Set or get legend item height. + * @param {Number} [itemHeight=12] + * @returns {Number|Legend} + */ + itemHeight (itemHeight) { + if (!arguments.length) { + return this._itemHeight; + } + this._itemHeight = itemHeight; + return this; + } + + /** + * Position legend horizontally instead of vertically. + * @param {Boolean} [horizontal=false] + * @returns {Boolean|Legend} + */ + horizontal (horizontal) { + if (!arguments.length) { + return this._horizontal; + } + this._horizontal = horizontal; + return this; + } + + /** + * Maximum width for horizontal legend. + * @param {Number} [legendWidth=500] + * @returns {Number|Legend} + */ + legendWidth (legendWidth) { + if (!arguments.length) { + return this._legendWidth; + } + this._legendWidth = legendWidth; + return this; + } + + /** + * Legend item width for horizontal legend. + * @param {Number} [itemWidth=70] + * @returns {Number|Legend} + */ + itemWidth (itemWidth) { + if (!arguments.length) { + return this._itemWidth; + } + this._itemWidth = itemWidth; + return this; + } + + /** + * Turn automatic width for legend items on or off. If true, {@link Legend#itemWidth itemWidth} is ignored. + * This setting takes into account the {@link Legend#gap gap}. + * @param {Boolean} [autoItemWidth=false] + * @returns {Boolean|Legend} + */ + autoItemWidth (autoItemWidth) { + if (!arguments.length) { + return this._autoItemWidth; + } + this._autoItemWidth = autoItemWidth; + return this; + } + + /** + * Set or get the legend text function. The legend widget uses this function to render the legend + * text for each item. If no function is specified the legend widget will display the names + * associated with each group. + * @param {Function} [legendText] + * @returns {Function|Legend} + * @example + * // default legendText + * legend.legendText(pluck('name')) + * + * // create numbered legend items + * chart.legend(new Legend().legendText(function(d, i) { return i + '. ' + d.name; })) + * + * // create legend displaying group counts + * chart.legend(new Legend().legendText(function(d) { return d.name + ': ' d.data; })) + */ + legendText (legendText) { + if (!arguments.length) { + return this._legendText; + } + this._legendText = legendText; + return this; + } + + /** + * Maximum number of legend items to display + * @param {Number} [maxItems] + * @return {Legend} + */ + maxItems (maxItems) { + if (!arguments.length) { + return this._maxItems; + } + this._maxItems = utils.isNumber(maxItems) ? maxItems : undefined; + return this; + } + + /** + * If set, individual legend items will be focusable from keyboard and on pressing Enter or Space + * will behave as if clicked on. + * + * If `svgDescription` on the parent chart has not been explicitly set, will also set the default + * SVG description text to the class constructor name, like BarChart or HeatMap, and make the entire + * SVG focusable. + * @param {Boolean} [keyboardAccessible=false] + * @returns {Boolean|Legend} + */ + keyboardAccessible (keyboardAccessible) { + if (!arguments.length) { + return this._keyboardAccessible; + } + this._keyboardAccessible = keyboardAccessible; + return this; + } + + // Implementation methods + + _legendItemHeight () { + return this._gap + this._itemHeight; + } + + _makeLegendKeyboardAccessible () { + + if (!this._parent._svgDescription) { + + this._parent.svg().append('desc') + .attr('id', `desc-id-${this._parent.__dcFlag__}`) + .html(`${this._parent.svgDescription()}`); + + this._parent.svg() + .attr('tabindex', '0') + .attr('role', 'img') + .attr('aria-labelledby', `desc-id-${this._parent.__dcFlag__}`); + } + + const tabElements = this._parent.svg() + .selectAll('.dc-legend .dc-tabbable') + .attr('tabindex', 0); + + tabElements + .on('keydown', d3compat.eventHandler((d, event) => { + // trigger only if d is an object + if (event.keyCode === 13 && typeof d === 'object') { + d.chart.legendToggle(d) + } + // special case for space key press - prevent scrolling + if (event.keyCode === 32 && typeof d === 'object') { + d.chart.legendToggle(d) + event.preventDefault(); + } + })) + .on('focus', d3compat.eventHandler(d => { + this._parent.legendHighlight(d); + })) + .on('blur', d3compat.eventHandler(d => { + this._parent.legendReset(d); + })); + } + + render () { + this._parent.svg().select('g.dc-legend').remove(); + this._g = this._parent.svg().append('g') + .attr('class', 'dc-legend') + .attr('transform', `translate(${this._x},${this._y})`); + let legendables = this._parent.legendables(); + const filters = this._parent.filters(); + + if (this._maxItems !== undefined) { + legendables = legendables.slice(0, this._maxItems); + } + + const itemEnter = this._g.selectAll('g.dc-legend-item') + .data(legendables) + .enter() + .append('g') + .attr('class', 'dc-legend-item') + .on('mouseover', d3compat.eventHandler(d => { + this._parent.legendHighlight(d); + })) + .on('mouseout', d3compat.eventHandler(d => { + this._parent.legendReset(d); + })) + .on('click', d3compat.eventHandler(d => { + d.chart.legendToggle(d); + })); + + if (this._highlightSelected) { + itemEnter.classed(constants.SELECTED_CLASS, + d => filters.indexOf(d.name) !== -1); + } + + + this._g.selectAll('g.dc-legend-item') + .classed('fadeout', d => d.chart.isLegendableHidden(d)); + + if (legendables.some(pluck('dashstyle'))) { + itemEnter + .append('line') + .attr('x1', 0) + .attr('y1', this._itemHeight / 2) + .attr('x2', this._itemHeight) + .attr('y2', this._itemHeight / 2) + .attr('stroke-width', 2) + .attr('stroke-dasharray', pluck('dashstyle')) + .attr('stroke', pluck('color')); + } else { + itemEnter + .append('rect') + .attr('width', this._itemHeight) + .attr('height', this._itemHeight) + .attr('fill', d => d ? d.color : 'blue'); + } + + { + const self = this; + + itemEnter.append('text') + .text(self._legendText) + .classed('dc-tabbable', this._keyboardAccessible) + .attr('x', self._itemHeight + LABEL_GAP) + .attr('y', function () { + return self._itemHeight / 2 + (this.clientHeight ? this.clientHeight : 13) / 2 - 2; + }); + + if (this._keyboardAccessible) { + this._makeLegendKeyboardAccessible(); + } + } + + let cumulativeLegendTextWidth = 0; + let row = 0; + + { + const self = this; + + itemEnter.attr('transform', function (d, i) { + if (self._horizontal) { + const itemWidth = self._autoItemWidth === true ? this.getBBox().width + self._gap : self._itemWidth; + if ((cumulativeLegendTextWidth + itemWidth) > self._legendWidth && cumulativeLegendTextWidth > 0) { + ++row; + cumulativeLegendTextWidth = 0; + } + const translateBy = `translate(${cumulativeLegendTextWidth},${row * self._legendItemHeight()})`; + cumulativeLegendTextWidth += itemWidth; + return translateBy; + } else { + return `translate(0,${i * self._legendItemHeight()})`; + } + }); + } + } + +} + +export const legend = () => new Legend(); diff --git a/src/charts/line-chart.js b/src/charts/line-chart.js new file mode 100644 index 0000000000..dfcf05b53b --- /dev/null +++ b/src/charts/line-chart.js @@ -0,0 +1,601 @@ +import { + area, + curveBasis, + curveBasisClosed, + curveBasisOpen, + curveBundle, + curveCardinal, + curveCardinalClosed, + curveCardinalOpen, + curveLinear, + curveLinearClosed, + curveMonotoneX, + curveStep, + curveStepAfter, + curveStepBefore, + line +} from 'd3-shape'; +import {select} from 'd3-selection'; + +import {logger} from '../core/logger'; +import {pluck, utils} from '../core/utils'; +import {StackMixin} from '../base/stack-mixin'; +import {transition} from '../core/core'; + +const DEFAULT_DOT_RADIUS = 5; +const TOOLTIP_G_CLASS = 'dc-tooltip'; +const DOT_CIRCLE_CLASS = 'dot'; +const Y_AXIS_REF_LINE_CLASS = 'yRef'; +const X_AXIS_REF_LINE_CLASS = 'xRef'; +const DEFAULT_DOT_OPACITY = 1e-6; +const LABEL_PADDING = 3; + +/** + * Concrete line/area chart implementation. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * - {@link https://dc-js.github.io/dc.js/crime/index.html Canadian City Crime Stats} + * @mixes StackMixin + * @mixes CoordinateGridMixin + */ +export class LineChart extends StackMixin { + /** + * Create a Line Chart. + * @example + * // create a line chart under #chart-container1 element using the default global chart group + * var chart1 = new LineChart('#chart-container1'); + * // create a line chart under #chart-container2 element using chart group A + * var chart2 = new LineChart('#chart-container2', 'chartGroupA'); + * // create a sub-chart under a composite parent chart + * var chart3 = new LineChart(compositeChart); + * @param {String|node|d3.selection|CompositeChart} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} + * specifying a dom block element such as a div; or a dom element or d3 selection. If the line + * chart is a sub-chart in a {@link CompositeChart Composite Chart} then pass in the parent + * composite chart instance instead. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._renderArea = false; + this._dotRadius = DEFAULT_DOT_RADIUS; + this._dataPointRadius = null; + this._dataPointFillOpacity = DEFAULT_DOT_OPACITY; + this._dataPointStrokeOpacity = DEFAULT_DOT_OPACITY; + this._curve = null; + this._interpolate = null; // d3.curveLinear; // deprecated in 3.0 + this._tension = null; // deprecated in 3.0 + this._defined = undefined; + this._dashStyle = undefined; + this._xyTipsOn = true; + + this.transitionDuration(500); + this.transitionDelay(0); + this._rangeBandPadding(1); + + this.label(d => utils.printSingleValue(d.y0 + d.y), false); + + this.anchor(parent, chartGroup); + } + + plotData () { + const chartBody = this.chartBodyG(); + let layersList = chartBody.select('g.stack-list'); + + if (layersList.empty()) { + layersList = chartBody.append('g').attr('class', 'stack-list'); + } + + let layers = layersList.selectAll('g.stack').data(this.data()); + + const layersEnter = layers + .enter() + .append('g') + .attr('class', (d, i) => `stack _${i}`); + + layers = layersEnter.merge(layers); + + this._drawLine(layersEnter, layers); + + this._drawArea(layersEnter, layers); + + this._drawDots(chartBody, layers); + + if (this.renderLabel()) { + this._drawLabels(layers); + } + } + + /** + * Gets or sets the curve factory to use for lines and areas drawn, allowing e.g. step + * functions, splines, and cubic interpolation. Typically you would use one of the interpolator functions + * provided by {@link https://github.com/d3/d3-shape/blob/master/README.md#curves d3 curves}. + * + * Replaces the use of {@link LineChart#interpolate} and {@link LineChart#tension} + * in dc.js < 3.0 + * + * This is passed to + * {@link https://github.com/d3/d3-shape/blob/master/README.md#line_curve line.curve} and + * {@link https://github.com/d3/d3-shape/blob/master/README.md#area_curve area.curve}. + * @example + * // default + * chart + * .curve(d3.curveLinear); + * // Add tension to curves that support it + * chart + * .curve(d3.curveCardinal.tension(0.5)); + * // You can use some specialized variation like + * // https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline + * chart + * .curve(d3.curveCatmullRom.alpha(0.5)); + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#line_curve line.curve} + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#area_curve area.curve} + * @param {d3.curve} [curve=d3.curveLinear] + * @returns {d3.curve|LineChart} + */ + curve (curve) { + if (!arguments.length) { + return this._curve; + } + this._curve = curve; + return this; + } + + /** + * Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step + * functions, splines, and cubic interpolation. + * + * Possible values are: 'linear', 'linear-closed', 'step', 'step-before', 'step-after', 'basis', + * 'basis-open', 'basis-closed', 'bundle', 'cardinal', 'cardinal-open', 'cardinal-closed', and + * 'monotone'. + * + * This function exists for backward compatibility. Use {@link LineChart#curve} + * which is generic and provides more options. + * Value set through `.curve` takes precedence over `.interpolate` and `.tension`. + * @deprecated since version 3.0 use {@link LineChart#curve} instead + * @see {@link LineChart#curve} + * @param {d3.curve} [interpolate=d3.curveLinear] + * @returns {d3.curve|LineChart} + */ + interpolate (interpolate) { + logger.warnOnce('dc.lineChart.interpolate has been deprecated since version 3.0 use dc.lineChart.curve instead'); + if (!arguments.length) { + return this._interpolate; + } + this._interpolate = interpolate; + return this; + } + + /** + * Gets or sets the tension to use for lines drawn, in the range 0 to 1. + * + * Passed to the {@link https://github.com/d3/d3-shape/blob/master/README.md#curves d3 curve function} + * if it provides a `.tension` function. Example: + * {@link https://github.com/d3/d3-shape/blob/master/README.md#curveCardinal_tension curveCardinal.tension}. + * + * This function exists for backward compatibility. Use {@link LineChart#curve} + * which is generic and provides more options. + * Value set through `.curve` takes precedence over `.interpolate` and `.tension`. + * @deprecated since version 3.0 use {@link LineChart#curve} instead + * @see {@link LineChart#curve} + * @param {Number} [tension=0] + * @returns {Number|LineChart} + */ + tension (tension) { + logger.warnOnce('dc.lineChart.tension has been deprecated since version 3.0 use dc.lineChart.curve instead'); + if (!arguments.length) { + return this._tension; + } + this._tension = tension; + return this; + } + + /** + * Gets or sets a function that will determine discontinuities in the line which should be + * skipped: the path will be broken into separate subpaths if some points are undefined. + * This function is passed to + * {@link https://github.com/d3/d3-shape/blob/master/README.md#line_defined line.defined} + * + * Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write + * custom reduce functions to get this to work, depending on your data. See + * {@link https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248 this GitHub comment} + * for more details and an example. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#line_defined line.defined} + * @param {Function} [defined] + * @returns {Function|LineChart} + */ + defined (defined) { + if (!arguments.length) { + return this._defined; + } + this._defined = defined; + return this; + } + + /** + * Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty + * array (solid line). + * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray stroke-dasharray} + * @example + * // create a Dash Dot Dot Dot + * chart.dashStyle([3,1,1,1]); + * @param {Array} [dashStyle=[]] + * @returns {Array|LineChart} + */ + dashStyle (dashStyle) { + if (!arguments.length) { + return this._dashStyle; + } + this._dashStyle = dashStyle; + return this; + } + + /** + * Get or set render area flag. If the flag is set to true then the chart will render the area + * beneath each line and the line chart effectively becomes an area chart. + * @param {Boolean} [renderArea=false] + * @returns {Boolean|LineChart} + */ + renderArea (renderArea) { + if (!arguments.length) { + return this._renderArea; + } + this._renderArea = renderArea; + return this; + } + + _getColor (d, i) { + return this.getColor.call(d, d.values, i); + } + + // To keep it backward compatible, this covers multiple cases + // See https://github.com/dc-js/dc.js/issues/1376 + // It will be removed when interpolate and tension are removed. + _getCurveFactory () { + let curve = null; + + // _curve takes precedence + if (this._curve) { + return this._curve; + } + + // Approximate the D3v3 behavior + if (typeof this._interpolate === 'function') { + curve = this._interpolate; + } else { + // If _interpolate is string + const mapping = { + 'linear': curveLinear, + 'linear-closed': curveLinearClosed, + 'step': curveStep, + 'step-before': curveStepBefore, + 'step-after': curveStepAfter, + 'basis': curveBasis, + 'basis-open': curveBasisOpen, + 'basis-closed': curveBasisClosed, + 'bundle': curveBundle, + 'cardinal': curveCardinal, + 'cardinal-open': curveCardinalOpen, + 'cardinal-closed': curveCardinalClosed, + 'monotone': curveMonotoneX + }; + curve = mapping[this._interpolate]; + } + + // Default value + if (!curve) { + curve = curveLinear; + } + + if (this._tension !== null) { + if (typeof curve.tension !== 'function') { + logger.warn('tension was specified but the curve/interpolate does not support it.'); + } else { + curve = curve.tension(this._tension); + } + } + return curve; + } + + _drawLine (layersEnter, layers) { + const _line = line() + .x(d => this.x()(d.x)) + .y(d => this.y()(d.y + d.y0)) + .curve(this._getCurveFactory()); + if (this._defined) { + _line.defined(this._defined); + } + + const path = layersEnter.append('path') + .attr('class', 'line') + .attr('stroke', (d, i) => this._getColor(d, i)); + if (this._dashStyle) { + path.attr('stroke-dasharray', this._dashStyle); + } + + transition(layers.select('path.line'), this.transitionDuration(), this.transitionDelay()) + //.ease('linear') + .attr('stroke', (d, i) => this._getColor(d, i)) + .attr('d', d => this._safeD(_line(d.values))); + } + + _drawArea (layersEnter, layers) { + if (this._renderArea) { + const _area = area() + .x(d => this.x()(d.x)) + .y1(d => this.y()(d.y + d.y0)) + .y0(d => this.y()(d.y0)) + .curve(this._getCurveFactory()); + if (this._defined) { + _area.defined(this._defined); + } + + layersEnter.append('path') + .attr('class', 'area') + .attr('fill', (d, i) => this._getColor(d, i)) + .attr('d', d => this._safeD(_area(d.values))); + + transition(layers.select('path.area'), this.transitionDuration(), this.transitionDelay()) + //.ease('linear') + .attr('fill', (d, i) => this._getColor(d, i)) + .attr('d', d => this._safeD(_area(d.values))); + } + } + + _safeD (d) { + return (!d || d.indexOf('NaN') >= 0) ? 'M0,0' : d; + } + + _drawDots (chartBody, layers) { + if (this.xyTipsOn() === 'always' || (!(this.brushOn() || this.parentBrushOn()) && this.xyTipsOn())) { + const tooltipListClass = `${TOOLTIP_G_CLASS}-list`; + let tooltips = chartBody.select(`g.${tooltipListClass}`); + + if (tooltips.empty()) { + tooltips = chartBody.append('g').attr('class', tooltipListClass); + } + + layers.each((data, layerIndex) => { + let points = data.values; + if (this._defined) { + points = points.filter(this._defined); + } + + let g = tooltips.select(`g.${TOOLTIP_G_CLASS}._${layerIndex}`); + if (g.empty()) { + g = tooltips.append('g').attr('class', `${TOOLTIP_G_CLASS} _${layerIndex}`); + } + + this._createRefLines(g); + + const dots = g.selectAll(`circle.${DOT_CIRCLE_CLASS}`) + .data(points, pluck('x')); + + const chart = this; + const dotsEnterModify = dots + .enter() + .append('circle') + .attr('class', DOT_CIRCLE_CLASS) + .classed('dc-tabbable', this._keyboardAccessible) + .attr('cx', d => utils.safeNumber(this.x()(d.x))) + .attr('cy', d => utils.safeNumber(this.y()(d.y + d.y0))) + .attr('r', this._getDotRadius()) + .style('fill-opacity', this._dataPointFillOpacity) + .style('stroke-opacity', this._dataPointStrokeOpacity) + .attr('fill', this.getColor) + .attr('stroke', this.getColor) + .on('mousemove', function () { + const dot = select(this); + chart._showDot(dot); + chart._showRefLines(dot, g); + }) + .on('mouseout', function () { + const dot = select(this); + chart._hideDot(dot); + chart._hideRefLines(g); + }) + .merge(dots); + + // special case for on-focus for line chart and its dots + if (this._keyboardAccessible) { + + this._svg.selectAll('.dc-tabbable') + .attr('tabindex', 0) + .on('focus', function () { + const dot = select(this); + chart._showDot(dot); + chart._showRefLines(dot, g); + }) + .on('blur', function () { + const dot = select(this); + chart._hideDot(dot); + chart._hideRefLines(g); + }); + } + + dotsEnterModify.call(dot => this._doRenderTitle(dot, data)); + + transition(dotsEnterModify, this.transitionDuration()) + .attr('cx', d => utils.safeNumber(this.x()(d.x))) + .attr('cy', d => utils.safeNumber(this.y()(d.y + d.y0))) + .attr('fill', this.getColor); + + dots.exit().remove(); + }); + } + } + + _drawLabels (layers) { + const chart = this; + layers.each(function (data, layerIndex) { + const layer = select(this); + const labels = layer.selectAll('text.lineLabel') + .data(data.values, pluck('x')); + + const labelsEnterModify = labels + .enter() + .append('text') + .attr('class', 'lineLabel') + .attr('text-anchor', 'middle') + .merge(labels); + + transition(labelsEnterModify, chart.transitionDuration()) + .attr('x', d => utils.safeNumber(chart.x()(d.x))) + .attr('y', d => { + const y = chart.y()(d.y + d.y0) - LABEL_PADDING; + return utils.safeNumber(y); + }) + .text(d => chart.label()(d)); + + transition(labels.exit(), chart.transitionDuration()) + .attr('height', 0) + .remove(); + }); + } + + _createRefLines (g) { + const yRefLine = g.select(`path.${Y_AXIS_REF_LINE_CLASS}`).empty() ? + g.append('path').attr('class', Y_AXIS_REF_LINE_CLASS) : g.select(`path.${Y_AXIS_REF_LINE_CLASS}`); + yRefLine.style('display', 'none').attr('stroke-dasharray', '5,5'); + + const xRefLine = g.select(`path.${X_AXIS_REF_LINE_CLASS}`).empty() ? + g.append('path').attr('class', X_AXIS_REF_LINE_CLASS) : g.select(`path.${X_AXIS_REF_LINE_CLASS}`); + xRefLine.style('display', 'none').attr('stroke-dasharray', '5,5'); + } + + _showDot (dot) { + dot.style('fill-opacity', 0.8); + dot.style('stroke-opacity', 0.8); + dot.attr('r', this._dotRadius); + return dot; + } + + _showRefLines (dot, g) { + const x = dot.attr('cx'); + const y = dot.attr('cy'); + const yAxisX = (this._yAxisX() - this.margins().left); + const yAxisRefPathD = `M${yAxisX} ${y}L${x} ${y}`; + const xAxisRefPathD = `M${x} ${this.yAxisHeight()}L${x} ${y}`; + g.select(`path.${Y_AXIS_REF_LINE_CLASS}`).style('display', '').attr('d', yAxisRefPathD); + g.select(`path.${X_AXIS_REF_LINE_CLASS}`).style('display', '').attr('d', xAxisRefPathD); + } + + _getDotRadius () { + return this._dataPointRadius || this._dotRadius; + } + + _hideDot (dot) { + dot.style('fill-opacity', this._dataPointFillOpacity) + .style('stroke-opacity', this._dataPointStrokeOpacity) + .attr('r', this._getDotRadius()); + } + + _hideRefLines (g) { + g.select(`path.${Y_AXIS_REF_LINE_CLASS}`).style('display', 'none'); + g.select(`path.${X_AXIS_REF_LINE_CLASS}`).style('display', 'none'); + } + + _doRenderTitle (dot, d) { + if (this.renderTitle()) { + dot.select('title').remove(); + dot.append('title').text(pluck('data', this.title(d.name))); + } + } + + /** + * Turn on/off the mouseover behavior of an individual data point which renders a circle and x/y axis + * dashed lines back to each respective axis. This is ignored if the chart + * {@link CoordinateGridMixin#brushOn brush} is on + * @param {Boolean} [xyTipsOn=false] + * @returns {Boolean|LineChart} + */ + xyTipsOn (xyTipsOn) { + if (!arguments.length) { + return this._xyTipsOn; + } + this._xyTipsOn = xyTipsOn; + return this; + } + + /** + * Get or set the radius (in px) for dots displayed on the data points. + * @param {Number} [dotRadius=5] + * @returns {Number|LineChart} + */ + dotRadius (dotRadius) { + if (!arguments.length) { + return this._dotRadius; + } + this._dotRadius = dotRadius; + return this; + } + + /** + * Always show individual dots for each datapoint. + * + * If `options` is falsy, it disables data point rendering. If no `options` are provided, the + * current `options` values are instead returned. + * @example + * chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.0}) + * @param {{fillOpacity: Number, strokeOpacity: Number, radius: Number}} [options={fillOpacity: 0.8, strokeOpacity: 0.0, radius: 2}] + * @returns {{fillOpacity: Number, strokeOpacity: Number, radius: Number}|LineChart} + */ + renderDataPoints (options) { + if (!arguments.length) { + return { + fillOpacity: this._dataPointFillOpacity, + strokeOpacity: this._dataPointStrokeOpacity, + radius: this._dataPointRadius + }; + } else if (!options) { + this._dataPointFillOpacity = DEFAULT_DOT_OPACITY; + this._dataPointStrokeOpacity = DEFAULT_DOT_OPACITY; + this._dataPointRadius = null; + } else { + this._dataPointFillOpacity = options.fillOpacity || 0.8; + this._dataPointStrokeOpacity = options.strokeOpacity || 0.0; + this._dataPointRadius = options.radius || 2; + } + return this; + } + + _colorFilter (color, dashstyle, inv) { + return function () { + const item = select(this); + const match = (item.attr('stroke') === color && + item.attr('stroke-dasharray') === ((dashstyle instanceof Array) ? + dashstyle.join(',') : null)) || item.attr('fill') === color; + return inv ? !match : match; + }; + } + + legendHighlight (d) { + if (!this.isLegendableHidden(d)) { + this.g().selectAll('path.line, path.area') + .classed('highlight', this._colorFilter(d.color, d.dashstyle)) + .classed('fadeout', this._colorFilter(d.color, d.dashstyle, true)); + } + } + + legendReset () { + this.g().selectAll('path.line, path.area') + .classed('highlight', false) + .classed('fadeout', false); + } + + legendables () { + const legendables = super.legendables(); + if (!this._dashStyle) { + return legendables; + } + return legendables.map(l => { + l.dashstyle = this._dashStyle; + return l; + }); + } +} + +export const lineChart = (parent, chartGroup) => new LineChart(parent, chartGroup); diff --git a/src/charts/number-display.js b/src/charts/number-display.js new file mode 100644 index 0000000000..713199859d --- /dev/null +++ b/src/charts/number-display.js @@ -0,0 +1,205 @@ +import {format} from 'd3-format'; +import {easeQuad} from 'd3-ease'; +import {interpolateNumber} from 'd3-interpolate'; + +import {BaseMixin} from '../base/base-mixin'; + +const SPAN_CLASS = 'number-display'; + +/** + * A display of a single numeric value. + * + * Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and + * a valueAccessor that returns a single value. + * + * If the group is a {@link https://github.com/crossfilter/crossfilter/wiki/API-Reference#crossfilter_groupAll groupAll} + * then its `.value()` will be displayed. This is the recommended usage. + * + * However, if it is given an ordinary group, the `numberDisplay` will show the last bin's value, after + * sorting with the {@link https://dc-js.github.io/dc.js/docs/html/dc.baseMixin.html#ordering__anchor ordering} + * function. `numberDisplay` defaults the `ordering` function to sorting by value, so this will display + * the largest value if the values are numeric. + * @mixes BaseMixin + */ +export class NumberDisplay extends BaseMixin { + /** + * Create a Number Display widget. + * + * @example + * // create a number display under #chart-container1 element using the default global chart group + * var display1 = new NumberDisplay('#chart-container1'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._formatNumber = format('.2s'); + this._html = {one: '', some: '', none: ''}; + this._lastValue = undefined; + this._ariaLiveRegion = false; + + // dimension not required + this._mandatoryAttributes(['group']); + + // default to ordering by value, to emulate old group.top(1) behavior when multiple groups + this.ordering(kv => kv.value); + + this.data(group => { + const valObj = group.value ? group.value() : this._maxBin(group.all()); + return this.valueAccessor()(valObj); + }); + + this.transitionDuration(250); // good default + this.transitionDelay(0); + + this.anchor(parent, chartGroup); + } + + /** + * Gets or sets an optional object specifying HTML templates to use depending on the number + * displayed. The text `%number` will be replaced with the current value. + * - one: HTML template to use if the number is 1 + * - zero: HTML template to use if the number is 0 + * - some: HTML template to use otherwise + * @example + * numberWidget.html({ + * one:'%number record', + * some:'%number records', + * none:'no records'}) + * @param {{one:String, some:String, none:String}} [html={one: '', some: '', none: ''}] + * @returns {{one:String, some:String, none:String}|NumberDisplay} + */ + html (html) { + if (!arguments.length) { + return this._html; + } + if (html.none) { + this._html.none = html.none;//if none available + } else if (html.one) { + this._html.none = html.one;//if none not available use one + } else if (html.some) { + this._html.none = html.some;//if none and one not available use some + } + if (html.one) { + this._html.one = html.one;//if one available + } else if (html.some) { + this._html.one = html.some;//if one not available use some + } + if (html.some) { + this._html.some = html.some;//if some available + } else if (html.one) { + this._html.some = html.one;//if some not available use one + } + return this; + } + + /** + * Calculate and return the underlying value of the display. + * @returns {Number} + */ + value () { + return this.data(); + } + + _maxBin (all) { + if (!all.length) { + return null; + } + const sorted = this._computeOrderedGroups(all); + return sorted[sorted.length - 1]; + } + + _doRender () { + const newValue = this.value(); + let span = this.selectAll(`.${SPAN_CLASS}`); + + if (span.empty()) { + span = span.data([0]) + .enter() + .append('span') + .attr('class', SPAN_CLASS) + .classed('dc-tabbable', this._keyboardAccessible) + .merge(span); + + if (this._keyboardAccessible) { + span.attr('tabindex', '0'); + } + + if (this._ariaLiveRegion) { + this.transitionDuration(0); + span.attr('aria-live', 'polite'); + } + } + + { + const chart = this; + span.transition() + .duration(chart.transitionDuration()) + .delay(chart.transitionDelay()) + .ease(easeQuad) + .tween('text', function () { + // [XA] don't try and interpolate from Infinity, else this breaks. + const interpStart = isFinite(chart._lastValue) ? chart._lastValue : 0; + const interp = interpolateNumber(interpStart || 0, newValue); + chart._lastValue = newValue; + + // need to save it in D3v4 + const node = this; + return t => { + let html = null; + const num = chart.formatNumber()(interp(t)); + if (newValue === 0 && (chart._html.none !== '')) { + html = chart._html.none; + } else if (newValue === 1 && (chart._html.one !== '')) { + html = chart._html.one; + } else if (chart._html.some !== '') { + html = chart._html.some; + } + node.innerHTML = html ? html.replace('%number', num) : num; + }; + }); + } + } + + _doRedraw () { + return this._doRender(); + } + + /** + * Get or set a function to format the value for the display. + * @see {@link https://github.com/d3/d3-format/blob/master/README.md#format d3.format} + * @param {Function} [formatter=d3.format('.2s')] + * @returns {Function|NumberDisplay} + */ + formatNumber (formatter) { + if (!arguments.length) { + return this._formatNumber; + } + this._formatNumber = formatter; + return this; + } + + /** + * If set, the Number Display widget will have its aria-live attribute set to 'polite' which will + * notify screen readers when the widget changes its value. Note that setting this method will also + * disable the default transition between the old and the new values. This is to avoid change + * notifications spoken out before the new value finishes re-drawing. It is also advisable to check + * if the widget has appropriately set accessibility description or label. + * @param {Boolean} [ariaLiveRegion=false] + * @returns {Boolean|NumberDisplay} + */ + ariaLiveRegion (ariaLiveRegion) { + if (!arguments.length) { + return this._ariaLiveRegion; + } + this._ariaLiveRegion = ariaLiveRegion; + return this; + } + +} + +export const numberDisplay = (parent, chartGroup) => new NumberDisplay(parent, chartGroup); diff --git a/src/charts/pie-chart.js b/src/charts/pie-chart.js new file mode 100644 index 0000000000..28273c21d1 --- /dev/null +++ b/src/charts/pie-chart.js @@ -0,0 +1,582 @@ +import {min, sum} from 'd3-array'; +import {arc, pie} from 'd3-shape'; +import {select} from 'd3-selection'; +import {interpolate} from 'd3-interpolate'; + +import {CapMixin} from '../base/cap-mixin'; +import {ColorMixin} from '../base/color-mixin'; +import {BaseMixin} from '../base/base-mixin'; +import {transition} from '../core/core'; +import {d3compat} from '../core/config'; + +const DEFAULT_MIN_ANGLE_FOR_LABEL = 0.5; + +/** + * The pie chart implementation is usually used to visualize a small categorical distribution. The pie + * chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each + * slice relative to the sum of all values. Slices are ordered by {@link BaseMixin#ordering ordering} + * which defaults to sorting by key. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * @mixes CapMixin + * @mixes ColorMixin + * @mixes BaseMixin + */ +export class PieChart extends CapMixin(ColorMixin(BaseMixin)) { + /** + * Create a Pie Chart + * + * @example + * // create a pie chart under #chart-container1 element using the default global chart group + * var chart1 = new PieChart('#chart-container1'); + * // create a pie chart under #chart-container2 element using chart group A + * var chart2 = new PieChart('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._sliceCssClass = 'pie-slice'; + this._labelCssClass = 'pie-label'; + this._sliceGroupCssClass = 'pie-slice-group'; + this._labelGroupCssClass = 'pie-label-group'; + this._emptyCssClass = 'empty-chart'; + this._emptyTitle = 'empty'; + + this._radius = undefined; + this._givenRadius = undefined; // specified radius, if any + this._innerRadius = 0; + this._externalRadiusPadding = 0; + + + this._g = undefined; + this._cx = undefined; + this._cy = undefined; + this._minAngleForLabel = DEFAULT_MIN_ANGLE_FOR_LABEL; + this._externalLabelRadius = undefined; + this._drawPaths = false; + + this.colorAccessor(d => this.cappedKeyAccessor(d)); + + this.title(d => `${this.cappedKeyAccessor(d)}: ${this.cappedValueAccessor(d)}`); + + this.label(d => this.cappedKeyAccessor(d)); + this.renderLabel(true); + + this.transitionDuration(350); + this.transitionDelay(0); + + this.anchor(parent, chartGroup); + } + + /** + * Get or set the maximum number of slices the pie chart will generate. The top slices are determined by + * value from high to low. Other slices exceeding the cap will be rolled up into one single *Others* slice. + * @param {Number} [cap] + * @returns {Number|PieChart} + */ + slicesCap (cap) { + return this.cap(cap) + } + + _doRender () { + this.resetSvg(); + + this._g = this.svg() + .append('g') + .attr('transform', `translate(${this.cx()},${this.cy()})`); + + this._g.append('g').attr('class', this._sliceGroupCssClass); + this._g.append('g').attr('class', this._labelGroupCssClass); + + this._drawChart(); + + return this; + } + + _drawChart () { + // set radius from chart size if none given, or if given radius is too large + const maxRadius = min([this.width(), this.height()]) / 2; + this._radius = this._givenRadius && this._givenRadius < maxRadius ? this._givenRadius : maxRadius; + + const arcs = this._buildArcs(); + + const pieLayout = this._pieLayout(); + let pieData; + // if we have data... + if (sum(this.data(), d => this.cappedValueAccessor(d))) { + pieData = pieLayout(this.data()); + this._g.classed(this._emptyCssClass, false); + } else { + // otherwise we'd be getting NaNs, so override + // note: abuse others for its ignoring the value accessor + pieData = pieLayout([{key: this._emptyTitle, value: 1, others: [this._emptyTitle]}]); + this._g.classed(this._emptyCssClass, true); + } + + if (this._g) { + const slices = this._g.select(`g.${this._sliceGroupCssClass}`) + .selectAll(`g.${this._sliceCssClass}`) + .data(pieData); + + const labels = this._g.select(`g.${this._labelGroupCssClass}`) + .selectAll(`text.${this._labelCssClass}`) + .data(pieData); + + this._removeElements(slices, labels); + + this._createElements(slices, labels, arcs, pieData); + + this._updateElements(pieData, arcs); + + this._highlightFilter(); + + transition(this._g, this.transitionDuration(), this.transitionDelay()) + .attr('transform', `translate(${this.cx()},${this.cy()})`); + } + } + + _createElements (slices, labels, arcs, pieData) { + const slicesEnter = this._createSliceNodes(slices); + + this._createSlicePath(slicesEnter, arcs); + + this._createTitles(slicesEnter); + + this._createLabels(labels, pieData, arcs); + } + + _createSliceNodes (slices) { + return slices + .enter() + .append('g') + .attr('class', (d, i) => `${this._sliceCssClass} _${i}`) + .classed('dc-tabbable', this._keyboardAccessible); + } + + _createSlicePath (slicesEnter, arcs) { + const slicePath = slicesEnter.append('path') + .attr('fill', (d, i) => this._fill(d, i)) + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .attr('d', (d, i) => this._safeArc(d, i, arcs)); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(this._onClick); + } + + const tranNodes = transition(slicePath, this.transitionDuration(), this.transitionDelay()); + if (tranNodes.attrTween) { + const chart = this; + tranNodes.attrTween('d', function (d) { + return chart._tweenPie(d, this); + }); + } + } + + _createTitles (slicesEnter) { + if (this.renderTitle()) { + slicesEnter.append('title').text(d => this.title()(d.data)); + } + } + + _applyLabelText (labels) { + labels + .text(d => { + const data = d.data; + if ((this._sliceHasNoData(data) || this._sliceTooSmall(d)) && !this._isSelectedSlice(d)) { + return ''; + } + return this.label()(d.data); + }); + } + + _positionLabels (labels, arcs) { + this._applyLabelText(labels); + transition(labels, this.transitionDuration(), this.transitionDelay()) + .attr('transform', d => this._labelPosition(d, arcs)) + .attr('text-anchor', 'middle'); + } + + _highlightSlice (i, whether) { + this.select(`g.pie-slice._${i}`) + .classed('highlight', whether); + } + + _createLabels (labels, pieData, arcs) { + if (this.renderLabel()) { + const labelsEnter = labels + .enter() + .append('text') + .attr('class', (d, i) => { + let classes = `${this._sliceCssClass} ${this._labelCssClass} _${i}`; + if (this._externalLabelRadius) { + classes += ' external'; + } + return classes; + }) + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .on('mouseover', d3compat.eventHandler(d => { + this._highlightSlice(d.index, true); + })) + .on('mouseout', d3compat.eventHandler(d => { + this._highlightSlice(d.index, false); + })); + this._positionLabels(labelsEnter, arcs); + if (this._externalLabelRadius && this._drawPaths) { + this._updateLabelPaths(pieData, arcs); + } + } + } + + _updateLabelPaths (pieData, arcs) { + let polyline = this._g.selectAll(`polyline.${this._sliceCssClass}`) + .data(pieData); + + polyline.exit().remove(); + + polyline = polyline + .enter() + .append('polyline') + .attr('class', (d, i) => `pie-path _${i} ${this._sliceCssClass}`) + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .on('mouseover', d3compat.eventHandler(d => { + this._highlightSlice(d.index, true); + })) + .on('mouseout', d3compat.eventHandler(d => { + this._highlightSlice(d.index, false); + })) + .merge(polyline); + + const arc2 = arc() + .outerRadius(this._radius - this._externalRadiusPadding + this._externalLabelRadius) + .innerRadius(this._radius - this._externalRadiusPadding); + const tranNodes = transition(polyline, this.transitionDuration(), this.transitionDelay()); + // this is one rare case where d3.selection differs from d3.transition + if (tranNodes.attrTween) { + tranNodes + .attrTween('points', function (d) { + let current = this._current || d; + current = {startAngle: current.startAngle, endAngle: current.endAngle}; + const _interpolate = interpolate(current, d); + this._current = _interpolate(0); + return t => { + const d2 = _interpolate(t); + return [arcs.centroid(d2), arc2.centroid(d2)]; + }; + }); + } else { + tranNodes.attr('points', d => [arcs.centroid(d), arc2.centroid(d)]); + } + tranNodes.style('visibility', d => d.endAngle - d.startAngle < 0.0001 ? 'hidden' : 'visible'); + + } + + _updateElements (pieData, arcs) { + this._updateSlicePaths(pieData, arcs); + this._updateLabels(pieData, arcs); + this._updateTitles(pieData); + } + + _updateSlicePaths (pieData, arcs) { + const slicePaths = this._g.selectAll(`g.${this._sliceCssClass}`) + .data(pieData) + .select('path') + .attr('d', (d, i) => this._safeArc(d, i, arcs)); + const tranNodes = transition(slicePaths, this.transitionDuration(), this.transitionDelay()); + if (tranNodes.attrTween) { + const chart = this; + tranNodes.attrTween('d', function (d) { + return chart._tweenPie(d, this); + }); + } + tranNodes.attr('fill', (d, i) => this._fill(d, i)); + } + + _updateLabels (pieData, arcs) { + if (this.renderLabel()) { + const labels = this._g.selectAll(`text.${this._labelCssClass}`) + .data(pieData); + this._positionLabels(labels, arcs); + if (this._externalLabelRadius && this._drawPaths) { + this._updateLabelPaths(pieData, arcs); + } + } + } + + _updateTitles (pieData) { + if (this.renderTitle()) { + this._g.selectAll(`g.${this._sliceCssClass}`) + .data(pieData) + .select('title') + .text(d => this.title()(d.data)); + } + } + + _removeElements (slices, labels) { + slices.exit().remove(); + labels.exit().remove(); + } + + _highlightFilter () { + const chart = this; + if (this.hasFilter()) { + this.selectAll(`g.${this._sliceCssClass}`).each(function (d) { + if (chart._isSelectedSlice(d)) { + chart.highlightSelected(this); + } else { + chart.fadeDeselected(this); + } + }); + } else { + this.selectAll(`g.${this._sliceCssClass}`).each(function () { + chart.resetHighlight(this); + }); + } + } + + /** + * Get or set the external radius padding of the pie chart. This will force the radius of the + * pie chart to become smaller or larger depending on the value. + * @param {Number} [externalRadiusPadding=0] + * @returns {Number|PieChart} + */ + externalRadiusPadding (externalRadiusPadding) { + if (!arguments.length) { + return this._externalRadiusPadding; + } + this._externalRadiusPadding = externalRadiusPadding; + return this; + } + + /** + * Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the + * pie chart will be rendered as a doughnut chart. + * @param {Number} [innerRadius=0] + * @returns {Number|PieChart} + */ + innerRadius (innerRadius) { + if (!arguments.length) { + return this._innerRadius; + } + this._innerRadius = innerRadius; + return this; + } + + /** + * Get or set the outer radius. If the radius is not set, it will be half of the minimum of the + * chart width and height. + * @param {Number} [radius] + * @returns {Number|PieChart} + */ + radius (radius) { + if (!arguments.length) { + return this._givenRadius; + } + this._givenRadius = radius; + return this; + } + + /** + * Get or set center x coordinate position. Default is center of svg. + * @param {Number} [cx] + * @returns {Number|PieChart} + */ + cx (cx) { + if (!arguments.length) { + return (this._cx || this.width() / 2); + } + this._cx = cx; + return this; + } + + /** + * Get or set center y coordinate position. Default is center of svg. + * @param {Number} [cy] + * @returns {Number|PieChart} + */ + cy (cy) { + if (!arguments.length) { + return (this._cy || this.height() / 2); + } + this._cy = cy; + return this; + } + + _buildArcs () { + return arc() + .outerRadius(this._radius - this._externalRadiusPadding) + .innerRadius(this._innerRadius); + } + + _isSelectedSlice (d) { + return this.hasFilter(this.cappedKeyAccessor(d.data)); + } + + _doRedraw () { + this._drawChart(); + return this; + } + + /** + * Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not + * display a slice label. + * @param {Number} [minAngleForLabel=0.5] + * @returns {Number|PieChart} + */ + minAngleForLabel (minAngleForLabel) { + if (!arguments.length) { + return this._minAngleForLabel; + } + this._minAngleForLabel = minAngleForLabel; + return this; + } + + _pieLayout () { + return pie().sort(null).value(d => this.cappedValueAccessor(d)); + } + + _sliceTooSmall (d) { + const angle = (d.endAngle - d.startAngle); + return isNaN(angle) || angle < this._minAngleForLabel; + } + + _sliceHasNoData (d) { + return this.cappedValueAccessor(d) === 0; + } + + _isOffCanvas (current) { + return !current || isNaN(current.startAngle) || isNaN(current.endAngle); + } + + _fill (d, i) { + return this.getColor(d.data, i); + } + + _onClick (d) { + if (this._g.attr('class') !== this._emptyCssClass) { + this.onClick(d.data); + } + } + + _safeArc (d, i, _arc) { + let path = _arc(d, i); + if (path.indexOf('NaN') >= 0) { + path = 'M0,0'; + } + return path; + } + + /** + * Title to use for the only slice when there is no data. + * @param {String} [title] + * @returns {String|PieChart} + */ + emptyTitle (title) { + if (arguments.length === 0) { + return this._emptyTitle; + } + this._emptyTitle = title; + return this; + } + + /** + * Position slice labels offset from the outer edge of the chart. + * + * The argument specifies the extra radius to be added for slice labels. + * @param {Number} [externalLabelRadius] + * @returns {Number|PieChart} + */ + externalLabels (externalLabelRadius) { + if (arguments.length === 0) { + return this._externalLabelRadius; + } else if (externalLabelRadius) { + this._externalLabelRadius = externalLabelRadius; + } else { + this._externalLabelRadius = undefined; + } + + return this; + } + + /** + * Get or set whether to draw lines from pie slices to their labels. + * + * @param {Boolean} [drawPaths] + * @returns {Boolean|PieChart} + */ + drawPaths (drawPaths) { + if (arguments.length === 0) { + return this._drawPaths; + } + this._drawPaths = drawPaths; + return this; + } + + _labelPosition (d, _arc) { + let centroid; + if (this._externalLabelRadius) { + centroid = arc() + .outerRadius(this._radius - this._externalRadiusPadding + this._externalLabelRadius) + .innerRadius(this._radius - this._externalRadiusPadding + this._externalLabelRadius) + .centroid(d); + } else { + centroid = _arc.centroid(d); + } + if (isNaN(centroid[0]) || isNaN(centroid[1])) { + return 'translate(0,0)'; + } else { + return `translate(${centroid})`; + } + } + + legendables () { + return this.data().map((d, i) => { + const legendable = {name: d.key, data: d.value, others: d.others, chart: this}; + legendable.color = this.getColor(d, i); + return legendable; + }); + } + + legendHighlight (d) { + this._highlightSliceFromLegendable(d, true); + } + + legendReset (d) { + this._highlightSliceFromLegendable(d, false); + } + + legendToggle (d) { + this.onClick({key: d.name, others: d.others}); + } + + _highlightSliceFromLegendable (legendable, highlighted) { + this.selectAll('g.pie-slice').each(function (d) { + if (legendable.name === d.data.key) { + select(this).classed('highlight', highlighted); + } + }); + } + + _tweenPie (b, element) { + b.innerRadius = this._innerRadius; + let current = element._current; + if (this._isOffCanvas(current)) { + current = {startAngle: 0, endAngle: 0}; + } else { + // only interpolate startAngle & endAngle, not the whole data object + current = {startAngle: current.startAngle, endAngle: current.endAngle}; + } + const i = interpolate(current, b); + element._current = i(0); + return t => this._safeArc(i(t), 0, this._buildArcs()); + } + + +} + +export const pieChart = (parent, chartGroup) => new PieChart(parent, chartGroup); diff --git a/src/charts/row-chart.js b/src/charts/row-chart.js new file mode 100644 index 0000000000..7043be1212 --- /dev/null +++ b/src/charts/row-chart.js @@ -0,0 +1,398 @@ +import {extent} from 'd3-array'; +import {axisBottom} from 'd3-axis'; +import {scaleLinear} from 'd3-scale'; + +import {CapMixin} from '../base/cap-mixin'; +import {MarginMixin} from '../base/margin-mixin'; +import {ColorMixin} from '../base/color-mixin'; +import {transition} from '../core/core'; +import {d3compat} from '../core/config'; + +/** + * Concrete row chart implementation. + * + * Examples: + * - {@link https://dc-js.github.io/dc.js/ Nasdaq 100 Index} + * @mixes CapMixin + * @mixes MarginMixin + * @mixes ColorMixin + * @mixes BaseMixin + */ +export class RowChart extends CapMixin(ColorMixin(MarginMixin)) { + /** + * Create a Row Chart. + * @example + * // create a row chart under #chart-container1 element using the default global chart group + * var chart1 = new RowChart('#chart-container1'); + * // create a row chart under #chart-container2 element using chart group A + * var chart2 = new RowChart('#chart-container2', 'chartGroupA'); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._g = undefined; + + this._labelOffsetX = 10; + this._labelOffsetY = 15; + this._hasLabelOffsetY = false; + this._dyOffset = '0.35em'; // this helps center labels https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes.md#svg_text + this._titleLabelOffsetX = 2; + + this._gap = 5; + + this._fixedBarHeight = false; + this._rowCssClass = 'row'; + this._titleRowCssClass = 'titlerow'; + this._renderTitleLabel = false; + + this._x = undefined; + + this._elasticX = undefined; + + this._xAxis = axisBottom(); + + this._rowData = undefined; + + this.rowsCap = this.cap; + + this.title(d => `${this.cappedKeyAccessor(d)}: ${this.cappedValueAccessor(d)}`); + + this.label(d => this.cappedKeyAccessor(d)); + + this.anchor(parent, chartGroup); + } + + _calculateAxisScale () { + if (!this._x || this._elasticX) { + const _extent = extent(this._rowData, d => this.cappedValueAccessor(d)); + if (_extent[0] > 0) { + _extent[0] = 0; + } + if (_extent[1] < 0) { + _extent[1] = 0; + } + this._x = scaleLinear().domain(_extent) + .range([0, this.effectiveWidth()]); + } + this._xAxis.scale(this._x); + } + + _drawAxis () { + let axisG = this._g.select('g.axis'); + + this._calculateAxisScale(); + + if (axisG.empty()) { + axisG = this._g.append('g').attr('class', 'axis'); + } + axisG.attr('transform', `translate(0, ${this.effectiveHeight()})`); + + transition(axisG, this.transitionDuration(), this.transitionDelay()) + .call(this._xAxis); + } + + _doRender () { + this.resetSvg(); + + this._g = this.svg() + .append('g') + .attr('transform', `translate(${this.margins().left},${this.margins().top})`); + + this._drawChart(); + + return this; + } + + /** + * Gets or sets the x scale. The x scale can be any d3 + * {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale}. + * @see {@link https://github.com/d3/d3-scale/blob/master/README.md d3.scale} + * @param {d3.scale} [scale] + * @returns {d3.scale|RowChart} + */ + x (scale) { + if (!arguments.length) { + return this._x; + } + this._x = scale; + return this; + } + + _drawGridLines () { + this._g.selectAll('g.tick') + .select('line.grid-line') + .remove(); + + this._g.selectAll('g.tick') + .append('line') + .attr('class', 'grid-line') + .attr('x1', 0) + .attr('y1', 0) + .attr('x2', 0) + .attr('y2', () => -this.effectiveHeight()); + } + + _drawChart () { + this._rowData = this.data(); + + this._drawAxis(); + this._drawGridLines(); + + let rows = this._g.selectAll(`g.${this._rowCssClass}`) + .data(this._rowData); + + this._removeElements(rows); + rows = this._createElements(rows) + .merge(rows); + this._updateElements(rows); + } + + _createElements (rows) { + const rowEnter = rows.enter() + .append('g') + .attr('class', (d, i) => `${this._rowCssClass} _${i}`); + + rowEnter.append('rect').attr('width', 0); + + this._createLabels(rowEnter); + + return rowEnter; + } + + _removeElements (rows) { + rows.exit().remove(); + } + + _rootValue () { + const root = this._x(0); + return (root === -Infinity || root !== root) ? this._x(1) : root; + } + + _updateElements (rows) { + const n = this._rowData.length; + + let height; + if (!this._fixedBarHeight) { + height = (this.effectiveHeight() - (n + 1) * this._gap) / n; + } else { + height = this._fixedBarHeight; + } + + // vertically align label in center unless they override the value via property setter + if (!this._hasLabelOffsetY) { + this._labelOffsetY = height / 2; + } + + const rect = rows.attr('transform', (d, i) => `translate(0,${(i + 1) * this._gap + i * height})`).select('rect') + .attr('height', height) + .attr('fill', this.getColor) + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .classed('dc-tabbable', this._keyboardAccessible) + .classed('deselected', d => (this.hasFilter()) ? !this._isSelectedRow(d) : false) + .classed('selected', d => (this.hasFilter()) ? this._isSelectedRow(d) : false); + + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(d => this._onClick(d)); + } + + transition(rect, this.transitionDuration(), this.transitionDelay()) + .attr('width', d => Math.abs(this._rootValue() - this._x(this.cappedValueAccessor(d)))) + .attr('transform', d => this._translateX(d)); + + this._createTitles(rows); + this._updateLabels(rows); + } + + _createTitles (rows) { + if (this.renderTitle()) { + rows.select('title').remove(); + rows.append('title').text(this.title()); + } + } + + _createLabels (rowEnter) { + if (this.renderLabel()) { + rowEnter.append('text') + .on('click', d3compat.eventHandler(d => this._onClick(d))); + } + if (this.renderTitleLabel()) { + rowEnter.append('text') + .attr('class', this._titleRowCssClass) + .on('click', d3compat.eventHandler(d => this._onClick(d))); + } + } + + _updateLabels (rows) { + if (this.renderLabel()) { + const lab = rows.select('text') + .attr('x', this._labelOffsetX) + .attr('y', this._labelOffsetY) + .attr('dy', this._dyOffset) + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .attr('class', (d, i) => `${this._rowCssClass} _${i}`) + .text(d => this.label()(d)); + transition(lab, this.transitionDuration(), this.transitionDelay()) + .attr('transform', d => this._translateX(d)); + } + if (this.renderTitleLabel()) { + const titlelab = rows.select(`.${this._titleRowCssClass}`) + .attr('x', this.effectiveWidth() - this._titleLabelOffsetX) + .attr('y', this._labelOffsetY) + .attr('dy', this._dyOffset) + .attr('text-anchor', 'end') + .on('click', d3compat.eventHandler(d => this._onClick(d))) + .attr('class', (d, i) => `${this._titleRowCssClass} _${i}`) + .text(d => this.title()(d)); + transition(titlelab, this.transitionDuration(), this.transitionDelay()) + .attr('transform', d => this._translateX(d)); + } + } + + /** + * Turn on/off Title label rendering (values) using SVG style of text-anchor 'end'. + * @param {Boolean} [renderTitleLabel=false] + * @returns {Boolean|RowChart} + */ + renderTitleLabel (renderTitleLabel) { + if (!arguments.length) { + return this._renderTitleLabel; + } + this._renderTitleLabel = renderTitleLabel; + return this; + } + + _onClick (d) { + this.onClick(d); + } + + _translateX (d) { + const x = this._x(this.cappedValueAccessor(d)), + x0 = this._rootValue(), + s = x > x0 ? x0 : x; + return `translate(${s},0)`; + } + + _doRedraw () { + this._drawChart(); + return this; + } + + /** + * Get or sets the x axis for the row chart instance. + * See the {@link https://github.com/d3/d3-axis/blob/master/README.md d3.axis} + * documention for more information. + * @param {d3.axis} [xAxis] + * @example + * // customize x axis tick format + * chart.xAxis().tickFormat(function (v) {return v + '%';}); + * // customize x axis tick values + * chart.xAxis().tickValues([0, 100, 200, 300]); + * // use a top-oriented axis. Note: position of the axis and grid lines will need to + * // be set manually, see https://dc-js.github.io/dc.js/examples/row-top-axis.html + * chart.xAxis(d3.axisTop()) + * @returns {d3.axis|RowChart} + */ + xAxis (xAxis) { + if (!arguments.length) { + return this._xAxis; + } + this._xAxis = xAxis; + return this; + } + + /** + * Get or set the fixed bar height. Default is [false] which will auto-scale bars. + * For example, if you want to fix the height for a specific number of bars (useful in TopN charts) + * you could fix height as follows (where count = total number of bars in your TopN and gap is + * your vertical gap space). + * @example + * chart.fixedBarHeight( chartheight - (count + 1) * gap / count); + * @param {Boolean|Number} [fixedBarHeight=false] + * @returns {Boolean|Number|RowChart} + */ + fixedBarHeight (fixedBarHeight) { + if (!arguments.length) { + return this._fixedBarHeight; + } + this._fixedBarHeight = fixedBarHeight; + return this; + } + + /** + * Get or set the vertical gap space between rows on a particular row chart instance. + * @param {Number} [gap=5] + * @returns {Number|RowChart} + */ + gap (gap) { + if (!arguments.length) { + return this._gap; + } + this._gap = gap; + return this; + } + + /** + * Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescale to auto-fit the + * data range when filtered. + * @param {Boolean} [elasticX] + * @returns {Boolean|RowChart} + */ + elasticX (elasticX) { + if (!arguments.length) { + return this._elasticX; + } + this._elasticX = elasticX; + return this; + } + + /** + * Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart. + * @param {Number} [labelOffsetX=10] + * @returns {Number|RowChart} + */ + labelOffsetX (labelOffsetX) { + if (!arguments.length) { + return this._labelOffsetX; + } + this._labelOffsetX = labelOffsetX; + return this; + } + + /** + * Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart. + * @param {Number} [labelOffsety=15] + * @returns {Number|RowChart} + */ + labelOffsetY (labelOffsety) { + if (!arguments.length) { + return this._labelOffsetY; + } + this._labelOffsetY = labelOffsety; + this._hasLabelOffsetY = true; + return this; + } + + /** + * Get of set the x offset (horizontal space between right edge of row and right edge or text. + * @param {Number} [titleLabelOffsetX=2] + * @returns {Number|RowChart} + */ + titleLabelOffsetX (titleLabelOffsetX) { + if (!arguments.length) { + return this._titleLabelOffsetX; + } + this._titleLabelOffsetX = titleLabelOffsetX; + return this; + } + + _isSelectedRow (d) { + return this.hasFilter(this.cappedKeyAccessor(d)); + } +} + +export const rowChart = (parent, chartGroup) => new RowChart(parent, chartGroup); diff --git a/src/charts/scatter-plot.js b/src/charts/scatter-plot.js new file mode 100644 index 0000000000..67a9c68c5a --- /dev/null +++ b/src/charts/scatter-plot.js @@ -0,0 +1,669 @@ +import {symbol} from 'd3-shape'; +import {select} from 'd3-selection'; +import {brush} from 'd3-brush'; +import {ascending} from 'd3-array' + +import {CoordinateGridMixin} from '../base/coordinate-grid-mixin'; +import {optionalTransition, transition} from '../core/core'; +import {filters} from '../core/filters'; +import {constants} from '../core/constants'; +import {events} from '../core/events'; + +/** + * A scatter plot chart + * + * Examples: + * - {@link http://dc-js.github.io/dc.js/examples/scatter.html Scatter Chart} + * - {@link http://dc-js.github.io/dc.js/examples/multi-scatter.html Multi-Scatter Chart} + * @mixes CoordinateGridMixin + */ +export class ScatterPlot extends CoordinateGridMixin { + /** + * Create a Scatter Plot. + * @example + * // create a scatter plot under #chart-container1 element using the default global chart group + * var chart1 = new ScatterPlot('#chart-container1'); + * // create a scatter plot under #chart-container2 element using chart group A + * var chart2 = new ScatterPlot('#chart-container2', 'chartGroupA'); + * // create a sub-chart under a composite parent chart + * var chart3 = new ScatterPlot(compositeChart); + * @param {String|node|d3.selection} parent - Any valid + * {@link https://github.com/d3/d3-selection/blob/master/README.md#select d3 single selector} specifying + * a dom block element such as a div; or a dom element or d3 selection. + * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. + * Interaction with a chart will only trigger events and redraws within the chart's group. + */ + constructor (parent, chartGroup) { + super(); + + this._symbol = symbol(); + + this._existenceAccessor = d => d.value; + + const originalKeyAccessor = this.keyAccessor(); + this.keyAccessor(d => originalKeyAccessor(d)[0]); + this.valueAccessor(d => originalKeyAccessor(d)[1]); + this.colorAccessor(() => this._groupName); + + // this basically just counteracts the setting of its own key/value accessors + // see https://github.com/dc-js/dc.js/issues/702 + this.title(d => `${this.keyAccessor()(d)},${this.valueAccessor()(d)}: ${this.existenceAccessor()(d)}`); + + this._highlightedSize = 7; + this._symbolSize = 5; + this._excludedSize = 3; + this._excludedColor = null; + this._excludedOpacity = 1.0; + this._emptySize = 0; + this._emptyOpacity = 0; + this._nonemptyOpacity = 1; + this._emptyColor = null; + this._filtered = []; + this._canvas = null; + this._context = null; + this._useCanvas = false; + + + // Use a 2 dimensional brush + this.brush(brush()); + + this._symbol.size((d, i) => this._elementSize(d, i)); + + this.anchor(parent, chartGroup); + } + + // Calculates element radius for canvas plot to be comparable to D3 area based symbol sizes + _canvasElementSize (d, isFiltered) { + if (!this._existenceAccessor(d)) { + return this._emptySize / Math.sqrt(Math.PI); + } else if (isFiltered) { + return this._symbolSize / Math.sqrt(Math.PI); + } else { + return this._excludedSize / Math.sqrt(Math.PI); + } + } + + _elementSize (d, i) { + if (!this._existenceAccessor(d)) { + return Math.pow(this._emptySize, 2); + } else if (this._filtered[i]) { + return Math.pow(this._symbolSize, 2); + } else { + return Math.pow(this._excludedSize, 2); + } + } + + _locator (d) { + return `translate(${this.x()(this.keyAccessor()(d))},${ + this.y()(this.valueAccessor()(d))})`; + } + + filter (filter) { + if (!arguments.length) { + return super.filter(); + } + + return super.filter(filters.RangedTwoDimensionalFilter(filter)); + } + + /** + * Method that replaces original resetSvg and appropriately inserts canvas + * element along with svg element and sets their CSS properties appropriately + * so they are overlapped on top of each other. + * Remove the chart's SVGElements from the dom and recreate the container SVGElement. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} + * @returns {SVGElement} + */ + resetSvg () { + if (!this._useCanvas) { + return super.resetSvg(); + } else { + super.resetSvg(); // Perform original svgReset inherited from baseMixin + this.select('canvas').remove(); // remove old canvas + + const svgSel = this.svg(); + const rootSel = this.root(); + + // Set root node to relative positioning and svg to absolute + rootSel.style('position', 'relative'); + svgSel.style('position', 'relative'); + + // Check if SVG element already has any extra top/left CSS offsets + const svgLeft = isNaN(parseInt(svgSel.style('left'), 10)) ? 0 : parseInt(svgSel.style('left'), 10); + const svgTop = isNaN(parseInt(svgSel.style('top'), 10)) ? 0 : parseInt(svgSel.style('top'), 10); + const width = this.effectiveWidth(); + const height = this.effectiveHeight(); + const margins = this.margins(); // {top: 10, right: 130, bottom: 42, left: 42} + + // Add the canvas element such that it perfectly overlaps the plot area of the scatter plot SVG + const devicePixelRatio = window.devicePixelRatio || 1; + this._canvas = this.root().append('canvas') + .attr('x', 0) + .attr('y', 0) + .attr('width', (width) * devicePixelRatio) + .attr('height', (height) * devicePixelRatio) + .style('width', `${width}px`) + .style('height', `${height}px`) + .style('position', 'absolute') + .style('top', `${margins.top + svgTop}px`) + .style('left', `${margins.left + svgLeft}px`) + .style('z-index', -1) // Place behind SVG + .style('pointer-events', 'none'); // Disable pointer events on canvas so SVG can capture brushing + + // Define canvas context and set clipping path + this._context = this._canvas.node().getContext('2d'); + this._context.scale(devicePixelRatio, devicePixelRatio); + this._context.rect(0, 0, width, height); + this._context.clip(); // Setup clipping path + this._context.imageSmoothingQuality = 'high'; + + return this.svg(); // Respect original return param for this.resetSvg; + } + } + + _resizeCanvas () { + const width = this.effectiveWidth(); + const height = this.effectiveHeight(); + + const devicePixelRatio = window.devicePixelRatio || 1; + this._canvas + .attr('width', (width) * devicePixelRatio) + .attr('height', (height) * devicePixelRatio) + .style('width', `${width}px`) + .style('height', `${height}px`); + this._context.scale(devicePixelRatio, devicePixelRatio); + } + + + /** + * Set or get whether to use canvas backend for plotting scatterPlot. Note that the + * canvas backend does not currently support + * {@link ScatterPlot#customSymbol customSymbol} or + * {@link ScatterPlot#symbol symbol} methods and is limited to always plotting + * with filled circles. Symbols are drawn with + * {@link ScatterPlot#symbolSize symbolSize} radius. By default, the SVG backend + * is used when `useCanvas` is set to `false`. + * @param {Boolean} [useCanvas=false] + * @return {Boolean|d3.selection} + */ + useCanvas (useCanvas) { + if (!arguments.length) { + return this._useCanvas; + } + this._useCanvas = useCanvas; + return this; + } + + /** + * Set or get canvas element. You should usually only ever use the get method as + * dc.js will handle canvas element generation. Provides valid canvas only when + * {@link ScatterPlot#useCanvas useCanvas} is set to `true` + * @param {CanvasElement|d3.selection} [canvasElement] + * @return {CanvasElement|d3.selection} + */ + canvas (canvasElement) { + if (!arguments.length) { + return this._canvas; + } + this._canvas = canvasElement; + return this; + } + + /** + * Get canvas 2D context. Provides valid context only when + * {@link ScatterPlot#useCanvas useCanvas} is set to `true` + * @return {CanvasContext} + */ + context () { + return this._context; + } + + /*eslint complexity: [2,11] */ + // Plots data on canvas element. If argument provided, assumes legend is + // currently being highlighted and modifies opacity/size of symbols accordingly + // @param {Object} [legendHighlightDatum] - Datum provided to legendHighlight method + _plotOnCanvas (legendHighlightDatum) { + this._resizeCanvas(); + const context = this.context(); + context.clearRect(0, 0, (context.canvas.width + 2) * 1, (context.canvas.height + 2) * 1); + const data = this.data(); + + // Draw the data on canvas + data.forEach((d, i) => { + const isFiltered = !this.filter() || this.filter().isFiltered([d.key[0], d.key[1]]); + // Calculate opacity for current data point + let cOpacity = 1; + if (!this._existenceAccessor(d)) { + cOpacity = this._emptyOpacity; + } else if (isFiltered) { + cOpacity = this._nonemptyOpacity; + } else { + cOpacity = this.excludedOpacity(); + } + // Calculate color for current data point + let cColor = null; + if (this._emptyColor && !this._existenceAccessor(d)) { + cColor = this._emptyColor; + } else if (this.excludedColor() && !isFiltered) { + cColor = this.excludedColor(); + } else { + cColor = this.getColor(d); + } + let cSize = this._canvasElementSize(d, isFiltered); + + // Adjust params for data points if legend is highlighted + if (legendHighlightDatum) { + const isHighlighted = (cColor === legendHighlightDatum.color); + // Calculate opacity for current data point + const fadeOutOpacity = 0.1; // TODO: Make this programmatically setable + if (!isHighlighted) { // Fade out non-highlighted colors + highlighted colors outside filter + cOpacity = fadeOutOpacity; + } + if (isHighlighted) { // Set size for highlighted color data points + cSize = this._highlightedSize / Math.sqrt(Math.PI); + } + } + + // Draw point on canvas + context.save(); + context.globalAlpha = cOpacity; + context.beginPath(); + context.arc(this.x()(this.keyAccessor()(d)), this.y()(this.valueAccessor()(d)), cSize, 0, 2 * Math.PI, true); + context.fillStyle = cColor; + context.fill(); + // context.lineWidth = 0.5; // Commented out code to add stroke around scatter points if desired + // context.strokeStyle = '#333'; + // context.stroke(); + context.restore(); + }); + } + + _plotOnSVG () { + + const data = this.data(); + + if (this._keyboardAccessible) { + // sort based on the x value (key) + data.sort((a, b) => ascending(this.keyAccessor()(a), this.keyAccessor()(b))); + } + + let symbols = this.chartBodyG().selectAll('path.symbol') + .data(data); + + transition(symbols.exit(), this.transitionDuration(), this.transitionDelay()) + .attr('opacity', 0).remove(); + + symbols = symbols + .enter() + .append('path') + .attr('class', 'symbol') + .classed('dc-tabbable', this._keyboardAccessible) + .attr('opacity', 0) + .attr('fill', this.getColor) + .attr('transform', d => this._locator(d)) + .merge(symbols); + + // no click handler - just tabindex for reading out of tooltips + if (this._keyboardAccessible) { + this._makeKeyboardAccessible(); + symbols.order(); + } + + symbols.call(s => this._renderTitles(s, data)); + + symbols.each((d, i) => { + this._filtered[i] = !this.filter() || this.filter().isFiltered([this.keyAccessor()(d), this.valueAccessor()(d)]); + }); + + transition(symbols, this.transitionDuration(), this.transitionDelay()) + .attr('opacity', (d, i) => { + if (!this._existenceAccessor(d)) { + return this._emptyOpacity; + } else if (this._filtered[i]) { + return this._nonemptyOpacity; + } else { + return this.excludedOpacity(); + } + }) + .attr('fill', (d, i) => { + if (this._emptyColor && !this._existenceAccessor(d)) { + return this._emptyColor; + } else if (this.excludedColor() && !this._filtered[i]) { + return this.excludedColor(); + } else { + return this.getColor(d); + } + }) + .attr('transform', d => this._locator(d)) + .attr('d', this._symbol); + } + + plotData () { + if (this._useCanvas) { + this._plotOnCanvas(); + } else { + this._plotOnSVG(); + } + } + + _renderTitles (_symbol, _d) { + if (this.renderTitle()) { + _symbol.selectAll('title').remove(); + _symbol.append('title').text(d => this.title()(d)); + } + } + + /** + * Get or set the existence accessor. If a point exists, it is drawn with + * {@link ScatterPlot#symbolSize symbolSize} radius and + * opacity 1; if it does not exist, it is drawn with + * {@link ScatterPlot#emptySize emptySize} radius and opacity 0. By default, + * the existence accessor checks if the reduced value is truthy. + * @see {@link ScatterPlot#symbolSize symbolSize} + * @see {@link ScatterPlot#emptySize emptySize} + * @example + * // default accessor + * chart.existenceAccessor(function (d) { return d.value; }); + * @param {Function} [accessor] + * @returns {Function|ScatterPlot} + */ + existenceAccessor (accessor) { + if (!arguments.length) { + return this._existenceAccessor; + } + this._existenceAccessor = accessor; + return this; + } + + /** + * Get or set the symbol type used for each point. By default the symbol is a circle (d3.symbolCircle). + * Type can be a constant or an accessor. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_type symbol.type} + * @example + * // Circle type + * chart.symbol(d3.symbolCircle); + * // Square type + * chart.symbol(d3.symbolSquare); + * @param {Function} [type=d3.symbolCircle] + * @returns {Function|ScatterPlot} + */ + symbol (type) { + if (!arguments.length) { + return this._symbol.type(); + } + this._symbol.type(type); + return this; + } + + /** + * Get or set the symbol generator. By default `ScatterPlot` will use + * {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol d3.symbol()} + * to generate symbols. `ScatterPlot` will set the + * {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_size symbol size accessor} + * on the symbol generator. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol d3.symbol} + * @see {@link https://stackoverflow.com/questions/25332120/create-additional-d3-js-symbols Create additional D3.js symbols} + * @param {String|Function} [customSymbol=d3.symbol()] + * @returns {String|Function|ScatterPlot} + */ + customSymbol (customSymbol) { + if (!arguments.length) { + return this._symbol; + } + this._symbol = customSymbol; + this._symbol.size((d, i) => this._elementSize(d, i)); + return this; + } + + /** + * Set or get radius for symbols. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_size d3.symbol.size} + * @param {Number} [symbolSize=3] + * @returns {Number|ScatterPlot} + */ + symbolSize (symbolSize) { + if (!arguments.length) { + return this._symbolSize; + } + this._symbolSize = symbolSize; + return this; + } + + /** + * Set or get radius for highlighted symbols. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_size d3.symbol.size} + * @param {Number} [highlightedSize=5] + * @returns {Number|ScatterPlot} + */ + highlightedSize (highlightedSize) { + if (!arguments.length) { + return this._highlightedSize; + } + this._highlightedSize = highlightedSize; + return this; + } + + /** + * Set or get size for symbols excluded from this chart's filter. If null, no + * special size is applied for symbols based on their filter status. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_size d3.symbol.size} + * @param {Number} [excludedSize=null] + * @returns {Number|ScatterPlot} + */ + excludedSize (excludedSize) { + if (!arguments.length) { + return this._excludedSize; + } + this._excludedSize = excludedSize; + return this; + } + + /** + * Set or get color for symbols excluded from this chart's filter. If null, no + * special color is applied for symbols based on their filter status. + * @param {Number} [excludedColor=null] + * @returns {Number|ScatterPlot} + */ + excludedColor (excludedColor) { + if (!arguments.length) { + return this._excludedColor; + } + this._excludedColor = excludedColor; + return this; + } + + /** + * Set or get opacity for symbols excluded from this chart's filter. + * @param {Number} [excludedOpacity=1.0] + * @returns {Number|ScatterPlot} + */ + excludedOpacity (excludedOpacity) { + if (!arguments.length) { + return this._excludedOpacity; + } + this._excludedOpacity = excludedOpacity; + return this; + } + + /** + * Set or get radius for symbols when the group is empty. + * @see {@link https://github.com/d3/d3-shape/blob/master/README.md#symbol_size d3.symbol.size} + * @param {Number} [emptySize=0] + * @returns {Number|ScatterPlot} + */ + emptySize (emptySize) { + if (!arguments.length) { + return this._emptySize; + } + this._emptySize = emptySize; + return this; + } + + hiddenSize (emptySize) { + if (!arguments.length) { + return this.emptySize(); + } + return this.emptySize(emptySize); + } + + /** + * Set or get color for symbols when the group is empty. If null, just use the + * {@link ColorMixin#colors colorMixin.colors} color scale zero value. + * @param {String} [emptyColor=null] + * @return {String} + * @return {ScatterPlot}/ + */ + emptyColor (emptyColor) { + if (!arguments.length) { + return this._emptyColor; + } + this._emptyColor = emptyColor; + return this; + } + + /** + * Set or get opacity for symbols when the group is empty. + * @param {Number} [emptyOpacity=0] + * @return {Number} + * @return {ScatterPlot} + */ + emptyOpacity (emptyOpacity) { + if (!arguments.length) { + return this._emptyOpacity; + } + this._emptyOpacity = emptyOpacity; + return this; + } + + /** + * Set or get opacity for symbols when the group is not empty. + * @param {Number} [nonemptyOpacity=1] + * @return {Number} + * @return {ScatterPlot} + */ + nonemptyOpacity (nonemptyOpacity) { + if (!arguments.length) { + return this._emptyOpacity; + } + this._nonemptyOpacity = nonemptyOpacity; + return this; + } + + legendables () { + return [{chart: this, name: this._groupName, color: this.getColor()}]; + } + + legendHighlight (d) { + if (this._useCanvas) { + this._plotOnCanvas(d); // Supply legend datum to plotOnCanvas + } else { + this._resizeSymbolsWhere(s => s.attr('fill') === d.color, this._highlightedSize); + this.chartBodyG().selectAll('.chart-body path.symbol').filter(function () { + return select(this).attr('fill') !== d.color; + }).classed('fadeout', true); + } + } + + legendReset (d) { + if (this._useCanvas) { + this._plotOnCanvas(d); // Supply legend datum to plotOnCanvas + } else { + this._resizeSymbolsWhere(s => s.attr('fill') === d.color, this._symbolSize); + this.chartBodyG().selectAll('.chart-body path.symbol').filter(function () { + return select(this).attr('fill') !== d.color; + }).classed('fadeout', false); + } + } + + _resizeSymbolsWhere (condition, size) { + const symbols = this.chartBodyG().selectAll('.chart-body path.symbol').filter(function () { + return condition(select(this)); + }); + const oldSize = this._symbol.size(); + this._symbol.size(Math.pow(size, 2)); + transition(symbols, this.transitionDuration(), this.transitionDelay()).attr('d', this._symbol); + this._symbol.size(oldSize); + } + createBrushHandlePaths () { + // no handle paths for poly-brushes + } + + extendBrush (brushSelection) { + if (this.round()) { + brushSelection[0] = brushSelection[0].map(this.round()); + brushSelection[1] = brushSelection[1].map(this.round()); + } + return brushSelection; + } + + brushIsEmpty (brushSelection) { + return !brushSelection || brushSelection[0][0] >= brushSelection[1][0] || brushSelection[0][1] >= brushSelection[1][1]; + } + + _brushing (evt) { + if (this._ignoreBrushEvents) { + return; + } + + let brushSelection = evt.selection; + + // Testing with pixels is more reliable + let brushIsEmpty = this.brushIsEmpty(brushSelection); + + if (brushSelection) { + brushSelection = brushSelection.map(point => point.map((coord, i) => { + const scale = i === 0 ? this.x() : this.y(); + return scale.invert(coord); + })); + + brushSelection = this.extendBrush(brushSelection); + + // The rounding process might have made brushSelection empty, so we need to recheck + brushIsEmpty = brushIsEmpty && this.brushIsEmpty(brushSelection); + } + + this.redrawBrush(brushSelection, false); + + const ranged2DFilter = brushIsEmpty ? null : filters.RangedTwoDimensionalFilter(brushSelection); + + events.trigger(() => { + this.replaceFilter(ranged2DFilter); + this.redrawGroup(); + }, constants.EVENT_DELAY); + } + + redrawBrush (brushSelection, doTransition) { + // override default x axis brush from parent chart + this._gBrush = this.gBrush(); + + if (this.brushOn() && this._gBrush) { + if (this.resizing()) { + this.setBrushExtents(doTransition); + } + + if (!brushSelection) { + this._withoutBrushEvents(() => { + this._gBrush + .call(this.brush().move, brushSelection); + }); + } else { + brushSelection = brushSelection.map(point => point.map((coord, i) => { + const scale = i === 0 ? this.x() : this.y(); + return scale(coord); + })); + + const gBrush = + optionalTransition(doTransition, this.transitionDuration(), this.transitionDelay())(this._gBrush); + + this._withoutBrushEvents(() => { + gBrush + .call(this.brush().move, brushSelection); + }); + } + } + + this.fadeDeselectedArea(brushSelection); + } +} + +export const scatterPlot = (parent, chartGroup) => new ScatterPlot(parent, chartGroup); diff --git a/src/charts/select-menu.js b/src/charts/select-menu.js new file mode 100644 index 0000000000..db15b138a8 --- /dev/null +++ b/src/charts/select-menu.js @@ -0,0 +1,266 @@ +import {events} from '../core/events'; +import {BaseMixin} from '../base/base-mixin'; +import {logger} from '../core/logger'; +import {d3compat} from '../core/config'; + +const SELECT_CSS_CLASS = 'dc-select-menu'; +const OPTION_CSS_CLASS = 'dc-select-option'; + +/** + * The select menu is a simple widget designed to filter a dimension by selecting an option from + * an HTML `` menu. The menu can be optionally turned into a multiselect. - * @class selectMenu - * @memberof dc - * @mixes dc.baseMixin - * @example - * // create a select menu under #select-container using the default global chart group - * var select = dc.selectMenu('#select-container') - * .dimension(states) - * .group(stateGroup); - * // the option text can be set via the title() function - * // by default the option text is '`key`: `value`' - * select.title(function (d){ - * return 'STATE: ' + d.key; - * }) - * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid - * [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this widget should be placed in. - * Interaction with the widget will only trigger events and redraws within its group. - * @returns {selectMenu} - **/ -dc.selectMenu = function (parent, chartGroup) { - var SELECT_CSS_CLASS = 'dc-select-menu'; - var OPTION_CSS_CLASS = 'dc-select-option'; - - var _chart = dc.baseMixin({}); - - var _select; - var _promptText = 'Select all'; - var _multiple = false; - var _promptValue = null; - var _numberVisible = null; - var _order = function (a, b) { - return _chart.keyAccessor()(a) > _chart.keyAccessor()(b) ? - 1 : _chart.keyAccessor()(b) > _chart.keyAccessor()(a) ? - -1 : 0; - }; - - var _filterDisplayed = function (d) { - return _chart.valueAccessor()(d) > 0; - }; - - _chart.data(function (group) { - return group.all().filter(_filterDisplayed); - }); - - _chart._doRender = function () { - _chart.select('select').remove(); - _select = _chart.root().append('select') - .classed(SELECT_CSS_CLASS, true); - _select.append('option').text(_promptText).attr('value', ''); - - _chart._doRedraw(); - return _chart; - }; - - _chart._doRedraw = function () { - setAttributes(); - renderOptions(); - // select the option(s) corresponding to current filter(s) - if (_chart.hasFilter() && _multiple) { - _select.selectAll('option') - .property('selected', function (d) { - return d && _chart.filters().indexOf(String(_chart.keyAccessor()(d))) >= 0; - }); - } else if (_chart.hasFilter()) { - _select.property('value', _chart.filter()); - } else { - _select.property('value', ''); - } - return _chart; - }; - - function renderOptions () { - var options = _select.selectAll('option.' + OPTION_CSS_CLASS) - .data(_chart.data(), function (d) { return _chart.keyAccessor()(d); }); - - options.enter() - .append('option') - .classed(OPTION_CSS_CLASS, true) - .attr('value', function (d) { return _chart.keyAccessor()(d); }); - - options.text(_chart.title()); - options.exit().remove(); - _select.selectAll('option.' + OPTION_CSS_CLASS).sort(_order); - - _select.on('change', onChange); - return options; - } - - function onChange (d, i) { - var values; - var target = d3.event.target; - if (target.selectedOptions) { - var selectedOptions = Array.prototype.slice.call(target.selectedOptions); - values = selectedOptions.map(function (d) { - return d.value; - }); - } else { // IE and other browsers do not support selectedOptions - // adapted from this polyfill: https://gist.github.com/brettz9/4212217 - var options = [].slice.call(d3.event.target.options); - values = options.filter(function (option) { - return option.selected; - }).map(function (option) { - return option.value; - }); - } - // console.log(values); - // check if only prompt option is selected - if (values.length === 1 && values[0] === '') { - values = _promptValue || null; - } else if (!_multiple && values.length === 1) { - values = values[0]; - } - _chart.onChange(values); - } - - _chart.onChange = function (val) { - if (val && _multiple) { - _chart.replaceFilter([val]); - } else if (val) { - _chart.replaceFilter(val); - } else { - _chart.filterAll(); - } - dc.events.trigger(function () { - _chart.redrawGroup(); - }); - }; - - function setAttributes () { - if (_multiple) { - _select.attr('multiple', true); - } else { - _select.attr('multiple', null); - } - if (_numberVisible !== null) { - _select.attr('size', _numberVisible); - } else { - _select.attr('size', null); - } - } - - /** - * Get or set the function that controls the ordering of option tags in the - * select menu. By default options are ordered by the group key in ascending - * order. - * @name order - * @memberof dc.selectMenu - * @instance - * @param {Function} [order] - * @example - * // order by the group's value - * chart.order(function (a,b) { - * return a.value > b.value ? 1 : b.value > a.value ? -1 : 0; - * }); - **/ - _chart.order = function (order) { - if (!arguments.length) { - return _order; - } - _order = order; - return _chart; - }; - - /** - * Get or set the text displayed in the options used to prompt selection. - * @name promptText - * @memberof dc.selectMenu - * @instance - * @param {String} [promptText='Select all'] - * @example - * chart.promptText('All states'); - **/ - _chart.promptText = function (_) { - if (!arguments.length) { - return _promptText; - } - _promptText = _; - return _chart; - }; - - /** - * Get or set the function that filters option tags prior to display. By default options - * with a value of < 1 are not displayed. - * @name filterDisplayed - * @memberof dc.selectMenu - * @instance - * @param {function} [filterDisplayed] - * @example - * // display all options override the `filterDisplayed` function: - * chart.filterDisplayed(function () { - * return true; - * }); - **/ - _chart.filterDisplayed = function (filterDisplayed) { - if (!arguments.length) { - return _filterDisplayed; - } - _filterDisplayed = filterDisplayed; - return _chart; - }; - - /** - * Controls the type of select menu. Setting it to true converts the underlying - * HTML tag into a multiple select. - * @name multiple - * @memberof dc.selectMenu - * @instance - * @param {boolean} [multiple=false] - * @example - * chart.multiple(true); - **/ - _chart.multiple = function (multiple) { - if (!arguments.length) { - return _multiple; - } - _multiple = multiple; - - return _chart; - }; - - /** - * Controls the default value to be used for - * [dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter) - * when only the prompt value is selected. If `null` (the default), no filtering will occur when - * just the prompt is selected. - * @name promptValue - * @memberof dc.selectMenu - * @instance - * @param {?*} [promptValue=null] - **/ - _chart.promptValue = function (promptValue) { - if (!arguments.length) { - return _promptValue; - } - _promptValue = promptValue; - - return _chart; - }; - - /** - * Controls the number of items to show in the select menu, when `.multiple()` is true. This - * controls the [`size` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Attributes) of - * the `select` element. If `null` (the default), uses the browser's default height. - * @name numberItems - * @memberof dc.selectMenu - * @instance - * @param {?number} [numberVisible=null] - * @example - * chart.numberVisible(10); - **/ - _chart.numberVisible = function (numberVisible) { - if (!arguments.length) { - return _numberVisible; - } - _numberVisible = numberVisible; - - return _chart; - }; - - _chart.size = dc.logger.deprecate(_chart.numberVisible, 'selectMenu.size is ambiguous - use numberVisible instead'); - - return _chart.anchor(parent, chartGroup); -}; diff --git a/src/series-chart.js b/src/series-chart.js deleted file mode 100644 index 28cc3b3def..0000000000 --- a/src/series-chart.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * A series chart is a chart that shows multiple series of data overlaid on one chart, where the - * series is specified in the data. It is a specialization of Composite Chart and inherits all - * composite features other than recomposing the chart. - * - * Examples: - * - {@link http://dc-js.github.io/dc.js/examples/series.html Series Chart} - * @class seriesChart - * @memberof dc - * @mixes dc.compositeChart - * @example - * // create a series chart under #chart-container1 element using the default global chart group - * var seriesChart1 = dc.seriesChart("#chart-container1"); - * // create a series chart under #chart-container2 element using chart group A - * var seriesChart2 = dc.seriesChart("#chart-container2", "chartGroupA"); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.seriesChart} - */ -dc.seriesChart = function (parent, chartGroup) { - var _chart = dc.compositeChart(parent, chartGroup); - - function keySort (a, b) { - return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b)); - } - - var _charts = {}; - var _chartFunction = dc.lineChart; - var _seriesAccessor; - var _seriesSort = d3.ascending; - var _valueSort = keySort; - - _chart._mandatoryAttributes().push('seriesAccessor', 'chart'); - _chart.shareColors(true); - - _chart._preprocessData = function () { - var keep = []; - var childrenChanged; - var nester = d3.nest().key(_seriesAccessor); - if (_seriesSort) { - nester.sortKeys(_seriesSort); - } - if (_valueSort) { - nester.sortValues(_valueSort); - } - var nesting = nester.entries(_chart.data()); - var children = - nesting.map(function (sub, i) { - var subChart = _charts[sub.key] || _chartFunction.call(_chart, _chart, chartGroup, sub.key, i); - if (!_charts[sub.key]) { - childrenChanged = true; - } - _charts[sub.key] = subChart; - keep.push(sub.key); - return subChart - .dimension(_chart.dimension()) - .group({all: d3.functor(sub.values)}, sub.key) - .keyAccessor(_chart.keyAccessor()) - .valueAccessor(_chart.valueAccessor()) - .brushOn(_chart.brushOn()); - }); - // this works around the fact compositeChart doesn't really - // have a removal interface - Object.keys(_charts) - .filter(function (c) {return keep.indexOf(c) === -1;}) - .forEach(function (c) { - clearChart(c); - childrenChanged = true; - }); - _chart._compose(children); - if (childrenChanged && _chart.legend()) { - _chart.legend().render(); - } - }; - - function clearChart (c) { - if (_charts[c].g()) { - _charts[c].g().remove(); - } - delete _charts[c]; - } - - function resetChildren () { - Object.keys(_charts).map(clearChart); - _charts = {}; - } - - /** - * Get or set the chart function, which generates the child charts. - * @method chart - * @memberof dc.seriesChart - * @instance - * @example - * // put interpolation on the line charts used for the series - * chart.chart(function(c) { return dc.lineChart(c).interpolate('basis'); }) - * // do a scatter series chart - * chart.chart(dc.scatterPlot) - * @param {Function} [chartFunction=dc.lineChart] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.chart = function (chartFunction) { - if (!arguments.length) { - return _chartFunction; - } - _chartFunction = chartFunction; - resetChildren(); - return _chart; - }; - - /** - * **mandatory** - * - * Get or set accessor function for the displayed series. Given a datum, this function - * should return the series that datum belongs to. - * @method seriesAccessor - * @memberof dc.seriesChart - * @instance - * @example - * // simple series accessor - * chart.seriesAccessor(function(d) { return "Expt: " + d.key[0]; }) - * @param {Function} [accessor] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.seriesAccessor = function (accessor) { - if (!arguments.length) { - return _seriesAccessor; - } - _seriesAccessor = accessor; - resetChildren(); - return _chart; - }; - - /** - * Get or set a function to sort the list of series by, given series values. - * @method seriesSort - * @memberof dc.seriesChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * chart.seriesSort(d3.descending); - * @param {Function} [sortFunction=d3.ascending] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.seriesSort = function (sortFunction) { - if (!arguments.length) { - return _seriesSort; - } - _seriesSort = sortFunction; - resetChildren(); - return _chart; - }; - - /** - * Get or set a function to sort each series values by. By default this is the key accessor which, - * for example, will ensure a lineChart series connects its points in increasing key/x order, - * rather than haphazardly. - * @method valueSort - * @memberof dc.seriesChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * // Default value sort - * _chart.valueSort(function keySort (a, b) { - * return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b)); - * }); - * @param {Function} [sortFunction] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.valueSort = function (sortFunction) { - if (!arguments.length) { - return _valueSort; - } - _valueSort = sortFunction; - resetChildren(); - return _chart; - }; - - // make compose private - _chart._compose = _chart.compose; - delete _chart.compose; - - return _chart; -}; diff --git a/src/stack-mixin.js b/src/stack-mixin.js deleted file mode 100644 index 46fa5b59b6..0000000000 --- a/src/stack-mixin.js +++ /dev/null @@ -1,319 +0,0 @@ -/** - * Stack Mixin is an mixin that provides cross-chart support of stackability using d3.layout.stack. - * @name stackMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.stackMixin} - */ -dc.stackMixin = function (_chart) { - - function prepareValues (layer, layerIdx) { - var valAccessor = layer.accessor || _chart.valueAccessor(); - layer.name = String(layer.name || layerIdx); - layer.values = layer.group.all().map(function (d, i) { - return { - x: _chart.keyAccessor()(d, i), - y: layer.hidden ? null : valAccessor(d, i), - data: d, - layer: layer.name, - hidden: layer.hidden - }; - }); - - layer.values = layer.values.filter(domainFilter()); - return layer.values; - } - - var _stackLayout = d3.layout.stack() - .values(prepareValues); - - var _stack = []; - var _titles = {}; - - var _hidableStacks = false; - - function domainFilter () { - if (!_chart.x()) { - return d3.functor(true); - } - var xDomain = _chart.x().domain(); - if (_chart.isOrdinal()) { - // TODO #416 - //var domainSet = d3.set(xDomain); - return function () { - return true; //domainSet.has(p.x); - }; - } - if (_chart.elasticX()) { - return function () { return true; }; - } - return function (p) { - //return true; - return p.x >= xDomain[0] && p.x <= xDomain[xDomain.length - 1]; - }; - } - - /** - * Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks - * in the same chart will share the same key accessor and therefore the same set of keys. - * - * For example, in a stacked bar chart, the bars of each stack will be positioned using the same set - * of keys on the x axis, while stacked vertically. If name is specified then it will be used to - * generate the legend label. - * @method stack - * @memberof dc.stackMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} - * @example - * // stack group using default accessor - * chart.stack(valueSumGroup) - * // stack group using custom accessor - * .stack(avgByDayGroup, function(d){return d.value.avgByDay;}); - * @param {crossfilter.group} group - * @param {String} [name] - * @param {Function} [accessor] - * @return {Array<{group: crossfilter.group, name: String, accessor: Function}>} - * @return {dc.stackMixin} - */ - _chart.stack = function (group, name, accessor) { - if (!arguments.length) { - return _stack; - } - - if (arguments.length <= 2) { - accessor = name; - } - - var layer = {group: group}; - if (typeof name === 'string') { - layer.name = name; - } - if (typeof accessor === 'function') { - layer.accessor = accessor; - } - _stack.push(layer); - - return _chart; - }; - - dc.override(_chart, 'group', function (g, n, f) { - if (!arguments.length) { - return _chart._group(); - } - _stack = []; - _titles = {}; - _chart.stack(g, n); - if (f) { - _chart.valueAccessor(f); - } - return _chart._group(g, n); - }); - - /** - * Allow named stacks to be hidden or shown by clicking on legend items. - * This does not affect the behavior of hideStack or showStack. - * @method hidableStacks - * @memberof dc.stackMixin - * @instance - * @param {Boolean} [hidableStacks=false] - * @return {Boolean} - * @return {dc.stackMixin} - */ - _chart.hidableStacks = function (hidableStacks) { - if (!arguments.length) { - return _hidableStacks; - } - _hidableStacks = hidableStacks; - return _chart; - }; - - function findLayerByName (n) { - var i = _stack.map(dc.pluck('name')).indexOf(n); - return _stack[i]; - } - - /** - * Hide all stacks on the chart with the given name. - * The chart must be re-rendered for this change to appear. - * @method hideStack - * @memberof dc.stackMixin - * @instance - * @param {String} stackName - * @return {dc.stackMixin} - */ - _chart.hideStack = function (stackName) { - var layer = findLayerByName(stackName); - if (layer) { - layer.hidden = true; - } - return _chart; - }; - - /** - * Show all stacks on the chart with the given name. - * The chart must be re-rendered for this change to appear. - * @method showStack - * @memberof dc.stackMixin - * @instance - * @param {String} stackName - * @return {dc.stackMixin} - */ - _chart.showStack = function (stackName) { - var layer = findLayerByName(stackName); - if (layer) { - layer.hidden = false; - } - return _chart; - }; - - _chart.getValueAccessorByIndex = function (index) { - return _stack[index].accessor || _chart.valueAccessor(); - }; - - _chart.yAxisMin = function () { - var min = d3.min(flattenStack(), function (p) { - return (p.y < 0) ? (p.y + p.y0) : p.y0; - }); - - return dc.utils.subtract(min, _chart.yAxisPadding()); - - }; - - _chart.yAxisMax = function () { - var max = d3.max(flattenStack(), function (p) { - return (p.y > 0) ? (p.y + p.y0) : p.y0; - }); - - return dc.utils.add(max, _chart.yAxisPadding()); - }; - - function flattenStack () { - var valueses = _chart.data().map(function (layer) { return layer.values; }); - return Array.prototype.concat.apply([], valueses); - } - - _chart.xAxisMin = function () { - var min = d3.min(flattenStack(), dc.pluck('x')); - return dc.utils.subtract(min, _chart.xAxisPadding()); - }; - - _chart.xAxisMax = function () { - var max = d3.max(flattenStack(), dc.pluck('x')); - return dc.utils.add(max, _chart.xAxisPadding()); - }; - - /** - * Set or get the title function. Chart class will use this function to render svg title (usually interpreted by - * browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart. - * Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to - * use title otherwise the brush layer will block tooltip trigger. - * - * If the first argument is a stack name, the title function will get or set the title for that stack. If stackName - * is not provided, the first stack is implied. - * @method title - * @memberof dc.stackMixin - * @instance - * @example - * // set a title function on 'first stack' - * chart.title('first stack', function(d) { return d.key + ': ' + d.value; }); - * // get a title function from 'second stack' - * var secondTitleFunction = chart.title('second stack'); - * @param {String} [stackName] - * @param {Function} [titleAccessor] - * @return {String} - * @return {dc.stackMixin} - */ - dc.override(_chart, 'title', function (stackName, titleAccessor) { - if (!stackName) { - return _chart._title(); - } - - if (typeof stackName === 'function') { - return _chart._title(stackName); - } - if (stackName === _chart._groupName && typeof titleAccessor === 'function') { - return _chart._title(titleAccessor); - } - - if (typeof titleAccessor !== 'function') { - return _titles[stackName] || _chart._title(); - } - - _titles[stackName] = titleAccessor; - - return _chart; - }); - - /** - * Gets or sets the stack layout algorithm, which computes a baseline for each stack and - * propagates it to the next - * @method stackLayout - * @memberof dc.stackMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Stack-Layout d3.layout.stack} - * @param {Function} [stack=d3.layout.stack] - * @return {Function} - * @return {dc.stackMixin} - */ - _chart.stackLayout = function (stack) { - if (!arguments.length) { - return _stackLayout; - } - _stackLayout = stack; - if (_stackLayout.values() === d3.layout.stack().values()) { - _stackLayout.values(prepareValues); - } - return _chart; - }; - - function visability (l) { - return !l.hidden; - } - - _chart.data(function () { - var layers = _stack.filter(visability); - return layers.length ? _chart.stackLayout()(layers) : []; - }); - - _chart._ordinalXDomain = function () { - var flat = flattenStack().map(dc.pluck('data')); - var ordered = _chart._computeOrderedGroups(flat); - return ordered.map(_chart.keyAccessor()); - }; - - _chart.colorAccessor(function (d) { - var layer = this.layer || this.name || d.name || d.layer; - return layer; - }); - - _chart.legendables = function () { - return _stack.map(function (layer, i) { - return { - chart: _chart, - name: layer.name, - hidden: layer.hidden || false, - color: _chart.getColor.call(layer, layer.values, i) - }; - }); - }; - - _chart.isLegendableHidden = function (d) { - var layer = findLayerByName(d.name); - return layer ? layer.hidden : false; - }; - - _chart.legendToggle = function (d) { - if (_hidableStacks) { - if (_chart.isLegendableHidden(d)) { - _chart.showStack(d.name); - } else { - _chart.hideStack(d.name); - } - //_chart.redraw(); - _chart.renderGroup(); - } - }; - - return _chart; -}; diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 00fbc0f35f..0000000000 --- a/src/utils.js +++ /dev/null @@ -1,290 +0,0 @@ -/** - * The default date format for dc.js - * @name dateFormat - * @memberof dc - * @type {Function} - * @default d3.time.format('%m/%d/%Y') - */ -dc.dateFormat = d3.time.format('%m/%d/%Y'); - -/** - * @namespace printers - * @memberof dc - * @type {{}} - */ -dc.printers = {}; - -/** - * Converts a list of filters into a readable string - * @method filters - * @memberof dc.printers - * @param {Array} filters - * @returns {String} - */ -dc.printers.filters = function (filters) { - var s = ''; - - for (var i = 0; i < filters.length; ++i) { - if (i > 0) { - s += ', '; - } - s += dc.printers.filter(filters[i]); - } - - return s; -}; - -/** - * Converts a filter into a readable string - * @method filter - * @memberof dc.printers - * @param {dc.filters|any|Array} filter - * @returns {String} - */ -dc.printers.filter = function (filter) { - var s = ''; - - if (typeof filter !== 'undefined' && filter !== null) { - if (filter instanceof Array) { - if (filter.length >= 2) { - s = '[' + dc.utils.printSingleValue(filter[0]) + ' -> ' + dc.utils.printSingleValue(filter[1]) + ']'; - } else if (filter.length >= 1) { - s = dc.utils.printSingleValue(filter[0]); - } - } else { - s = dc.utils.printSingleValue(filter); - } - } - - return s; -}; - -/** - * Returns a function that given a string property name, can be used to pluck the property off an object. A function - * can be passed as the second argument to also alter the data being returned. This can be a useful shorthand method to create - * accessor functions. - * @method pluck - * @memberof dc - * @example - * var xPluck = dc.pluck('x'); - * var objA = {x: 1}; - * xPluck(objA) // 1 - * @example - * var xPosition = dc.pluck('x', function (x, i) { - * // `this` is the original datum, - * // `x` is the x property of the datum, - * // `i` is the position in the array - * return this.radius + x; - * }); - * dc.selectAll('.circle').data(...).x(xPosition); - * @param {String} n - * @param {Function} [f] - * @returns {Function} - */ -dc.pluck = function (n, f) { - if (!f) { - return function (d) { return d[n]; }; - } - return function (d, i) { return f.call(d, d[n], i); }; -}; - -/** - * @namespace utils - * @memberof dc - * @type {{}} - */ -dc.utils = {}; - -/** - * Print a single value filter - * @method printSingleValue - * @memberof dc.utils - * @param {any} filter - * @returns {String} - */ -dc.utils.printSingleValue = function (filter) { - var s = '' + filter; - - if (filter instanceof Date) { - s = dc.dateFormat(filter); - } else if (typeof(filter) === 'string') { - s = filter; - } else if (dc.utils.isFloat(filter)) { - s = dc.utils.printSingleValue.fformat(filter); - } else if (dc.utils.isInteger(filter)) { - s = Math.round(filter); - } - - return s; -}; -dc.utils.printSingleValue.fformat = d3.format('.2f'); - -/** - * Arbitrary add one value to another. - * @method add - * @memberof dc.utils - * @todo - * These assume than any string r is a percentage (whether or not it includes %). - * They also generate strange results if l is a string. - * @param {String|Date|Number} l - * @param {Number} r - * @returns {String|Date|Number} - */ -dc.utils.add = function (l, r) { - if (typeof r === 'string') { - r = r.replace('%', ''); - } - - if (l instanceof Date) { - if (typeof r === 'string') { - r = +r; - } - var d = new Date(); - d.setTime(l.getTime()); - d.setDate(l.getDate() + r); - return d; - } else if (typeof r === 'string') { - var percentage = (+r / 100); - return l > 0 ? l * (1 + percentage) : l * (1 - percentage); - } else { - return l + r; - } -}; - -/** - * Arbitrary subtract one value from another. - * @method subtract - * @memberof dc.utils - * @todo - * These assume than any string r is a percentage (whether or not it includes %). - * They also generate strange results if l is a string. - * @param {String|Date|Number} l - * @param {Number} r - * @returns {String|Date|Number} - */ -dc.utils.subtract = function (l, r) { - if (typeof r === 'string') { - r = r.replace('%', ''); - } - - if (l instanceof Date) { - if (typeof r === 'string') { - r = +r; - } - var d = new Date(); - d.setTime(l.getTime()); - d.setDate(l.getDate() - r); - return d; - } else if (typeof r === 'string') { - var percentage = (+r / 100); - return l < 0 ? l * (1 + percentage) : l * (1 - percentage); - } else { - return l - r; - } -}; - -/** - * Is the value a number? - * @method isNumber - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isNumber = function (n) { - return n === +n; -}; - -/** - * Is the value a float? - * @method isFloat - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isFloat = function (n) { - return n === +n && n !== (n | 0); -}; - -/** - * Is the value an integer? - * @method isInteger - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isInteger = function (n) { - return n === +n && n === (n | 0); -}; - -/** - * Is the value very close to zero? - * @method isNegligible - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isNegligible = function (n) { - return !dc.utils.isNumber(n) || (n < dc.constants.NEGLIGIBLE_NUMBER && n > -dc.constants.NEGLIGIBLE_NUMBER); -}; - -/** - * Ensure the value is no greater or less than the min/max values. If it is return the boundary value. - * @method clamp - * @memberof dc.utils - * @param {any} val - * @param {any} min - * @param {any} max - * @returns {any} - */ -dc.utils.clamp = function (val, min, max) { - return val < min ? min : (val > max ? max : val); -}; - -/** - * Using a simple static counter, provide a unique integer id. - * @method uniqueId - * @memberof dc.utils - * @returns {Number} - */ -var _idCounter = 0; -dc.utils.uniqueId = function () { - return ++_idCounter; -}; - -/** - * Convert a name to an ID. - * @method nameToId - * @memberof dc.utils - * @param {String} name - * @returns {String} - */ -dc.utils.nameToId = function (name) { - return name.toLowerCase().replace(/[\s]/g, '_').replace(/[\.']/g, ''); -}; - -/** - * Append or select an item on a parent element - * @method appendOrSelect - * @memberof dc.utils - * @param {d3.selection} parent - * @param {String} selector - * @param {String} tag - * @returns {d3.selection} - */ -dc.utils.appendOrSelect = function (parent, selector, tag) { - tag = tag || selector; - var element = parent.select(selector); - if (element.empty()) { - element = parent.append(tag); - } - return element; -}; - -/** - * Return the number if the value is a number; else 0. - * @method safeNumber - * @memberof dc.utils - * @param {Number|any} n - * @returns {Number} - */ -dc.utils.safeNumber = function (n) { return dc.utils.isNumber(+n) ? +n : 0;}; diff --git a/style/dc.scss b/style/dc.scss new file mode 100644 index 0000000000..6eb877389b --- /dev/null +++ b/style/dc.scss @@ -0,0 +1,325 @@ +//colors +$color_celeste: #ccc; +$color_fair_pink: #fee; +$color_white: #fff; +$color_black: #000; +$color_steel_blue: #4682b4; +$color_gallery: #eee; +$color_storm_dust: #666; +$color_grey: #808080; +$color_boston_blue: #3182bd; +$color_blue: #00f; + +//fonts +$font_sans_serif: sans-serif; + +@mixin no-select { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +//original selectors +//.dc-chart path.dc-symbol, g.dc-legend-item.fadeout +%extend_1 { + fill-opacity: 0.5; + stroke-opacity: 0.5; +} + +.dc-chart { + rect { + &.bar { + stroke: none; + cursor: pointer; + &:hover,&:focus { + fill-opacity: .5; + } + } + &.deselected { + stroke: none; + fill: $color_celeste; + } + } + .pie-slice { + fill: $color_white; + font-size: 12px; + cursor: pointer; + &.external { + fill: $color_black; + } + &:focus { + fill-opacity: .8; + } + :hover &.highlight { + fill-opacity: .8; + } + } + .pie-path { + fill: none; + stroke-width: 2px; + stroke: $color_black; + opacity: 0.4; + } + .selected { + path, circle { + stroke-width: 3; + stroke: $color_celeste; + fill-opacity: 1; + } + } + .deselected { + path, circle { + stroke: none; + fill-opacity: .5; + fill: $color_celeste; + } + } + .axis { + path, line { + fill: none; + stroke: $color_black; + shape-rendering: crispEdges; + } + text { + font: 10px $font_sans_serif; + } + } + .grid-line, .axis .grid-line, .grid-line line, .axis .grid-line line { + fill: none; + stroke: $color_celeste; + shape-rendering: crispEdges; + } + .brush { + rect { + &.selection { + fill: $color_steel_blue; + fill-opacity: .125; + } + } + .custom-brush-handle { + fill: $color_gallery; + stroke: $color_storm_dust; + cursor: ew-resize; + } + } + path { + &.line { + fill: none; + stroke-width: 1.5px; + } + &.area { + fill-opacity: .3; + stroke: none; + } + &.highlight { + stroke-width: 3; + fill-opacity: 1; + stroke-opacity: 1; + } + &.dc-symbol { + @extend %extend_1; + } + } + g { + &.state { + cursor: pointer; + :hover,:focus { + fill-opacity: .8; + } + path { + stroke: $color_white; + } + } + &.deselected { + path { + fill: $color_grey; + } + text { + display: none; + } + } + &.row { + rect { + fill-opacity: 0.8; + cursor: pointer; + &:hover,&:focus { + fill-opacity: 0.6; + } + } + text { + fill: $color_white; + font-size: 12px; + cursor: pointer; + } + } + &.dc-tooltip path { + fill: none; + stroke: $color_grey; + stroke-opacity: .8; + } + &.county path { + stroke: $color_white; + fill: none; + } + &.debug rect { + fill: $color_blue; + fill-opacity: .2; + } + &.axis text { + @include no-select; + pointer-events: none; + } + } + .node { + font-size: 0.7em; + cursor: pointer; + :hover,:focus { + fill-opacity: .8; + } + } + .bubble { + stroke: none; + fill-opacity: 0.6; + } + .highlight { + fill-opacity: 1; + stroke-opacity: 1; + } + .fadeout { + fill-opacity: 0.2; + stroke-opacity: 0.2; + } + .box { + text { + font: 10px $font_sans_serif; + @include no-select; + pointer-events: none; + } + line { + fill: $color_white; + } + rect, line, circle { + stroke: $color_black; + stroke-width: 1.5px; + } + .center { + stroke-dasharray: 3, 3; + } + .data { + stroke: none; + stroke-width: 0px; + } + .outlier { + fill: none; + stroke: $color_celeste; + } + .outlierBold { + fill: red; + stroke: none; + } + &.deselected { + opacity: 0.5; + .box { + fill: $color_celeste; + } + } + } + .symbol { + stroke: none; + } + .heatmap { + .box-group.deselected rect { + stroke: none; + fill-opacity: 0.5; + fill: $color_celeste; + } + g.axis text { + pointer-events: all; + cursor: pointer; + } + } + .empty-chart .pie-slice { + cursor: default; + path { + fill: $color_fair_pink; + cursor: default; + } + } +} + +.dc-data-count { + float: right; + margin-top: 15px; + margin-right: 15px; + .filter-count, .total-count { + color: $color_boston_blue; + font-weight: bold; + } +} + +.dc-legend { + font-size: 11px; + .dc-legend-item { + cursor: pointer; + } + g.dc-legend-item.fadeout { + @extend %extend_1; + } + g.dc-legend-item.selected { + fill: blue; + } +} + +.dc-hard .number-display { + float: none; +} + + +div.dc-html-legend { + overflow-y: auto; + overflow-x: hidden; + height: inherit; + float: right; + padding-right: 2px; + .dc-legend-item-horizontal { + display: inline-block; + margin-left: 5px; + margin-right: 5px; + cursor: pointer; + &.selected{ + background-color: rgb(49, 130, 189); + color: white; + } + } + .dc-legend-item-vertical { + display: block; + margin-top: 5px; + padding-top: 1px; + padding-bottom: 1px; + cursor: pointer; + &.selected{ + background-color: rgb(49, 130, 189); + color: white; + } + } + .dc-legend-item-color { + display: table-cell; + width: 12px; + height: 12px; + } + .dc-legend-item-label { + line-height: 12px; + display: table-cell; + vertical-align: middle; + padding-left: 3px; + padding-right: 3px; + font-size: 0.75em; + } +} + +.dc-html-legend-container{ + height: inherit; +} diff --git a/web/crime/canada_map.svg b/web-src/crime/canada_map.svg similarity index 100% rename from web/crime/canada_map.svg rename to web-src/crime/canada_map.svg diff --git a/web/crime/crime.csv b/web-src/crime/crime.csv similarity index 100% rename from web/crime/crime.csv rename to web-src/crime/crime.csv diff --git a/web/crime/filter_stats.rb b/web-src/crime/filter_stats.rb similarity index 100% rename from web/crime/filter_stats.rb rename to web-src/crime/filter_stats.rb diff --git a/web/crime/index.html b/web-src/crime/index.html similarity index 98% rename from web/crime/index.html rename to web-src/crime/index.html index 6af9a7f3ca..ab062319de 100644 --- a/web/crime/index.html +++ b/web-src/crime/index.html @@ -328,38 +328,38 @@

Major Canadian City Crime Stats 1998-2011

- - + + + + + + + diff --git a/web-src/examples/brush-ordinal.html b/web-src/examples/brush-ordinal.html new file mode 100644 index 0000000000..9a94450116 --- /dev/null +++ b/web-src/examples/brush-ordinal.html @@ -0,0 +1,114 @@ + + + + dc.js - Brushing on an Ordinal Bar Chart + + + + + + +
+ +

This example demonstrates brushing on an ordinal bar chart, by mapping the values to +integers and specifying a linear scale. The data is sorted alphabetically.

+
+
+ + + + + + + +
+ + diff --git a/web-src/examples/cap-and-sort-differently.html b/web-src/examples/cap-and-sort-differently.html new file mode 100644 index 0000000000..01de8c8c41 --- /dev/null +++ b/web-src/examples/cap-and-sort-differently.html @@ -0,0 +1,73 @@ + + + + dc.js - Cap and Sort Differently + + + + + + +
+ +
+ + + + + + +
+ + diff --git a/web-src/examples/cat.tsv b/web-src/examples/cat.tsv new file mode 100644 index 0000000000..2cbacd2a57 --- /dev/null +++ b/web-src/examples/cat.tsv @@ -0,0 +1,10 @@ +file size type +pics/cats/pixel/jumping.jpg 25000 jpg +pics/all/wedding/aftermath/wife.jpg 12000 jpg +pics/others/child.mov 14000 mov +pics/wellington.jpg 18000 jpg +pics/park.jpg 1200 jpg +music/hiphop/chap/mr b/likeachap.mp3 25000 mp3 +new/movie.mov 14000 mov +code/project/current/dc3.zip 12000 zip +mail.zip 20000 zip \ No newline at end of file diff --git a/web-src/examples/cbox-menu.html b/web-src/examples/cbox-menu.html new file mode 100644 index 0000000000..b6b6496b30 --- /dev/null +++ b/web-src/examples/cbox-menu.html @@ -0,0 +1,162 @@ + + + + dc.js - Checkbox Menu Example + + + + + + + +
+ +

A meaningless example of multiple cboxMenus on some random data...

+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + + + + + + + + +
+ + diff --git a/web-src/examples/click-limit-on-histogram.html b/web-src/examples/click-limit-on-histogram.html new file mode 100644 index 0000000000..d65bb6e098 --- /dev/null +++ b/web-src/examples/click-limit-on-histogram.html @@ -0,0 +1,82 @@ + + + + dc.js - Click a limit on a histogram + + + + + + +
+ +
+ + + + + + +
+ + diff --git a/web-src/examples/color-swatch.html b/web-src/examples/color-swatch.html new file mode 100644 index 0000000000..bab8b640ab --- /dev/null +++ b/web-src/examples/color-swatch.html @@ -0,0 +1,110 @@ + + + + dc.js - Color Swatch Example + + + + + + +
+ + +

Example of creating a simple external chart and attaching it to the dc.js +chart registry.

+ +

The color swatch widget is not supposed to be useful, just the most minimal example. It watches a +groupAll value and maps it to a color using a color scale.

+ +
+
+ + + + + + +
+ + diff --git a/web-src/examples/compare-unfiltered.html b/web-src/examples/compare-unfiltered.html new file mode 100644 index 0000000000..ee3887b4d5 --- /dev/null +++ b/web-src/examples/compare-unfiltered.html @@ -0,0 +1,243 @@ + + + + dc.js - Comparing Against Unfiltered Data + + + + + + + +
+ + + + + +
+

Comparing filtered data against unfiltered

+

by copying the initial group values into a fake group, and displaying them in a composite bar chart.

+

See this Stack Overflow answer for a description of the technique. (This answer describes the toggling logic.)

+
+
+ | + + selected out of + + points | + Reset All +
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ + + + + + diff --git a/web/examples/complex-reduce.html b/web-src/examples/complex-reduce.html similarity index 92% rename from web/examples/complex-reduce.html rename to web-src/examples/complex-reduce.html index 359c4cb005..44e5f1a162 100644 --- a/web/examples/complex-reduce.html +++ b/web-src/examples/complex-reduce.html @@ -5,6 +5,7 @@ + + + + +
+ +
+ + + + + +
+ + diff --git a/web-src/examples/composite-brush-multi-dim.html b/web-src/examples/composite-brush-multi-dim.html new file mode 100644 index 0000000000..4c82d0950e --- /dev/null +++ b/web-src/examples/composite-brush-multi-dim.html @@ -0,0 +1,105 @@ + + + + dc.js - Composite Chart Brushing Example + + + + + + +
+ + +

Usually sub charts of a composite chart share the dimension of the parent. + However sometimes, especially when scatter plots are composed, the sub charts may + use different dimensions. This example uses two scatter plots both using array dimensions. + Typically scatter plots use two dimensional brushing (see scatter brushing); + however, composite charts only support one dimensional brushing along the x axis.

+

Try brushing on the chart and see data getting filtered in the table on the right.

+

Notice that unlike in other charts, brushing removes points outside range of the brush + instead of just fading them. + This is because the composite chart uses three different dimensions for the child charts, + so each observes the filter applied to the others.

+
+
+ + + + + + +
+ + diff --git a/web/examples/composite.html b/web-src/examples/composite.html similarity index 81% rename from web/examples/composite.html rename to web-src/examples/composite.html index 5cb4be364c..c1df9134c6 100644 --- a/web/examples/composite.html +++ b/web-src/examples/composite.html @@ -12,19 +12,16 @@
- +
+ +
+
+ +
+ + + + + + + + + diff --git a/web/examples/filtering-removing.html b/web-src/examples/filtering-removing.html similarity index 82% rename from web/examples/filtering-removing.html rename to web-src/examples/filtering-removing.html index 934451a8c2..42b09dd308 100644 --- a/web/examples/filtering-removing.html +++ b/web-src/examples/filtering-removing.html @@ -1,10 +1,11 @@ - dc.js - Filtering Example + dc.js - Removing Empty Bars + @@ -13,7 +14,7 @@

Example demonstrating using a "Fake Group" to remove the empty bars of an ordinal bar chart when their values drop to zero.

-

(Note the use of .elasticX(true) +

(Note the use of .elasticX(true) to force calculation of the X domain each round.)

@@ -25,11 +26,11 @@ +

This page demonstrates filtering and accessibility features.

+

Charts can be labelled for screen readers with BaseMixin.svgDescription, and internal chart elements (like bars in a bar chart) can be made accessible with BaseMixin.keyboardAccessible.

+

Try it here: +

  • select elements using the tab key
  • +
  • toggle filtering using the space or enter keys
  • + + diff --git a/web-src/examples/html-legend.html b/web-src/examples/html-legend.html new file mode 100644 index 0000000000..753a051ce3 --- /dev/null +++ b/web-src/examples/html-legend.html @@ -0,0 +1,93 @@ + + + + dc.js - HTML Legend Example + + + + + + + +
    + + +

    This page demonstrates the usage of the html legend. + It shows example of scrollbars for the vertical menu and setting up a horizontal menu. +

    +

    + It also shows the selected legend highlighted +

    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + + +
    + + diff --git a/web/examples/intervals.csv b/web-src/examples/intervals.csv similarity index 100% rename from web/examples/intervals.csv rename to web-src/examples/intervals.csv diff --git a/web-src/examples/iris.csv b/web-src/examples/iris.csv new file mode 100644 index 0000000000..6464198b97 --- /dev/null +++ b/web-src/examples/iris.csv @@ -0,0 +1,151 @@ +sepal_length,sepal_width,petal_length,petal_width,species +5.1,3.5,1.4,0.2,setosa +4.9,3,1.4,0.2,setosa +4.7,3.2,1.3,0.2,setosa +4.6,3.1,1.5,0.2,setosa +5,3.6,1.4,0.2,setosa +5.4,3.9,1.7,0.4,setosa +4.6,3.4,1.4,0.3,setosa +5,3.4,1.5,0.2,setosa +4.4,2.9,1.4,0.2,setosa +4.9,3.1,1.5,0.1,setosa +5.4,3.7,1.5,0.2,setosa +4.8,3.4,1.6,0.2,setosa +4.8,3,1.4,0.1,setosa +4.3,3,1.1,0.1,setosa +5.8,4,1.2,0.2,setosa +5.7,4.4,1.5,0.4,setosa +5.4,3.9,1.3,0.4,setosa +5.1,3.5,1.4,0.3,setosa +5.7,3.8,1.7,0.3,setosa +5.1,3.8,1.5,0.3,setosa +5.4,3.4,1.7,0.2,setosa +5.1,3.7,1.5,0.4,setosa +4.6,3.6,1,0.2,setosa +5.1,3.3,1.7,0.5,setosa +4.8,3.4,1.9,0.2,setosa +5,3,1.6,0.2,setosa +5,3.4,1.6,0.4,setosa +5.2,3.5,1.5,0.2,setosa +5.2,3.4,1.4,0.2,setosa +4.7,3.2,1.6,0.2,setosa +4.8,3.1,1.6,0.2,setosa +5.4,3.4,1.5,0.4,setosa +5.2,4.1,1.5,0.1,setosa +5.5,4.2,1.4,0.2,setosa +4.9,3.1,1.5,0.1,setosa +5,3.2,1.2,0.2,setosa +5.5,3.5,1.3,0.2,setosa +4.9,3.1,1.5,0.1,setosa +4.4,3,1.3,0.2,setosa +5.1,3.4,1.5,0.2,setosa +5,3.5,1.3,0.3,setosa +4.5,2.3,1.3,0.3,setosa +4.4,3.2,1.3,0.2,setosa +5,3.5,1.6,0.6,setosa +5.1,3.8,1.9,0.4,setosa +4.8,3,1.4,0.3,setosa +5.1,3.8,1.6,0.2,setosa +4.6,3.2,1.4,0.2,setosa +5.3,3.7,1.5,0.2,setosa +5,3.3,1.4,0.2,setosa +7,3.2,4.7,1.4,versicolor +6.4,3.2,4.5,1.5,versicolor +6.9,3.1,4.9,1.5,versicolor +5.5,2.3,4,1.3,versicolor +6.5,2.8,4.6,1.5,versicolor +5.7,2.8,4.5,1.3,versicolor +6.3,3.3,4.7,1.6,versicolor +4.9,2.4,3.3,1,versicolor +6.6,2.9,4.6,1.3,versicolor +5.2,2.7,3.9,1.4,versicolor +5,2,3.5,1,versicolor +5.9,3,4.2,1.5,versicolor +6,2.2,4,1,versicolor +6.1,2.9,4.7,1.4,versicolor +5.6,2.9,3.6,1.3,versicolor +6.7,3.1,4.4,1.4,versicolor +5.6,3,4.5,1.5,versicolor +5.8,2.7,4.1,1,versicolor +6.2,2.2,4.5,1.5,versicolor +5.6,2.5,3.9,1.1,versicolor +5.9,3.2,4.8,1.8,versicolor +6.1,2.8,4,1.3,versicolor +6.3,2.5,4.9,1.5,versicolor +6.1,2.8,4.7,1.2,versicolor +6.4,2.9,4.3,1.3,versicolor +6.6,3,4.4,1.4,versicolor +6.8,2.8,4.8,1.4,versicolor +6.7,3,5,1.7,versicolor +6,2.9,4.5,1.5,versicolor +5.7,2.6,3.5,1,versicolor +5.5,2.4,3.8,1.1,versicolor +5.5,2.4,3.7,1,versicolor +5.8,2.7,3.9,1.2,versicolor +6,2.7,5.1,1.6,versicolor +5.4,3,4.5,1.5,versicolor +6,3.4,4.5,1.6,versicolor +6.7,3.1,4.7,1.5,versicolor +6.3,2.3,4.4,1.3,versicolor +5.6,3,4.1,1.3,versicolor +5.5,2.5,4,1.3,versicolor +5.5,2.6,4.4,1.2,versicolor +6.1,3,4.6,1.4,versicolor +5.8,2.6,4,1.2,versicolor +5,2.3,3.3,1,versicolor +5.6,2.7,4.2,1.3,versicolor +5.7,3,4.2,1.2,versicolor +5.7,2.9,4.2,1.3,versicolor +6.2,2.9,4.3,1.3,versicolor +5.1,2.5,3,1.1,versicolor +5.7,2.8,4.1,1.3,versicolor +6.3,3.3,6,2.5,virginica +5.8,2.7,5.1,1.9,virginica +7.1,3,5.9,2.1,virginica +6.3,2.9,5.6,1.8,virginica +6.5,3,5.8,2.2,virginica +7.6,3,6.6,2.1,virginica +4.9,2.5,4.5,1.7,virginica +7.3,2.9,6.3,1.8,virginica +6.7,2.5,5.8,1.8,virginica +7.2,3.6,6.1,2.5,virginica +6.5,3.2,5.1,2,virginica +6.4,2.7,5.3,1.9,virginica +6.8,3,5.5,2.1,virginica +5.7,2.5,5,2,virginica +5.8,2.8,5.1,2.4,virginica +6.4,3.2,5.3,2.3,virginica +6.5,3,5.5,1.8,virginica +7.7,3.8,6.7,2.2,virginica +7.7,2.6,6.9,2.3,virginica +6,2.2,5,1.5,virginica +6.9,3.2,5.7,2.3,virginica +5.6,2.8,4.9,2,virginica +7.7,2.8,6.7,2,virginica +6.3,2.7,4.9,1.8,virginica +6.7,3.3,5.7,2.1,virginica +7.2,3.2,6,1.8,virginica +6.2,2.8,4.8,1.8,virginica +6.1,3,4.9,1.8,virginica +6.4,2.8,5.6,2.1,virginica +7.2,3,5.8,1.6,virginica +7.4,2.8,6.1,1.9,virginica +7.9,3.8,6.4,2,virginica +6.4,2.8,5.6,2.2,virginica +6.3,2.8,5.1,1.5,virginica +6.1,2.6,5.6,1.4,virginica +7.7,3,6.1,2.3,virginica +6.3,3.4,5.6,2.4,virginica +6.4,3.1,5.5,1.8,virginica +6,3,4.8,1.8,virginica +6.9,3.1,5.4,2.1,virginica +6.7,3.1,5.6,2.4,virginica +6.9,3.1,5.1,2.3,virginica +5.8,2.7,5.1,1.9,virginica +6.8,3.2,5.9,2.3,virginica +6.7,3.3,5.7,2.5,virginica +6.7,3,5.2,2.3,virginica +6.3,2.5,5,1.9,virginica +6.5,3,5.2,2,virginica +6.2,3.4,5.4,2.3,virginica +5.9,3,5.1,1.8,virginica diff --git a/web/examples/line.html b/web-src/examples/line.html similarity index 88% rename from web/examples/line.html rename to web-src/examples/line.html index 39960e3be6..522e7d3af6 100644 --- a/web/examples/line.html +++ b/web-src/examples/line.html @@ -17,8 +17,8 @@ +
    +
    +
    +
    + + + + + + +
    + + diff --git a/web/examples/lysenko-interval-tree.js b/web-src/examples/lysenko-interval-tree.js similarity index 100% rename from web/examples/lysenko-interval-tree.js rename to web-src/examples/lysenko-interval-tree.js diff --git a/web/examples/monthly-move.csv b/web-src/examples/monthly-move.csv similarity index 100% rename from web/examples/monthly-move.csv rename to web-src/examples/monthly-move.csv diff --git a/web/examples/morley.csv b/web-src/examples/morley.csv similarity index 100% rename from web/examples/morley.csv rename to web-src/examples/morley.csv diff --git a/web/examples/morley2.csv b/web-src/examples/morley2.csv similarity index 100% rename from web/examples/morley2.csv rename to web-src/examples/morley2.csv diff --git a/web/examples/morley3.csv b/web-src/examples/morley3.csv similarity index 100% rename from web/examples/morley3.csv rename to web-src/examples/morley3.csv diff --git a/web/examples/multi-focus.html b/web-src/examples/multi-focus.html similarity index 83% rename from web/examples/multi-focus.html rename to web-src/examples/multi-focus.html index 437b763edc..63f1c38d76 100644 --- a/web/examples/multi-focus.html +++ b/web-src/examples/multi-focus.html @@ -1,10 +1,11 @@ - dc.js - Filter Group Example + dc.js - Multiple Focus Charts for a Range Chart + @@ -20,12 +21,12 @@ + + + + + + +
    + + +

    You can use fake groups and a composite chart to implement a dynamic Pareto chart in dc.js.

    + +
    +
    + + +
    + + diff --git a/web/examples/pie-external-labels.html b/web-src/examples/pie-external-labels.html similarity index 91% rename from web/examples/pie-external-labels.html rename to web-src/examples/pie-external-labels.html index a8adeaf1cb..41b4dc4d30 100644 --- a/web/examples/pie-external-labels.html +++ b/web-src/examples/pie-external-labels.html @@ -1,7 +1,7 @@ - dc.js - Pie Chart External Labels Example + dc.js - Pie Chart with External Labels @@ -17,8 +17,8 @@ -

    This page demonstrates a very hacky workaround for issue #479, using a series chart as a range chart. +

    This page demonstrates a line chart used as a rangeChart after #479 + is fixed by #1408.

    @@ -20,11 +21,13 @@ +

    This example demonstrates using regression.js + to calculate a linear regression on the points in a scatter plot.

    + +
    + + + + + + + + + + diff --git a/web/examples/replacing-data.html b/web-src/examples/replacing-data.html similarity index 69% rename from web/examples/replacing-data.html rename to web-src/examples/replacing-data.html index 1a3415920b..98ebd9e7d3 100644 --- a/web/examples/replacing-data.html +++ b/web-src/examples/replacing-data.html @@ -8,25 +8,25 @@ - +
    - - - + + +

    This page will replace the crossfilter data in 5 seconds. If you modify the filters before then, the filters will be restored.

    -

    It's based on a question +

    It's based on a question and answer on Stack Overflow; question by geotheory, answer by Ethan Jewett.

    +
    + + + + + + +
    + + diff --git a/web-src/examples/row-top-axis.html b/web-src/examples/row-top-axis.html new file mode 100644 index 0000000000..75002ddcc4 --- /dev/null +++ b/web-src/examples/row-top-axis.html @@ -0,0 +1,53 @@ + + + + dc.js - Row Chart with a Top Axis + + + + + + +
    + +
    + + + + + + +
    + + diff --git a/web-src/examples/row-vertical-line.html b/web-src/examples/row-vertical-line.html new file mode 100644 index 0000000000..6500d536f5 --- /dev/null +++ b/web-src/examples/row-vertical-line.html @@ -0,0 +1,67 @@ + + + + dc.js - Row Chart with Vertical Line + + + + + + +
    + +
    + + + + + + +
    + + diff --git a/web/examples/row.html b/web-src/examples/row.html similarity index 89% rename from web/examples/row.html rename to web-src/examples/row.html index 9e342e3e64..7df8c64fa0 100644 --- a/web/examples/row.html +++ b/web-src/examples/row.html @@ -17,8 +17,8 @@ + +

    Plotting 20,000 data points in 2 plots. Plots may take several seconds to load. Brush on one chart to see the points filtered on the other.

    +
    +
    + + + + + + + + + diff --git a/web-src/examples/scatter-canvas-large.html b/web-src/examples/scatter-canvas-large.html new file mode 100644 index 0000000000..11c47af374 --- /dev/null +++ b/web-src/examples/scatter-canvas-large.html @@ -0,0 +1,118 @@ + + + + dc.js - Scatter Plot Brushing Example - Large Dataset, Canvas Backend + + + + + + + + +
    + +

    dc.js - Scatter Plot Brushing Example - Large Dataset, Canvas Backend

    +

    Plotting 20,000 data points in 2 plots. Plots may take several seconds to load. Brush on one chart to see the points filtered on the other. Compare against performance using SVG backend in the SVG large dataset scatter plot example.

    +
    +
    +
    +
    + +
    + +
    + diff --git a/web/examples/scatter-series.html b/web-src/examples/scatter-series.html similarity index 80% rename from web/examples/scatter-series.html rename to web-src/examples/scatter-series.html index 1d34d8927d..c79ad20039 100644 --- a/web/examples/scatter-series.html +++ b/web-src/examples/scatter-series.html @@ -1,7 +1,7 @@ - dc.js - Series Example + dc.js - Series Scatter Plot Example @@ -17,19 +17,19 @@ + + + + +
    + +

    dc.js - Scatter Plot Brushing Example - Large Dataset, SVG Backend

    +

    Plotting 20,000 data points in 2 plots. Plots may take a few seconds to load. Brush on one chart to see the points filtered on the other. Compare against performance using Canvas backend in the Canvas scatter plot example.

    +
    +
    +
    +
    + +
    + +
    + diff --git a/web-src/examples/scatter-top.html b/web-src/examples/scatter-top.html new file mode 100644 index 0000000000..d2775b72c0 --- /dev/null +++ b/web-src/examples/scatter-top.html @@ -0,0 +1,53 @@ + + + + dc.js - Scatter Plot Top X Axis Example + + + + + + +
    + +
    + + + + + + +
    + + diff --git a/web/examples/scatter.html b/web-src/examples/scatter.html similarity index 81% rename from web/examples/scatter.html rename to web-src/examples/scatter.html index d72232400a..df8fd30ee4 100644 --- a/web/examples/scatter.html +++ b/web-src/examples/scatter.html @@ -17,21 +17,21 @@

    Sparklines

    -

    A sparkline is just a tiny chart that fits in to the flow of text. We can achieve this by using a span instead of a div, and making the dimensions really small. They will work well for any chart with a large x:y aspect ratio, like a line chart or a bar chart but other kinds of charts probably won't work so well. We'll also use a little bit of custom CSS to hide the axes (see the source for details).

    +

    A sparkline is just a tiny chart that fits in to the flow of text. We can achieve this by using a span instead of a div, and making the dimensions really small. They will work well for any chart with a large x:y aspect ratio, like a line chart or a bar chart but other kinds of charts probably won't work so well. We'll also use a little bit of custom CSS to hide the axes (see the source for details).

    @@ -23,9 +23,9 @@

    Sparklines

    + + +
    + + +

    Scatterplot Matrix Brushing in + dc.js. Imitating Mike's bl.ock.

    + +

    dc.js will not be as efficient as a custom implementation, and there's a perceptible lag, + but this technique may be useful sometimes. By default, dc.js always waits to trigger events + because it is assumed that updating will be costly + - add ?nowait to see how this + performs without event delay.

    +
    +
    + + + + diff --git a/web-src/examples/stacked-bar.html b/web-src/examples/stacked-bar.html new file mode 100644 index 0000000000..98f2d2e536 --- /dev/null +++ b/web-src/examples/stacked-bar.html @@ -0,0 +1,81 @@ + + + + dc.js - Stacked Bar Example + + + + + + + +
    + +
    + + + + + + +
    + + diff --git a/web-src/examples/sunburst-cat.html b/web-src/examples/sunburst-cat.html new file mode 100644 index 0000000000..b6b392215a --- /dev/null +++ b/web-src/examples/sunburst-cat.html @@ -0,0 +1,81 @@ + + + + dc.js - Sunburst File Listing + + + + + + + + +
    + + +
    +
    + + + + + + +
    + + diff --git a/web-src/examples/sunburst-equal-radii.html b/web-src/examples/sunburst-equal-radii.html new file mode 100644 index 0000000000..432a4f46f8 --- /dev/null +++ b/web-src/examples/sunburst-equal-radii.html @@ -0,0 +1,64 @@ + + + + dc.js - Sunburst Chart Example with equally sized rings + + + + + + + + +
    + + +
    + + + + + + +
    + + diff --git a/web-src/examples/sunburst-with-value-accessor.html b/web-src/examples/sunburst-with-value-accessor.html new file mode 100644 index 0000000000..69219eb622 --- /dev/null +++ b/web-src/examples/sunburst-with-value-accessor.html @@ -0,0 +1,85 @@ + + + + dc.js - Sunburst with Reductio + + + + + + + +
    + + +

    + This example uses Reductio to reduce groups. + It generates multiple reductions - the chart uses one of the those using a custom value accessor. + This example also demonstrates fix for issue #1440. +

    + +
    + + + + + + + +
    + + diff --git a/web-src/examples/sunburst.html b/web-src/examples/sunburst.html new file mode 100644 index 0000000000..e946c3c1ed --- /dev/null +++ b/web-src/examples/sunburst.html @@ -0,0 +1,90 @@ + + + + dc.js - Sunburst Chart Example + + + + + + + + +
    + + +
    +
    +
    + + + + + + +
    + + diff --git a/web-src/examples/switching-time-intervals.html b/web-src/examples/switching-time-intervals.html new file mode 100644 index 0000000000..c20de1104b --- /dev/null +++ b/web-src/examples/switching-time-intervals.html @@ -0,0 +1,179 @@ + + + + dc.js - Switching Time Intervals + + + + + + + +
    + + +

    This example demonstrates switching between different intervals of aggregation over time.

    + + +
    +
    +
    +

    You can supply your own data source with query string parameters: +

    +
    data
    URL to load
    +
    aggregate
    Aggregation method: average or total +
    date
    Date column name
    +
    val
    Value column name
    +
    +

    +
    + + + + + + +
    + + diff --git a/web/examples/table-on-aggregated-data.html b/web-src/examples/table-on-aggregated-data.html similarity index 50% rename from web/examples/table-on-aggregated-data.html rename to web-src/examples/table-on-aggregated-data.html index 7eda418fc5..fac5dc13c4 100644 --- a/web/examples/table-on-aggregated-data.html +++ b/web-src/examples/table-on-aggregated-data.html @@ -10,6 +10,12 @@
    + +
    + + +
    + @@ -25,24 +31,29 @@ diff --git a/web-src/examples/table-pagination.html b/web-src/examples/table-pagination.html new file mode 100644 index 0000000000..e7304e93eb --- /dev/null +++ b/web-src/examples/table-pagination.html @@ -0,0 +1,113 @@ + + + + dc.js - Table Pagination Example + + + + + + +
    + + +
    +

    Expt:

    + +
    +
    +
    +
    + Showing - of + + +
    +
    +
    + + + + + + + + + diff --git a/web-src/examples/text-filter-widget.html b/web-src/examples/text-filter-widget.html new file mode 100644 index 0000000000..03653217a1 --- /dev/null +++ b/web-src/examples/text-filter-widget.html @@ -0,0 +1,79 @@ + + + + dc.js - Text Filter Example + + + + + +
    + + + +
    + + + + + + + + +
    NbFirst NameLast Name
    +
    + + + + + + + +
    + + diff --git a/web/examples/time-intervals.html b/web-src/examples/time-intervals.html similarity index 80% rename from web/examples/time-intervals.html rename to web-src/examples/time-intervals.html index 099606e7ea..0a8180b185 100644 --- a/web/examples/time-intervals.html +++ b/web-src/examples/time-intervals.html @@ -5,6 +5,7 @@ + @@ -14,14 +15,18 @@

    This demonstrates using an interval tree to plot items which span from a begin date to an end date. The brush will intersect with any items whose intervals overlap with it.

    + +

    It uses the interval-tree-1d +library by Mikola Lysenko.

    +
    @@ -34,7 +39,7 @@ function intervalTreeGroup(tree, firstDate, lastDate) { return { all: function() { - var begin = d3.time.month(firstDate), end = d3.time.month(lastDate); + var begin = d3.timeMonth(firstDate), end = d3.timeMonth(lastDate); var i = new Date(begin); var ret = [], count; do { @@ -52,15 +57,18 @@ } }; } - var timeFormat = d3.time.format('%x'); - var monthChart = dc.barChart("#month"); - var costChart = dc.barChart("#cost"); + + var dateFormatSpecifier = '%x'; + var timeFormat = d3.timeFormat(dateFormatSpecifier); + var dateFormatParser = d3.timeParse(dateFormatSpecifier); + var monthChart = new dc.BarChart("#month"); + var costChart = new dc.BarChart("#cost"); // data from http://stackoverflow.com/questions/22603788/crossfilter-how-to-extract-time-information-from-start-date-and-end-date-column - d3.csv("intervals.csv", function(error, projects) { + d3.csv("intervals.csv").then(function(projects) { projects.forEach(function(x) { - x['Start Date'] = timeFormat.parse(x['Start Date']); - x['End Date'] = timeFormat.parse(x['End Date']); + x['Start Date'] = dateFormatParser(x['Start Date']); + x['End Date'] = dateFormatParser(x['End Date']); // the library uses object identity so we have to cache the interval arrays x.interval = [x['Start Date'].getTime(), x['End Date'].getTime()]; x.Cost = +x.Cost; @@ -91,9 +99,9 @@ monthChart .width(400) .height(300) - .x(d3.time.scale()) - .y(d3.scale.linear().domain([0,25])) - .xUnits(d3.time.months) + .x(d3.scaleTime()) + .y(d3.scaleLinear().domain([0,25])) + .xUnits(d3.timeMonths) .gap(5) .elasticX(true) .brushOn(true) @@ -120,8 +128,8 @@ costChart .width(400) .height(300) - .x(d3.scale.linear().domain([0,24])) - .y(d3.scale.linear().domain([0,25])) + .x(d3.scaleLinear().domain([0,24])) + .y(d3.scaleLinear().domain([0,25])) .brushOn(true) .yAxisLabel("Number of Projects") .xAxisLabel("Cost") diff --git a/web-src/examples/wide-ordinal.json b/web-src/examples/wide-ordinal.json new file mode 100644 index 0000000000..4a33c5c948 --- /dev/null +++ b/web-src/examples/wide-ordinal.json @@ -0,0 +1,1942 @@ +[ + { + "key": "bassist vocalise wrung execrate", + "value": 887 + }, + { + "key": "mugger infarct prosaic linking", + "value": 40 + }, + { + "key": "neophyte soppy natality afforest", + "value": 895 + }, + { + "key": "diver bedcover woolfell durbar", + "value": 14 + }, + { + "key": "shippen manicure vin wasting", + "value": 2 + }, + { + "key": "curiae coition mistress slipover", + "value": 2 + }, + { + "key": "hadst blowout therm phase", + "value": 2 + }, + { + "key": "speiss caloyer batwing legman", + "value": 495 + }, + { + "key": "amitosis sirup digress saunter", + "value": 838 + }, + { + "key": "deformed gerbil abradant pursuer", + "value": 3 + }, + { + "key": "parament wamble dollop oboe", + "value": 7 + }, + { + "key": "peptide casque hall trivia", + "value": 8 + }, + { + "key": "subway saving scenic anodyne", + "value": 2 + }, + { + "key": "expense typical gyral conclave", + "value": 7 + }, + { + "key": "syndetic prosaism unreel sheepdog", + "value": 5 + }, + { + "key": "smarten trouveur cutis satirize", + "value": 7 + }, + { + "key": "develop spend crural inflame", + "value": 6 + }, + { + "key": "entreaty tubby borehole result", + "value": 6 + }, + { + "key": "ocrea mechanic riotous cerulean", + "value": 3 + }, + { + "key": "unblock scroll mauve let", + "value": 3 + }, + { + "key": "ixia dirge gauger toot", + "value": 2 + }, + { + "key": "nickel grange obdurate aphotic", + "value": 2 + }, + { + "key": "submerge motmot treatise galling", + "value": 2 + }, + { + "key": "acicula sorcery fallout widely", + "value": 2 + }, + { + "key": "gaudy shirt scilicet cuddle", + "value": 10 + }, + { + "key": "foredo holdover revive threat", + "value": 5 + }, + { + "key": "cowling charter rhizome cholent", + "value": 2 + }, + { + "key": "sniper corpora murine poco", + "value": 2 + }, + { + "key": "format intend rancho saran", + "value": 2 + }, + { + "key": "jerry punnet adopted nearby", + "value": 7 + }, + { + "key": "leafage peddle fretted gravity", + "value": 8 + }, + { + "key": "swart urbane coccyx match", + "value": 2 + }, + { + "key": "fuss tut claiming agile", + "value": 2 + }, + { + "key": "borsch wingback thumb footworn", + "value": 5 + }, + { + "key": "access taut cube cortege", + "value": 4 + }, + { + "key": "baddie outspeak sejant ether", + "value": 2 + }, + { + "key": "quantize empanel guru satinet", + "value": 6 + }, + { + "key": "fee seducer peeve misdoubt", + "value": 27 + }, + { + "key": "washing pacific up detailed", + "value": 7 + }, + { + "key": "ostiole beehive cascabel agency", + "value": 5 + }, + { + "key": "describe bobwhite carving unite", + "value": 4 + }, + { + "key": "illicit masked lappet hoarding", + "value": 2 + }, + { + "key": "frump bottom throttle gleeman", + "value": 2 + }, + { + "key": "forepart sabre stagger pilau", + "value": 2 + }, + { + "key": "tannin trypsin revisory pedicab", + "value": 2 + }, + { + "key": "likable religion civil degauss", + "value": 4 + }, + { + "key": "entirety procaine alienism duress", + "value": 770 + }, + { + "key": "murphy hilt octoroon allay", + "value": 753 + }, + { + "key": "taffrail divagate dramatic mattress", + "value": 28 + }, + { + "key": "charr ammonal strath lacework", + "value": 35 + }, + { + "key": "buran plank youthful scrawl", + "value": 1048 + }, + { + "key": "whoops hazel mil copalm", + "value": 33 + }, + { + "key": "acuate corpsman shelled halo", + "value": 498 + }, + { + "key": "phi mishear stone neath", + "value": 59 + }, + { + "key": "jury centuple fleshly smug", + "value": 13 + }, + { + "key": "lithic squirm ladylove porphyry", + "value": 357 + }, + { + "key": "coat shallop catalpa dimple", + "value": 927 + }, + { + "key": "gabelle yacht frill instance", + "value": 72 + }, + { + "key": "duress prithee phatic kibe", + "value": 21 + }, + { + "key": "stannary jiggle foothold epicycle", + "value": 2 + }, + { + "key": "teenager lodging hotspur fickle", + "value": 55 + }, + { + "key": "edifice motorcar luck guenon", + "value": 2 + }, + { + "key": "emirate bosk cell spry", + "value": 2 + }, + { + "key": "revival evanesce alarmist fire", + "value": 2 + }, + { + "key": "hoodlum eldest lysine burke", + "value": 2 + }, + { + "key": "ruthless leister evince know", + "value": 459 + }, + { + "key": "fable labor zipper mm", + "value": 1019 + }, + { + "key": "coaler columnar divisor aculeus", + "value": 836 + }, + { + "key": "bicker lacteal savage trine", + "value": 1180 + }, + { + "key": "bound jocose snooty masthead", + "value": 489 + }, + { + "key": "locoism nympho division crowded", + "value": 321 + }, + { + "key": "assassin kendo magnum probity", + "value": 519 + }, + { + "key": "chore stereo instate myopia", + "value": 672 + }, + { + "key": "jury forby bellied titanite", + "value": 680 + }, + { + "key": "breviary clothier insipid valine", + "value": 672 + }, + { + "key": "feeble stud neonatal stalwart", + "value": 673 + }, + { + "key": "jab flange cheery taco", + "value": 676 + }, + { + "key": "fermion frazzled karyotin tenia", + "value": 676 + }, + { + "key": "arcature gloriole attack defrost", + "value": 677 + }, + { + "key": "whoreson pullet clang bowleg", + "value": 687 + }, + { + "key": "brunt clypeate garotte gravity", + "value": 677 + }, + { + "key": "lemma ganglion wither quagmire", + "value": 675 + }, + { + "key": "consols pharisee lentigo belly", + "value": 674 + }, + { + "key": "brisling baler sloppy shopping", + "value": 681 + }, + { + "key": "fill batiste steel huffish", + "value": 2 + }, + { + "key": "ruth bottoms logbook caudate", + "value": 677 + }, + { + "key": "algebra bandy stibnite notation", + "value": 334 + }, + { + "key": "floaty llama thatch ariel", + "value": 1177 + }, + { + "key": "televise secondly cosmism nuptial", + "value": 674 + }, + { + "key": "drawl stall redtop uphill", + "value": 336 + }, + { + "key": "pochard between guttle swaddle", + "value": 334 + }, + { + "key": "gratin mutation napoleon fleck", + "value": 336 + }, + { + "key": "cutis lamella anxious skullcap", + "value": 336 + }, + { + "key": "fervor kakapo impend dubious", + "value": 675 + }, + { + "key": "hothouse feculent cupreous cabaret", + "value": 845 + }, + { + "key": "banana hold failing besom", + "value": 334 + }, + { + "key": "tinnitus lookout mandamus limner", + "value": 843 + }, + { + "key": "cantor bream pareu economy", + "value": 334 + }, + { + "key": "panty jacal whip passion", + "value": 677 + }, + { + "key": "strep bestial fancier cuticula", + "value": 26 + }, + { + "key": "hyaloid date unkenned spud", + "value": 31 + }, + { + "key": "flax akee alter pedicure", + "value": 24 + }, + { + "key": "dizen drum buss tramp", + "value": 482 + }, + { + "key": "weirdo lar gnosis courses", + "value": 178 + }, + { + "key": "now eight forborne costumer", + "value": 30 + }, + { + "key": "bookie costa foehn pooh", + "value": 508 + }, + { + "key": "away cowpox mortise headless", + "value": 12 + }, + { + "key": "swab crown doings mimosa", + "value": 2 + }, + { + "key": "venetian arrest chamfron politick", + "value": 26 + }, + { + "key": "torpid indue hormonal uphill", + "value": 2 + }, + { + "key": "kulak repulse ingrown peltry", + "value": 23 + }, + { + "key": "previse abampere period tagmemic", + "value": 2 + }, + { + "key": "shadowy whirl windward loot", + "value": 16 + }, + { + "key": "citrate foal aurist mesial", + "value": 490 + }, + { + "key": "geisha bosom squander hokku", + "value": 80 + }, + { + "key": "streaky doura tigress sauna", + "value": 21 + }, + { + "key": "triptych lapidary playboy triangle", + "value": 34 + }, + { + "key": "lancer doorstop vaporize ganister", + "value": 125 + }, + { + "key": "farriery predial parterre spark", + "value": 10 + }, + { + "key": "hydropic paperboy sheikdom tutorial", + "value": 21 + }, + { + "key": "shingly polenta wheaten beldam", + "value": 24 + }, + { + "key": "portiere rite actinon sly", + "value": 387 + }, + { + "key": "eruct bogey tenaille benefice", + "value": 386 + }, + { + "key": "untie aptitude tribunal graph", + "value": 504 + }, + { + "key": "bracing autarchy ternate exsect", + "value": 503 + }, + { + "key": "haar weaken continue unsure", + "value": 498 + }, + { + "key": "piggy moult aspirate parquet", + "value": 470 + }, + { + "key": "heist ocreate ambsace scutter", + "value": 501 + }, + { + "key": "cod corium stagey vignette", + "value": 39 + }, + { + "key": "ermine glans peony anvil", + "value": 2 + }, + { + "key": "consols refinery burg windage", + "value": 379 + }, + { + "key": "drivel agio mandible precess", + "value": 30 + }, + { + "key": "lathe scofflaw castle enclave", + "value": 14 + }, + { + "key": "barge isoline dihedron anlage", + "value": 2 + }, + { + "key": "khanate xanthin basis airdrome", + "value": 1489 + }, + { + "key": "outwear skeg have calcine", + "value": 836 + }, + { + "key": "rhapsody simply tamandua giant", + "value": 79 + }, + { + "key": "loaded irritate thing festal", + "value": 46 + }, + { + "key": "hunt assess barbaric flare", + "value": 2 + }, + { + "key": "fatally furl marasca covering", + "value": 2 + }, + { + "key": "bairn allonge spree tankard", + "value": 34 + }, + { + "key": "blintz rapper tressure keg", + "value": 38 + }, + { + "key": "opaline peewit pyrosis conduct", + "value": 2 + }, + { + "key": "group fleam forspent guide", + "value": 5 + }, + { + "key": "sparing postdate gorgeous admiral", + "value": 2 + }, + { + "key": "dilate nelson stoma trinal", + "value": 2 + }, + { + "key": "daytime signor sneer viscount", + "value": 23 + }, + { + "key": "comitia linesman tetany amnion", + "value": 21 + }, + { + "key": "pekan drunkard iodine emmet", + "value": 334 + }, + { + "key": "volcano track gook decrepit", + "value": 334 + }, + { + "key": "estrin motivity pagurian avens", + "value": 334 + }, + { + "key": "funded clue evacuate spillway", + "value": 334 + }, + { + "key": "much prorate haycock staves", + "value": 334 + }, + { + "key": "bucksaw obturate flagpole indoxyl", + "value": 334 + }, + { + "key": "trace sobriety shashlik fuzzy", + "value": 334 + }, + { + "key": "vaunt bennet jackal manhunt", + "value": 334 + }, + { + "key": "grizzled aft debase bolo", + "value": 334 + }, + { + "key": "mince retrench ringdove cleome", + "value": 334 + }, + { + "key": "lanneret superadd shoot rapport", + "value": 334 + }, + { + "key": "lineal maritime staying morse", + "value": 334 + }, + { + "key": "smoker copperas basking itchy", + "value": 28 + }, + { + "key": "shingle jackleg nib venose", + "value": 157 + }, + { + "key": "elicit redolent osier dietary", + "value": 4 + }, + { + "key": "devisor claim fustic rakish", + "value": 4 + }, + { + "key": "occident avenue agency amen", + "value": 2 + }, + { + "key": "scion special oyez orrery", + "value": 188 + }, + { + "key": "baobab chukker titania software", + "value": 20 + }, + { + "key": "fusion puttee uncinate not", + "value": 15 + }, + { + "key": "fives agave yarn parting", + "value": 15 + }, + { + "key": "crown pilchard gapped mush", + "value": 2 + }, + { + "key": "prudish mule ingoing whimsey", + "value": 2 + }, + { + "key": "kisser caseose widen fleawort", + "value": 420 + }, + { + "key": "bearded scaup lockout lemon", + "value": 424 + }, + { + "key": "orgulous wither sacred disunite", + "value": 157 + }, + { + "key": "rubbing ere tacket puny", + "value": 391 + }, + { + "key": "midriff yashmak suspend mirror", + "value": 28 + }, + { + "key": "rapport medial astral tile", + "value": 197 + }, + { + "key": "rig logo deadbeat hamster", + "value": 500 + }, + { + "key": "nursling purpura ormolu vein", + "value": 360 + }, + { + "key": "conte bricole havoc exorcism", + "value": 375 + }, + { + "key": "anyway tactual ratal agora", + "value": 322 + }, + { + "key": "ungainly booklet novelist carpet", + "value": 15 + }, + { + "key": "bidarka durbar locule hornwort", + "value": 2 + }, + { + "key": "palestra nerve odeum alchemy", + "value": 56 + }, + { + "key": "staff covet axilla signpost", + "value": 52 + }, + { + "key": "restrain reposit malefic whistler", + "value": 241 + }, + { + "key": "maihem anele snake festival", + "value": 49 + }, + { + "key": "whittle debunk abfarad dystopia", + "value": 402 + }, + { + "key": "advanced amuse salify diazine", + "value": 66 + }, + { + "key": "reseat figurant sumac rind", + "value": 9 + }, + { + "key": "spline whore paraph accursed", + "value": 504 + }, + { + "key": "thrash trailing ibex shush", + "value": 506 + }, + { + "key": "pastern so lobbyist jugular", + "value": 501 + }, + { + "key": "gauge rattling gorilla textile", + "value": 505 + }, + { + "key": "anapest hieratic work annulose", + "value": 385 + }, + { + "key": "out enounce sawyer outsole", + "value": 28 + }, + { + "key": "pertain credence stammer sennet", + "value": 28 + }, + { + "key": "gynecic coccus sieve zaibatsu", + "value": 36 + }, + { + "key": "spire snick laddie motion", + "value": 42 + }, + { + "key": "quinsy foveola memento sleekit", + "value": 58 + }, + { + "key": "analemma clouded restate cheque", + "value": 495 + }, + { + "key": "bomber aryl eau groping", + "value": 117 + }, + { + "key": "cowberry gnome ancient firing", + "value": 41 + }, + { + "key": "antilog oryx assassin lapwing", + "value": 4 + }, + { + "key": "dray radicle unbroken dell", + "value": 14 + }, + { + "key": "comic blame pic pollen", + "value": 28 + }, + { + "key": "heroin mort collapse maverick", + "value": 430 + }, + { + "key": "strait momentum sports wearable", + "value": 4 + }, + { + "key": "aye joule crystal velar", + "value": 14 + }, + { + "key": "outcrop allied naphthyl peddle", + "value": 44 + }, + { + "key": "hippy deme skysail mettle", + "value": 18 + }, + { + "key": "foment lunatic swirl faraway", + "value": 84 + }, + { + "key": "pion giblets frizzly retake", + "value": 25 + }, + { + "key": "neutral critter prowess vermin", + "value": 40 + }, + { + "key": "denture burgage estrus koa", + "value": 2 + }, + { + "key": "polling confine kat shashlik", + "value": 2 + }, + { + "key": "shroud trunk bastion prandial", + "value": 234 + }, + { + "key": "sap claver amenity marcher", + "value": 28 + }, + { + "key": "sauterne wide cleaver fowl", + "value": 10 + }, + { + "key": "bedding quirt helping barrio", + "value": 375 + }, + { + "key": "inexpert manage leaven decided", + "value": 597 + }, + { + "key": "linkman wolf thespian harness", + "value": 2 + }, + { + "key": "impress seta cutis whimsy", + "value": 10 + }, + { + "key": "possess muticous insanity curacy", + "value": 25 + }, + { + "key": "coquet clink frizzle filum", + "value": 425 + }, + { + "key": "priggish auto callus fitter", + "value": 14 + }, + { + "key": "skiplane hagfish speech fulcrum", + "value": 2 + }, + { + "key": "sung roue diarchy burl", + "value": 184 + }, + { + "key": "rapine windbag fewness apace", + "value": 196 + }, + { + "key": "hayward coating frenulum druid", + "value": 1561 + }, + { + "key": "exoteric nap vidette hast", + "value": 8 + }, + { + "key": "tilde combine diphenyl bulbul", + "value": 21 + }, + { + "key": "upland sloppy formal garrote", + "value": 845 + }, + { + "key": "seaman twit stopover fantom", + "value": 195 + }, + { + "key": "discard defraud froufrou conchoid", + "value": 338 + }, + { + "key": "placid basilisk hakim verecund", + "value": 840 + }, + { + "key": "repp bott weakling baize", + "value": 1471 + }, + { + "key": "bosk giblets kerchief imaret", + "value": 280 + }, + { + "key": "conidium inchoate yeanling haplite", + "value": 35 + }, + { + "key": "ament vedette cutch ionize", + "value": 932 + }, + { + "key": "mailer embowed sirree hosiery", + "value": 30 + }, + { + "key": "soar typhoid six certify", + "value": 385 + }, + { + "key": "fledge mage axle amongst", + "value": 18 + }, + { + "key": "approve taxicab longish overtly", + "value": 1041 + }, + { + "key": "groyne bear hards hilarity", + "value": 670 + }, + { + "key": "clinker degas meddle punish", + "value": 560 + }, + { + "key": "morpheme affine hotfoot phyla", + "value": 3 + }, + { + "key": "firelock thyrse boiler chervil", + "value": 22 + }, + { + "key": "rundle trimaran fanciful holp", + "value": 507 + }, + { + "key": "dwarf wormhole hombre nailhead", + "value": 1020 + }, + { + "key": "bulky triplex colossus bailment", + "value": 501 + }, + { + "key": "aneurin cooncan gossip untwine", + "value": 334 + }, + { + "key": "socage briony ikebana tract", + "value": 18 + }, + { + "key": "curricle disguise though ribbon", + "value": 33 + }, + { + "key": "plonk calyces quiche kingdom", + "value": 840 + }, + { + "key": "datary nappy generate evil", + "value": 835 + }, + { + "key": "social fracas haut neckwear", + "value": 23 + }, + { + "key": "cartel homely ululant pegboard", + "value": 230 + }, + { + "key": "podiatry bear misusage exertion", + "value": 260 + }, + { + "key": "trot fed wheeled supreme", + "value": 667 + }, + { + "key": "cycle timer trick gasser", + "value": 557 + }, + { + "key": "outdoors forint bean byssus", + "value": 74 + }, + { + "key": "immature squares weighty quota", + "value": 251 + }, + { + "key": "deicer mamey hoopla bowshot", + "value": 397 + }, + { + "key": "vector venture otto fourth", + "value": 131 + }, + { + "key": "rubbing sneak seamy azon", + "value": 502 + }, + { + "key": "skyward creeping silent whimper", + "value": 505 + }, + { + "key": "ringer reversal chug carrying", + "value": 503 + }, + { + "key": "wafture codon heading ripen", + "value": 29 + }, + { + "key": "thankful froe foxtail weigela", + "value": 165 + }, + { + "key": "calcium listing lopsided gusher", + "value": 114 + }, + { + "key": "carry divan gusty supernal", + "value": 10 + }, + { + "key": "celibate seventh machree cushion", + "value": 335 + }, + { + "key": "suzerain tenpins nicknack faro", + "value": 197 + }, + { + "key": "stalag clough bats smith", + "value": 36 + }, + { + "key": "trip corn bustle genitor", + "value": 110 + }, + { + "key": "teen immersed seaway sylvite", + "value": 8 + }, + { + "key": "remove entreaty almighty brasilin", + "value": 3 + }, + { + "key": "issuable crowd bobbin bomb", + "value": 88 + }, + { + "key": "pulley maffick trull bronchi", + "value": 21 + }, + { + "key": "suboxide terminal rutile harm", + "value": 214 + }, + { + "key": "minimum pitiless radix peewit", + "value": 341 + }, + { + "key": "beach referred neutrino potency", + "value": 678 + }, + { + "key": "nu nom photopia dead", + "value": 545 + }, + { + "key": "chatter bushbuck jinks fleshy", + "value": 504 + }, + { + "key": "dovekie nummary distil triumph", + "value": 4 + }, + { + "key": "piscator dulcinea kelp carotene", + "value": 290 + }, + { + "key": "sweven gunpaper melanite iceboat", + "value": 503 + }, + { + "key": "courtly accrual speedway geste", + "value": 504 + }, + { + "key": "calla disseise nerves simplism", + "value": 503 + }, + { + "key": "misfile wight kept aloud", + "value": 502 + }, + { + "key": "misplay hospital coyote devisee", + "value": 499 + }, + { + "key": "blab enact yttria chore", + "value": 493 + }, + { + "key": "bestrew plicate evection outwork", + "value": 499 + }, + { + "key": "unbated yippie or deist", + "value": 501 + }, + { + "key": "branks fuze impunity vesica", + "value": 504 + }, + { + "key": "carioca petty lodging goose", + "value": 503 + }, + { + "key": "mousy cosy suture plebe", + "value": 502 + }, + { + "key": "unhand always assuming slope", + "value": 3 + }, + { + "key": "skewness curet silence predict", + "value": 141 + }, + { + "key": "exacting rice suttee titrate", + "value": 500 + }, + { + "key": "chignon gullet draff sequitur", + "value": 503 + }, + { + "key": "bumf martini purine crumhorn", + "value": 563 + }, + { + "key": "myriapod cure apomixis producer", + "value": 40 + }, + { + "key": "pinguid musty longways prayer", + "value": 38 + }, + { + "key": "wizen soricine gonfalon piddle", + "value": 38 + }, + { + "key": "popinjay croaker hyaloid deictic", + "value": 38 + }, + { + "key": "slipover ti collop nobility", + "value": 39 + }, + { + "key": "redbird faller protium kestrel", + "value": 503 + }, + { + "key": "domain gravid intone sawmill", + "value": 42 + }, + { + "key": "trumpet index unclothe gneiss", + "value": 1488 + }, + { + "key": "pion conclave dona beneath", + "value": 18 + }, + { + "key": "aft quilt claver picket", + "value": 543 + }, + { + "key": "scabies ichor loath rayon", + "value": 201 + }, + { + "key": "calyx ordinal congou pentode", + "value": 15 + }, + { + "key": "chump felid german flourish", + "value": 367 + }, + { + "key": "holiday tiffin bugbane amused", + "value": 204 + }, + { + "key": "pace beano ambit sept", + "value": 269 + }, + { + "key": "yard liegeman indicant morion", + "value": 2 + }, + { + "key": "salmi thresh corn sot", + "value": 15 + }, + { + "key": "agitato arkose dabchick acidify", + "value": 46 + }, + { + "key": "cudbear carotid incubate trump", + "value": 1020 + }, + { + "key": "alexin cablet doorjamb accuse", + "value": 501 + }, + { + "key": "bicorn trinket chirk forgive", + "value": 501 + }, + { + "key": "crannog gracile gabby pharos", + "value": 21 + }, + { + "key": "embalm anosmia vantage penult", + "value": 306 + }, + { + "key": "sleave bregma roar jeu", + "value": 503 + }, + { + "key": "strumpet hawse elflock muss", + "value": 502 + }, + { + "key": "inhalant ferine pithy sandbox", + "value": 485 + }, + { + "key": "coff ablaze stern gnathion", + "value": 4 + }, + { + "key": "hookup creative whimsy euonymus", + "value": 3 + }, + { + "key": "vogue humidify tsarina ukulele", + "value": 3 + }, + { + "key": "halting luetic efface implead", + "value": 4 + }, + { + "key": "multure chute suiting nervine", + "value": 3 + }, + { + "key": "gadoid nebulose gravamen signal", + "value": 503 + }, + { + "key": "slipknot hopeless tucker dramatic", + "value": 366 + }, + { + "key": "gin acre yield digger", + "value": 164 + }, + { + "key": "terete kalends polled cursor", + "value": 86 + }, + { + "key": "choragus wayward jowl tod", + "value": 66 + }, + { + "key": "moony aardwolf glade grapple", + "value": 52 + }, + { + "key": "ratter gadoid bumper suspend", + "value": 2 + }, + { + "key": "cutty hug exigible clot", + "value": 2 + }, + { + "key": "cachet kosher cook response", + "value": 325 + }, + { + "key": "glacier maudlin vintner inoculum", + "value": 730 + }, + { + "key": "given postal visually anger", + "value": 300 + }, + { + "key": "teamster pulvinus forgat variola", + "value": 413 + }, + { + "key": "arctic console oxtail gremlin", + "value": 197 + }, + { + "key": "effluent workroom wahoo solidary", + "value": 530 + }, + { + "key": "quackery brand outstrip noose", + "value": 94 + }, + { + "key": "primal ora gagman launce", + "value": 398 + }, + { + "key": "gorgerin whatnot plicate aerostat", + "value": 288 + }, + { + "key": "newborn falsify prunelle hexad", + "value": 540 + }, + { + "key": "crosier lamia kris dibs", + "value": 217 + }, + { + "key": "bale pome blameful climbing", + "value": 164 + }, + { + "key": "whinchat cheque wiry calamite", + "value": 484 + }, + { + "key": "director redroot instar misnomer", + "value": 140 + }, + { + "key": "hunter loth affluent sales", + "value": 504 + }, + { + "key": "tetchy beatify festoon homonym", + "value": 1167 + }, + { + "key": "offend transfer kingship postcard", + "value": 2 + }, + { + "key": "coquille antigen surfboat fictive", + "value": 2 + }, + { + "key": "foppish hag fineable hematite", + "value": 168 + }, + { + "key": "boxer cursed recap wary", + "value": 29 + }, + { + "key": "piddling peg opinion ago", + "value": 2352 + }, + { + "key": "cahoot silica remise icefall", + "value": 320 + }, + { + "key": "caird chrome dilatory arbitral", + "value": 504 + }, + { + "key": "bonus mailbox gimmick demy", + "value": 507 + }, + { + "key": "tier faceless moiety wildwood", + "value": 369 + }, + { + "key": "rapeseed gurgle euphuism meninges", + "value": 294 + }, + { + "key": "reseda sol sponger songful", + "value": 14 + }, + { + "key": "remorse overcoat trotter crore", + "value": 12 + }, + { + "key": "pedicure ophidian momentum silica", + "value": 529 + }, + { + "key": "aliment rachis cocksure tacit", + "value": 501 + }, + { + "key": "panoptic stalky spelter wealth", + "value": 679 + }, + { + "key": "guile gamba taper monies", + "value": 329 + }, + { + "key": "upwind lancers thuya gross", + "value": 2 + }, + { + "key": "suttee knightly preface purity", + "value": 501 + }, + { + "key": "gumboil feral drink ashen", + "value": 532 + }, + { + "key": "hetman peppery forked worst", + "value": 457 + }, + { + "key": "wildfowl gauntry deter scilla", + "value": 3 + }, + { + "key": "floppy ash overhead sickroom", + "value": 1104 + }, + { + "key": "sporadic much eversion stinko", + "value": 336 + }, + { + "key": "jeweler prorate diazole untwist", + "value": 675 + }, + { + "key": "worsen screamer drilling prosody", + "value": 501 + }, + { + "key": "beriberi trifocal islander gnostic", + "value": 269 + }, + { + "key": "repel cherry frag alary", + "value": 11 + }, + { + "key": "shank yolk emblem dey", + "value": 15 + }, + { + "key": "leghorn kiloton ailment dumpy", + "value": 4 + }, + { + "key": "shooter remnant contempt crunch", + "value": 375 + }, + { + "key": "impinge trap shone starter", + "value": 341 + }, + { + "key": "barnyard tally wintery harmless", + "value": 1053 + }, + { + "key": "rampant scolex mugwump quail", + "value": 18 + }, + { + "key": "haruspex vocalism medal enow", + "value": 289 + }, + { + "key": "serai eudemon academic eidetic", + "value": 503 + }, + { + "key": "yeanling ubiety aloof perdure", + "value": 505 + }, + { + "key": "antipole disinter rakish ivories", + "value": 504 + }, + { + "key": "arachnid uredium fruiter highball", + "value": 504 + }, + { + "key": "hatching sloshy boltonia gnosis", + "value": 825 + }, + { + "key": "cool aborning goulash scouting", + "value": 675 + }, + { + "key": "cryogen hexyl beef playbill", + "value": 503 + }, + { + "key": "loony pleurisy suck netsuke", + "value": 665 + }, + { + "key": "alloy cockney labret anole", + "value": 497 + }, + { + "key": "retable tantivy rover grade", + "value": 500 + }, + { + "key": "burlap arillode avenue trow", + "value": 502 + }, + { + "key": "rounded lotion bibber scribble", + "value": 773 + }, + { + "key": "testudo tepid penitent grandson", + "value": 312 + }, + { + "key": "topmast weanling cello panda", + "value": 322 + }, + { + "key": "crusade unrest panfish caruncle", + "value": 414 + }, + { + "key": "unhappy ailing catenate rubidium", + "value": 18 + }, + { + "key": "chemism filmy shape fever", + "value": 4 + }, + { + "key": "gnarly smutty outgoing came", + "value": 326 + }, + { + "key": "fruition tubule prate graphics", + "value": 6 + }, + { + "key": "darkish fizz ruthless wistful", + "value": 14 + }, + { + "key": "blond shampoo burgle whaler", + "value": 13 + }, + { + "key": "dryad diatonic aplasia beggary", + "value": 501 + }, + { + "key": "frog gesso boom baste", + "value": 6 + }, + { + "key": "narrow emplane obstacle lone", + "value": 6 + }, + { + "key": "lastly spigot camise lump", + "value": 5 + }, + { + "key": "vesta sax brier somite", + "value": 2 + }, + { + "key": "sapota cache abalone fragrant", + "value": 4 + }, + { + "key": "pretend englut bob oasis", + "value": 5 + }, + { + "key": "not acedia orts zany", + "value": 8 + }, + { + "key": "pair should makefast pervious", + "value": 27 + }, + { + "key": "yule modeling enroot simoom", + "value": 6 + }, + { + "key": "dor pedicel commend circa", + "value": 14 + }, + { + "key": "dignity time thrower locum", + "value": 6 + }, + { + "key": "franc diner sacral chancy", + "value": 9 + }, + { + "key": "comate rigorism peignoir vender", + "value": 4 + }, + { + "key": "nawab fauna coquito protease", + "value": 4 + }, + { + "key": "chord trinal inhale muddler", + "value": 2 + }, + { + "key": "tax suffix lengthen bedlam", + "value": 4 + }, + { + "key": "midrib minium looming braunite", + "value": 2 + }, + { + "key": "snipe pillage drug hydranth", + "value": 2 + }, + { + "key": "suboxide wriggly armhole bricky", + "value": 6 + }, + { + "key": "capable boiler yaw koto", + "value": 2 + }, + { + "key": "history tithing footing headache", + "value": 2 + }, + { + "key": "sobriety nuance tumid corves", + "value": 503 + }, + { + "key": "lacewing recede baguette deckle", + "value": 503 + }, + { + "key": "starve loyalty ankh foul", + "value": 26 + }, + { + "key": "scabious gallery cannular facer", + "value": 503 + }, + { + "key": "crackle pinnate familiar sprang", + "value": 496 + }, + { + "key": "cross gride dancers caper", + "value": 2 + }, + { + "key": "burial henna antiphon annatto", + "value": 14 + }, + { + "key": "waxwork topfull balata bumper", + "value": 2 + }, + { + "key": "enamour inure riverine operatic", + "value": 1393 + }, + { + "key": "borate crucial glitter atom", + "value": 1229 + }, + { + "key": "halfbeak trotting cackle stout", + "value": 854 + }, + { + "key": "bankroll bloke phony mess", + "value": 1226 + }, + { + "key": "mouldy gap jargon redroot", + "value": 72 + }, + { + "key": "geisha titrant cascade corned", + "value": 8 + }, + { + "key": "jaws languid regolith breeding", + "value": 246 + }, + { + "key": "coaxial atrophy gink dozen", + "value": 504 + }, + { + "key": "variole amperage unbolt nous", + "value": 380 + }, + { + "key": "spencer towering totter auger", + "value": 337 + }, + { + "key": "aspire shouldst superman lame", + "value": 582 + }, + { + "key": "steinbok chestnut bummer formless", + "value": 101 + }, + { + "key": "archery dough protist buffalo", + "value": 21 + }, + { + "key": "macaque holder project socle", + "value": 504 + }, + { + "key": "pantile pitfall clothing tandem", + "value": 451 + }, + { + "key": "butchery mood mullah host", + "value": 504 + }, + { + "key": "misfire brachial cheese maker", + "value": 503 + }, + { + "key": "overlive fading comber chilli", + "value": 12 + }, + { + "key": "slinky downcome carcass horal", + "value": 503 + }, + { + "key": "eastern suggest extender acrylic", + "value": 525 + }, + { + "key": "referred paisley queenly aspect", + "value": 1466 + }, + { + "key": "finesse brindle comfort kick", + "value": 721 + }, + { + "key": "waif challis brevity pervious", + "value": 30 + }, + { + "key": "walking carding triaxial epiphany", + "value": 1020 + }, + { + "key": "urushiol flathead fissile cellule", + "value": 498 + }, + { + "key": "hoof spaetzle conto creodont", + "value": 15 + }, + { + "key": "wheaten gleam numerary jinni", + "value": 2 + }, + { + "key": "artistry rowing unific anisole", + "value": 88 + }, + { + "key": "absorbed feller settee aroma", + "value": 755 + }, + { + "key": "rally oldwife ossified cracker", + "value": 88 + }, + { + "key": "patentee fourteen savoy snapback", + "value": 532 + }, + { + "key": "tache jazzy decare compound", + "value": 369 + }, + { + "key": "goiter silicon maximal finding", + "value": 337 + }, + { + "key": "outhouse doughy synodic miles", + "value": 669 + }, + { + "key": "gemsbok debutant tell kike", + "value": 637 + }, + { + "key": "howdy cobwebby neritic sulphur", + "value": 343 + }, + { + "key": "ablation colorado dormouse ligure", + "value": 58 + }, + { + "key": "stoup fakir sociable lotus", + "value": 105 + }, + { + "key": "cohere protract defender obelize", + "value": 102 + }, + { + "key": "exegete aspirin wrongly nocuous", + "value": 66 + }, + { + "key": "dashing axolotl banshee edgy", + "value": 513 + }, + { + "key": "envisage exemplum leftward crumble", + "value": 40 + } +] diff --git a/web/geo/us-counties.json b/web-src/geo/us-counties.json similarity index 100% rename from web/geo/us-counties.json rename to web-src/geo/us-counties.json diff --git a/web/geo/us-states.json b/web-src/geo/us-states.json similarity index 100% rename from web/geo/us-states.json rename to web-src/geo/us-states.json diff --git a/web/highlighter/shAutoloader.js b/web-src/highlighter/shAutoloader.js similarity index 100% rename from web/highlighter/shAutoloader.js rename to web-src/highlighter/shAutoloader.js diff --git a/web/highlighter/shBrushJScript.js b/web-src/highlighter/shBrushJScript.js similarity index 100% rename from web/highlighter/shBrushJScript.js rename to web-src/highlighter/shBrushJScript.js diff --git a/web/highlighter/shBrushXml.js b/web-src/highlighter/shBrushXml.js similarity index 100% rename from web/highlighter/shBrushXml.js rename to web-src/highlighter/shBrushXml.js diff --git a/web/highlighter/shCore.css b/web-src/highlighter/shCore.css similarity index 100% rename from web/highlighter/shCore.css rename to web-src/highlighter/shCore.css diff --git a/web/highlighter/shCore.js b/web-src/highlighter/shCore.js similarity index 100% rename from web/highlighter/shCore.js rename to web-src/highlighter/shCore.js diff --git a/web/highlighter/shThemeDefault.css b/web-src/highlighter/shThemeDefault.css similarity index 100% rename from web/highlighter/shThemeDefault.css rename to web-src/highlighter/shThemeDefault.css diff --git a/web-src/img/class-hierarchy.svg b/web-src/img/class-hierarchy.svg new file mode 100644 index 0000000000..e5a88a5adf --- /dev/null +++ b/web-src/img/class-hierarchy.svg @@ -0,0 +1,394 @@ + + + + + + +dcHierarchy + + +BaseMixin + + +BaseMixin + + + + +ColorMixin + + +ColorMixin + + + + +BaseMixin->ColorMixin + + + + +MarginMixin + + +MarginMixin + + + + +BaseMixin->MarginMixin + + + + +CapMixin + + +CapMixin + + + + +BaseMixin->CapMixin + + + + +DataCount + + +DataCount + + + + +BaseMixin->DataCount + + + + +DataGrid + + +DataGrid + + + + +BaseMixin->DataGrid + + + + +DataTable + + +DataTable + + + + +BaseMixin->DataTable + + + + +NumberDisplay + + +NumberDisplay + + + + +BaseMixin->NumberDisplay + + + + +SelectMenu + + +SelectMenu + + + + +BaseMixin->SelectMenu + + + + +CboxMenu + + +CboxMenu + + + + +BaseMixin->CboxMenu + + + + +TextFilterWidget + + +TextFilterWidget + + + + +BaseMixin->TextFilterWidget + + + + +BubbleMixin + + +BubbleMixin + + + + +ColorMixin->BubbleMixin + + + + +CoordinateGridMixin + + +CoordinateGridMixin + + + + +ColorMixin->CoordinateGridMixin + + + + +GeoChoroplethChart + + +GeoChoroplethChart + + + + +ColorMixin->GeoChoroplethChart + + + + +HeatMap + + +HeatMap + + + + +ColorMixin->HeatMap + + + + +PieChart + + +PieChart + + + + +ColorMixin->PieChart + + + + +RowChart + + +RowChart + + + + +ColorMixin->RowChart + + + + +SunburstChart + + +SunburstChart + + + + +ColorMixin->SunburstChart + + + + +MarginMixin->CoordinateGridMixin + + + + +MarginMixin->HeatMap + + + + +MarginMixin->RowChart + + + + +BubbleChart + + +BubbleChart + + + + +BubbleMixin->BubbleChart + + + + +BubbleOverlay + + +BubbleOverlay + + + + +BubbleMixin->BubbleOverlay + + + + +StackMixin + + +StackMixin + + + + +CoordinateGridMixin->StackMixin + + + + +BoxPlot + + +BoxPlot + + + + +CoordinateGridMixin->BoxPlot + + + + +CoordinateGridMixin->BubbleChart + + + + +CompositeChart + + +CompositeChart + + + + +CoordinateGridMixin->CompositeChart + + + + +ScatterPlot + + +ScatterPlot + + + + +CoordinateGridMixin->ScatterPlot + + + + +BarChart + + +BarChart + + + + +StackMixin->BarChart + + + + +LineChart + + +LineChart + + + + +StackMixin->LineChart + + + + +CapMixin->PieChart + + + + +CapMixin->RowChart + + + + +CapMixin->SunburstChart + + + + +SeriesChart + + +SeriesChart + + + + +CompositeChart->SeriesChart + + + + + diff --git a/web/img/glyphicons-halflings-white.png b/web-src/img/glyphicons-halflings-white.png similarity index 100% rename from web/img/glyphicons-halflings-white.png rename to web-src/img/glyphicons-halflings-white.png diff --git a/web/img/glyphicons-halflings.png b/web-src/img/glyphicons-halflings.png similarity index 100% rename from web/img/glyphicons-halflings.png rename to web-src/img/glyphicons-halflings.png diff --git a/web/index.html b/web-src/index.html similarity index 66% rename from web/index.html rename to web-src/index.html index b70441e094..e29707a413 100644 --- a/web/index.html +++ b/web-src/index.html @@ -10,6 +10,9 @@ + + +
    +
    + +
    +
    +
    +
    +
    + + + + + + + +
    + + diff --git a/web/resizing/resizing-series.html b/web-src/resizing/resizing-series.html similarity index 70% rename from web/resizing/resizing-series.html rename to web-src/resizing/resizing-series.html index f2e758a96a..6e4d5d42ba 100644 --- a/web/resizing/resizing-series.html +++ b/web-src/resizing/resizing-series.html @@ -1,9 +1,10 @@ - dc.js - Series Example + dc.js - Resizing Series Example + @@ -15,12 +16,14 @@ + + diff --git a/web-src/resizing/resizing-sunburst.html b/web-src/resizing/resizing-sunburst.html new file mode 100644 index 0000000000..c1fb4f5f1b --- /dev/null +++ b/web-src/resizing/resizing-sunburst.html @@ -0,0 +1,55 @@ + + + + dc.js - Resizing Sunburst Example + + + + + + +
    + + + + + + + + + + diff --git a/web/stock.js b/web-src/stock.js similarity index 57% rename from web/stock.js rename to web-src/stock.js index 4955410669..91fc9b556d 100644 --- a/web/stock.js +++ b/web-src/stock.js @@ -1,23 +1,20 @@ //# dc.js Getting Started and How-To Guide 'use strict'; -/* jshint globalstrict: true */ -/* global dc,d3,crossfilter,colorbrewer */ - // ### Create Chart Objects // Create chart objects associated with the container elements identified by the css selector. // Note: It is often a good idea to have these objects accessible at the global scope so that they can be modified or // filtered by other page controls. -var gainOrLossChart = dc.pieChart('#gain-loss-chart'); -var fluctuationChart = dc.barChart('#fluctuation-chart'); -var quarterChart = dc.pieChart('#quarter-chart'); -var dayOfWeekChart = dc.rowChart('#day-of-week-chart'); -var moveChart = dc.lineChart('#monthly-move-chart'); -var volumeChart = dc.barChart('#monthly-volume-chart'); -var yearlyBubbleChart = dc.bubbleChart('#yearly-bubble-chart'); -var nasdaqCount = dc.dataCount('.dc-data-count'); -var nasdaqTable = dc.dataTable('.dc-data-table'); +const gainOrLossChart = new dc.PieChart('#gain-loss-chart'); +const fluctuationChart = new dc.BarChart('#fluctuation-chart'); +const quarterChart = new dc.PieChart('#quarter-chart'); +const dayOfWeekChart = new dc.RowChart('#day-of-week-chart'); +const moveChart = new dc.LineChart('#monthly-move-chart'); +const volumeChart = new dc.BarChart('#monthly-volume-chart'); +const yearlyBubbleChart = new dc.BubbleChart('#yearly-bubble-chart'); +const nasdaqCount = new dc.DataCount('.dc-data-count'); +const nasdaqTable = new dc.DataTable('.dc-data-table'); // ### Anchor Div for Charts /* @@ -32,9 +29,10 @@ var nasdaqTable = dc.dataTable('.dc-data-table'); // set on the chart (e.g. slice selection for pie chart and brush // selection for bar chart). Enable this with `chart.turnOnControls(true)` -// dc.js >=2.1 uses `visibility: hidden` to hide/show controls without -// disrupting the layout. To return the old `display: none` behavior, -// set `chart.controlsUseVisibility(false)` and use that style instead. +// By default, dc.js >=2.1 uses `display: none` to control whether or not chart +// controls are shown. To use `visibility: hidden` to hide/show controls +// without disrupting the layout, set `chart.controlsUseVisibility(true)`. +
    { // Since its a csv file we need to format the data a bit. - var dateFormat = d3.time.format('%m/%d/%Y'); - var numberFormat = d3.format('.2f'); - - data.forEach(function (d) { - d.dd = dateFormat.parse(d.date); - d.month = d3.time.month(d.dd); // pre-calculate month for better performance + const dateFormatSpecifier = '%m/%d/%Y'; + const dateFormat = d3.timeFormat(dateFormatSpecifier); + const dateFormatParser = d3.timeParse(dateFormatSpecifier); + const numberFormat = d3.format('.2f'); + + data.forEach(d => { + d.dd = dateFormatParser(d.date); + d.month = d3.timeMonth(d.dd); // pre-calculate month for better performance d.close = +d.close; // coerce to number d.open = +d.open; }); @@ -74,17 +74,15 @@ d3.csv('ndx.csv', function (data) { //### Create Crossfilter Dimensions and Groups //See the [crossfilter API](https://github.com/square/crossfilter/wiki/API-Reference) for reference. - var ndx = crossfilter(data); - var all = ndx.groupAll(); + const ndx = crossfilter(data); + const all = ndx.groupAll(); // Dimension by year - var yearlyDimension = ndx.dimension(function (d) { - return d3.time.year(d.dd).getFullYear(); - }); + const yearlyDimension = ndx.dimension(d => d3.timeYear(d.dd).getFullYear()); // Maintain running tallies by year as filters are applied or removed - var yearlyPerformanceGroup = yearlyDimension.group().reduce( + const yearlyPerformanceGroup = yearlyDimension.group().reduce( /* callback for when data is added to the current filter results */ - function (p, v) { + (p, v) => { ++p.count; p.absGain += v.close - v.open; p.fluctuation += Math.abs(v.close - v.open); @@ -95,7 +93,7 @@ d3.csv('ndx.csv', function (data) { return p; }, /* callback for when data is removed from the current filter results */ - function (p, v) { + (p, v) => { --p.count; p.absGain -= v.close - v.open; p.fluctuation -= Math.abs(v.close - v.open); @@ -106,70 +104,54 @@ d3.csv('ndx.csv', function (data) { return p; }, /* initialize p */ - function () { - return { - count: 0, - absGain: 0, - fluctuation: 0, - fluctuationPercentage: 0, - sumIndex: 0, - avgIndex: 0, - percentageGain: 0 - }; - } + () => ({ + count: 0, + absGain: 0, + fluctuation: 0, + fluctuationPercentage: 0, + sumIndex: 0, + avgIndex: 0, + percentageGain: 0 + }) ); // Dimension by full date - var dateDimension = ndx.dimension(function (d) { - return d.dd; - }); + const dateDimension = ndx.dimension(d => d.dd); // Dimension by month - var moveMonths = ndx.dimension(function (d) { - return d.month; - }); + const moveMonths = ndx.dimension(d => d.month); // Group by total movement within month - var monthlyMoveGroup = moveMonths.group().reduceSum(function (d) { - return Math.abs(d.close - d.open); - }); + const monthlyMoveGroup = moveMonths.group().reduceSum(d => Math.abs(d.close - d.open)); // Group by total volume within move, and scale down result - var volumeByMonthGroup = moveMonths.group().reduceSum(function (d) { - return d.volume / 500000; - }); - var indexAvgByMonthGroup = moveMonths.group().reduce( - function (p, v) { + const volumeByMonthGroup = moveMonths.group().reduceSum(d => d.volume / 500000); + const indexAvgByMonthGroup = moveMonths.group().reduce( + (p, v) => { ++p.days; p.total += (v.open + v.close) / 2; p.avg = Math.round(p.total / p.days); return p; }, - function (p, v) { + (p, v) => { --p.days; p.total -= (v.open + v.close) / 2; p.avg = p.days ? Math.round(p.total / p.days) : 0; return p; }, - function () { - return {days: 0, total: 0, avg: 0}; - } + () => ({days: 0, total: 0, avg: 0}) ); // Create categorical dimension - var gainOrLoss = ndx.dimension(function (d) { - return d.open > d.close ? 'Loss' : 'Gain'; - }); + const gainOrLoss = ndx.dimension(d => d.open > d.close ? 'Loss' : 'Gain'); // Produce counts records in the dimension - var gainOrLossGroup = gainOrLoss.group(); + const gainOrLossGroup = gainOrLoss.group(); // Determine a histogram of percent changes - var fluctuation = ndx.dimension(function (d) { - return Math.round((d.close - d.open) / d.open * 100); - }); - var fluctuationGroup = fluctuation.group(); + const fluctuation = ndx.dimension(d => Math.round((d.close - d.open) / d.open * 100)); + const fluctuationGroup = fluctuation.group(); // Summarize volume by quarter - var quarter = ndx.dimension(function (d) { - var month = d.dd.getMonth(); + const quarter = ndx.dimension(d => { + const month = d.dd.getMonth(); if (month <= 2) { return 'Q1'; } else if (month > 2 && month <= 5) { @@ -180,21 +162,19 @@ d3.csv('ndx.csv', function (data) { return 'Q4'; } }); - var quarterGroup = quarter.group().reduceSum(function (d) { - return d.volume; - }); + const quarterGroup = quarter.group().reduceSum(d => d.volume); // Counts per weekday - var dayOfWeek = ndx.dimension(function (d) { - var day = d.dd.getDay(); - var name = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - return day + '.' + name[day]; + const dayOfWeek = ndx.dimension(d => { + const day = d.dd.getDay(); + const name = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + return `${day}.${name[day]}`; }); - var dayOfWeekGroup = dayOfWeek.group(); + const dayOfWeekGroup = dayOfWeek.group(); //### Define Chart Attributes // Define chart attributes using fluent methods. See the - // [dc.js API Reference](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md) for more information + // [dc.js API Reference](https://dc-js.github.io/dc.js/docs/html/) for more information // //#### Bubble Chart @@ -203,7 +183,7 @@ d3.csv('ndx.csv', function (data) { //an optional chart group for this chart to be scoped within. When a chart belongs //to a specific group then any interaction with the chart will only trigger redraws //on charts within the same chart group. - //
    API: [Bubble Chart](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#bubble-chart) + //
    API: [Bubble Chart](https://dc-js.github.io/dc.js/docs/html/BubbleChart.html) yearlyBubbleChart /* dc.bubbleChart('#yearly-bubble-chart', 'chartGroup') */ // (_optional_) define chart width, `default = 200` @@ -218,34 +198,26 @@ d3.csv('ndx.csv', function (data) { //to generate x, y, and radius for each key (bubble) in the group .group(yearlyPerformanceGroup) // (_optional_) define color function or array for bubbles: [ColorBrewer](http://colorbrewer2.org/) - .colors(colorbrewer.RdYlGn[9]) + .colors(d3.schemeRdYlGn[9]) //(optional) define color domain to match your data domain if you want to bind data or color .colorDomain([-500, 500]) //##### Accessors - //Accessor functions are applied to each value returned by the grouping + //Accessor functions are applied to each value returned by the grouping // `.colorAccessor` - the returned value will be passed to the `.colors()` scale to determine a fill color - .colorAccessor(function (d) { - return d.value.absGain; - }) + .colorAccessor(d => d.value.absGain) // `.keyAccessor` - the `X` value will be passed to the `.x()` scale to determine pixel location - .keyAccessor(function (p) { - return p.value.absGain; - }) + .keyAccessor(p => p.value.absGain) // `.valueAccessor` - the `Y` value will be passed to the `.y()` scale to determine pixel location - .valueAccessor(function (p) { - return p.value.percentageGain; - }) + .valueAccessor(p => p.value.percentageGain) // `.radiusValueAccessor` - the value will be passed to the `.r()` scale to determine radius size; // by default this maps linearly to [0,100] - .radiusValueAccessor(function (p) { - return p.value.fluctuationPercentage; - }) + .radiusValueAccessor(p => p.value.fluctuationPercentage) .maxBubbleRelativeSize(0.3) - .x(d3.scale.linear().domain([-2500, 2500])) - .y(d3.scale.linear().domain([-100, 100])) - .r(d3.scale.linear().domain([0, 4000])) + .x(d3.scaleLinear().domain([-2500, 2500])) + .y(d3.scaleLinear().domain([-100, 100])) + .r(d3.scaleLinear().domain([0, 4000])) //##### Elastic Scaling //`.elasticY` and `.elasticX` determine whether the chart should rescale each axis to fit the data. @@ -268,26 +240,20 @@ d3.csv('ndx.csv', function (data) { //Labels are displayed on the chart for each bubble. Titles displayed on mouseover. // (_optional_) whether chart should render labels, `default = true` .renderLabel(true) - .label(function (p) { - return p.key; - }) + .label(p => p.key) // (_optional_) whether chart should render titles, `default = false` .renderTitle(true) - .title(function (p) { - return [ - p.key, - 'Index Gain: ' + numberFormat(p.value.absGain), - 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%', - 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%' - ].join('\n'); - }) + .title(p => [ + p.key, + `Index Gain: ${numberFormat(p.value.absGain)}`, + `Index Gain in Percentage: ${numberFormat(p.value.percentageGain)}%`, + `Fluctuation / Index Ratio: ${numberFormat(p.value.fluctuationPercentage)}%` + ].join('\n')) //#### Customize Axes // Set a custom tick format. Both `.yAxis()` and `.xAxis()` return an axis object, // so any additional method chaining applies to the axis, not the chart. - .yAxis().tickFormat(function (v) { - return v + '%'; - }); + .yAxis().tickFormat(v => `${v}%`); // #### Pie/Donut Charts @@ -295,7 +261,7 @@ d3.csv('ndx.csv', function (data) { // an optional chart group for this chart to be scoped within. When a chart belongs // to a specific group then any interaction with such chart will only trigger redraw // on other charts within the same chart group. - //
    API: [Pie Chart](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#pie-chart) + //
    API: [Pie Chart](https://dc-js.github.io/dc.js/docs/html/PieChart.html) gainOrLossChart /* dc.pieChart('#gain-loss-chart', 'chartGroup') */ // (_optional_) define chart width, `default = 200` @@ -309,13 +275,13 @@ d3.csv('ndx.csv', function (data) { // Set group .group(gainOrLossGroup) // (_optional_) by default pie chart will use `group.key` as its label but you can overwrite it with a closure. - .label(function (d) { + .label(d => { if (gainOrLossChart.hasFilter() && !gainOrLossChart.hasFilter(d.key)) { - return d.key + '(0%)'; + return `${d.key}(0%)`; } - var label = d.key; + let label = d.key; if (all.value()) { - label += '(' + Math.floor(d.value / all.value() * 100) + '%)'; + label += `(${Math.floor(d.value / all.value() * 100)}%)`; } return label; }) @@ -348,7 +314,7 @@ d3.csv('ndx.csv', function (data) { // an optional chart group for this chart to be scoped within. When a chart belongs // to a specific group then any interaction with such chart will only trigger redraw // on other charts within the same chart group. - //
    API: [Row Chart](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#row-chart) + //
    API: [Row Chart](https://dc-js.github.io/dc.js/docs/html/RowChart.html) dayOfWeekChart /* dc.rowChart('#day-of-week-chart', 'chartGroup') */ .width(180) .height(180) @@ -357,13 +323,9 @@ d3.csv('ndx.csv', function (data) { .dimension(dayOfWeek) // Assign colors to each value in the x scale domain .ordinalColors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb']) - .label(function (d) { - return d.key.split('.')[1]; - }) + .label(d => d.key.split('.')[1]) // Title sets the row text - .title(function (d) { - return d.value; - }) + .title(d => d.value) .elasticX(true) .xAxis().ticks(4); @@ -373,7 +335,7 @@ d3.csv('ndx.csv', function (data) { // an optional chart group for this chart to be scoped within. When a chart belongs // to a specific group then any interaction with such chart will only trigger redraw // on other charts within the same chart group. - //
    API: [Bar Chart](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#bar-chart) + //
    API: [Bar Chart](https://dc-js.github.io/dc.js/docs/html/BarChart.html) fluctuationChart /* dc.barChart('#volume-month-chart', 'chartGroup') */ .width(420) .height(180) @@ -386,27 +348,28 @@ d3.csv('ndx.csv', function (data) { // (_optional_) set gap between bars manually in px, `default=2` .gap(1) // (_optional_) set filter brush rounding - .round(dc.round.floor) + .round(Math.floor) .alwaysUseRounding(true) - .x(d3.scale.linear().domain([-25, 25])) + .x(d3.scaleLinear().domain([-25, 25])) .renderHorizontalGridLines(true) // Customize the filter displayed in the control span - .filterPrinter(function (filters) { - var filter = filters[0], s = ''; - s += numberFormat(filter[0]) + '% -> ' + numberFormat(filter[1]) + '%'; + .filterPrinter(filters => { + const filter = filters[0]; + let s = ''; + s += `${numberFormat(filter[0])}% -> ${numberFormat(filter[1])}%`; return s; }); // Customize axes fluctuationChart.xAxis().tickFormat( - function (v) { return v + '%'; }); + v => `${v}%`); fluctuationChart.yAxis().ticks(5); //#### Stacked Area Chart //Specify an area chart by using a line chart with `.renderArea(true)`. - //
    API: [Stack Mixin](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#stack-mixin), - // [Line Chart](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#line-chart) + //
    API: [Stack Mixin](https://dc-js.github.io/dc.js/docs/html/StackMixin.html), + // [Line Chart](https://dc-js.github.io/dc.js/docs/html/LineChart.html) moveChart /* dc.lineChart('#monthly-move-chart', 'chartGroup') */ .renderArea(true) .width(990) @@ -417,35 +380,31 @@ d3.csv('ndx.csv', function (data) { .mouseZoomable(true) // Specify a "range chart" to link its brush extent with the zoom of the current "focus chart". .rangeChart(volumeChart) - .x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) - .round(d3.time.month.round) - .xUnits(d3.time.months) + .x(d3.scaleTime().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) + .round(d3.timeMonth.round) + .xUnits(d3.timeMonths) .elasticY(true) .renderHorizontalGridLines(true) //##### Legend // Position the legend relative to the chart origin and specify items' height and separation. - .legend(dc.legend().x(800).y(10).itemHeight(13).gap(5)) + .legend(new dc.Legend().x(800).y(10).itemHeight(13).gap(5)) .brushOn(false) // Add the base layer of the stack with group. The second parameter specifies a series name for use in the // legend. // The `.valueAccessor` will be used for the base layer .group(indexAvgByMonthGroup, 'Monthly Index Average') - .valueAccessor(function (d) { - return d.value.avg; - }) + .valueAccessor(d => d.value.avg) // Stack additional layers with `.stack`. The first paramenter is a new group. // The second parameter is the series name. The third is a value accessor. - .stack(monthlyMoveGroup, 'Monthly Index Move', function (d) { - return d.value; - }) + .stack(monthlyMoveGroup, 'Monthly Index Move', d => d.value) // Title can be called by any stack layer. - .title(function (d) { - var value = d.value.avg ? d.value.avg : d.value; + .title(d => { + let value = d.value.avg ? d.value.avg : d.value; if (isNaN(value)) { value = 0; } - return dateFormat(d.key) + '\n' + numberFormat(value); + return `${dateFormat(d.key)}\n${numberFormat(value)}`; }); //#### Range Chart @@ -459,10 +418,10 @@ d3.csv('ndx.csv', function (data) { .group(volumeByMonthGroup) .centerBar(true) .gap(1) - .x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) - .round(d3.time.month.round) + .x(d3.scaleTime().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) + .round(d3.timeMonth.round) .alwaysUseRounding(true) - .xUnits(d3.time.months); + .xUnits(d3.timeMonths); //#### Data Count @@ -470,7 +429,7 @@ d3.csv('ndx.csv', function (data) { // an optional chart group for this chart to be scoped within. When a chart belongs // to a specific group then any interaction with such chart will only trigger redraw // on other charts within the same chart group. - //
    API: [Data Count Widget](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#data-count-widget) + //
    API: [Data Count Widget](https://dc-js.github.io/dc.js/docs/html/DataCount.html) // //```html //
    @@ -480,8 +439,8 @@ d3.csv('ndx.csv', function (data) { //``` nasdaqCount /* dc.dataCount('.dc-data-count', 'chartGroup'); */ - .dimension(ndx) - .group(all) + .crossfilter(ndx) + .groupAll(all) // (_optional_) `.html` sets different html when some records or all records are selected. // `.html` replaces everything in the anchor with the html given using the following function. // `%filter-count` and `%total-count` are replaced with the values obtained. @@ -497,7 +456,7 @@ d3.csv('ndx.csv', function (data) { // an optional chart group for this chart to be scoped within. When a chart belongs // to a specific group then any interaction with such chart will only trigger redraw // on other charts within the same chart group. - //
    API: [Data Table Widget](https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#data-table-widget) + //
    API: [Data Table Widget](https://dc-js.github.io/dc.js/docs/html/DataTable.html) // // You can statically define the headers like in // @@ -519,11 +478,10 @@ d3.csv('ndx.csv', function (data) { nasdaqTable /* dc.dataTable('.dc-data-table', 'chartGroup') */ .dimension(dateDimension) - // Data table does not use crossfilter group but rather a closure - // as a grouping function - .group(function (d) { - var format = d3.format('02d'); - return d.dd.getFullYear() + '/' + format((d.dd.getMonth() + 1)); + // Specify a section function to nest rows of the table + .section(d => { + const format = d3.format('02d'); + return `${d.dd.getFullYear()}/${format((d.dd.getMonth() + 1))}`; }) // (_optional_) max number of records to be shown, `default = 25` .size(10) @@ -547,116 +505,14 @@ d3.csv('ndx.csv', function (data) { ]) // (_optional_) sort using the given field, `default = function(d){return d;}` - .sortBy(function (d) { - return d.dd; - }) + .sortBy(d => d.dd) // (_optional_) sort order, `default = d3.ascending` .order(d3.ascending) // (_optional_) custom renderlet to post-process chart using [D3](http://d3js.org) - .on('renderlet', function (table) { + .on('renderlet', table => { table.selectAll('.dc-table-group').classed('info', true); }); - /* - //#### Geo Choropleth Chart - - //Create a choropleth chart and use the given css selector as anchor. You can also specify - //an optional chart group for this chart to be scoped within. When a chart belongs - //to a specific group then any interaction with such chart will only trigger redraw - //on other charts within the same chart group. - //
    API: [Geo Chroropleth Chart][choro] - // [choro]: https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#geo-choropleth-chart - dc.geoChoroplethChart('#us-chart') - // (_optional_) define chart width, default 200 - .width(990) - // (optional) define chart height, default 200 - .height(500) - // (optional) define chart transition duration, default 1000 - .transitionDuration(1000) - // set crossfilter dimension, dimension key should match the name retrieved in geojson layer - .dimension(states) - // set crossfilter group - .group(stateRaisedSum) - // (_optional_) define color function or array for bubbles - .colors(['#ccc', '#E2F2FF','#C4E4FF','#9ED2FF','#81C5FF','#6BBAFF','#51AEFF','#36A2FF','#1E96FF','#0089FF', - '#0061B5']) - // (_optional_) define color domain to match your data domain if you want to bind data or color - .colorDomain([-5, 200]) - // (_optional_) define color value accessor - .colorAccessor(function(d, i){return d.value;}) - // Project the given geojson. You can call this function multiple times with different geojson feed to generate - // multiple layers of geo paths. - // - // * 1st param - geojson data - // * 2nd param - name of the layer which will be used to generate css class - // * 3rd param - (_optional_) a function used to generate key for geo path, it should match the dimension key - // in order for the coloring to work properly - .overlayGeoJson(statesJson.features, 'state', function(d) { - return d.properties.name; - }) - // (_optional_) closure to generate title for path, `default = d.key + ': ' + d.value` - .title(function(d) { - return 'State: ' + d.key + '\nTotal Amount Raised: ' + numberFormat(d.value ? d.value : 0) + 'M'; - }); - - //#### Bubble Overlay Chart - - // Create a overlay bubble chart and use the given css selector as anchor. You can also specify - // an optional chart group for this chart to be scoped within. When a chart belongs - // to a specific group then any interaction with the chart will only trigger redraw - // on charts within the same chart group. - //
    API: [Bubble Overlay Chart][bubble] - // [bubble]: https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md#bubble-overlay-chart - dc.bubbleOverlay('#bubble-overlay', 'chartGroup') - // The bubble overlay chart does not generate its own svg element but rather reuses an existing - // svg to generate its overlay layer - .svg(d3.select('#bubble-overlay svg')) - // (_optional_) define chart width, `default = 200` - .width(990) - // (_optional_) define chart height, `default = 200` - .height(500) - // (_optional_) define chart transition duration, `default = 1000` - .transitionDuration(1000) - // Set crossfilter dimension, dimension key should match the name retrieved in geo json layer - .dimension(states) - // Set crossfilter group - .group(stateRaisedSum) - // Closure used to retrieve x value from multi-value group - .keyAccessor(function(p) {return p.value.absGain;}) - // Closure used to retrieve y value from multi-value group - .valueAccessor(function(p) {return p.value.percentageGain;}) - // (_optional_) define color function or array for bubbles - .colors(['#ccc', '#E2F2FF','#C4E4FF','#9ED2FF','#81C5FF','#6BBAFF','#51AEFF','#36A2FF','#1E96FF','#0089FF', - '#0061B5']) - // (_optional_) define color domain to match your data domain if you want to bind data or color - .colorDomain([-5, 200]) - // (_optional_) define color value accessor - .colorAccessor(function(d, i){return d.value;}) - // Closure used to retrieve radius value from multi-value group - .radiusValueAccessor(function(p) {return p.value.fluctuationPercentage;}) - // set radius scale - .r(d3.scale.linear().domain([0, 3])) - // (_optional_) whether chart should render labels, `default = true` - .renderLabel(true) - // (_optional_) closure to generate label per bubble, `default = group.key` - .label(function(p) {return p.key.getFullYear();}) - // (_optional_) whether chart should render titles, `default = false` - .renderTitle(true) - // (_optional_) closure to generate title per bubble, `default = d.key + ': ' + d.value` - .title(function(d) { - return 'Title: ' + d.key; - }) - // add data point to its layer dimension key that matches point name: it will be used to - // generate a bubble. Multiple data points can be added to the bubble overlay to generate - // multiple bubbles. - .point('California', 100, 120) - .point('Colorado', 300, 120) - // (_optional_) setting debug flag to true will generate a transparent layer on top of - // bubble overlay which can be used to obtain relative `x`,`y` coordinate for specific - // data point, `default = false` - .debug(true); - */ - //#### Rendering //simply call `.renderAll()` to render all charts on the page @@ -679,7 +535,7 @@ d3.csv('ndx.csv', function (data) { d3.selectAll('#version').text(dc.version); // Determine latest stable version in the repo via Github API -d3.json('https://api.github.com/repos/dc-js/dc.js/releases/latest', function (error, latestRelease) { - /*jshint camelcase: false */ - d3.selectAll('#latest').text(latestRelease.tag_name); /* jscs:disable */ +d3.json('https://api.github.com/repos/dc-js/dc.js/releases/latest').then(latestRelease => { + /* eslint camelcase: 0 */ + d3.selectAll('#latest').text(latestRelease.tag_name); }); diff --git a/web-src/transitions/area-progression.html b/web-src/transitions/area-progression.html new file mode 100644 index 0000000000..c782194b68 --- /dev/null +++ b/web-src/transitions/area-progression.html @@ -0,0 +1,80 @@ + + + + dc.js - Area Progression + + + + + +
    + + +
    + + + + + + + + + +
    + + diff --git a/web/transitions/area-transitions.html b/web-src/transitions/area-transitions.html similarity index 93% rename from web/transitions/area-transitions.html rename to web-src/transitions/area-transitions.html index db811f9504..d11a7da370 100644 --- a/web/transitions/area-transitions.html +++ b/web-src/transitions/area-transitions.html @@ -1,7 +1,7 @@ - dc.js - Area Transitions Example + dc.js - Area Transitions @@ -23,8 +23,8 @@ + +
    + + + + + + + + + +
    + + diff --git a/web/transitions/bar-transitions.html b/web-src/transitions/bar-transitions.html similarity index 91% rename from web/transitions/bar-transitions.html rename to web-src/transitions/bar-transitions.html index 8839a22c28..2a65d54dd6 100644 --- a/web/transitions/bar-transitions.html +++ b/web-src/transitions/bar-transitions.html @@ -1,7 +1,7 @@ - dc.js - Bar Chart Transition Tester + dc.js - Bar Transitions @@ -22,8 +22,8 @@ + +
    + + + + + + + + + +
    + + diff --git a/web/transitions/number-transitions.html b/web-src/transitions/number-transitions.html similarity index 94% rename from web/transitions/number-transitions.html rename to web-src/transitions/number-transitions.html index edf03f6777..b8521a267a 100644 --- a/web/transitions/number-transitions.html +++ b/web-src/transitions/number-transitions.html @@ -1,7 +1,7 @@ - dc.js - Number Transition Tester + dc.js - Number Transitions @@ -104,7 +104,7 @@

    bands n' stuff

    // which turns to NaN% when deselecting "Not Rush". The number can be restored by pressing Redraw Charts. // [XA] somewhat amusingly, this is the exact same test case as last time despite the bug being // different. Gads! -var chart_band = dc.pieChart ("#dc-band") +var chart_band = new dc.PieChart ("#dc-band") .height(230) .width (230) .transitionDuration(1000) @@ -114,7 +114,7 @@

    bands n' stuff

    .minAngleForLabel(0) .title(function() { return ''; }) ; -var chart_band = dc.pieChart ("#dc-member") +var chart_band = new dc.PieChart ("#dc-member") .height(230) .width (230) .transitionDuration(1000) @@ -124,7 +124,7 @@

    bands n' stuff

    .minAngleForLabel(0) .title(function() { return ''; }) ; -var label_percent = dc.numberDisplay("#dc-percent") +var label_percent = new dc.NumberDisplay("#dc-percent") .transitionDuration(1000) .group(grp_all) .valueAccessor(function(d) { return d.number / d.othernumber; }) @@ -132,7 +132,7 @@

    bands n' stuff

    return d3.format('%')(d); }) ; -var label_percent2 = dc.numberDisplay("#dc-percent2") +var label_percent2 = new dc.NumberDisplay("#dc-percent2") .transitionDuration(1000) .group(grp_all) .valueAccessor(function(d) { return d.othernumber ? (d.number / d.othernumber) : NaN; }) diff --git a/web/transitions/ordinal-bar-transitions.html b/web-src/transitions/ordinal-bar-transitions.html similarity index 92% rename from web/transitions/ordinal-bar-transitions.html rename to web-src/transitions/ordinal-bar-transitions.html index b2ac602f19..74ae929c29 100644 --- a/web/transitions/ordinal-bar-transitions.html +++ b/web-src/transitions/ordinal-bar-transitions.html @@ -1,7 +1,7 @@ - dc.js - Ordinal Bar Chart Transition Tester + dc.js - Ordinal Bar Transitions @@ -26,12 +26,12 @@ diff --git a/web/transitions/ordinal-transition.js b/web-src/transitions/ordinal-transition.js similarity index 93% rename from web/transitions/ordinal-transition.js rename to web-src/transitions/ordinal-transition.js index a19bef549b..f6bf2e3bdf 100644 --- a/web/transitions/ordinal-transition.js +++ b/web-src/transitions/ordinal-transition.js @@ -2,7 +2,7 @@ function remove_empty_bins(source_group) { return { all:function () { return source_group.all().filter(function(d) { - return d.value != 0; + return d.value !== 0; }); } }; @@ -14,10 +14,7 @@ function ordinal_filter(bins) { } function startOrdinal(initChart) { - d3.json('../examples/fruits.json', function(error, counts) { - if(error) - throw new Error(error); - + d3.json('../examples/fruits.json').then(function(counts) { var ndx = crossfilter(counts), fruitDimension = ndx.dimension(function(d) {return d.name;}), sumGroup = fruitDimension.group().reduceSum(function(d) {return d.cnt;}), diff --git a/web/transitions/pie-external-label-transitions.html b/web-src/transitions/pie-external-label-transitions.html similarity index 93% rename from web/transitions/pie-external-label-transitions.html rename to web-src/transitions/pie-external-label-transitions.html index 8c772a7c80..4f1f9400f8 100644 --- a/web/transitions/pie-external-label-transitions.html +++ b/web-src/transitions/pie-external-label-transitions.html @@ -1,7 +1,7 @@ - dc.js - Pie Chart Transition Tester + dc.js - Pie Chart External Label Transitions @@ -23,9 +23,9 @@ + +
    + + + + + + + + + + + + diff --git a/web/transitions/stacked-bar-transitions.html b/web-src/transitions/stacked-bar-transitions.html similarity index 93% rename from web/transitions/stacked-bar-transitions.html rename to web-src/transitions/stacked-bar-transitions.html index 5952c26192..8689e15484 100644 --- a/web/transitions/stacked-bar-transitions.html +++ b/web-src/transitions/stacked-bar-transitions.html @@ -1,7 +1,7 @@ - dc.js - Area Chart Example + dc.js - Stacked Bar Transitions @@ -23,8 +23,8 @@ +
    +
    + + + + + + + + diff --git a/web/css/colorbrewer.css b/web/css/colorbrewer.css deleted file mode 100644 index de8f8ba344..0000000000 --- a/web/css/colorbrewer.css +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * This product includes color specifications and designs developed by Cynthia - * Brewer (http://colorbrewer.org/). - */ -.YlGn .q0-3{fill:rgb(247,252,185)} -.YlGn .q1-3{fill:rgb(173,221,142)} -.YlGn .q2-3{fill:rgb(49,163,84)} -.YlGn .q0-4{fill:rgb(255,255,204)} -.YlGn .q1-4{fill:rgb(194,230,153)} -.YlGn .q2-4{fill:rgb(120,198,121)} -.YlGn .q3-4{fill:rgb(35,132,67)} -.YlGn .q0-5{fill:rgb(255,255,204)} -.YlGn .q1-5{fill:rgb(194,230,153)} -.YlGn .q2-5{fill:rgb(120,198,121)} -.YlGn .q3-5{fill:rgb(49,163,84)} -.YlGn .q4-5{fill:rgb(0,104,55)} -.YlGn .q0-6{fill:rgb(255,255,204)} -.YlGn .q1-6{fill:rgb(217,240,163)} -.YlGn .q2-6{fill:rgb(173,221,142)} -.YlGn .q3-6{fill:rgb(120,198,121)} -.YlGn .q4-6{fill:rgb(49,163,84)} -.YlGn .q5-6{fill:rgb(0,104,55)} -.YlGn .q0-7{fill:rgb(255,255,204)} -.YlGn .q1-7{fill:rgb(217,240,163)} -.YlGn .q2-7{fill:rgb(173,221,142)} -.YlGn .q3-7{fill:rgb(120,198,121)} -.YlGn .q4-7{fill:rgb(65,171,93)} -.YlGn .q5-7{fill:rgb(35,132,67)} -.YlGn .q6-7{fill:rgb(0,90,50)} -.YlGn .q0-8{fill:rgb(255,255,229)} -.YlGn .q1-8{fill:rgb(247,252,185)} -.YlGn .q2-8{fill:rgb(217,240,163)} -.YlGn .q3-8{fill:rgb(173,221,142)} -.YlGn .q4-8{fill:rgb(120,198,121)} -.YlGn .q5-8{fill:rgb(65,171,93)} -.YlGn .q6-8{fill:rgb(35,132,67)} -.YlGn .q7-8{fill:rgb(0,90,50)} -.YlGn .q0-9{fill:rgb(255,255,229)} -.YlGn .q1-9{fill:rgb(247,252,185)} -.YlGn .q2-9{fill:rgb(217,240,163)} -.YlGn .q3-9{fill:rgb(173,221,142)} -.YlGn .q4-9{fill:rgb(120,198,121)} -.YlGn .q5-9{fill:rgb(65,171,93)} -.YlGn .q6-9{fill:rgb(35,132,67)} -.YlGn .q7-9{fill:rgb(0,104,55)} -.YlGn .q8-9{fill:rgb(0,69,41)} -.YlGnBu .q0-3{fill:rgb(237,248,177)} -.YlGnBu .q1-3{fill:rgb(127,205,187)} -.YlGnBu .q2-3{fill:rgb(44,127,184)} -.YlGnBu .q0-4{fill:rgb(255,255,204)} -.YlGnBu .q1-4{fill:rgb(161,218,180)} -.YlGnBu .q2-4{fill:rgb(65,182,196)} -.YlGnBu .q3-4{fill:rgb(34,94,168)} -.YlGnBu .q0-5{fill:rgb(255,255,204)} -.YlGnBu .q1-5{fill:rgb(161,218,180)} -.YlGnBu .q2-5{fill:rgb(65,182,196)} -.YlGnBu .q3-5{fill:rgb(44,127,184)} -.YlGnBu .q4-5{fill:rgb(37,52,148)} -.YlGnBu .q0-6{fill:rgb(255,255,204)} -.YlGnBu .q1-6{fill:rgb(199,233,180)} -.YlGnBu .q2-6{fill:rgb(127,205,187)} -.YlGnBu .q3-6{fill:rgb(65,182,196)} -.YlGnBu .q4-6{fill:rgb(44,127,184)} -.YlGnBu .q5-6{fill:rgb(37,52,148)} -.YlGnBu .q0-7{fill:rgb(255,255,204)} -.YlGnBu .q1-7{fill:rgb(199,233,180)} -.YlGnBu .q2-7{fill:rgb(127,205,187)} -.YlGnBu .q3-7{fill:rgb(65,182,196)} -.YlGnBu .q4-7{fill:rgb(29,145,192)} -.YlGnBu .q5-7{fill:rgb(34,94,168)} -.YlGnBu .q6-7{fill:rgb(12,44,132)} -.YlGnBu .q0-8{fill:rgb(255,255,217)} -.YlGnBu .q1-8{fill:rgb(237,248,177)} -.YlGnBu .q2-8{fill:rgb(199,233,180)} -.YlGnBu .q3-8{fill:rgb(127,205,187)} -.YlGnBu .q4-8{fill:rgb(65,182,196)} -.YlGnBu .q5-8{fill:rgb(29,145,192)} -.YlGnBu .q6-8{fill:rgb(34,94,168)} -.YlGnBu .q7-8{fill:rgb(12,44,132)} -.YlGnBu .q0-9{fill:rgb(255,255,217)} -.YlGnBu .q1-9{fill:rgb(237,248,177)} -.YlGnBu .q2-9{fill:rgb(199,233,180)} -.YlGnBu .q3-9{fill:rgb(127,205,187)} -.YlGnBu .q4-9{fill:rgb(65,182,196)} -.YlGnBu .q5-9{fill:rgb(29,145,192)} -.YlGnBu .q6-9{fill:rgb(34,94,168)} -.YlGnBu .q7-9{fill:rgb(37,52,148)} -.YlGnBu .q8-9{fill:rgb(8,29,88)} -.GnBu .q0-3{fill:rgb(224,243,219)} -.GnBu .q1-3{fill:rgb(168,221,181)} -.GnBu .q2-3{fill:rgb(67,162,202)} -.GnBu .q0-4{fill:rgb(240,249,232)} -.GnBu .q1-4{fill:rgb(186,228,188)} -.GnBu .q2-4{fill:rgb(123,204,196)} -.GnBu .q3-4{fill:rgb(43,140,190)} -.GnBu .q0-5{fill:rgb(240,249,232)} -.GnBu .q1-5{fill:rgb(186,228,188)} -.GnBu .q2-5{fill:rgb(123,204,196)} -.GnBu .q3-5{fill:rgb(67,162,202)} -.GnBu .q4-5{fill:rgb(8,104,172)} -.GnBu .q0-6{fill:rgb(240,249,232)} -.GnBu .q1-6{fill:rgb(204,235,197)} -.GnBu .q2-6{fill:rgb(168,221,181)} -.GnBu .q3-6{fill:rgb(123,204,196)} -.GnBu .q4-6{fill:rgb(67,162,202)} -.GnBu .q5-6{fill:rgb(8,104,172)} -.GnBu .q0-7{fill:rgb(240,249,232)} -.GnBu .q1-7{fill:rgb(204,235,197)} -.GnBu .q2-7{fill:rgb(168,221,181)} -.GnBu .q3-7{fill:rgb(123,204,196)} -.GnBu .q4-7{fill:rgb(78,179,211)} -.GnBu .q5-7{fill:rgb(43,140,190)} -.GnBu .q6-7{fill:rgb(8,88,158)} -.GnBu .q0-8{fill:rgb(247,252,240)} -.GnBu .q1-8{fill:rgb(224,243,219)} -.GnBu .q2-8{fill:rgb(204,235,197)} -.GnBu .q3-8{fill:rgb(168,221,181)} -.GnBu .q4-8{fill:rgb(123,204,196)} -.GnBu .q5-8{fill:rgb(78,179,211)} -.GnBu .q6-8{fill:rgb(43,140,190)} -.GnBu .q7-8{fill:rgb(8,88,158)} -.GnBu .q0-9{fill:rgb(247,252,240)} -.GnBu .q1-9{fill:rgb(224,243,219)} -.GnBu .q2-9{fill:rgb(204,235,197)} -.GnBu .q3-9{fill:rgb(168,221,181)} -.GnBu .q4-9{fill:rgb(123,204,196)} -.GnBu .q5-9{fill:rgb(78,179,211)} -.GnBu .q6-9{fill:rgb(43,140,190)} -.GnBu .q7-9{fill:rgb(8,104,172)} -.GnBu .q8-9{fill:rgb(8,64,129)} -.BuGn .q0-3{fill:rgb(229,245,249)} -.BuGn .q1-3{fill:rgb(153,216,201)} -.BuGn .q2-3{fill:rgb(44,162,95)} -.BuGn .q0-4{fill:rgb(237,248,251)} -.BuGn .q1-4{fill:rgb(178,226,226)} -.BuGn .q2-4{fill:rgb(102,194,164)} -.BuGn .q3-4{fill:rgb(35,139,69)} -.BuGn .q0-5{fill:rgb(237,248,251)} -.BuGn .q1-5{fill:rgb(178,226,226)} -.BuGn .q2-5{fill:rgb(102,194,164)} -.BuGn .q3-5{fill:rgb(44,162,95)} -.BuGn .q4-5{fill:rgb(0,109,44)} -.BuGn .q0-6{fill:rgb(237,248,251)} -.BuGn .q1-6{fill:rgb(204,236,230)} -.BuGn .q2-6{fill:rgb(153,216,201)} -.BuGn .q3-6{fill:rgb(102,194,164)} -.BuGn .q4-6{fill:rgb(44,162,95)} -.BuGn .q5-6{fill:rgb(0,109,44)} -.BuGn .q0-7{fill:rgb(237,248,251)} -.BuGn .q1-7{fill:rgb(204,236,230)} -.BuGn .q2-7{fill:rgb(153,216,201)} -.BuGn .q3-7{fill:rgb(102,194,164)} -.BuGn .q4-7{fill:rgb(65,174,118)} -.BuGn .q5-7{fill:rgb(35,139,69)} -.BuGn .q6-7{fill:rgb(0,88,36)} -.BuGn .q0-8{fill:rgb(247,252,253)} -.BuGn .q1-8{fill:rgb(229,245,249)} -.BuGn .q2-8{fill:rgb(204,236,230)} -.BuGn .q3-8{fill:rgb(153,216,201)} -.BuGn .q4-8{fill:rgb(102,194,164)} -.BuGn .q5-8{fill:rgb(65,174,118)} -.BuGn .q6-8{fill:rgb(35,139,69)} -.BuGn .q7-8{fill:rgb(0,88,36)} -.BuGn .q0-9{fill:rgb(247,252,253)} -.BuGn .q1-9{fill:rgb(229,245,249)} -.BuGn .q2-9{fill:rgb(204,236,230)} -.BuGn .q3-9{fill:rgb(153,216,201)} -.BuGn .q4-9{fill:rgb(102,194,164)} -.BuGn .q5-9{fill:rgb(65,174,118)} -.BuGn .q6-9{fill:rgb(35,139,69)} -.BuGn .q7-9{fill:rgb(0,109,44)} -.BuGn .q8-9{fill:rgb(0,68,27)} -.PuBuGn .q0-3{fill:rgb(236,226,240)} -.PuBuGn .q1-3{fill:rgb(166,189,219)} -.PuBuGn .q2-3{fill:rgb(28,144,153)} -.PuBuGn .q0-4{fill:rgb(246,239,247)} -.PuBuGn .q1-4{fill:rgb(189,201,225)} -.PuBuGn .q2-4{fill:rgb(103,169,207)} -.PuBuGn .q3-4{fill:rgb(2,129,138)} -.PuBuGn .q0-5{fill:rgb(246,239,247)} -.PuBuGn .q1-5{fill:rgb(189,201,225)} -.PuBuGn .q2-5{fill:rgb(103,169,207)} -.PuBuGn .q3-5{fill:rgb(28,144,153)} -.PuBuGn .q4-5{fill:rgb(1,108,89)} -.PuBuGn .q0-6{fill:rgb(246,239,247)} -.PuBuGn .q1-6{fill:rgb(208,209,230)} -.PuBuGn .q2-6{fill:rgb(166,189,219)} -.PuBuGn .q3-6{fill:rgb(103,169,207)} -.PuBuGn .q4-6{fill:rgb(28,144,153)} -.PuBuGn .q5-6{fill:rgb(1,108,89)} -.PuBuGn .q0-7{fill:rgb(246,239,247)} -.PuBuGn .q1-7{fill:rgb(208,209,230)} -.PuBuGn .q2-7{fill:rgb(166,189,219)} -.PuBuGn .q3-7{fill:rgb(103,169,207)} -.PuBuGn .q4-7{fill:rgb(54,144,192)} -.PuBuGn .q5-7{fill:rgb(2,129,138)} -.PuBuGn .q6-7{fill:rgb(1,100,80)} -.PuBuGn .q0-8{fill:rgb(255,247,251)} -.PuBuGn .q1-8{fill:rgb(236,226,240)} -.PuBuGn .q2-8{fill:rgb(208,209,230)} -.PuBuGn .q3-8{fill:rgb(166,189,219)} -.PuBuGn .q4-8{fill:rgb(103,169,207)} -.PuBuGn .q5-8{fill:rgb(54,144,192)} -.PuBuGn .q6-8{fill:rgb(2,129,138)} -.PuBuGn .q7-8{fill:rgb(1,100,80)} -.PuBuGn .q0-9{fill:rgb(255,247,251)} -.PuBuGn .q1-9{fill:rgb(236,226,240)} -.PuBuGn .q2-9{fill:rgb(208,209,230)} -.PuBuGn .q3-9{fill:rgb(166,189,219)} -.PuBuGn .q4-9{fill:rgb(103,169,207)} -.PuBuGn .q5-9{fill:rgb(54,144,192)} -.PuBuGn .q6-9{fill:rgb(2,129,138)} -.PuBuGn .q7-9{fill:rgb(1,108,89)} -.PuBuGn .q8-9{fill:rgb(1,70,54)} -.PuBu .q0-3{fill:rgb(236,231,242)} -.PuBu .q1-3{fill:rgb(166,189,219)} -.PuBu .q2-3{fill:rgb(43,140,190)} -.PuBu .q0-4{fill:rgb(241,238,246)} -.PuBu .q1-4{fill:rgb(189,201,225)} -.PuBu .q2-4{fill:rgb(116,169,207)} -.PuBu .q3-4{fill:rgb(5,112,176)} -.PuBu .q0-5{fill:rgb(241,238,246)} -.PuBu .q1-5{fill:rgb(189,201,225)} -.PuBu .q2-5{fill:rgb(116,169,207)} -.PuBu .q3-5{fill:rgb(43,140,190)} -.PuBu .q4-5{fill:rgb(4,90,141)} -.PuBu .q0-6{fill:rgb(241,238,246)} -.PuBu .q1-6{fill:rgb(208,209,230)} -.PuBu .q2-6{fill:rgb(166,189,219)} -.PuBu .q3-6{fill:rgb(116,169,207)} -.PuBu .q4-6{fill:rgb(43,140,190)} -.PuBu .q5-6{fill:rgb(4,90,141)} -.PuBu .q0-7{fill:rgb(241,238,246)} -.PuBu .q1-7{fill:rgb(208,209,230)} -.PuBu .q2-7{fill:rgb(166,189,219)} -.PuBu .q3-7{fill:rgb(116,169,207)} -.PuBu .q4-7{fill:rgb(54,144,192)} -.PuBu .q5-7{fill:rgb(5,112,176)} -.PuBu .q6-7{fill:rgb(3,78,123)} -.PuBu .q0-8{fill:rgb(255,247,251)} -.PuBu .q1-8{fill:rgb(236,231,242)} -.PuBu .q2-8{fill:rgb(208,209,230)} -.PuBu .q3-8{fill:rgb(166,189,219)} -.PuBu .q4-8{fill:rgb(116,169,207)} -.PuBu .q5-8{fill:rgb(54,144,192)} -.PuBu .q6-8{fill:rgb(5,112,176)} -.PuBu .q7-8{fill:rgb(3,78,123)} -.PuBu .q0-9{fill:rgb(255,247,251)} -.PuBu .q1-9{fill:rgb(236,231,242)} -.PuBu .q2-9{fill:rgb(208,209,230)} -.PuBu .q3-9{fill:rgb(166,189,219)} -.PuBu .q4-9{fill:rgb(116,169,207)} -.PuBu .q5-9{fill:rgb(54,144,192)} -.PuBu .q6-9{fill:rgb(5,112,176)} -.PuBu .q7-9{fill:rgb(4,90,141)} -.PuBu .q8-9{fill:rgb(2,56,88)} -.BuPu .q0-3{fill:rgb(224,236,244)} -.BuPu .q1-3{fill:rgb(158,188,218)} -.BuPu .q2-3{fill:rgb(136,86,167)} -.BuPu .q0-4{fill:rgb(237,248,251)} -.BuPu .q1-4{fill:rgb(179,205,227)} -.BuPu .q2-4{fill:rgb(140,150,198)} -.BuPu .q3-4{fill:rgb(136,65,157)} -.BuPu .q0-5{fill:rgb(237,248,251)} -.BuPu .q1-5{fill:rgb(179,205,227)} -.BuPu .q2-5{fill:rgb(140,150,198)} -.BuPu .q3-5{fill:rgb(136,86,167)} -.BuPu .q4-5{fill:rgb(129,15,124)} -.BuPu .q0-6{fill:rgb(237,248,251)} -.BuPu .q1-6{fill:rgb(191,211,230)} -.BuPu .q2-6{fill:rgb(158,188,218)} -.BuPu .q3-6{fill:rgb(140,150,198)} -.BuPu .q4-6{fill:rgb(136,86,167)} -.BuPu .q5-6{fill:rgb(129,15,124)} -.BuPu .q0-7{fill:rgb(237,248,251)} -.BuPu .q1-7{fill:rgb(191,211,230)} -.BuPu .q2-7{fill:rgb(158,188,218)} -.BuPu .q3-7{fill:rgb(140,150,198)} -.BuPu .q4-7{fill:rgb(140,107,177)} -.BuPu .q5-7{fill:rgb(136,65,157)} -.BuPu .q6-7{fill:rgb(110,1,107)} -.BuPu .q0-8{fill:rgb(247,252,253)} -.BuPu .q1-8{fill:rgb(224,236,244)} -.BuPu .q2-8{fill:rgb(191,211,230)} -.BuPu .q3-8{fill:rgb(158,188,218)} -.BuPu .q4-8{fill:rgb(140,150,198)} -.BuPu .q5-8{fill:rgb(140,107,177)} -.BuPu .q6-8{fill:rgb(136,65,157)} -.BuPu .q7-8{fill:rgb(110,1,107)} -.BuPu .q0-9{fill:rgb(247,252,253)} -.BuPu .q1-9{fill:rgb(224,236,244)} -.BuPu .q2-9{fill:rgb(191,211,230)} -.BuPu .q3-9{fill:rgb(158,188,218)} -.BuPu .q4-9{fill:rgb(140,150,198)} -.BuPu .q5-9{fill:rgb(140,107,177)} -.BuPu .q6-9{fill:rgb(136,65,157)} -.BuPu .q7-9{fill:rgb(129,15,124)} -.BuPu .q8-9{fill:rgb(77,0,75)} -.RdPu .q0-3{fill:rgb(253,224,221)} -.RdPu .q1-3{fill:rgb(250,159,181)} -.RdPu .q2-3{fill:rgb(197,27,138)} -.RdPu .q0-4{fill:rgb(254,235,226)} -.RdPu .q1-4{fill:rgb(251,180,185)} -.RdPu .q2-4{fill:rgb(247,104,161)} -.RdPu .q3-4{fill:rgb(174,1,126)} -.RdPu .q0-5{fill:rgb(254,235,226)} -.RdPu .q1-5{fill:rgb(251,180,185)} -.RdPu .q2-5{fill:rgb(247,104,161)} -.RdPu .q3-5{fill:rgb(197,27,138)} -.RdPu .q4-5{fill:rgb(122,1,119)} -.RdPu .q0-6{fill:rgb(254,235,226)} -.RdPu .q1-6{fill:rgb(252,197,192)} -.RdPu .q2-6{fill:rgb(250,159,181)} -.RdPu .q3-6{fill:rgb(247,104,161)} -.RdPu .q4-6{fill:rgb(197,27,138)} -.RdPu .q5-6{fill:rgb(122,1,119)} -.RdPu .q0-7{fill:rgb(254,235,226)} -.RdPu .q1-7{fill:rgb(252,197,192)} -.RdPu .q2-7{fill:rgb(250,159,181)} -.RdPu .q3-7{fill:rgb(247,104,161)} -.RdPu .q4-7{fill:rgb(221,52,151)} -.RdPu .q5-7{fill:rgb(174,1,126)} -.RdPu .q6-7{fill:rgb(122,1,119)} -.RdPu .q0-8{fill:rgb(255,247,243)} -.RdPu .q1-8{fill:rgb(253,224,221)} -.RdPu .q2-8{fill:rgb(252,197,192)} -.RdPu .q3-8{fill:rgb(250,159,181)} -.RdPu .q4-8{fill:rgb(247,104,161)} -.RdPu .q5-8{fill:rgb(221,52,151)} -.RdPu .q6-8{fill:rgb(174,1,126)} -.RdPu .q7-8{fill:rgb(122,1,119)} -.RdPu .q0-9{fill:rgb(255,247,243)} -.RdPu .q1-9{fill:rgb(253,224,221)} -.RdPu .q2-9{fill:rgb(252,197,192)} -.RdPu .q3-9{fill:rgb(250,159,181)} -.RdPu .q4-9{fill:rgb(247,104,161)} -.RdPu .q5-9{fill:rgb(221,52,151)} -.RdPu .q6-9{fill:rgb(174,1,126)} -.RdPu .q7-9{fill:rgb(122,1,119)} -.RdPu .q8-9{fill:rgb(73,0,106)} -.PuRd .q0-3{fill:rgb(231,225,239)} -.PuRd .q1-3{fill:rgb(201,148,199)} -.PuRd .q2-3{fill:rgb(221,28,119)} -.PuRd .q0-4{fill:rgb(241,238,246)} -.PuRd .q1-4{fill:rgb(215,181,216)} -.PuRd .q2-4{fill:rgb(223,101,176)} -.PuRd .q3-4{fill:rgb(206,18,86)} -.PuRd .q0-5{fill:rgb(241,238,246)} -.PuRd .q1-5{fill:rgb(215,181,216)} -.PuRd .q2-5{fill:rgb(223,101,176)} -.PuRd .q3-5{fill:rgb(221,28,119)} -.PuRd .q4-5{fill:rgb(152,0,67)} -.PuRd .q0-6{fill:rgb(241,238,246)} -.PuRd .q1-6{fill:rgb(212,185,218)} -.PuRd .q2-6{fill:rgb(201,148,199)} -.PuRd .q3-6{fill:rgb(223,101,176)} -.PuRd .q4-6{fill:rgb(221,28,119)} -.PuRd .q5-6{fill:rgb(152,0,67)} -.PuRd .q0-7{fill:rgb(241,238,246)} -.PuRd .q1-7{fill:rgb(212,185,218)} -.PuRd .q2-7{fill:rgb(201,148,199)} -.PuRd .q3-7{fill:rgb(223,101,176)} -.PuRd .q4-7{fill:rgb(231,41,138)} -.PuRd .q5-7{fill:rgb(206,18,86)} -.PuRd .q6-7{fill:rgb(145,0,63)} -.PuRd .q0-8{fill:rgb(247,244,249)} -.PuRd .q1-8{fill:rgb(231,225,239)} -.PuRd .q2-8{fill:rgb(212,185,218)} -.PuRd .q3-8{fill:rgb(201,148,199)} -.PuRd .q4-8{fill:rgb(223,101,176)} -.PuRd .q5-8{fill:rgb(231,41,138)} -.PuRd .q6-8{fill:rgb(206,18,86)} -.PuRd .q7-8{fill:rgb(145,0,63)} -.PuRd .q0-9{fill:rgb(247,244,249)} -.PuRd .q1-9{fill:rgb(231,225,239)} -.PuRd .q2-9{fill:rgb(212,185,218)} -.PuRd .q3-9{fill:rgb(201,148,199)} -.PuRd .q4-9{fill:rgb(223,101,176)} -.PuRd .q5-9{fill:rgb(231,41,138)} -.PuRd .q6-9{fill:rgb(206,18,86)} -.PuRd .q7-9{fill:rgb(152,0,67)} -.PuRd .q8-9{fill:rgb(103,0,31)} -.OrRd .q0-3{fill:rgb(254,232,200)} -.OrRd .q1-3{fill:rgb(253,187,132)} -.OrRd .q2-3{fill:rgb(227,74,51)} -.OrRd .q0-4{fill:rgb(254,240,217)} -.OrRd .q1-4{fill:rgb(253,204,138)} -.OrRd .q2-4{fill:rgb(252,141,89)} -.OrRd .q3-4{fill:rgb(215,48,31)} -.OrRd .q0-5{fill:rgb(254,240,217)} -.OrRd .q1-5{fill:rgb(253,204,138)} -.OrRd .q2-5{fill:rgb(252,141,89)} -.OrRd .q3-5{fill:rgb(227,74,51)} -.OrRd .q4-5{fill:rgb(179,0,0)} -.OrRd .q0-6{fill:rgb(254,240,217)} -.OrRd .q1-6{fill:rgb(253,212,158)} -.OrRd .q2-6{fill:rgb(253,187,132)} -.OrRd .q3-6{fill:rgb(252,141,89)} -.OrRd .q4-6{fill:rgb(227,74,51)} -.OrRd .q5-6{fill:rgb(179,0,0)} -.OrRd .q0-7{fill:rgb(254,240,217)} -.OrRd .q1-7{fill:rgb(253,212,158)} -.OrRd .q2-7{fill:rgb(253,187,132)} -.OrRd .q3-7{fill:rgb(252,141,89)} -.OrRd .q4-7{fill:rgb(239,101,72)} -.OrRd .q5-7{fill:rgb(215,48,31)} -.OrRd .q6-7{fill:rgb(153,0,0)} -.OrRd .q0-8{fill:rgb(255,247,236)} -.OrRd .q1-8{fill:rgb(254,232,200)} -.OrRd .q2-8{fill:rgb(253,212,158)} -.OrRd .q3-8{fill:rgb(253,187,132)} -.OrRd .q4-8{fill:rgb(252,141,89)} -.OrRd .q5-8{fill:rgb(239,101,72)} -.OrRd .q6-8{fill:rgb(215,48,31)} -.OrRd .q7-8{fill:rgb(153,0,0)} -.OrRd .q0-9{fill:rgb(255,247,236)} -.OrRd .q1-9{fill:rgb(254,232,200)} -.OrRd .q2-9{fill:rgb(253,212,158)} -.OrRd .q3-9{fill:rgb(253,187,132)} -.OrRd .q4-9{fill:rgb(252,141,89)} -.OrRd .q5-9{fill:rgb(239,101,72)} -.OrRd .q6-9{fill:rgb(215,48,31)} -.OrRd .q7-9{fill:rgb(179,0,0)} -.OrRd .q8-9{fill:rgb(127,0,0)} -.YlOrRd .q0-3{fill:rgb(255,237,160)} -.YlOrRd .q1-3{fill:rgb(254,178,76)} -.YlOrRd .q2-3{fill:rgb(240,59,32)} -.YlOrRd .q0-4{fill:rgb(255,255,178)} -.YlOrRd .q1-4{fill:rgb(254,204,92)} -.YlOrRd .q2-4{fill:rgb(253,141,60)} -.YlOrRd .q3-4{fill:rgb(227,26,28)} -.YlOrRd .q0-5{fill:rgb(255,255,178)} -.YlOrRd .q1-5{fill:rgb(254,204,92)} -.YlOrRd .q2-5{fill:rgb(253,141,60)} -.YlOrRd .q3-5{fill:rgb(240,59,32)} -.YlOrRd .q4-5{fill:rgb(189,0,38)} -.YlOrRd .q0-6{fill:rgb(255,255,178)} -.YlOrRd .q1-6{fill:rgb(254,217,118)} -.YlOrRd .q2-6{fill:rgb(254,178,76)} -.YlOrRd .q3-6{fill:rgb(253,141,60)} -.YlOrRd .q4-6{fill:rgb(240,59,32)} -.YlOrRd .q5-6{fill:rgb(189,0,38)} -.YlOrRd .q0-7{fill:rgb(255,255,178)} -.YlOrRd .q1-7{fill:rgb(254,217,118)} -.YlOrRd .q2-7{fill:rgb(254,178,76)} -.YlOrRd .q3-7{fill:rgb(253,141,60)} -.YlOrRd .q4-7{fill:rgb(252,78,42)} -.YlOrRd .q5-7{fill:rgb(227,26,28)} -.YlOrRd .q6-7{fill:rgb(177,0,38)} -.YlOrRd .q0-8{fill:rgb(255,255,204)} -.YlOrRd .q1-8{fill:rgb(255,237,160)} -.YlOrRd .q2-8{fill:rgb(254,217,118)} -.YlOrRd .q3-8{fill:rgb(254,178,76)} -.YlOrRd .q4-8{fill:rgb(253,141,60)} -.YlOrRd .q5-8{fill:rgb(252,78,42)} -.YlOrRd .q6-8{fill:rgb(227,26,28)} -.YlOrRd .q7-8{fill:rgb(177,0,38)} -.YlOrRd .q0-9{fill:rgb(255,255,204)} -.YlOrRd .q1-9{fill:rgb(255,237,160)} -.YlOrRd .q2-9{fill:rgb(254,217,118)} -.YlOrRd .q3-9{fill:rgb(254,178,76)} -.YlOrRd .q4-9{fill:rgb(253,141,60)} -.YlOrRd .q5-9{fill:rgb(252,78,42)} -.YlOrRd .q6-9{fill:rgb(227,26,28)} -.YlOrRd .q7-9{fill:rgb(189,0,38)} -.YlOrRd .q8-9{fill:rgb(128,0,38)} -.YlOrBr .q0-3{fill:rgb(255,247,188)} -.YlOrBr .q1-3{fill:rgb(254,196,79)} -.YlOrBr .q2-3{fill:rgb(217,95,14)} -.YlOrBr .q0-4{fill:rgb(255,255,212)} -.YlOrBr .q1-4{fill:rgb(254,217,142)} -.YlOrBr .q2-4{fill:rgb(254,153,41)} -.YlOrBr .q3-4{fill:rgb(204,76,2)} -.YlOrBr .q0-5{fill:rgb(255,255,212)} -.YlOrBr .q1-5{fill:rgb(254,217,142)} -.YlOrBr .q2-5{fill:rgb(254,153,41)} -.YlOrBr .q3-5{fill:rgb(217,95,14)} -.YlOrBr .q4-5{fill:rgb(153,52,4)} -.YlOrBr .q0-6{fill:rgb(255,255,212)} -.YlOrBr .q1-6{fill:rgb(254,227,145)} -.YlOrBr .q2-6{fill:rgb(254,196,79)} -.YlOrBr .q3-6{fill:rgb(254,153,41)} -.YlOrBr .q4-6{fill:rgb(217,95,14)} -.YlOrBr .q5-6{fill:rgb(153,52,4)} -.YlOrBr .q0-7{fill:rgb(255,255,212)} -.YlOrBr .q1-7{fill:rgb(254,227,145)} -.YlOrBr .q2-7{fill:rgb(254,196,79)} -.YlOrBr .q3-7{fill:rgb(254,153,41)} -.YlOrBr .q4-7{fill:rgb(236,112,20)} -.YlOrBr .q5-7{fill:rgb(204,76,2)} -.YlOrBr .q6-7{fill:rgb(140,45,4)} -.YlOrBr .q0-8{fill:rgb(255,255,229)} -.YlOrBr .q1-8{fill:rgb(255,247,188)} -.YlOrBr .q2-8{fill:rgb(254,227,145)} -.YlOrBr .q3-8{fill:rgb(254,196,79)} -.YlOrBr .q4-8{fill:rgb(254,153,41)} -.YlOrBr .q5-8{fill:rgb(236,112,20)} -.YlOrBr .q6-8{fill:rgb(204,76,2)} -.YlOrBr .q7-8{fill:rgb(140,45,4)} -.YlOrBr .q0-9{fill:rgb(255,255,229)} -.YlOrBr .q1-9{fill:rgb(255,247,188)} -.YlOrBr .q2-9{fill:rgb(254,227,145)} -.YlOrBr .q3-9{fill:rgb(254,196,79)} -.YlOrBr .q4-9{fill:rgb(254,153,41)} -.YlOrBr .q5-9{fill:rgb(236,112,20)} -.YlOrBr .q6-9{fill:rgb(204,76,2)} -.YlOrBr .q7-9{fill:rgb(153,52,4)} -.YlOrBr .q8-9{fill:rgb(102,37,6)} -.Purples .q0-3{fill:rgb(239,237,245)} -.Purples .q1-3{fill:rgb(188,189,220)} -.Purples .q2-3{fill:rgb(117,107,177)} -.Purples .q0-4{fill:rgb(242,240,247)} -.Purples .q1-4{fill:rgb(203,201,226)} -.Purples .q2-4{fill:rgb(158,154,200)} -.Purples .q3-4{fill:rgb(106,81,163)} -.Purples .q0-5{fill:rgb(242,240,247)} -.Purples .q1-5{fill:rgb(203,201,226)} -.Purples .q2-5{fill:rgb(158,154,200)} -.Purples .q3-5{fill:rgb(117,107,177)} -.Purples .q4-5{fill:rgb(84,39,143)} -.Purples .q0-6{fill:rgb(242,240,247)} -.Purples .q1-6{fill:rgb(218,218,235)} -.Purples .q2-6{fill:rgb(188,189,220)} -.Purples .q3-6{fill:rgb(158,154,200)} -.Purples .q4-6{fill:rgb(117,107,177)} -.Purples .q5-6{fill:rgb(84,39,143)} -.Purples .q0-7{fill:rgb(242,240,247)} -.Purples .q1-7{fill:rgb(218,218,235)} -.Purples .q2-7{fill:rgb(188,189,220)} -.Purples .q3-7{fill:rgb(158,154,200)} -.Purples .q4-7{fill:rgb(128,125,186)} -.Purples .q5-7{fill:rgb(106,81,163)} -.Purples .q6-7{fill:rgb(74,20,134)} -.Purples .q0-8{fill:rgb(252,251,253)} -.Purples .q1-8{fill:rgb(239,237,245)} -.Purples .q2-8{fill:rgb(218,218,235)} -.Purples .q3-8{fill:rgb(188,189,220)} -.Purples .q4-8{fill:rgb(158,154,200)} -.Purples .q5-8{fill:rgb(128,125,186)} -.Purples .q6-8{fill:rgb(106,81,163)} -.Purples .q7-8{fill:rgb(74,20,134)} -.Purples .q0-9{fill:rgb(252,251,253)} -.Purples .q1-9{fill:rgb(239,237,245)} -.Purples .q2-9{fill:rgb(218,218,235)} -.Purples .q3-9{fill:rgb(188,189,220)} -.Purples .q4-9{fill:rgb(158,154,200)} -.Purples .q5-9{fill:rgb(128,125,186)} -.Purples .q6-9{fill:rgb(106,81,163)} -.Purples .q7-9{fill:rgb(84,39,143)} -.Purples .q8-9{fill:rgb(63,0,125)} -.Blues .q0-3{fill:rgb(222,235,247)} -.Blues .q1-3{fill:rgb(158,202,225)} -.Blues .q2-3{fill:rgb(49,130,189)} -.Blues .q0-4{fill:rgb(239,243,255)} -.Blues .q1-4{fill:rgb(189,215,231)} -.Blues .q2-4{fill:rgb(107,174,214)} -.Blues .q3-4{fill:rgb(33,113,181)} -.Blues .q0-5{fill:rgb(239,243,255)} -.Blues .q1-5{fill:rgb(189,215,231)} -.Blues .q2-5{fill:rgb(107,174,214)} -.Blues .q3-5{fill:rgb(49,130,189)} -.Blues .q4-5{fill:rgb(8,81,156)} -.Blues .q0-6{fill:rgb(239,243,255)} -.Blues .q1-6{fill:rgb(198,219,239)} -.Blues .q2-6{fill:rgb(158,202,225)} -.Blues .q3-6{fill:rgb(107,174,214)} -.Blues .q4-6{fill:rgb(49,130,189)} -.Blues .q5-6{fill:rgb(8,81,156)} -.Blues .q0-7{fill:rgb(239,243,255)} -.Blues .q1-7{fill:rgb(198,219,239)} -.Blues .q2-7{fill:rgb(158,202,225)} -.Blues .q3-7{fill:rgb(107,174,214)} -.Blues .q4-7{fill:rgb(66,146,198)} -.Blues .q5-7{fill:rgb(33,113,181)} -.Blues .q6-7{fill:rgb(8,69,148)} -.Blues .q0-8{fill:rgb(247,251,255)} -.Blues .q1-8{fill:rgb(222,235,247)} -.Blues .q2-8{fill:rgb(198,219,239)} -.Blues .q3-8{fill:rgb(158,202,225)} -.Blues .q4-8{fill:rgb(107,174,214)} -.Blues .q5-8{fill:rgb(66,146,198)} -.Blues .q6-8{fill:rgb(33,113,181)} -.Blues .q7-8{fill:rgb(8,69,148)} -.Blues .q0-9{fill:rgb(247,251,255)} -.Blues .q1-9{fill:rgb(222,235,247)} -.Blues .q2-9{fill:rgb(198,219,239)} -.Blues .q3-9{fill:rgb(158,202,225)} -.Blues .q4-9{fill:rgb(107,174,214)} -.Blues .q5-9{fill:rgb(66,146,198)} -.Blues .q6-9{fill:rgb(33,113,181)} -.Blues .q7-9{fill:rgb(8,81,156)} -.Blues .q8-9{fill:rgb(8,48,107)} -.Greens .q0-3{fill:rgb(229,245,224)} -.Greens .q1-3{fill:rgb(161,217,155)} -.Greens .q2-3{fill:rgb(49,163,84)} -.Greens .q0-4{fill:rgb(237,248,233)} -.Greens .q1-4{fill:rgb(186,228,179)} -.Greens .q2-4{fill:rgb(116,196,118)} -.Greens .q3-4{fill:rgb(35,139,69)} -.Greens .q0-5{fill:rgb(237,248,233)} -.Greens .q1-5{fill:rgb(186,228,179)} -.Greens .q2-5{fill:rgb(116,196,118)} -.Greens .q3-5{fill:rgb(49,163,84)} -.Greens .q4-5{fill:rgb(0,109,44)} -.Greens .q0-6{fill:rgb(237,248,233)} -.Greens .q1-6{fill:rgb(199,233,192)} -.Greens .q2-6{fill:rgb(161,217,155)} -.Greens .q3-6{fill:rgb(116,196,118)} -.Greens .q4-6{fill:rgb(49,163,84)} -.Greens .q5-6{fill:rgb(0,109,44)} -.Greens .q0-7{fill:rgb(237,248,233)} -.Greens .q1-7{fill:rgb(199,233,192)} -.Greens .q2-7{fill:rgb(161,217,155)} -.Greens .q3-7{fill:rgb(116,196,118)} -.Greens .q4-7{fill:rgb(65,171,93)} -.Greens .q5-7{fill:rgb(35,139,69)} -.Greens .q6-7{fill:rgb(0,90,50)} -.Greens .q0-8{fill:rgb(247,252,245)} -.Greens .q1-8{fill:rgb(229,245,224)} -.Greens .q2-8{fill:rgb(199,233,192)} -.Greens .q3-8{fill:rgb(161,217,155)} -.Greens .q4-8{fill:rgb(116,196,118)} -.Greens .q5-8{fill:rgb(65,171,93)} -.Greens .q6-8{fill:rgb(35,139,69)} -.Greens .q7-8{fill:rgb(0,90,50)} -.Greens .q0-9{fill:rgb(247,252,245)} -.Greens .q1-9{fill:rgb(229,245,224)} -.Greens .q2-9{fill:rgb(199,233,192)} -.Greens .q3-9{fill:rgb(161,217,155)} -.Greens .q4-9{fill:rgb(116,196,118)} -.Greens .q5-9{fill:rgb(65,171,93)} -.Greens .q6-9{fill:rgb(35,139,69)} -.Greens .q7-9{fill:rgb(0,109,44)} -.Greens .q8-9{fill:rgb(0,68,27)} -.Oranges .q0-3{fill:rgb(254,230,206)} -.Oranges .q1-3{fill:rgb(253,174,107)} -.Oranges .q2-3{fill:rgb(230,85,13)} -.Oranges .q0-4{fill:rgb(254,237,222)} -.Oranges .q1-4{fill:rgb(253,190,133)} -.Oranges .q2-4{fill:rgb(253,141,60)} -.Oranges .q3-4{fill:rgb(217,71,1)} -.Oranges .q0-5{fill:rgb(254,237,222)} -.Oranges .q1-5{fill:rgb(253,190,133)} -.Oranges .q2-5{fill:rgb(253,141,60)} -.Oranges .q3-5{fill:rgb(230,85,13)} -.Oranges .q4-5{fill:rgb(166,54,3)} -.Oranges .q0-6{fill:rgb(254,237,222)} -.Oranges .q1-6{fill:rgb(253,208,162)} -.Oranges .q2-6{fill:rgb(253,174,107)} -.Oranges .q3-6{fill:rgb(253,141,60)} -.Oranges .q4-6{fill:rgb(230,85,13)} -.Oranges .q5-6{fill:rgb(166,54,3)} -.Oranges .q0-7{fill:rgb(254,237,222)} -.Oranges .q1-7{fill:rgb(253,208,162)} -.Oranges .q2-7{fill:rgb(253,174,107)} -.Oranges .q3-7{fill:rgb(253,141,60)} -.Oranges .q4-7{fill:rgb(241,105,19)} -.Oranges .q5-7{fill:rgb(217,72,1)} -.Oranges .q6-7{fill:rgb(140,45,4)} -.Oranges .q0-8{fill:rgb(255,245,235)} -.Oranges .q1-8{fill:rgb(254,230,206)} -.Oranges .q2-8{fill:rgb(253,208,162)} -.Oranges .q3-8{fill:rgb(253,174,107)} -.Oranges .q4-8{fill:rgb(253,141,60)} -.Oranges .q5-8{fill:rgb(241,105,19)} -.Oranges .q6-8{fill:rgb(217,72,1)} -.Oranges .q7-8{fill:rgb(140,45,4)} -.Oranges .q0-9{fill:rgb(255,245,235)} -.Oranges .q1-9{fill:rgb(254,230,206)} -.Oranges .q2-9{fill:rgb(253,208,162)} -.Oranges .q3-9{fill:rgb(253,174,107)} -.Oranges .q4-9{fill:rgb(253,141,60)} -.Oranges .q5-9{fill:rgb(241,105,19)} -.Oranges .q6-9{fill:rgb(217,72,1)} -.Oranges .q7-9{fill:rgb(166,54,3)} -.Oranges .q8-9{fill:rgb(127,39,4)} -.Reds .q0-3{fill:rgb(254,224,210)} -.Reds .q1-3{fill:rgb(252,146,114)} -.Reds .q2-3{fill:rgb(222,45,38)} -.Reds .q0-4{fill:rgb(254,229,217)} -.Reds .q1-4{fill:rgb(252,174,145)} -.Reds .q2-4{fill:rgb(251,106,74)} -.Reds .q3-4{fill:rgb(203,24,29)} -.Reds .q0-5{fill:rgb(254,229,217)} -.Reds .q1-5{fill:rgb(252,174,145)} -.Reds .q2-5{fill:rgb(251,106,74)} -.Reds .q3-5{fill:rgb(222,45,38)} -.Reds .q4-5{fill:rgb(165,15,21)} -.Reds .q0-6{fill:rgb(254,229,217)} -.Reds .q1-6{fill:rgb(252,187,161)} -.Reds .q2-6{fill:rgb(252,146,114)} -.Reds .q3-6{fill:rgb(251,106,74)} -.Reds .q4-6{fill:rgb(222,45,38)} -.Reds .q5-6{fill:rgb(165,15,21)} -.Reds .q0-7{fill:rgb(254,229,217)} -.Reds .q1-7{fill:rgb(252,187,161)} -.Reds .q2-7{fill:rgb(252,146,114)} -.Reds .q3-7{fill:rgb(251,106,74)} -.Reds .q4-7{fill:rgb(239,59,44)} -.Reds .q5-7{fill:rgb(203,24,29)} -.Reds .q6-7{fill:rgb(153,0,13)} -.Reds .q0-8{fill:rgb(255,245,240)} -.Reds .q1-8{fill:rgb(254,224,210)} -.Reds .q2-8{fill:rgb(252,187,161)} -.Reds .q3-8{fill:rgb(252,146,114)} -.Reds .q4-8{fill:rgb(251,106,74)} -.Reds .q5-8{fill:rgb(239,59,44)} -.Reds .q6-8{fill:rgb(203,24,29)} -.Reds .q7-8{fill:rgb(153,0,13)} -.Reds .q0-9{fill:rgb(255,245,240)} -.Reds .q1-9{fill:rgb(254,224,210)} -.Reds .q2-9{fill:rgb(252,187,161)} -.Reds .q3-9{fill:rgb(252,146,114)} -.Reds .q4-9{fill:rgb(251,106,74)} -.Reds .q5-9{fill:rgb(239,59,44)} -.Reds .q6-9{fill:rgb(203,24,29)} -.Reds .q7-9{fill:rgb(165,15,21)} -.Reds .q8-9{fill:rgb(103,0,13)} -.Greys .q0-3{fill:rgb(240,240,240)} -.Greys .q1-3{fill:rgb(189,189,189)} -.Greys .q2-3{fill:rgb(99,99,99)} -.Greys .q0-4{fill:rgb(247,247,247)} -.Greys .q1-4{fill:rgb(204,204,204)} -.Greys .q2-4{fill:rgb(150,150,150)} -.Greys .q3-4{fill:rgb(82,82,82)} -.Greys .q0-5{fill:rgb(247,247,247)} -.Greys .q1-5{fill:rgb(204,204,204)} -.Greys .q2-5{fill:rgb(150,150,150)} -.Greys .q3-5{fill:rgb(99,99,99)} -.Greys .q4-5{fill:rgb(37,37,37)} -.Greys .q0-6{fill:rgb(247,247,247)} -.Greys .q1-6{fill:rgb(217,217,217)} -.Greys .q2-6{fill:rgb(189,189,189)} -.Greys .q3-6{fill:rgb(150,150,150)} -.Greys .q4-6{fill:rgb(99,99,99)} -.Greys .q5-6{fill:rgb(37,37,37)} -.Greys .q0-7{fill:rgb(247,247,247)} -.Greys .q1-7{fill:rgb(217,217,217)} -.Greys .q2-7{fill:rgb(189,189,189)} -.Greys .q3-7{fill:rgb(150,150,150)} -.Greys .q4-7{fill:rgb(115,115,115)} -.Greys .q5-7{fill:rgb(82,82,82)} -.Greys .q6-7{fill:rgb(37,37,37)} -.Greys .q0-8{fill:rgb(255,255,255)} -.Greys .q1-8{fill:rgb(240,240,240)} -.Greys .q2-8{fill:rgb(217,217,217)} -.Greys .q3-8{fill:rgb(189,189,189)} -.Greys .q4-8{fill:rgb(150,150,150)} -.Greys .q5-8{fill:rgb(115,115,115)} -.Greys .q6-8{fill:rgb(82,82,82)} -.Greys .q7-8{fill:rgb(37,37,37)} -.Greys .q0-9{fill:rgb(255,255,255)} -.Greys .q1-9{fill:rgb(240,240,240)} -.Greys .q2-9{fill:rgb(217,217,217)} -.Greys .q3-9{fill:rgb(189,189,189)} -.Greys .q4-9{fill:rgb(150,150,150)} -.Greys .q5-9{fill:rgb(115,115,115)} -.Greys .q6-9{fill:rgb(82,82,82)} -.Greys .q7-9{fill:rgb(37,37,37)} -.Greys .q8-9{fill:rgb(0,0,0)} -.PuOr .q0-3{fill:rgb(241,163,64)} -.PuOr .q1-3{fill:rgb(247,247,247)} -.PuOr .q2-3{fill:rgb(153,142,195)} -.PuOr .q0-4{fill:rgb(230,97,1)} -.PuOr .q1-4{fill:rgb(253,184,99)} -.PuOr .q2-4{fill:rgb(178,171,210)} -.PuOr .q3-4{fill:rgb(94,60,153)} -.PuOr .q0-5{fill:rgb(230,97,1)} -.PuOr .q1-5{fill:rgb(253,184,99)} -.PuOr .q2-5{fill:rgb(247,247,247)} -.PuOr .q3-5{fill:rgb(178,171,210)} -.PuOr .q4-5{fill:rgb(94,60,153)} -.PuOr .q0-6{fill:rgb(179,88,6)} -.PuOr .q1-6{fill:rgb(241,163,64)} -.PuOr .q2-6{fill:rgb(254,224,182)} -.PuOr .q3-6{fill:rgb(216,218,235)} -.PuOr .q4-6{fill:rgb(153,142,195)} -.PuOr .q5-6{fill:rgb(84,39,136)} -.PuOr .q0-7{fill:rgb(179,88,6)} -.PuOr .q1-7{fill:rgb(241,163,64)} -.PuOr .q2-7{fill:rgb(254,224,182)} -.PuOr .q3-7{fill:rgb(247,247,247)} -.PuOr .q4-7{fill:rgb(216,218,235)} -.PuOr .q5-7{fill:rgb(153,142,195)} -.PuOr .q6-7{fill:rgb(84,39,136)} -.PuOr .q0-8{fill:rgb(179,88,6)} -.PuOr .q1-8{fill:rgb(224,130,20)} -.PuOr .q2-8{fill:rgb(253,184,99)} -.PuOr .q3-8{fill:rgb(254,224,182)} -.PuOr .q4-8{fill:rgb(216,218,235)} -.PuOr .q5-8{fill:rgb(178,171,210)} -.PuOr .q6-8{fill:rgb(128,115,172)} -.PuOr .q7-8{fill:rgb(84,39,136)} -.PuOr .q0-9{fill:rgb(179,88,6)} -.PuOr .q1-9{fill:rgb(224,130,20)} -.PuOr .q2-9{fill:rgb(253,184,99)} -.PuOr .q3-9{fill:rgb(254,224,182)} -.PuOr .q4-9{fill:rgb(247,247,247)} -.PuOr .q5-9{fill:rgb(216,218,235)} -.PuOr .q6-9{fill:rgb(178,171,210)} -.PuOr .q7-9{fill:rgb(128,115,172)} -.PuOr .q8-9{fill:rgb(84,39,136)} -.PuOr .q0-10{fill:rgb(127,59,8)} -.PuOr .q1-10{fill:rgb(179,88,6)} -.PuOr .q2-10{fill:rgb(224,130,20)} -.PuOr .q3-10{fill:rgb(253,184,99)} -.PuOr .q4-10{fill:rgb(254,224,182)} -.PuOr .q5-10{fill:rgb(216,218,235)} -.PuOr .q6-10{fill:rgb(178,171,210)} -.PuOr .q7-10{fill:rgb(128,115,172)} -.PuOr .q8-10{fill:rgb(84,39,136)} -.PuOr .q9-10{fill:rgb(45,0,75)} -.PuOr .q0-11{fill:rgb(127,59,8)} -.PuOr .q1-11{fill:rgb(179,88,6)} -.PuOr .q2-11{fill:rgb(224,130,20)} -.PuOr .q3-11{fill:rgb(253,184,99)} -.PuOr .q4-11{fill:rgb(254,224,182)} -.PuOr .q5-11{fill:rgb(247,247,247)} -.PuOr .q6-11{fill:rgb(216,218,235)} -.PuOr .q7-11{fill:rgb(178,171,210)} -.PuOr .q8-11{fill:rgb(128,115,172)} -.PuOr .q9-11{fill:rgb(84,39,136)} -.PuOr .q10-11{fill:rgb(45,0,75)} -.BrBG .q0-3{fill:rgb(216,179,101)} -.BrBG .q1-3{fill:rgb(245,245,245)} -.BrBG .q2-3{fill:rgb(90,180,172)} -.BrBG .q0-4{fill:rgb(166,97,26)} -.BrBG .q1-4{fill:rgb(223,194,125)} -.BrBG .q2-4{fill:rgb(128,205,193)} -.BrBG .q3-4{fill:rgb(1,133,113)} -.BrBG .q0-5{fill:rgb(166,97,26)} -.BrBG .q1-5{fill:rgb(223,194,125)} -.BrBG .q2-5{fill:rgb(245,245,245)} -.BrBG .q3-5{fill:rgb(128,205,193)} -.BrBG .q4-5{fill:rgb(1,133,113)} -.BrBG .q0-6{fill:rgb(140,81,10)} -.BrBG .q1-6{fill:rgb(216,179,101)} -.BrBG .q2-6{fill:rgb(246,232,195)} -.BrBG .q3-6{fill:rgb(199,234,229)} -.BrBG .q4-6{fill:rgb(90,180,172)} -.BrBG .q5-6{fill:rgb(1,102,94)} -.BrBG .q0-7{fill:rgb(140,81,10)} -.BrBG .q1-7{fill:rgb(216,179,101)} -.BrBG .q2-7{fill:rgb(246,232,195)} -.BrBG .q3-7{fill:rgb(245,245,245)} -.BrBG .q4-7{fill:rgb(199,234,229)} -.BrBG .q5-7{fill:rgb(90,180,172)} -.BrBG .q6-7{fill:rgb(1,102,94)} -.BrBG .q0-8{fill:rgb(140,81,10)} -.BrBG .q1-8{fill:rgb(191,129,45)} -.BrBG .q2-8{fill:rgb(223,194,125)} -.BrBG .q3-8{fill:rgb(246,232,195)} -.BrBG .q4-8{fill:rgb(199,234,229)} -.BrBG .q5-8{fill:rgb(128,205,193)} -.BrBG .q6-8{fill:rgb(53,151,143)} -.BrBG .q7-8{fill:rgb(1,102,94)} -.BrBG .q0-9{fill:rgb(140,81,10)} -.BrBG .q1-9{fill:rgb(191,129,45)} -.BrBG .q2-9{fill:rgb(223,194,125)} -.BrBG .q3-9{fill:rgb(246,232,195)} -.BrBG .q4-9{fill:rgb(245,245,245)} -.BrBG .q5-9{fill:rgb(199,234,229)} -.BrBG .q6-9{fill:rgb(128,205,193)} -.BrBG .q7-9{fill:rgb(53,151,143)} -.BrBG .q8-9{fill:rgb(1,102,94)} -.BrBG .q0-10{fill:rgb(84,48,5)} -.BrBG .q1-10{fill:rgb(140,81,10)} -.BrBG .q2-10{fill:rgb(191,129,45)} -.BrBG .q3-10{fill:rgb(223,194,125)} -.BrBG .q4-10{fill:rgb(246,232,195)} -.BrBG .q5-10{fill:rgb(199,234,229)} -.BrBG .q6-10{fill:rgb(128,205,193)} -.BrBG .q7-10{fill:rgb(53,151,143)} -.BrBG .q8-10{fill:rgb(1,102,94)} -.BrBG .q9-10{fill:rgb(0,60,48)} -.BrBG .q0-11{fill:rgb(84,48,5)} -.BrBG .q1-11{fill:rgb(140,81,10)} -.BrBG .q2-11{fill:rgb(191,129,45)} -.BrBG .q3-11{fill:rgb(223,194,125)} -.BrBG .q4-11{fill:rgb(246,232,195)} -.BrBG .q5-11{fill:rgb(245,245,245)} -.BrBG .q6-11{fill:rgb(199,234,229)} -.BrBG .q7-11{fill:rgb(128,205,193)} -.BrBG .q8-11{fill:rgb(53,151,143)} -.BrBG .q9-11{fill:rgb(1,102,94)} -.BrBG .q10-11{fill:rgb(0,60,48)} -.PRGn .q0-3{fill:rgb(175,141,195)} -.PRGn .q1-3{fill:rgb(247,247,247)} -.PRGn .q2-3{fill:rgb(127,191,123)} -.PRGn .q0-4{fill:rgb(123,50,148)} -.PRGn .q1-4{fill:rgb(194,165,207)} -.PRGn .q2-4{fill:rgb(166,219,160)} -.PRGn .q3-4{fill:rgb(0,136,55)} -.PRGn .q0-5{fill:rgb(123,50,148)} -.PRGn .q1-5{fill:rgb(194,165,207)} -.PRGn .q2-5{fill:rgb(247,247,247)} -.PRGn .q3-5{fill:rgb(166,219,160)} -.PRGn .q4-5{fill:rgb(0,136,55)} -.PRGn .q0-6{fill:rgb(118,42,131)} -.PRGn .q1-6{fill:rgb(175,141,195)} -.PRGn .q2-6{fill:rgb(231,212,232)} -.PRGn .q3-6{fill:rgb(217,240,211)} -.PRGn .q4-6{fill:rgb(127,191,123)} -.PRGn .q5-6{fill:rgb(27,120,55)} -.PRGn .q0-7{fill:rgb(118,42,131)} -.PRGn .q1-7{fill:rgb(175,141,195)} -.PRGn .q2-7{fill:rgb(231,212,232)} -.PRGn .q3-7{fill:rgb(247,247,247)} -.PRGn .q4-7{fill:rgb(217,240,211)} -.PRGn .q5-7{fill:rgb(127,191,123)} -.PRGn .q6-7{fill:rgb(27,120,55)} -.PRGn .q0-8{fill:rgb(118,42,131)} -.PRGn .q1-8{fill:rgb(153,112,171)} -.PRGn .q2-8{fill:rgb(194,165,207)} -.PRGn .q3-8{fill:rgb(231,212,232)} -.PRGn .q4-8{fill:rgb(217,240,211)} -.PRGn .q5-8{fill:rgb(166,219,160)} -.PRGn .q6-8{fill:rgb(90,174,97)} -.PRGn .q7-8{fill:rgb(27,120,55)} -.PRGn .q0-9{fill:rgb(118,42,131)} -.PRGn .q1-9{fill:rgb(153,112,171)} -.PRGn .q2-9{fill:rgb(194,165,207)} -.PRGn .q3-9{fill:rgb(231,212,232)} -.PRGn .q4-9{fill:rgb(247,247,247)} -.PRGn .q5-9{fill:rgb(217,240,211)} -.PRGn .q6-9{fill:rgb(166,219,160)} -.PRGn .q7-9{fill:rgb(90,174,97)} -.PRGn .q8-9{fill:rgb(27,120,55)} -.PRGn .q0-10{fill:rgb(64,0,75)} -.PRGn .q1-10{fill:rgb(118,42,131)} -.PRGn .q2-10{fill:rgb(153,112,171)} -.PRGn .q3-10{fill:rgb(194,165,207)} -.PRGn .q4-10{fill:rgb(231,212,232)} -.PRGn .q5-10{fill:rgb(217,240,211)} -.PRGn .q6-10{fill:rgb(166,219,160)} -.PRGn .q7-10{fill:rgb(90,174,97)} -.PRGn .q8-10{fill:rgb(27,120,55)} -.PRGn .q9-10{fill:rgb(0,68,27)} -.PRGn .q0-11{fill:rgb(64,0,75)} -.PRGn .q1-11{fill:rgb(118,42,131)} -.PRGn .q2-11{fill:rgb(153,112,171)} -.PRGn .q3-11{fill:rgb(194,165,207)} -.PRGn .q4-11{fill:rgb(231,212,232)} -.PRGn .q5-11{fill:rgb(247,247,247)} -.PRGn .q6-11{fill:rgb(217,240,211)} -.PRGn .q7-11{fill:rgb(166,219,160)} -.PRGn .q8-11{fill:rgb(90,174,97)} -.PRGn .q9-11{fill:rgb(27,120,55)} -.PRGn .q10-11{fill:rgb(0,68,27)} -.PiYG .q0-3{fill:rgb(233,163,201)} -.PiYG .q1-3{fill:rgb(247,247,247)} -.PiYG .q2-3{fill:rgb(161,215,106)} -.PiYG .q0-4{fill:rgb(208,28,139)} -.PiYG .q1-4{fill:rgb(241,182,218)} -.PiYG .q2-4{fill:rgb(184,225,134)} -.PiYG .q3-4{fill:rgb(77,172,38)} -.PiYG .q0-5{fill:rgb(208,28,139)} -.PiYG .q1-5{fill:rgb(241,182,218)} -.PiYG .q2-5{fill:rgb(247,247,247)} -.PiYG .q3-5{fill:rgb(184,225,134)} -.PiYG .q4-5{fill:rgb(77,172,38)} -.PiYG .q0-6{fill:rgb(197,27,125)} -.PiYG .q1-6{fill:rgb(233,163,201)} -.PiYG .q2-6{fill:rgb(253,224,239)} -.PiYG .q3-6{fill:rgb(230,245,208)} -.PiYG .q4-6{fill:rgb(161,215,106)} -.PiYG .q5-6{fill:rgb(77,146,33)} -.PiYG .q0-7{fill:rgb(197,27,125)} -.PiYG .q1-7{fill:rgb(233,163,201)} -.PiYG .q2-7{fill:rgb(253,224,239)} -.PiYG .q3-7{fill:rgb(247,247,247)} -.PiYG .q4-7{fill:rgb(230,245,208)} -.PiYG .q5-7{fill:rgb(161,215,106)} -.PiYG .q6-7{fill:rgb(77,146,33)} -.PiYG .q0-8{fill:rgb(197,27,125)} -.PiYG .q1-8{fill:rgb(222,119,174)} -.PiYG .q2-8{fill:rgb(241,182,218)} -.PiYG .q3-8{fill:rgb(253,224,239)} -.PiYG .q4-8{fill:rgb(230,245,208)} -.PiYG .q5-8{fill:rgb(184,225,134)} -.PiYG .q6-8{fill:rgb(127,188,65)} -.PiYG .q7-8{fill:rgb(77,146,33)} -.PiYG .q0-9{fill:rgb(197,27,125)} -.PiYG .q1-9{fill:rgb(222,119,174)} -.PiYG .q2-9{fill:rgb(241,182,218)} -.PiYG .q3-9{fill:rgb(253,224,239)} -.PiYG .q4-9{fill:rgb(247,247,247)} -.PiYG .q5-9{fill:rgb(230,245,208)} -.PiYG .q6-9{fill:rgb(184,225,134)} -.PiYG .q7-9{fill:rgb(127,188,65)} -.PiYG .q8-9{fill:rgb(77,146,33)} -.PiYG .q0-10{fill:rgb(142,1,82)} -.PiYG .q1-10{fill:rgb(197,27,125)} -.PiYG .q2-10{fill:rgb(222,119,174)} -.PiYG .q3-10{fill:rgb(241,182,218)} -.PiYG .q4-10{fill:rgb(253,224,239)} -.PiYG .q5-10{fill:rgb(230,245,208)} -.PiYG .q6-10{fill:rgb(184,225,134)} -.PiYG .q7-10{fill:rgb(127,188,65)} -.PiYG .q8-10{fill:rgb(77,146,33)} -.PiYG .q9-10{fill:rgb(39,100,25)} -.PiYG .q0-11{fill:rgb(142,1,82)} -.PiYG .q1-11{fill:rgb(197,27,125)} -.PiYG .q2-11{fill:rgb(222,119,174)} -.PiYG .q3-11{fill:rgb(241,182,218)} -.PiYG .q4-11{fill:rgb(253,224,239)} -.PiYG .q5-11{fill:rgb(247,247,247)} -.PiYG .q6-11{fill:rgb(230,245,208)} -.PiYG .q7-11{fill:rgb(184,225,134)} -.PiYG .q8-11{fill:rgb(127,188,65)} -.PiYG .q9-11{fill:rgb(77,146,33)} -.PiYG .q10-11{fill:rgb(39,100,25)} -.RdBu .q0-3{fill:rgb(239,138,98)} -.RdBu .q1-3{fill:rgb(247,247,247)} -.RdBu .q2-3{fill:rgb(103,169,207)} -.RdBu .q0-4{fill:rgb(202,0,32)} -.RdBu .q1-4{fill:rgb(244,165,130)} -.RdBu .q2-4{fill:rgb(146,197,222)} -.RdBu .q3-4{fill:rgb(5,113,176)} -.RdBu .q0-5{fill:rgb(202,0,32)} -.RdBu .q1-5{fill:rgb(244,165,130)} -.RdBu .q2-5{fill:rgb(247,247,247)} -.RdBu .q3-5{fill:rgb(146,197,222)} -.RdBu .q4-5{fill:rgb(5,113,176)} -.RdBu .q0-6{fill:rgb(178,24,43)} -.RdBu .q1-6{fill:rgb(239,138,98)} -.RdBu .q2-6{fill:rgb(253,219,199)} -.RdBu .q3-6{fill:rgb(209,229,240)} -.RdBu .q4-6{fill:rgb(103,169,207)} -.RdBu .q5-6{fill:rgb(33,102,172)} -.RdBu .q0-7{fill:rgb(178,24,43)} -.RdBu .q1-7{fill:rgb(239,138,98)} -.RdBu .q2-7{fill:rgb(253,219,199)} -.RdBu .q3-7{fill:rgb(247,247,247)} -.RdBu .q4-7{fill:rgb(209,229,240)} -.RdBu .q5-7{fill:rgb(103,169,207)} -.RdBu .q6-7{fill:rgb(33,102,172)} -.RdBu .q0-8{fill:rgb(178,24,43)} -.RdBu .q1-8{fill:rgb(214,96,77)} -.RdBu .q2-8{fill:rgb(244,165,130)} -.RdBu .q3-8{fill:rgb(253,219,199)} -.RdBu .q4-8{fill:rgb(209,229,240)} -.RdBu .q5-8{fill:rgb(146,197,222)} -.RdBu .q6-8{fill:rgb(67,147,195)} -.RdBu .q7-8{fill:rgb(33,102,172)} -.RdBu .q0-9{fill:rgb(178,24,43)} -.RdBu .q1-9{fill:rgb(214,96,77)} -.RdBu .q2-9{fill:rgb(244,165,130)} -.RdBu .q3-9{fill:rgb(253,219,199)} -.RdBu .q4-9{fill:rgb(247,247,247)} -.RdBu .q5-9{fill:rgb(209,229,240)} -.RdBu .q6-9{fill:rgb(146,197,222)} -.RdBu .q7-9{fill:rgb(67,147,195)} -.RdBu .q8-9{fill:rgb(33,102,172)} -.RdBu .q0-10{fill:rgb(103,0,31)} -.RdBu .q1-10{fill:rgb(178,24,43)} -.RdBu .q2-10{fill:rgb(214,96,77)} -.RdBu .q3-10{fill:rgb(244,165,130)} -.RdBu .q4-10{fill:rgb(253,219,199)} -.RdBu .q5-10{fill:rgb(209,229,240)} -.RdBu .q6-10{fill:rgb(146,197,222)} -.RdBu .q7-10{fill:rgb(67,147,195)} -.RdBu .q8-10{fill:rgb(33,102,172)} -.RdBu .q9-10{fill:rgb(5,48,97)} -.RdBu .q0-11{fill:rgb(103,0,31)} -.RdBu .q1-11{fill:rgb(178,24,43)} -.RdBu .q2-11{fill:rgb(214,96,77)} -.RdBu .q3-11{fill:rgb(244,165,130)} -.RdBu .q4-11{fill:rgb(253,219,199)} -.RdBu .q5-11{fill:rgb(247,247,247)} -.RdBu .q6-11{fill:rgb(209,229,240)} -.RdBu .q7-11{fill:rgb(146,197,222)} -.RdBu .q8-11{fill:rgb(67,147,195)} -.RdBu .q9-11{fill:rgb(33,102,172)} -.RdBu .q10-11{fill:rgb(5,48,97)} -.RdGy .q0-3{fill:rgb(239,138,98)} -.RdGy .q1-3{fill:rgb(255,255,255)} -.RdGy .q2-3{fill:rgb(153,153,153)} -.RdGy .q0-4{fill:rgb(202,0,32)} -.RdGy .q1-4{fill:rgb(244,165,130)} -.RdGy .q2-4{fill:rgb(186,186,186)} -.RdGy .q3-4{fill:rgb(64,64,64)} -.RdGy .q0-5{fill:rgb(202,0,32)} -.RdGy .q1-5{fill:rgb(244,165,130)} -.RdGy .q2-5{fill:rgb(255,255,255)} -.RdGy .q3-5{fill:rgb(186,186,186)} -.RdGy .q4-5{fill:rgb(64,64,64)} -.RdGy .q0-6{fill:rgb(178,24,43)} -.RdGy .q1-6{fill:rgb(239,138,98)} -.RdGy .q2-6{fill:rgb(253,219,199)} -.RdGy .q3-6{fill:rgb(224,224,224)} -.RdGy .q4-6{fill:rgb(153,153,153)} -.RdGy .q5-6{fill:rgb(77,77,77)} -.RdGy .q0-7{fill:rgb(178,24,43)} -.RdGy .q1-7{fill:rgb(239,138,98)} -.RdGy .q2-7{fill:rgb(253,219,199)} -.RdGy .q3-7{fill:rgb(255,255,255)} -.RdGy .q4-7{fill:rgb(224,224,224)} -.RdGy .q5-7{fill:rgb(153,153,153)} -.RdGy .q6-7{fill:rgb(77,77,77)} -.RdGy .q0-8{fill:rgb(178,24,43)} -.RdGy .q1-8{fill:rgb(214,96,77)} -.RdGy .q2-8{fill:rgb(244,165,130)} -.RdGy .q3-8{fill:rgb(253,219,199)} -.RdGy .q4-8{fill:rgb(224,224,224)} -.RdGy .q5-8{fill:rgb(186,186,186)} -.RdGy .q6-8{fill:rgb(135,135,135)} -.RdGy .q7-8{fill:rgb(77,77,77)} -.RdGy .q0-9{fill:rgb(178,24,43)} -.RdGy .q1-9{fill:rgb(214,96,77)} -.RdGy .q2-9{fill:rgb(244,165,130)} -.RdGy .q3-9{fill:rgb(253,219,199)} -.RdGy .q4-9{fill:rgb(255,255,255)} -.RdGy .q5-9{fill:rgb(224,224,224)} -.RdGy .q6-9{fill:rgb(186,186,186)} -.RdGy .q7-9{fill:rgb(135,135,135)} -.RdGy .q8-9{fill:rgb(77,77,77)} -.RdGy .q0-10{fill:rgb(103,0,31)} -.RdGy .q1-10{fill:rgb(178,24,43)} -.RdGy .q2-10{fill:rgb(214,96,77)} -.RdGy .q3-10{fill:rgb(244,165,130)} -.RdGy .q4-10{fill:rgb(253,219,199)} -.RdGy .q5-10{fill:rgb(224,224,224)} -.RdGy .q6-10{fill:rgb(186,186,186)} -.RdGy .q7-10{fill:rgb(135,135,135)} -.RdGy .q8-10{fill:rgb(77,77,77)} -.RdGy .q9-10{fill:rgb(26,26,26)} -.RdGy .q0-11{fill:rgb(103,0,31)} -.RdGy .q1-11{fill:rgb(178,24,43)} -.RdGy .q2-11{fill:rgb(214,96,77)} -.RdGy .q3-11{fill:rgb(244,165,130)} -.RdGy .q4-11{fill:rgb(253,219,199)} -.RdGy .q5-11{fill:rgb(255,255,255)} -.RdGy .q6-11{fill:rgb(224,224,224)} -.RdGy .q7-11{fill:rgb(186,186,186)} -.RdGy .q8-11{fill:rgb(135,135,135)} -.RdGy .q9-11{fill:rgb(77,77,77)} -.RdGy .q10-11{fill:rgb(26,26,26)} -.RdYlBu .q0-3{fill:rgb(252,141,89)} -.RdYlBu .q1-3{fill:rgb(255,255,191)} -.RdYlBu .q2-3{fill:rgb(145,191,219)} -.RdYlBu .q0-4{fill:rgb(215,25,28)} -.RdYlBu .q1-4{fill:rgb(253,174,97)} -.RdYlBu .q2-4{fill:rgb(171,217,233)} -.RdYlBu .q3-4{fill:rgb(44,123,182)} -.RdYlBu .q0-5{fill:rgb(215,25,28)} -.RdYlBu .q1-5{fill:rgb(253,174,97)} -.RdYlBu .q2-5{fill:rgb(255,255,191)} -.RdYlBu .q3-5{fill:rgb(171,217,233)} -.RdYlBu .q4-5{fill:rgb(44,123,182)} -.RdYlBu .q0-6{fill:rgb(215,48,39)} -.RdYlBu .q1-6{fill:rgb(252,141,89)} -.RdYlBu .q2-6{fill:rgb(254,224,144)} -.RdYlBu .q3-6{fill:rgb(224,243,248)} -.RdYlBu .q4-6{fill:rgb(145,191,219)} -.RdYlBu .q5-6{fill:rgb(69,117,180)} -.RdYlBu .q0-7{fill:rgb(215,48,39)} -.RdYlBu .q1-7{fill:rgb(252,141,89)} -.RdYlBu .q2-7{fill:rgb(254,224,144)} -.RdYlBu .q3-7{fill:rgb(255,255,191)} -.RdYlBu .q4-7{fill:rgb(224,243,248)} -.RdYlBu .q5-7{fill:rgb(145,191,219)} -.RdYlBu .q6-7{fill:rgb(69,117,180)} -.RdYlBu .q0-8{fill:rgb(215,48,39)} -.RdYlBu .q1-8{fill:rgb(244,109,67)} -.RdYlBu .q2-8{fill:rgb(253,174,97)} -.RdYlBu .q3-8{fill:rgb(254,224,144)} -.RdYlBu .q4-8{fill:rgb(224,243,248)} -.RdYlBu .q5-8{fill:rgb(171,217,233)} -.RdYlBu .q6-8{fill:rgb(116,173,209)} -.RdYlBu .q7-8{fill:rgb(69,117,180)} -.RdYlBu .q0-9{fill:rgb(215,48,39)} -.RdYlBu .q1-9{fill:rgb(244,109,67)} -.RdYlBu .q2-9{fill:rgb(253,174,97)} -.RdYlBu .q3-9{fill:rgb(254,224,144)} -.RdYlBu .q4-9{fill:rgb(255,255,191)} -.RdYlBu .q5-9{fill:rgb(224,243,248)} -.RdYlBu .q6-9{fill:rgb(171,217,233)} -.RdYlBu .q7-9{fill:rgb(116,173,209)} -.RdYlBu .q8-9{fill:rgb(69,117,180)} -.RdYlBu .q0-10{fill:rgb(165,0,38)} -.RdYlBu .q1-10{fill:rgb(215,48,39)} -.RdYlBu .q2-10{fill:rgb(244,109,67)} -.RdYlBu .q3-10{fill:rgb(253,174,97)} -.RdYlBu .q4-10{fill:rgb(254,224,144)} -.RdYlBu .q5-10{fill:rgb(224,243,248)} -.RdYlBu .q6-10{fill:rgb(171,217,233)} -.RdYlBu .q7-10{fill:rgb(116,173,209)} -.RdYlBu .q8-10{fill:rgb(69,117,180)} -.RdYlBu .q9-10{fill:rgb(49,54,149)} -.RdYlBu .q0-11{fill:rgb(165,0,38)} -.RdYlBu .q1-11{fill:rgb(215,48,39)} -.RdYlBu .q2-11{fill:rgb(244,109,67)} -.RdYlBu .q3-11{fill:rgb(253,174,97)} -.RdYlBu .q4-11{fill:rgb(254,224,144)} -.RdYlBu .q5-11{fill:rgb(255,255,191)} -.RdYlBu .q6-11{fill:rgb(224,243,248)} -.RdYlBu .q7-11{fill:rgb(171,217,233)} -.RdYlBu .q8-11{fill:rgb(116,173,209)} -.RdYlBu .q9-11{fill:rgb(69,117,180)} -.RdYlBu .q10-11{fill:rgb(49,54,149)} -.Spectral .q0-3{fill:rgb(252,141,89)} -.Spectral .q1-3{fill:rgb(255,255,191)} -.Spectral .q2-3{fill:rgb(153,213,148)} -.Spectral .q0-4{fill:rgb(215,25,28)} -.Spectral .q1-4{fill:rgb(253,174,97)} -.Spectral .q2-4{fill:rgb(171,221,164)} -.Spectral .q3-4{fill:rgb(43,131,186)} -.Spectral .q0-5{fill:rgb(215,25,28)} -.Spectral .q1-5{fill:rgb(253,174,97)} -.Spectral .q2-5{fill:rgb(255,255,191)} -.Spectral .q3-5{fill:rgb(171,221,164)} -.Spectral .q4-5{fill:rgb(43,131,186)} -.Spectral .q0-6{fill:rgb(213,62,79)} -.Spectral .q1-6{fill:rgb(252,141,89)} -.Spectral .q2-6{fill:rgb(254,224,139)} -.Spectral .q3-6{fill:rgb(230,245,152)} -.Spectral .q4-6{fill:rgb(153,213,148)} -.Spectral .q5-6{fill:rgb(50,136,189)} -.Spectral .q0-7{fill:rgb(213,62,79)} -.Spectral .q1-7{fill:rgb(252,141,89)} -.Spectral .q2-7{fill:rgb(254,224,139)} -.Spectral .q3-7{fill:rgb(255,255,191)} -.Spectral .q4-7{fill:rgb(230,245,152)} -.Spectral .q5-7{fill:rgb(153,213,148)} -.Spectral .q6-7{fill:rgb(50,136,189)} -.Spectral .q0-8{fill:rgb(213,62,79)} -.Spectral .q1-8{fill:rgb(244,109,67)} -.Spectral .q2-8{fill:rgb(253,174,97)} -.Spectral .q3-8{fill:rgb(254,224,139)} -.Spectral .q4-8{fill:rgb(230,245,152)} -.Spectral .q5-8{fill:rgb(171,221,164)} -.Spectral .q6-8{fill:rgb(102,194,165)} -.Spectral .q7-8{fill:rgb(50,136,189)} -.Spectral .q0-9{fill:rgb(213,62,79)} -.Spectral .q1-9{fill:rgb(244,109,67)} -.Spectral .q2-9{fill:rgb(253,174,97)} -.Spectral .q3-9{fill:rgb(254,224,139)} -.Spectral .q4-9{fill:rgb(255,255,191)} -.Spectral .q5-9{fill:rgb(230,245,152)} -.Spectral .q6-9{fill:rgb(171,221,164)} -.Spectral .q7-9{fill:rgb(102,194,165)} -.Spectral .q8-9{fill:rgb(50,136,189)} -.Spectral .q0-10{fill:rgb(158,1,66)} -.Spectral .q1-10{fill:rgb(213,62,79)} -.Spectral .q2-10{fill:rgb(244,109,67)} -.Spectral .q3-10{fill:rgb(253,174,97)} -.Spectral .q4-10{fill:rgb(254,224,139)} -.Spectral .q5-10{fill:rgb(230,245,152)} -.Spectral .q6-10{fill:rgb(171,221,164)} -.Spectral .q7-10{fill:rgb(102,194,165)} -.Spectral .q8-10{fill:rgb(50,136,189)} -.Spectral .q9-10{fill:rgb(94,79,162)} -.Spectral .q0-11{fill:rgb(158,1,66)} -.Spectral .q1-11{fill:rgb(213,62,79)} -.Spectral .q2-11{fill:rgb(244,109,67)} -.Spectral .q3-11{fill:rgb(253,174,97)} -.Spectral .q4-11{fill:rgb(254,224,139)} -.Spectral .q5-11{fill:rgb(255,255,191)} -.Spectral .q6-11{fill:rgb(230,245,152)} -.Spectral .q7-11{fill:rgb(171,221,164)} -.Spectral .q8-11{fill:rgb(102,194,165)} -.Spectral .q9-11{fill:rgb(50,136,189)} -.Spectral .q10-11{fill:rgb(94,79,162)} -.RdYlGn .q0-3{fill:rgb(252,141,89)} -.RdYlGn .q1-3{fill:rgb(255,255,191)} -.RdYlGn .q2-3{fill:rgb(145,207,96)} -.RdYlGn .q0-4{fill:rgb(215,25,28)} -.RdYlGn .q1-4{fill:rgb(253,174,97)} -.RdYlGn .q2-4{fill:rgb(166,217,106)} -.RdYlGn .q3-4{fill:rgb(26,150,65)} -.RdYlGn .q0-5{fill:rgb(215,25,28)} -.RdYlGn .q1-5{fill:rgb(253,174,97)} -.RdYlGn .q2-5{fill:rgb(255,255,191)} -.RdYlGn .q3-5{fill:rgb(166,217,106)} -.RdYlGn .q4-5{fill:rgb(26,150,65)} -.RdYlGn .q0-6{fill:rgb(215,48,39)} -.RdYlGn .q1-6{fill:rgb(252,141,89)} -.RdYlGn .q2-6{fill:rgb(254,224,139)} -.RdYlGn .q3-6{fill:rgb(217,239,139)} -.RdYlGn .q4-6{fill:rgb(145,207,96)} -.RdYlGn .q5-6{fill:rgb(26,152,80)} -.RdYlGn .q0-7{fill:rgb(215,48,39)} -.RdYlGn .q1-7{fill:rgb(252,141,89)} -.RdYlGn .q2-7{fill:rgb(254,224,139)} -.RdYlGn .q3-7{fill:rgb(255,255,191)} -.RdYlGn .q4-7{fill:rgb(217,239,139)} -.RdYlGn .q5-7{fill:rgb(145,207,96)} -.RdYlGn .q6-7{fill:rgb(26,152,80)} -.RdYlGn .q0-8{fill:rgb(215,48,39)} -.RdYlGn .q1-8{fill:rgb(244,109,67)} -.RdYlGn .q2-8{fill:rgb(253,174,97)} -.RdYlGn .q3-8{fill:rgb(254,224,139)} -.RdYlGn .q4-8{fill:rgb(217,239,139)} -.RdYlGn .q5-8{fill:rgb(166,217,106)} -.RdYlGn .q6-8{fill:rgb(102,189,99)} -.RdYlGn .q7-8{fill:rgb(26,152,80)} -.RdYlGn .q0-9{fill:rgb(215,48,39)} -.RdYlGn .q1-9{fill:rgb(244,109,67)} -.RdYlGn .q2-9{fill:rgb(253,174,97)} -.RdYlGn .q3-9{fill:rgb(254,224,139)} -.RdYlGn .q4-9{fill:rgb(255,255,191)} -.RdYlGn .q5-9{fill:rgb(217,239,139)} -.RdYlGn .q6-9{fill:rgb(166,217,106)} -.RdYlGn .q7-9{fill:rgb(102,189,99)} -.RdYlGn .q8-9{fill:rgb(26,152,80)} -.RdYlGn .q0-10{fill:rgb(165,0,38)} -.RdYlGn .q1-10{fill:rgb(215,48,39)} -.RdYlGn .q2-10{fill:rgb(244,109,67)} -.RdYlGn .q3-10{fill:rgb(253,174,97)} -.RdYlGn .q4-10{fill:rgb(254,224,139)} -.RdYlGn .q5-10{fill:rgb(217,239,139)} -.RdYlGn .q6-10{fill:rgb(166,217,106)} -.RdYlGn .q7-10{fill:rgb(102,189,99)} -.RdYlGn .q8-10{fill:rgb(26,152,80)} -.RdYlGn .q9-10{fill:rgb(0,104,55)} -.RdYlGn .q0-11{fill:rgb(165,0,38)} -.RdYlGn .q1-11{fill:rgb(215,48,39)} -.RdYlGn .q2-11{fill:rgb(244,109,67)} -.RdYlGn .q3-11{fill:rgb(253,174,97)} -.RdYlGn .q4-11{fill:rgb(254,224,139)} -.RdYlGn .q5-11{fill:rgb(255,255,191)} -.RdYlGn .q6-11{fill:rgb(217,239,139)} -.RdYlGn .q7-11{fill:rgb(166,217,106)} -.RdYlGn .q8-11{fill:rgb(102,189,99)} -.RdYlGn .q9-11{fill:rgb(26,152,80)} -.RdYlGn .q10-11{fill:rgb(0,104,55)} diff --git a/web/css/dc.css b/web/css/dc.css deleted file mode 100644 index eb907a4fa5..0000000000 --- a/web/css/dc.css +++ /dev/null @@ -1,328 +0,0 @@ -div.dc-chart { - float: left; -} - -.dc-chart rect.bar { - stroke: none; - cursor: pointer; -} - -.dc-chart rect.bar:hover { - fill-opacity: .5; -} - -.dc-chart rect.stack1 { - stroke: none; - fill: red; -} - -.dc-chart rect.stack2 { - stroke: none; - fill: green; -} - -.dc-chart rect.deselected { - stroke: none; - fill: #ccc; -} - -.dc-chart .empty-chart .pie-slice path { - fill: #FFEEEE; - cursor: default; -} - -.dc-chart .empty-chart .pie-slice { - cursor: default; -} - -.dc-chart .pie-slice { - fill: white; - font-size: 12px; - cursor: pointer; -} - -.dc-chart .pie-slice.external{ - fill: black; -} - -.dc-chart .pie-slice :hover { - fill-opacity: .8; -} - -.dc-chart .pie-slice.highlight { - fill-opacity: .8; -} - -.dc-chart .pie-path { - fill:none; - stroke-width: 2px; - stroke: black; - opacity: 0.4; -} - -.dc-chart .selected path { - stroke-width: 3; - stroke: #ccc; - fill-opacity: 1; -} - -.dc-chart .deselected path { - stroke: none; - fill-opacity: .5; - fill: #ccc; -} - -.dc-chart .axis path, -.dc-chart .axis line { - fill: none; - stroke: #000; - shape-rendering: crispEdges; -} - -.dc-chart .axis text { - font: 10px sans-serif; -} - -.dc-chart .grid-line, -.dc-chart .axis .grid-line { - fill: none; - stroke: #ccc; - opacity: .5; - shape-rendering: crispEdges; -} - -.dc-chart .grid-line line, -.dc-chart .axis .grid-line line { - fill: none; - stroke: #ccc; - opacity: .5; - shape-rendering: crispEdges; -} - -.dc-chart .brush rect.background { - z-index: -999; -} - -.dc-chart .brush rect.extent { - fill: steelblue; - fill-opacity: .125; -} - -.dc-chart .brush .resize path { - fill: #eee; - stroke: #666; -} - -.dc-chart path.line { - fill: none; - stroke-width: 1.5px; -} - -.dc-chart circle.dot { - stroke: none; -} - -.dc-chart g.dc-tooltip path { - fill: none; - stroke: grey; - stroke-opacity: .8; -} - -.dc-chart path.area { - fill-opacity: .3; - stroke: none; -} - -.dc-chart .node { - font-size: 0.7em; - cursor: pointer; -} - -.dc-chart .node :hover { - fill-opacity: .8; -} - -.dc-chart .selected circle { - stroke-width: 3; - stroke: #ccc; - fill-opacity: 1; -} - -.dc-chart .deselected circle { - stroke: none; - fill-opacity: .5; - fill: #ccc; -} - -.dc-chart .bubble { - stroke: none; - fill-opacity: 0.6; -} - -.dc-data-count { - float: right; - margin-top: 15px; - margin-right: 15px; -} - -.dc-data-count .filter-count { - color: #3182bd; - font-weight: bold; -} - -.dc-data-count .total-count { - color: #3182bd; - font-weight: bold; -} - -.dc-data-table { -} - -.dc-chart g.state { - cursor: pointer; -} - -.dc-chart g.state :hover { - fill-opacity: .8; -} - -.dc-chart g.state path { - stroke: white; -} - -.dc-chart g.selected path { -} - -.dc-chart g.deselected path { - fill: grey; -} - -.dc-chart g.selected text { -} - -.dc-chart g.deselected text { - display: none; -} - -.dc-chart g.county path { - stroke: white; - fill: none; -} - -.dc-chart g.debug rect { - fill: blue; - fill-opacity: .2; -} - -.dc-chart g.row rect { - fill-opacity: 0.8; - cursor: pointer; -} - -.dc-chart g.row rect:hover { - fill-opacity: 0.6; -} - -.dc-chart g.row text { - fill: white; - font-size: 12px; - cursor: pointer; -} - -.dc-legend { - font-size: 11px; -} - -.dc-legend-item { - cursor: pointer; -} - -.dc-chart g.axis text { - /* Makes it so the user can't accidentally click and select text that is meant as a label only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10 */ - -o-user-select: none; - user-select: none; - pointer-events: none; -} - -.dc-chart path.highlight { - stroke-width: 3; - fill-opacity: 1; - stroke-opacity: 1; -} - -.dc-chart .highlight { - fill-opacity: 1; - stroke-opacity: 1; -} - -.dc-chart .fadeout { - fill-opacity: 0.2; - stroke-opacity: 0.2; -} - -.dc-chart path.dc-symbol, -g.dc-legend-item.fadeout { - fill-opacity: 0.5; - stroke-opacity: 0.5; -} - -.dc-hard .number-display { - float: none; -} - -.dc-chart .box text { - font: 10px sans-serif; - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10 */ - -o-user-select: none; - user-select: none; - pointer-events: none; -} - -.dc-chart .box line, -.dc-chart .box circle { - fill: #fff; - stroke: #000; - stroke-width: 1.5px; -} - -.dc-chart .box rect { - stroke: #000; - stroke-width: 1.5px; -} - -.dc-chart .box .center { - stroke-dasharray: 3,3; -} - -.dc-chart .box .outlier { - fill: none; - stroke: #ccc; -} - -.dc-chart .box.deselected .box { - fill: #ccc; -} - -.dc-chart .box.deselected { - opacity: .5; -} - -.dc-chart .symbol{ - stroke: none; -} - -.dc-chart .heatmap .box-group.deselected rect { - stroke: none; - fill-opacity: .5; - fill: #ccc; -} - -.dc-chart .heatmap g.axis text { - pointer-events: all; - cursor: pointer; -} diff --git a/web/css/dc.min.css b/web/css/dc.min.css deleted file mode 100644 index 5e690cf66a..0000000000 --- a/web/css/dc.min.css +++ /dev/null @@ -1 +0,0 @@ -div.dc-chart{float:left}.dc-chart rect.bar{stroke:none;cursor:pointer}.dc-chart rect.bar:hover{fill-opacity:.5}.dc-chart rect.stack1{stroke:none;fill:red}.dc-chart rect.stack2{stroke:none;fill:green}.dc-chart rect.deselected{stroke:none;fill:#ccc}.dc-chart .empty-chart .pie-slice path{fill:#FEE;cursor:default}.dc-chart .empty-chart .pie-slice{cursor:default}.dc-chart .pie-slice{fill:#fff;font-size:12px;cursor:pointer}.dc-chart .pie-slice.external{fill:#000}.dc-chart .pie-slice :hover,.dc-chart .pie-slice.highlight{fill-opacity:.8}.dc-chart .pie-path{fill:none;stroke-width:2px;stroke:#000;opacity:.4}.dc-chart .selected path{stroke-width:3;stroke:#ccc;fill-opacity:1}.dc-chart .deselected path{stroke:none;fill-opacity:.5;fill:#ccc}.dc-chart .axis line,.dc-chart .axis path{fill:none;stroke:#000;shape-rendering:crispEdges}.dc-chart .axis text{font:10px sans-serif}.dc-chart .axis .grid-line,.dc-chart .axis .grid-line line,.dc-chart .grid-line,.dc-chart .grid-line line{fill:none;stroke:#ccc;opacity:.5;shape-rendering:crispEdges}.dc-chart .brush rect.background{z-index:-999}.dc-chart .brush rect.extent{fill:#4682b4;fill-opacity:.125}.dc-chart .brush .resize path{fill:#eee;stroke:#666}.dc-chart path.line{fill:none;stroke-width:1.5px}.dc-chart circle.dot{stroke:none}.dc-chart g.dc-tooltip path{fill:none;stroke:grey;stroke-opacity:.8}.dc-chart path.area{fill-opacity:.3;stroke:none}.dc-chart .node{font-size:.7em;cursor:pointer}.dc-chart .node :hover{fill-opacity:.8}.dc-chart .selected circle{stroke-width:3;stroke:#ccc;fill-opacity:1}.dc-chart .deselected circle{stroke:none;fill-opacity:.5;fill:#ccc}.dc-chart .bubble{stroke:none;fill-opacity:.6}.dc-data-count{float:right;margin-top:15px;margin-right:15px}.dc-data-count .filter-count,.dc-data-count .total-count{color:#3182bd;font-weight:700}.dc-chart g.state{cursor:pointer}.dc-chart g.state :hover{fill-opacity:.8}.dc-chart g.state path{stroke:#fff}.dc-chart g.deselected path{fill:grey}.dc-chart g.deselected text{display:none}.dc-chart g.county path{stroke:#fff;fill:none}.dc-chart g.debug rect{fill:#00f;fill-opacity:.2}.dc-chart g.row rect{fill-opacity:.8;cursor:pointer}.dc-chart g.row rect:hover{fill-opacity:.6}.dc-chart g.row text{fill:#fff;font-size:12px;cursor:pointer}.dc-chart .highlight,.dc-chart path.highlight{fill-opacity:1;stroke-opacity:1}.dc-legend{font-size:11px}.dc-legend-item{cursor:pointer}.dc-chart g.axis text{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;pointer-events:none}.dc-chart path.highlight{stroke-width:3}.dc-chart .fadeout{fill-opacity:.2;stroke-opacity:.2}.dc-chart path.dc-symbol,g.dc-legend-item.fadeout{fill-opacity:.5;stroke-opacity:.5}.dc-hard .number-display{float:none}.dc-chart .box text{font:10px sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;pointer-events:none}.dc-chart .box circle,.dc-chart .box line{fill:#fff;stroke:#000;stroke-width:1.5px}.dc-chart .box rect{stroke:#000;stroke-width:1.5px}.dc-chart .box .center{stroke-dasharray:3,3}.dc-chart .box .outlier{fill:none;stroke:#ccc}.dc-chart .box.deselected .box{fill:#ccc}.dc-chart .box.deselected{opacity:.5}.dc-chart .symbol{stroke:none}.dc-chart .heatmap .box-group.deselected rect{stroke:none;fill-opacity:.5;fill:#ccc}.dc-chart .heatmap g.axis text{pointer-events:all;cursor:pointer} \ No newline at end of file diff --git a/web/docs/api-2.0.0.md b/web/docs/api-2.0.0.md deleted file mode 100644 index 5b6240a0f9..0000000000 --- a/web/docs/api-2.0.0.md +++ /dev/null @@ -1,2003 +0,0 @@ -# DC API - * [Utilities](#utilities) - * [Filters](#filters) - * [Base Mixin](#base-mixin) - * [Listeners](#listeners) - * [Margin Mixin](#margin-mixin) - * [Color Mixin](#color-mixin) - * [Coordinate Grid Mixin](#coordinate-grid-mixin) - * [Stack Mixin](#stack-mixin) - * [Cap Mixin](#cap-mixin) - * [Bubble Mixin](#bubble-mixin) - * [Pie Chart](#pie-chart) - * [Bar Chart](#bar-chart) - * [Line Chart](#line-chart) - * [Data Count Widget](#data-count-widget) - * [Data Table Widget](#data-table-widget) - * [Data Grid Widget](#data-grid-widget) - * [Bubble Chart](#bubble-chart) - * [Composite Chart](#composite-chart) - * [Series Chart](#series-chart) - * [Geo Choropleth Chart](#geo-choropleth-chart) - * [Bubble Overlay Chart](#bubble-overlay-chart) - * [Row Chart](#row-chart) - * [Legend](#legend) - * [Scatter Plot](#scatter-plot) - * [Number Display Widget](#number-display-widget) - * [Heat Map](#heat-map) - * [Box Plot](#box-plot) - -#### Version 2.0.0-alpha.5 -The entire dc.js library is scoped under the **dc** name space. It does not introduce anything else -into the global name space. -#### Function Chaining -Most dc functions are designed to allow function chaining, meaning they return the current chart -instance whenever it is appropriate. This way chart configuration can be written in the following -style: -```js -chart.width(300) -.height(300) -.filter('sunday') -``` -The getter forms of functions do not participate in function chaining because they necessarily -return values that are not the chart. (Although some, such as `.svg` and `.xAxis`, return values -that are chainable d3 objects.) - -## Utilities - -#### dc.filterAll([chartGroup]) -Clear all filters on all charts within the given chart group. If the chart group is not given then -only charts that belong to the default chart group will be reset. - -#### dc.refocusAll([chartGroup]) -Reset zoom level / focus on all charts that belong to the given chart group. If the chart group is -not given then only charts that belong to the default chart group will be reset. - -#### dc.renderAll([chartGroup]) -Re-render all charts belong to the given chart group. If the chart group is not given then only -charts that belong to the default chart group will be re-rendered. - -#### dc.redrawAll([chartGroup]) -Redraw all charts belong to the given chart group. If the chart group is not given then only charts -that belong to the default chart group will be re-drawn. Redraw is different from re-render since -when redrawing dc tries to update the graphic incrementally, using transitions, instead of starting -from scratch. - -#### dc.disableTransitions -If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen -immediately. Default: false - -#### dc.units.integers -`dc.units.integers` is the default value for `xUnits` for the [Coordinate Grid -Chart](#coordinate-grid-chart) and should be used when the x values are a sequence of integers. - -It is a function that counts the number of integers in the range supplied in its start and end parameters. - -```js -chart.xUnits(dc.units.integers) // already the default -``` - -#### dc.units.ordinal -This argument can be passed to the `xUnits` function of the to specify ordinal units for the x -axis. Usually this parameter is used in combination with passing `d3.scale.ordinal()` to `.x`. - -It just returns the domain passed to it, which for ordinal charts is an array of all values. - -```js -chart.xUnits(dc.units.ordinal) -.x(d3.scale.ordinal()) -``` - -#### dc.units.fp.precision(precision) -This function generates an argument for the [Coordinate Grid Chart's](#coordinate-grid-chart) -`xUnits` function specifying that the x values are floating-point numbers with the given -precision. - -The returned function determines how many values at the given precision will fit into the range -supplied in its start and end parameters. - -```js -// specify values (and ticks) every 0.1 units -chart.xUnits(dc.units.fp.precision(0.1) -// there are 500 units between 0.5 and 1 if the precision is 0.001 -var thousandths = dc.units.fp.precision(0.001); -thousandths(0.5, 1.0) // returns 500 -``` - -#### dc.events.trigger(function[, delay]) -This function triggers a throttled event function with a specified delay (in milli-seconds). Events -that are triggered repetitively due to user interaction such brush dragging might flood the library -and invoke more renders than can be executed in time. Using this function to wrap your event -function allows the library to smooth out the rendering by throttling events and only responding to -the most recent event. - -```js -chart.renderlet(function(chart){ - // smooth the rendering through event throttling - dc.events.trigger(function(){ - // focus some other chart to the range selected by user on this chart - someOtherChart.focus(chart.filter()); - }); -}) -``` - -## Filters -The dc.js filters are functions which are passed into crossfilter to chose which records will be -accumulated to produce values for the charts. In the crossfilter model, any filters applied on one -dimension will affect all the other dimensions but not that one. dc always applies a filter -function to the dimension; the function combines multiple filters and if any of them accept a -record, it is filtered in. - -These filter constructors are used as appropriate by the various charts to implement brushing. We -mention below which chart uses which filter. In some cases, many instances of a filter will be added. - -#### dc.filters.RangedFilter(low, high) -RangedFilter is a filter which accepts keys between `low` and `high`. It is used to implement X -axis brushing for the [coordinate grid charts](#coordinate-grid-mixin). - -#### dc.filters.TwoDimensionalFilter(array) -TwoDimensionalFilter is a filter which accepts a single two-dimensional value. It is used by the -[heat map chart](#heat-map) to include particular cells as they are clicked. (Rows and columns are -filtered by filtering all the cells in the row or column.) - -#### dc.filters.RangedTwoDimensionalFilter(array) -The RangedTwoDimensionalFilter allows filtering all values which fit within a rectangular -region. It is used by the [scatter plot](#scatter-plot) to implement rectangular brushing. - -It takes two two-dimensional points in the form `[[x1,y1],[x2,y2]]`, and normalizes them so that -`x1 <= x2` and `y1 <- y2`. It then returns a filter which accepts any points which are in the -rectangular range including the lower values but excluding the higher values. - -If an array of two values are given to the RangedTwoDimensionalFilter, it interprets the values as -two x coordinates `x1` and `x2` and returns a filter which accepts any points for which `x1 <= x < -x2`. - -## Base Mixin -Base Mixin is an abstract functional object representing a basic dc chart object -for all chart and widget implementations. Methods from the Base Mixin are inherited -and available on all chart implementation in the DC library. - -#### .width([value]) -Set or get the width attribute of a chart. See `.height` below for further description of the -behavior. - -#### .height([value]) -Set or get the height attribute of a chart. The height is applied to the SVG element generated by -the chart when rendered (or rerendered). If a value is given, then it will be used to calculate -the new height and the chart returned for method chaining. The value can either be a numeric, a -function, or falsy. If no value is specified then the value of the current height attribute will -be returned. - -By default, without an explicit height being given, the chart will select the width of its -anchor element. If that isn't possible it defaults to 200. Setting the value falsy will return -the chart to the default behavior - -Examples: - -```js -chart.height(250); // Set the chart's height to 250px; -chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function -chart.height(null); // reset the height to the default auto calculation -``` - -#### .minWidth([value]) -Set or get the minimum width attribute of a chart. This only applicable if the width is -calculated by dc. - -#### .minHeight([value]) -Set or get the minimum height attribute of a chart. This only applicable if the height is -calculated by dc. - -#### .dimension([value]) - **mandatory** -Set or get the dimension attribute of a chart. In dc a dimension can be any valid [crossfilter -dimension](https://github.com/square/crossfilter/wiki/API-Reference#wiki-dimension). - -If a value is given, then it will be used as the new dimension. If no value is specified then -the current dimension will be returned. - -#### .data([callback]) -Set the data callback or retrieve the chart's data set. The data callback is passed the chart's -group and by default will return `group.all()`. This behavior may be modified to, for instance, -return only the top 5 groups: -``` - chart.data(function(group) { - return group.top(5); - }); -``` - -#### .group([value, [name]]) - **mandatory** -Set or get the group attribute of a chart. In dc a group is a [crossfilter -group](https://github.com/square/crossfilter/wiki/API-Reference#wiki-group). Usually the group -should be created from the particular dimension associated with the same chart. If a value is -given, then it will be used as the new group. - -If no value specified then the current group will be returned. -If `name` is specified then it will be used to generate legend label. - -#### .ordering([orderFunction]) -Get or set an accessor to order ordinal charts - -#### .filterAll() -Clear all filters associated with this chart. - -#### .select(selector) -Execute d3 single selection in the chart's scope using the given selector and return the d3 -selection. Roughly the same as: -```js -d3.select('#chart-id').select(selector); -``` -This function is **not chainable** since it does not return a chart instance; however the d3 -selection result can be chained to d3 function calls. - -#### .selectAll(selector) -Execute in scope d3 selectAll using the given selector and return d3 selection result. Roughly -the same as: -```js -d3.select('#chart-id').selectAll(selector); -``` -This function is **not chainable** since it does not return a chart instance; however the d3 -selection result can be chained to d3 function calls. - -#### .anchor([anchorChart|anchorSelector|anchorNode], [chartGroup]) -Set the svg root to either be an existing chart's root; or any valid [d3 single -selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom -block element such as a div; or a dom element or d3 selection. Optionally registers the chart -within the chartGroup. This class is called internally on chart initialization, but be called -again to relocate the chart. However, it will orphan any previously created SVG elements. - -#### .anchorName() -Returns the dom id for the chart's anchored location. - -#### .root([rootElement]) -Returns the root element where a chart resides. Usually it will be the parent div element where -the svg was created. You can also pass in a new root element however this is usually handled by -dc internally. Resetting the root element on a chart outside of dc internals may have -unexpected consequences. - -#### .svg([svgElement]) -Returns the top svg element for this specific chart. You can also pass in a new svg element, -however this is usually handled by dc internally. Resetting the svg element on a chart outside -of dc internals may have unexpected consequences. - -#### .resetSvg() -Remove the chart's SVG elements from the dom and recreate the container SVG element. - -#### .filterPrinter([filterPrinterFunction]) -Set or get the filter printer function. The filter printer function is used to generate human -friendly text for filter value(s) associated with the chart instance. By default dc charts use a -default filter printer `dc.printers.filter` that provides simple printing support for both -single value and ranged filters. - -#### .turnOnControls() & .turnOffControls() -Turn on/off optional control elements within the root element. dc currently supports the -following html control elements. - -* root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type - of control element is usually used to store a reset link to allow user to reset filter on a - certain chart. This element will be turned off automatically if the filter is cleared. -* root.selectAll('.filter') elements are turned on if the chart has an active filter. The text - content of this element is then replaced with the current filter value using the filter printer - function. This type of element will be turned off automatically if the filter is cleared. - -#### .transitionDuration([duration]) -Set or get the animation transition duration(in milliseconds) for this chart instance. Default -duration is 750ms. - -#### .render() -Invoking this method will force the chart to re-render everything from scratch. Generally it -should only be used to render the chart for the first time on the page or if you want to make -sure everything is redrawn from scratch instead of relying on the default incremental redrawing -behaviour. - -#### .redraw() -Calling redraw will cause the chart to re-render data changes incrementally. If there is no -change in the underlying data dimension then calling this method will have no effect on the -chart. Most chart interaction in dc will automatically trigger this method through internal -events (in particular [dc.redrawAll](#dcredrawallchartgroup)); therefore, you only need to -manually invoke this function if data is manipulated outside of dc's control (for example if -data is loaded in the background using `crossfilter.add()`). - -#### .hasFilterHandler([function]) -Set or get the has filter handler. The has filter handler is a function that checks to see if -the chart's current filters include a specific filter. Using a custom has filter handler allows -you to change the way filters are checked for and replaced. - -```js -// default has filter handler -function (filters, filter) { - if (filter === null || typeof(filter) === 'undefined') { - return filters.length > 0; - } - return filters.some(function (f) { - return filter <= f && filter >= f; - }); -} - -// custom filter handler (no-op) -chart.hasFilterHandler(function(filters, filter) { - return false; -}); -``` - -#### .hasFilter([filter]) -Check whether any active filter or a specific filter is associated with particular chart instance. -This function is **not chainable**. - -#### .removeFilterHandler([function]) -Set or get the remove filter handler. The remove filter handler is a function that removes a -filter from the chart's current filters. Using a custom remove filter handler allows you to -change how filters are removed or perform additional work when removing a filter, e.g. when -using a filter server other than crossfilter. - -Any changes should modify the `filters` array argument and return that array. - -```js -// default remove filter handler -function (filters, filter) { - for (var i = 0; i < filters.length; i++) { - if (filters[i] <= filter && filters[i] >= filter) { - filters.splice(i, 1); - break; - } - } - return filters; -} - -// custom filter handler (no-op) -chart.removeFilterHandler(function(filters, filter) { - return filters; -}); -``` - -#### .addFilterHandler([function]) -Set or get the add filter handler. The add filter handler is a function that adds a filter to -the chart's filter list. Using a custom add filter handler allows you to change the way filters -are added or perform additional work when adding a filter, e.g. when using a filter server other -than crossfilter. - -Any changes should modify the `filters` array argument and return that array. - -```js -// default add filter handler -function (filters, filter) { - filters.push(filter); - return filters; -} - -// custom filter handler (no-op) -chart.addFilterHandler(function(filters, filter) { - return filters; -}); -``` - -#### .resetFilterHandler([function]) -Set or get the reset filter handler. The reset filter handler is a function that resets the -chart's filter list by returning a new list. Using a custom reset filter handler allows you to -change the way filters are reset, or perform additional work when resetting the filters, -e.g. when using a filter server other than crossfilter. - -This function should return an array. - -```js -// default remove filter handler -function (filters) { - return []; -} - -// custom filter handler (no-op) -chart.resetFilterHandler(function(filters) { - return filters; -}); -``` - -#### .filter([filterValue]) -Filter the chart by the given value or return the current filter if the input parameter is missing. -```js -// filter by a single string -chart.filter('Sunday'); -// filter by a single age -chart.filter(18); -``` - -#### .filters() -Returns all current filters. This method does not perform defensive cloning of the internal -filter array before returning, therefore any modification of the returned array will effect the -chart's internal filter storage. - -#### .onClick(datum) -This function is passed to d3 as the onClick handler for each chart. The default behavior is to -filter on the clicked datum (passed to the callback) and redraw the chart group. - -#### .filterHandler([function]) -Set or get the filter handler. The filter handler is a function that performs the filter action -on a specific dimension. Using a custom filter handler allows you to perform additional logic -before or after filtering. - -```js -// default filter handler -function(dimension, filter){ - dimension.filter(filter); // perform filtering - return filter; // return the actual filter value -} - -// custom filter handler -chart.filterHandler(function(dimension, filter){ - var newFilter = filter + 10; - dimension.filter(newFilter); - return newFilter; // set the actual filter value to the new value -}); -``` - -#### .keyAccessor([keyAccessorFunction]) -Set or get the key accessor function. The key accessor function is used to retrieve the key -value from the crossfilter group. Key values are used differently in different charts, for -example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart. -```js -// default key accessor -chart.keyAccessor(function(d) { return d.key; }); -// custom key accessor for a multi-value crossfilter reduction -chart.keyAccessor(function(p) { return p.value.absGain; }); -``` - -#### .valueAccessor([valueAccessorFunction]) -Set or get the value accessor function. The value accessor function is used to retrieve the -value from the crossfilter group. Group values are used differently in different charts, for -example values correspond to slice sizes in a pie chart and y axis positions in a grid -coordinate chart. -```js -// default value accessor -chart.valueAccessor(function(d) { return d.value; }); -// custom value accessor for a multi-value crossfilter reduction -chart.valueAccessor(function(p) { return p.value.percentageGain; }); -``` - -#### .label([labelFunction]) -Set or get the label function. The chart class will use this function to render labels for each -child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every -chart supports the label function for example bar chart and line chart do not use this function -at all. -```js -// default label function just return the key -chart.label(function(d) { return d.key; }); -// label function has access to the standard d3 data binding and can get quite complicated -chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; }); -``` - -#### .renderLabel(boolean) -Turn on/off label rendering - -#### .title([titleFunction]) -Set or get the title function. The chart class will use this function to render the svg title -(usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice -in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function; -however in grid coordinate charts you need to turn off the brush in order to see titles, because -otherwise the brush layer will block tooltip triggering. -```js -// default title function just return the key -chart.title(function(d) { return d.key + ': ' + d.value; }); -// title function has access to the standard d3 data binding and can get quite complicated -chart.title(function(p) { - return p.key.getFullYear() - + '\n' - + 'Index Gain: ' + numberFormat(p.value.absGain) + '\n' - + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\n' - + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'; -}); -``` - -#### .renderTitle(boolean) -Turn on/off title rendering, or return the state of the render title flag if no arguments are -given. - -#### .renderlet(renderletFunction) -A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added -to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked -right after the chart finishes its own drawing routine, giving you a way to modify the svg -elements. Renderlet functions take the chart instance as the only input parameter and you can -use the dc API or use raw d3 to achieve pretty much any effect. -```js -// renderlet function -chart.renderlet(function(chart){ - // mix of dc API and d3 manipulation - chart.select('g.y').style('display', 'none'); - // its a closure so you can also access other chart variable available in the closure scope - moveChart.filter(chart.filter()); -}); -``` - -#### .chartGroup([group]) -Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn -together since it is expected they share the same underlying crossfilter data set. - -#### .expireCache() -Expire the internal chart cache. dc charts cache some data internally on a per chart basis to -speed up rendering and avoid unnecessary calculation; however it might be useful to clear the -cache if you have changed state which will affect rendering. For example if you invoke the -`crossfilter.add` function or reset group or dimension after rendering it is a good idea to -clear the cache to make sure charts are rendered properly. - -#### .legend([dc.legend]) -Attach a dc.legend widget to this chart. The legend widget will automatically draw legend labels -based on the color setting and names associated with each group. - -```js -chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) -``` - -#### .chartID() -Returns the internal numeric ID of the chart. - -#### .options(optionsObject) -Set chart options using a configuration object. Each key in the object will cause the method of -the same name to be called with the value to set that attribute for the chart. - -Example: -``` -chart.options({dimension: myDimension, group: myGroup}); -``` - -## Listeners -All dc chart instance supports the following listeners. - -#### .on('preRender', function(chart){...}) -This listener function will be invoked before chart rendering. - -#### .on('postRender', function(chart){...}) -This listener function will be invoked after chart finish rendering including all renderlets' logic. - -#### .on('preRedraw', function(chart){...}) -This listener function will be invoked before chart redrawing. - -#### .on('postRedraw', function(chart){...}) -This listener function will be invoked after chart finish redrawing including all renderlets' logic. - -#### .on('filtered', function(chart, filter){...}) -This listener function will be invoked after a filter is applied, added or removed. - -#### .on('zoomed', function(chart, filter){...}) -This listener function will be invoked after a zoom is triggered. - -## Margin Mixin -Margin is a mixin that provides margin utility functions for both the Row Chart and Coordinate Grid -Charts. - -#### .margins([margins]) -Get or set the margins for a particular coordinate grid chart instance. The margins is stored as -an associative Javascript array. Default margins: {top: 10, right: 50, bottom: 30, left: 30}. - -The margins can be accessed directly from the getter. -```js -var leftMargin = chart.margins().left; // 30 by default -chart.margins().left = 50; -leftMargin = chart.margins().left; // now 50 -``` - -## Color Mixin -The Color Mixin is an abstract chart functional class providing universal coloring support -as a mix-in for any concrete chart implementation. - -#### .colors([colorScale]) -Retrieve current color scale or set a new color scale. This methods accepts any function that -operates like a d3 scale. If not set the default is -`d3.scale.category20c()`. -```js -// alternate categorical scale -chart.colors(d3.scale.category20b()); - -// ordinal scale -chart.colors(d3.scale.ordinal().range(['red','green','blue'])); -// convenience method, the same as above -chart.ordinalColors(['red','green','blue']); - -// set a linear scale -chart.linearColors(["#4575b4", "#ffffbf", "#a50026"]); -``` - -#### .ordinalColors(r) -Convenience method to set the color scale to d3.scale.ordinal with range `r`. - -#### .linearColors(r) -Convenience method to set the color scale to an Hcl interpolated linear scale with range `r`. - -#### .colorAccessor([colorAccessorFunction]) -Set or the get color accessor function. This function will be used to map a data point in a -crossfilter group to a color value on the color scale. The default function uses the key -accessor. -```js -// default index based color accessor -.colorAccessor(function (d, i){return i;}) -// color accessor for a multi-value crossfilter reduction -.colorAccessor(function (d){return d.value.absGain;}) -``` - -#### .colorDomain([domain]) -Set or get the current domain for the color mapping function. The domain must be supplied as an -array. - -Note: previously this method accepted a callback function. Instead you may use a custom scale -set by `.colors`. - -#### .calculateColorDomain() -Set the domain by determining the min and max values as retrieved by `.colorAccessor` over the -chart's dataset. - -#### .getColor(d [, i]) -Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. - -#### .colorCalculator([value]) -Gets or sets chart.getColor. - -## Coordinate Grid Mixin -Includes: [Color Mixin](#color-mixin), [Margin Mixin](#margin-mixin), [Base Mixin](#base-mixin) - -Coordinate Grid is an abstract base chart designed to support a number of coordinate grid based -concrete chart types, e.g. bar chart, line chart, and bubble chart. - -#### .rangeChart([chart]) -Get or set the range selection chart associated with this instance. Setting the range selection -chart using this function will automatically update its selection brush when the current chart -zooms in. In return the given range chart will also automatically attach this chart as its focus -chart hence zoom in when range brush updates. See the [Nasdaq 100 -Index](http://dc-js.github.com/dc.js/) example for this effect in action. - -#### .zoomScale([extent]) -Get or set the scale extent for mouse zooms. - -#### .zoomOutRestrict([true/false]) -Get or set the zoom restriction for the chart. If true limits the zoom to origional domain of the chart. - -#### .g([gElement]) -Get or set the root g element. This method is usually used to retrieve the g element in order to -overlay custom svg drawing programatically. **Caution**: The root g element is usually generated -by dc.js internals, and resetting it might produce unpredictable result. - -#### .mouseZoomable([boolean]) -Set or get mouse zoom capability flag (default: false). When turned on the chart will be -zoomable using the mouse wheel. If the range selector chart is attached zooming will also update -the range selection brush on the associated range selector chart. - -#### .chartBodyG() -Retrieve the svg group for the chart body. - -#### .x([xScale]) - **mandatory** -Get or set the x scale. The x scale can be any d3 -[quantitive scale](https://github.com/mbostock/d3/wiki/Quantitative-Scales) or -[ordinal scale](https://github.com/mbostock/d3/wiki/Ordinal-Scales). -```js -// set x to a linear scale -chart.x(d3.scale.linear().domain([-2500, 2500])) -// set x to a time scale to generate histogram -chart.x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) -``` - -#### .xUnits([xUnits function]) -Set or get the xUnits function. The coordinate grid chart uses the xUnits function to calculate -the number of data projections on x axis such as the number of bars for a bar chart or the -number of dots for a line chart. This function is expected to return a Javascript array of all -data points on x axis, or the number of points on the axis. [d3 time range functions -d3.time.days, d3.time.months, and -d3.time.years](https://github.com/mbostock/d3/wiki/Time-Intervals#aliases) are all valid xUnits -function. dc.js also provides a few units function, see the [Utilities](#utilities) section for -a list of built-in units functions. The default xUnits function is dc.units.integers. -```js -// set x units to count days -chart.xUnits(d3.time.days); -// set x units to count months -chart.xUnits(d3.time.months); -``` -A custom xUnits function can be used as long as it follows the following interface: -```js -// units in integer -function(start, end, xDomain) { - // simply calculates how many integers in the domain - return Math.abs(end - start); -}; - -// fixed units -function(start, end, xDomain) { - // be aware using fixed units will disable the focus/zoom ability on the chart - return 1000; -}; -``` - -#### .xAxis([xAxis]) -Set or get the x axis used by a particular coordinate grid chart instance. This function is most -useful when x axis customization is required. The x axis in dc.js is an instance of a [d3 -axis object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis); therefore it supports any -valid d3 axis manipulation. **Caution**: The x axis is usually generated internally by dc; -resetting it may cause unexpected results. -```js -// customize x axis tick format -chart.xAxis().tickFormat(function(v) {return v + '%';}); -// customize x axis tick values -chart.xAxis().tickValues([0, 100, 200, 300]); -``` - -#### .elasticX([boolean]) -Turn on/off elastic x axis behavior. If x axis elasticity is turned on, then the grid chart will -attempt to recalculate the x axis range whenever a redraw event is triggered. - -#### .xAxisPadding([padding]) -Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x -axis if elasticX is turned on; otherwise it is ignored. - -* padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to -number or date x axes. When padding a date axis, an integer represents number of days being padded -and a percentage string will be treated the same as an integer. - -#### .xUnitCount() -Returns the number of units displayed on the x axis using the unit measure configured by -.xUnits. - -#### .useRightYAxis() -Gets or sets whether the chart should be drawn with a right axis instead of a left axis. When -used with a chart in a composite chart, allows both left and right Y axes to be shown on a -chart. - -#### isOrdinal() -Returns true if the chart is using ordinal xUnits ([dc.units.ordinal](#dcunitsordinal)), or false -otherwise. Most charts behave differently with ordinal data and use the result of this method to -trigger the appropriate logic. - -#### .xAxisLabel([labelText, [, padding]]) -Set or get the x axis label. If setting the label, you may optionally include additional padding to -the margin to make room for the label. By default the padded is set to 12 to accomodate the text height. - -#### .yAxisLabel([labelText, [, padding]]) -Set or get the y axis label. If setting the label, you may optionally include additional padding -to the margin to make room for the label. By default the padded is set to 12 to accomodate the -text height. - -#### .y([yScale]) -Get or set the y scale. The y scale is typically automatically determined by the chart implementation. - -#### .yAxis([yAxis]) -Set or get the y axis used by the coordinate grid chart instance. This function is most useful -when y axis customization is required. The y axis in dc.js is simply an instance of a [d3 axis -object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis); therefore it supports any -valid d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc; -resetting it may cause unexpected results. -```js -// customize y axis tick format -chart.yAxis().tickFormat(function(v) {return v + '%';}); -// customize y axis tick values -chart.yAxis().tickValues([0, 100, 200, 300]); -``` - -#### .elasticY([boolean]) -Turn on/off elastic y axis behavior. If y axis elasticity is turned on, then the grid chart will -attempt to recalculate the y axis range whenever a redraw event is triggered. - -#### .renderHorizontalGridLines([boolean]) -Turn on/off horizontal grid lines. - -#### .renderVerticalGridLines([boolean]) -Turn on/off vertical grid lines. - -#### .xAxisMin() -Calculates the minimum x value to display in the chart. Includes xAxisPadding if set. - -#### .xAxisMax() -Calculates the maximum x value to display in the chart. Includes xAxisPadding if set. - -#### .yAxisMin() -Calculates the minimum y value to display in the chart. Includes yAxisPadding if set. - -#### .yAxisMax() -Calculates the maximum y value to display in the chart. Includes yAxisPadding if set. - -#### .yAxisPadding([padding]) -Set or get y axis padding for the elastic y axis. The padding will be added to the top of the y -axis if elasticY is turned on; otherwise it is ignored. - -* padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to -number or date axes. When padding a date axis, an integer represents number of days being padded -and a percentage string will be treated the same as an integer. - -#### .round([rounding function]) -Set or get the rounding function used to quantize the selection when brushing is enabled. -```js -// set x unit round to by month, this will make sure range selection brush will -// select whole months -chart.round(d3.time.month.round); -``` - -#### .clipPadding([padding]) -Get or set the padding in pixels for the clip path. Once set padding will be applied evenly to -the top, left, right, and bottom when the clip path is generated. If set to zero, the clip area -will be exactly the chart body area minus the margins. Default: 5 - -#### .focus([range]) -Zoom this chart to focus on the given range. The given range should be an array containing only -2 elements (`[start, end]`) defining a range in the x domain. If the range is not given or set -to null, then the zoom will be reset. _For focus to work elasticX has to be turned off; -otherwise focus will be ignored._ -```js -chart.renderlet(function(chart){ - // smooth the rendering through event throttling - dc.events.trigger(function(){ - // focus some other chart to the range selected by user on this chart - someOtherChart.focus(chart.filter()); - }); -}) -``` - -#### .brushOn([boolean]) -Turn on/off the brush-based range filter. When brushing is on then user can drag the mouse -across a chart with a quantitative scale to perform range filtering based on the extent of the -brush, or click on the bars of an ordinal bar chart or slices of a pie chart to filter and -unfilter them. However turning on the brush filter will disable other interactive elements on -the chart such as highlighting, tool tips, and reference lines. Zooming will still be possible -if enabled, but only via scrolling (panning will be disabled.) Default: true - -## Stack Mixin -Stack Mixin is an mixin that provides cross-chart support of stackability using d3.layout.stack. - -#### .stack(group[, name, accessor]) -Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks -in the same chart will share the same key accessor and therefore the same set of keys. - -For example, in a stacked bar chart, the bars of each stack will be positioned using the same set -of keys on the x axis, while stacked vertically. If name is specified then it will be used to -generate the legend label. -```js -// stack group using default accessor -chart.stack(valueSumGroup) -// stack group using custom accessor -.stack(avgByDayGroup, function(d){return d.value.avgByDay;}); -``` - -#### .hidableStacks([boolean]) -Allow named stacks to be hidden or shown by clicking on legend items. -This does not affect the behavior of hideStack or showStack. - -#### .hideStack(name) -Hide all stacks on the chart with the given name. -The chart must be re-rendered for this change to appear. - -#### .showStack(name) -Show all stacks on the chart with the given name. -The chart must be re-rendered for this change to appear. - -#### .title([stackName], [titleFunction]) -Set or get the title function. Chart class will use this function to render svg title (usually interpreted by -browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart. -Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to -use title otherwise the brush layer will block tooltip trigger. - -If the first argument is a stack name, the title function will get or set the title for that stack. If stackName -is not provided, the first stack is implied. -```js -// set a title function on 'first stack' -chart.title('first stack', function(d) { return d.key + ': ' + d.value; }); -// get a title function from 'second stack' -var secondTitleFunction = chart.title('second stack'); -); -``` - -#### .stackLayout([layout]) -Gets or sets the stack layout algorithm, which computes a baseline for each stack and -propagates it to the next. The default is -[d3.layout.stack](https://github.com/mbostock/d3/wiki/Stack-Layout#stack). - -## Cap Mixin -Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the -Row and Pie Charts. - -The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest -will be replaced with an *others* element, with value equal to the sum of the replaced values. The -keys of the elements below the cap limit are recorded in order to filter by those keys when the -*others* element is clicked. - -#### .cap([count]) -Get or set the count of elements to that will be included in the cap. - -#### .othersLabel([label]) -Get or set the label for *Others* slice when slices cap is specified. Default label is **Others**. - -#### .othersGrouper([grouperFunction]) -Get or set the grouper function that will perform the insertion of data for the *Others* slice -if the slices cap is specified. If set to a falsy value, no others will be added. By default the -grouper function computes the sum of all values below the cap. -```js -chart.othersGrouper(function (data) { - // compute the value for others, presumably the sum of all values below the cap - var othersSum = yourComputeOthersValueLogic(data) - - // the keys are needed to properly filter when the others element is clicked - var othersKeys = yourComputeOthersKeysArrayLogic(data); - - // add the others row to the dataset - data.push({'key': 'Others', 'value': othersSum, 'others': othersKeys }); - - return data; -}); -``` - -## Bubble Mixin -Includes: [Color Mixin](#color-mixin) - -This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles. - -#### .r([bubbleRadiusScale]) -Get or set the bubble radius scale. By default the bubble chart uses -`d3.scale.linear().domain([0, 100])` as its r scale . - -#### .radiusValueAccessor([radiusValueAccessor]) -Get or set the radius value accessor function. If set, the radius value accessor function will -be used to retrieve a data value for each bubble. The data retrieved then will be mapped using -the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble -size. - -#### .minRadiusWithLabel([radius]) -Get or set the minimum radius for label rendering. If a bubble's radius is less than this value -then no label will be rendered. Default: 10 - -#### .maxBubbleRelativeSize([relativeSize]) -Get or set the maximum relative size of a bubble to the length of x axis. This value is useful -when the difference in radius between bubbles is too great. Default: 0.3 - -## Pie Chart -Includes: [Cap Mixin](#cap-mixin), [Color Mixin](#color-mixin), [Base Mixin](#base-mixin) - -The pie chart implementation is usually used to visualize a small categorical distribution. The pie -chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each -slice relative to the sum of all values. Slices are ordered by `.ordering` which defaults to sorting -by key. - -Examples: - -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -#### dc.pieChart(parent[, chartGroup]) -Create a pie chart instance and attaches it to the given parent element. - -Parameters: - -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created pie chart instance - -```js -// create a pie chart under #chart-container1 element using the default global chart group -var chart1 = dc.pieChart('#chart-container1'); -// create a pie chart under #chart-container2 element using chart group A -var chart2 = dc.pieChart('#chart-container2', 'chartGroupA'); -``` - -#### .slicesCap([cap]) -Get or set the maximum number of slices the pie chart will generate. The top slices are determined by -value from high to low. Other slices exeeding the cap will be rolled up into one single *Others* slice. -The resulting data will still be sorted by .ordering (default by key). - -#### .innerRadius([innerRadius]) -Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the -pie chart will be rendered as a doughnut chart. Default inner radius is 0px. - -#### .radius([radius]) -Get or set the outer radius. If the radius is not set, it will be half of the minimum of the -chart width and height. - -#### .cx([cx]) -Get or set center x coordinate position. Default is center of svg. - -#### .cy([cy]) -Get or set center y coordinate position. Default is center of svg. - -#### .minAngleForLabel([minAngle]) -Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not -display a slice label. Default min angle is 0.5. - -## Bar Chart -Includes: [Stack Mixin](#stack Mixin), [Coordinate Grid Mixin](#coordinate-grid-mixin) - -Concrete bar chart/histogram implementation. - -Examples: - -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -* [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) -#### dc.barChart(parent[, chartGroup]) -Create a bar chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection | compositeChart - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -If the bar chart is a sub-chart in a [Composite Chart](#composite-chart) then pass in the parent composite -chart instance. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created bar chart instance - -```js -// create a bar chart under #chart-container1 element using the default global chart group -var chart1 = dc.barChart('#chart-container1'); -// create a bar chart under #chart-container2 element using chart group A -var chart2 = dc.barChart('#chart-container2', 'chartGroupA'); -// create a sub-chart under a composite parent chart -var chart3 = dc.barChart(compositeChart); -``` - -#### .centerBar(boolean) -Whether the bar chart will render each bar centered around the data position on x axis. Default: false - -#### .barPadding([padding]) -Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1. -Setting this value will also remove any previously set `gap`. See the -[d3 docs](https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands) -for a visual description of how the padding is applied. - -#### .outerPadding([padding]) -Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts. -Will pad the width by `padding * barWidth` on each side of the chart. - -Default: 0.5 - -#### .gap(gapBetweenBars) -Manually set fixed gap (in px) between bars instead of relying on the default auto-generated -gap. By default the bar chart implementation will calculate and set the gap automatically -based on the number of data points and the length of the x axis. - -#### .alwaysUseRounding([boolean]) -Set or get whether rounding is enabled when bars are centered. Default: false. If false, using -rounding with centered bars will result in a warning and rounding will be ignored. This flag -has no effect if bars are not centered. - -When using standard d3.js rounding methods, the brush often doesn't align correctly with -centered bars since the bars are offset. The rounding function must add an offset to -compensate, such as in the following example. -```js -chart.round(function(n) {return Math.floor(n)+0.5}); -``` - -## Line Chart -Includes [Stack Mixin](#stack-mixin), [Coordinate Grid Mixin](#coordinate-grid-mixin) - -Concrete line/area chart implementation. - -Examples: -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -* [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) -#### dc.lineChart(parent[, chartGroup]) -Create a line chart instance and attach it to the given parent element. - -Parameters: - -* parent : string | node | selection | compositeChart - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -If the line chart is a sub-chart in a [Composite Chart](#composite-chart) then pass in the parent composite -chart instance. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created line chart instance - -```js -// create a line chart under #chart-container1 element using the default global chart group -var chart1 = dc.lineChart('#chart-container1'); -// create a line chart under #chart-container2 element using chart group A -var chart2 = dc.lineChart('#chart-container2', 'chartGroupA'); -// create a sub-chart under a composite parent chart -var chart3 = dc.lineChart(compositeChart); -``` - -#### .interpolate([value]) -Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step -functions, splines, and cubic interpolation. This is passed to -[d3.svg.line.interpolate](https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate) and -[d3.svg.area.interpolate](https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate), -where you can find a complete list of valid arguments - -#### .tension([value]) Gets or sets the tension to use for lines drawn, in the range 0 to 1. -This parameter further customizes the interpolation behavior. It is passed to -[d3.svg.line.tension](https://github.com/mbostock/d3/wiki/SVG-Shapes#line_tension) and -[d3.svg.area.tension](https://github.com/mbostock/d3/wiki/SVG-Shapes#area_tension). Default: -0.7 - -#### .defined([value]) -Gets or sets a function that will determine discontinuities in the line which should be -skipped: the path will be broken into separate subpaths if some points are undefined. -This function is passed to -[d3.svg.line.defined](https://github.com/mbostock/d3/wiki/SVG-Shapes#line_defined) - -Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write -custom reduce functions to get this to work, depending on your data. See -https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248 - -#### .dashStyle([array]) -Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty -array (solid line). - ```js - // create a Dash Dot Dot Dot - chart.dashStyle([3,1,1,1]); - ``` - -#### .renderArea([boolean]) -Get or set render area flag. If the flag is set to true then the chart will render the area -beneath each line and the line chart effectively becomes an area chart. - -#### .dotRadius([dotRadius]) -Get or set the radius (in px) for dots displayed on the data points. Default dot radius is 5. - -#### .renderDataPoints([options]) -Always show individual dots for each datapoint. - -Options, if given, is an object that can contain the following: - -* fillOpacity (default 0.8) -* strokeOpacity (default 0.8) -* radius (default 2) - -If `options` is falsy, it disables data point rendering. - -If no `options` are provided, the current `options` values are instead returned. - -Example: -``` -chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.8}) -``` - -## Data Count Widget -Includes: [Base Mixin](#base-mixin) - -The data count widget is a simple widget designed to display the number of records selected by the -current filters out of the total number of records in the data set. Once created the data count widget -will automatically update the text content of the following elements under the parent element. - -* '.total-count' - total number of records -* '.filter-count' - number of records matched by the current filters - -Examples: - -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -#### dc.dataCount(parent[, chartGroup]) -Create a data count widget and attach it to the given parent element. - -Parameters: - -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -* chartGroup : string (optional) - name of the chart group this widget should be placed in. -The data count widget will only react to filter changes in the chart group. - -Returns: -A newly created data count widget instance -#### .dimension(allData) - **mandatory** -For the data count widget the only valid dimension is the entire data set. -#### .group(groupAll) - **mandatory** -For the data count widget the only valid group is the group returned by `dimension.groupAll()`. - -```js -var ndx = crossfilter(data); -var all = ndx.groupAll(); - -dc.dataCount('.dc-data-count') - .dimension(ndx) - .group(all); -``` - -#### html([object]) -Gets or sets an optional object specifying HTML templates to use depending how many items are -selected. The text `%total-count` will replaced with the total number of records, and the text -`%filter-count` will be replaced with the number of selected records. -- all: HTML template to use if all items are selected -- some: HTML template to use if not all items are selected - -```js -counter.html({ - some: '%filter-count out of %total-count records selected', - all: 'All records selected. Click on charts to apply filters' -}) -``` - -#### formatNumber([formatter]) -Gets or sets an optional function to format the filter count and total count. - -```js -counter.formatNumber(d3.format('.2g')) -``` - -## Data Table Widget -Includes: [Base Mixin](#base-mixin) - -The data table is a simple widget designed to list crossfilter focused data set (rows being -filtered) in a good old tabular fashion. - -Examples: -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -#### dc.dataTable(parent[, chartGroup]) -Create a data table widget instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created data table widget instance - -#### .size([size]) -Get or set the table size which determines the number of rows displayed by the widget. - -#### .columns([columnFunctionArray]) -Get or set column functions. The data table widget now supports several methods of specifying -the columns to display. The original method, first shown below, uses an array of functions to -generate dynamic columns. Column functions are simple javascript functions with only one input -argument `d` which represents a row in the data set. The return value of these functions will be -used directly to generate table content for each cell. However, this method requires the .html -table entry to have a fixed set of column headers. - -```js - chart.columns([ - function(d) { - return d.date; - }, - function(d) { - return d.open; - }, - function(d) { - return d.close; - }, - function(d) { - return numberFormat(d.close - d.open); - }, - function(d) { - return d.volume; - } - ]); -``` - -The next example shows you can simply list the data (d) content directly without -specifying it as a function, except where necessary (ie, computed columns). Note -the data element accessor name is capitalized when displayed in the table. You can -also mix in functions as desired or necessary, but you must use the - Object = [Label, Fn] method as shown below. -You may wish to override the following two functions, which are internally used to -translate the column information or function into a displayed header. The first one -is used on the simple "string" column specifier, the second is used to transform the -String(fn) into something displayable. For the Stock example, the function for Change -becomes a header of 'd.close - d.open'. - _chart._doColumnHeaderCapitalize _chart._doColumnHeaderFnToString -You may use your own Object definition, however you must then override - _chart._doColumnHeaderFormat , _chart._doColumnValueFormat -Be aware that fields without numberFormat specification will be displayed just as -they are stored in the data, unformatted. -```js - chart.columns([ - "date", // d["date"], ie, a field accessor; capitalized automatically - "open", // ... - "close", // ... - ["Change", // Specify an Object = [Label, Fn] - function (d) { - return numberFormat(d.close - d.open); - }], - "volume" // d["volume"], ie, a field accessor; capitalized automatically - ]); -``` - -A third example, where all fields are specified using the Object = [Label, Fn] method. - -```js - chart.columns([ - ["Date", // Specify an Object = [Label, Fn] - function (d) { - return d.date; - }], - ["Open", - function (d) { - return numberFormat(d.open); - }], - ["Close", - function (d) { - return numberFormat(d.close); - }], - ["Change", - function (d) { - return numberFormat(d.close - d.open); - }], - ["Volume", - function (d) { - return d.volume; - }] - ]); -``` - -#### .sortBy([sortByFunction]) -Get or set sort-by function. This function works as a value accessor at row level and returns a -particular field to be sorted by. Default value: identity function - -```js - chart.sortBy(function(d) { - return d.date; - }); -``` - -#### .order([order]) -Get or set sort order. Default value: ``` d3.ascending ``` - -```js - chart.order(d3.descending); -``` - -## Data Grid Widget - -Includes: [Base Mixin](#base-mixin) - -Data grid is a simple widget designed to list the filtered records, providing -a simple way to define how the items are displayed. - -Examples: -* [List of members of the european parliament](http://europarl.me/dc.js/web/ep/index.html) - -#### dc.dataGrid(parent[, chartGroup]) -Create a data grid widget instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created data grid widget instance - -#### .size([size]) -Get or set the grid size which determines the number of items displayed by the widget. - -#### .html( function (data) { return ''; }) -Get or set the function that formats an item. The data grid widget uses a -function to generate dynamic html. Use your favourite templating engine or -generate the string directly. -```js -chart.html(function (d) { return '
    '+data.exampleString+'
    ';}); -``` - -#### .htmlGroup( function (data) { return ''; }) -Get or set the function that formats a group label. -```js -chart.htmlGroup (function (d) { return '

    '.d.key . 'with ' . d.values.length .' items

    '}); -``` - -#### .sortBy([sortByFunction]) -Get or set sort-by function. This function works as a value accessor at the item -level and returns a particular field to be sorted. -by. Default: identity function - -```js -chart.sortBy(function(d) { - return d.date; -}); -``` - -#### .order([order]) -Get or set sort order function. Default value: ``` d3.ascending ``` - -```js -chart.order(d3.descending); -``` - -## Bubble Chart -Includes: [Bubble Mixin](#bubble-mixin), [Coordinate Grid Mixin](#coordinate-grid-mixin) - -A concrete implementation of a general purpose bubble chart that allows data visualization using the -following dimensions: - -* x axis position -* y axis position -* bubble radius -* color - -Examples: -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -* [US Venture Capital Landscape 2011](http://dc-js.github.com/dc.js/vc/index.html) -#### dc.bubbleChart(parent[, chartGroup]) -Create a bubble chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection | compositeChart - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created bubble chart instance - -```js -// create a bubble chart under #chart-container1 element using the default global chart group -var bubbleChart1 = dc.bubbleChart('#chart-container1'); -// create a bubble chart under #chart-container2 element using chart group A -var bubbleChart2 = dc.bubbleChart('#chart-container2', 'chartGroupA'); -``` - -#### .elasticRadius([boolean]) -Turn on or off the elastic bubble radius feature, or return the value of the flag. If this -feature is turned on, then bubble radii will be automatically rescaled to fit the chart better. - -## Composite Chart -Includes: [Coordinate Grid Mixin](#coordinate-grid-mixin) - -Composite charts are a special kind of chart that render multiple charts on the same Coordinate -Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to -achieve some quite flexible charting effects. -#### dc.compositeChart(parent[, chartGroup]) -Create a composite chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created composite chart instance - -```js -// create a composite chart under #chart-container1 element using the default global chart group -var compositeChart1 = dc.compositeChart('#chart-container1'); -// create a composite chart under #chart-container2 element using chart group A -var compositeChart2 = dc.compositeChart('#chart-container2', 'chartGroupA'); -``` - -#### .useRightAxisGridLines(bool) -Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the -default behavior. This option is only respected when subcharts with both left and right y-axes -are present. - -#### .childOptions({object}) -Get or set chart-specific options for all child charts. This is equivalent to calling `.options` -on each child chart. - -#### .rightYAxisLabel([labelText]) -Set or get the right y axis label. - -#### .compose(subChartArray) -Combine the given charts into one single composite coordinate grid chart. - -```js -// compose the given charts in the array into one single composite chart -moveChart.compose([ - // when creating sub-chart you need to pass in the parent chart - dc.lineChart(moveChart) - .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used - .valueAccessor(function (d){return d.value.avg;}) - // most of the normal functions will continue to work in a composed chart - .renderArea(true) - .stack(monthlyMoveGroup, function (d){return d.value;}) - .title(function (d){ - var value = d.value.avg?d.value.avg:d.value; - if(isNaN(value)) value = 0; - return dateFormat(d.key) + '\n' + numberFormat(value); - }), - dc.barChart(moveChart) - .group(volumeByMonthGroup) - .centerBar(true) -]); -``` - -#### .children() -Returns the child charts which are composed into the composite chart. - -#### .shareColors([boolean]) -Get or set color sharing for the chart. If set, the `.colors()` value from this chart -will be shared with composed children. Additionally if the child chart implements -Stackable and has not set a custom .colorAccessor, then it will generate a color -specific to its order in the composition. - -#### .shareTitle([[boolean]) -Get or set title sharing for the chart. If set, the `.title()` value from this chart will be -shared with composed children. Default value is true. - -#### .rightY([yScale]) -Get or set the y scale for the right axis. The right y scale is typically automatically -generated by the chart implementation. - -#### .rightYAxis([yAxis]) -Set or get the right y axis used by the composite chart. This function is most useful when y -axis customization is required. The y axis in dc.js is an instance of a [d3 axis -object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis) therefore it supports any valid -d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc; -resetting it may cause unexpected results. -```jså -// customize y axis tick format -chart.rightYAxis().tickFormat(function (v) {return v + '%';}); -// customize y axis tick values -chart.rightYAxis().tickValues([0, 100, 200, 300]); -``` - -## Series Chart - -Includes: [Composite Chart](#composite chart) - -A series chart is a chart that shows multiple series of data overlaid on one chart, where the -series is specified in the data. It is a specialization of Composite Chart and inherits all -composite features other than recomposing the chart. - -#### dc.seriesChart(parent[, chartGroup]) -Create a series chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created series chart instance - -```js -// create a series chart under #chart-container1 element using the default global chart group -var seriesChart1 = dc.seriesChart("#chart-container1"); -// create a series chart under #chart-container2 element using chart group A -var seriesChart2 = dc.seriesChart("#chart-container2", "chartGroupA"); -``` - -#### .chart([function]) -Get or set the chart function, which generates the child charts. Default: dc.lineChart - -``` -// put interpolation on the line charts used for the series -chart.chart(function(c) { return dc.lineChart(c).interpolate('basis'); }) -// do a scatter series chart -chart.chart(dc.scatterPlot) -``` - -#### .seriesAccessor([accessor]) -Get or set accessor function for the displayed series. Given a datum, this function -should return the series that datum belongs to. - -#### .seriesSort([sortFunction]) -Get or set a function to sort the list of series by, given series values. - -Example: -``` -chart.seriesSort(d3.descending); -``` - -#### .valueSort([sortFunction]) -Get or set a function to sort each series values by. By default this is the key accessor which, -for example, will ensure a lineChart series connects its points in increasing key/x order, -rather than haphazardly. - -## Geo Choropleth Chart -Includes: [Color Mixin](#color-mixin), [Base Mixin](#base-mixin) - -The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map -from GeoJson data. This chart implementation was inspired by [the great d3 choropleth -example](http://bl.ocks.org/4060606). - -Examples: -* [US Venture Capital Landscape 2011](http://dc-js.github.com/dc.js/vc/index.html) -#### dc.geoChoroplethChart(parent[, chartGroup]) -Create a choropleth chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created choropleth chart instance - -```js -// create a choropleth chart under '#us-chart' element using the default global chart group -var chart1 = dc.geoChoroplethChart('#us-chart'); -// create a choropleth chart under '#us-chart2' element using chart group A -var chart2 = dc.compositeChart('#us-chart2', 'chartGroupA'); -``` - -#### .overlayGeoJson(json, name, keyAccessor) - **mandatory** -Use this function to insert a new GeoJson map layer. This function can be invoked multiple times -if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple -layers with the same name the new overlay will override the existing one. - -Parameters: -* json - GeoJson feed -* name - name of the layer -* keyAccessor - accessor function used to extract 'key' from the GeoJson data. The key extracted by -this function should match the keys returned by the crossfilter groups. - -```js -// insert a layer for rendering US states -chart.overlayGeoJson(statesJson.features, 'state', function(d) { - return d.properties.name; -}); -``` - -#### .projection(projection) -Set custom geo projection function. See the available [d3 geo projection -functions](https://github.com/mbostock/d3/wiki/Geo-Projections). Default value: albersUsa. - -#### .geoJsons() -Returns all GeoJson layers currently registered with this chart. The returned array is a -reference to this chart's internal data structure, so any modification to this array will also -modify this chart's internal registration. - -Returns an array of objects containing fields {name, data, accessor} - -#### .geoPath() -Returns the [d3.geo.path](https://github.com/mbostock/d3/wiki/Geo-Paths#path) object used to -render the projection and features. Can be useful for figuring out the bounding box of the -feature set and thus a way to calculate scale and translation for the projection. - -#### .removeGeoJson(name) -Remove a GeoJson layer from this chart by name - -## Bubble Overlay Chart -Includes: [Bubble Mixin](#bubble-mixin), [Base Mixin](#base-mixin) - -The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay -chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the -typical x and y positioning while retaining the capability to visualize data using bubble radius -and coloring. - -Examples: -* [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) -#### dc.bubbleOverlay(parent[, chartGroup]) -Create a bubble overlay chart instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -off-screen. Typically this element should also be the parent of the underlying image. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created bubble overlay chart instance - -```js -// create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group -var bubbleChart1 = dc.bubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg')); -// create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A -var bubbleChart2 = dc.compositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg')); -``` -#### .svg(imageElement) - **mandatory** -Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg -element; therefore the bubble overlay chart will not work if this function is not invoked. If the -underlying image is a bitmap, then an empty svg will need to be created on top of the image. - -```js -// set up underlying svg element -chart.svg(d3.select('#chart svg')); -``` - -#### .point(name, x, y) - **mandatory** -Set up a data point on the overlay. The name of a data point should match a specific 'key' among -data groups generated using keyAccessor. If a match is found (point name <-> data group key) -then a bubble will be generated at the position specified by the function. x and y -value specified here are relative to the underlying svg. - -## Row Chart -Includes: [Cap Mixin](#cap-mixin), [Margin Mixin](#margin-mixin), [Color Mixin](#color-mixin), [Base Mixin](#base-mixin) - -Concrete row chart implementation. -#### dc.rowChart(parent[, chartGroup]) -Create a row chart instance and attach it to the given parent element. - -Parameters: - -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created row chart instance - -```js -// create a row chart under #chart-container1 element using the default global chart group -var chart1 = dc.rowChart('#chart-container1'); -// create a row chart under #chart-container2 element using chart group A -var chart2 = dc.rowChart('#chart-container2', 'chartGroupA'); -``` - -#### .x([scale]) -Gets or sets the x scale. The x scale can be any d3 -[quantitive scale](https://github.com/mbostock/d3/wiki/Quantitative-Scales) - -#### .renderTitleLabel(boolean) -Turn on/off Title label rendering (values) using SVG style of text-anchor 'end' - -#### .xAxis() -Get the x axis for the row chart instance. Note: not settable for row charts. -See the [d3 axis object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis) documention for more information. -```js -// customize x axis tick format -chart.xAxis().tickFormat(function (v) {return v + '%';}); -// customize x axis tick values -chart.xAxis().tickValues([0, 100, 200, 300]); -``` - -#### .fixedBarHeight([height]) -Get or set the fixed bar height. Default is [false] which will auto-scale bars. -For example, if you want to fix the height for a specific number of bars (useful in TopN charts) -you could fix height as follows (where count = total number of bars in your TopN and gap is -your vertical gap space). -```js - chart.fixedBarHeight( chartheight - (count + 1) * gap / count); -``` - -#### .gap([gap]) -Get or set the vertical gap space between rows on a particular row chart instance. Default gap is 5px; - -#### .elasticX([boolean]) -Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescle to auto-fit the -data range when filtered. - -#### .labelOffsetX([x]) -Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart. -Default x offset is 10px; - -#### .labelOffsetY([y]) -Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart. -Default y offset is 15px; - -#### .titleLabelOffsetx([x]) -Get of set the x offset (horizontal space between right edge of row and right edge or text. -Default x offset is 2px; - -## Legend -Legend is a attachable widget that can be added to other dc charts to render horizontal legend -labels. - -```js -chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) -``` - -Examples: -* [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) -* [Canadian City Crime Stats](http://dc-js.github.com/dc.js/crime/index.html) - -#### .x([value]) -Set or get x coordinate for legend widget. Default: 0. - -#### .y([value]) -Set or get y coordinate for legend widget. Default: 0. - -#### .gap([value]) -Set or get gap between legend items. Default: 5. - -#### .itemHeight([value]) -Set or get legend item height. Default: 12. - -#### .horizontal([boolean]) -Position legend horizontally instead of vertically - -#### .legendWidth([value]) -Maximum width for horizontal legend. Default: 560. - -#### .itemWidth([value]) -legendItem width for horizontal legend. Default: 70. - -#### .autoItemWidth([value]) -Turn automatic width for legend items on or off. If true, itemWidth() is ignored. -This setting takes into account gap(). Default: false. - -## Scatter Plot -Includes: [Coordinate Grid Mixin](#coordinate-grid-mixin) - -A scatter plot chart -#### dc.scatterPlot(parent[, chartGroup]) -Create a scatter plot instance and attach it to the given parent element. - -Parameters: - -* parent : string | node | selection | compositeChart - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -If the scatter plot is a sub-chart in a [Composite Chart](#composite-chart) then pass in the parent composite -chart instance. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created scatter plot instance - -```js -// create a scatter plot under #chart-container1 element using the default global chart group -var chart1 = dc.scatterPlot('#chart-container1'); -// create a scatter plot under #chart-container2 element using chart group A -var chart2 = dc.scatterPlot('#chart-container2', 'chartGroupA'); -// create a sub-chart under a composite parent chart -var chart3 = dc.scatterPlot(compositeChart); -``` - -#### .existenceAccessor([accessor]) -Get or set the existence accessor. If a point exists, it is drawn with symbolSize radius and -opacity 1; if it does not exist, it is drawn with hiddenSize radius and opacity 0. By default, -the existence accessor checks if the reduced value is truthy. - -#### .symbol([type]) -Get or set the symbol type used for each point. By default the symbol is a circle. See the D3 -[docs](https://github.com/mbostock/d3/wiki/SVG-Shapes#wiki-symbol_type) for acceptable types. -Type can be a constant or an accessor. - -#### .symbolSize([radius]) -Set or get radius for symbols. Default: 3. - -#### .highlightedSize([radius]) -Set or get radius for highlighted symbols. Default: 4. - -#### .hiddenSize([radius]) -Set or get radius for symbols when the group is empty. Default: 0. - -## Number Display Widget -Includes: [Base Mixin](#base-mixin) - -A display of a single numeric value. - -Examples: - -* [Test Example](http://dc-js.github.io/dc.js/examples/number.html) -#### dc.numberDisplay(parent[, chartGroup]) -Create a Number Display instance and attach it to the given parent element. - -Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and -a valueAccessor that returns a single value. - -Parameters: - -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -The number display widget will only react to filter changes in the chart group. - -Returns: -A newly created number display instance - -```js -// create a number display under #chart-container1 element using the default global chart group -var display1 = dc.numberDisplay('#chart-container1'); -``` - -#### .html([object]) - Gets or sets an optional object specifying HTML templates to use depending on the number - displayed. The text `%number` will be replaced with the current value. - - one: HTML template to use if the number is 1 - - zero: HTML template to use if the number is 0 - - some: HTML template to use otherwise - - ```js - numberWidget.html({ - one:'%number record', - some:'%number records', - none:'no records'}) - ``` - -#### .value() -Calculate and return the underlying value of the display - -#### .formatNumber([formatter]) -Get or set a function to format the value for the display. By default `d3.format('.2s');` is used. - -## Heat Map - -Includes: [Color Mixin](#color-mixin), [Margin Mixin](#margin-mixin), [Base Mixin](#base-mixin) - -A heat map is matrix that represents the values of two dimensions of data using colors. - -#### dc.heatMap(parent[, chartGroup]) -Create a heat map instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying -a dom block element such as a div; or a dom element or d3 selection. - -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created heat map instance - -```js -// create a heat map under #chart-container1 element using the default global chart group -var heatMap1 = dc.heatMap('#chart-container1'); -// create a heat map under #chart-container2 element using chart group A -var heatMap2 = dc.heatMap('#chart-container2', 'chartGroupA'); -``` - -#### .rows([values]) -Gets or sets the values used to create the rows of the heatmap, as an array. By default, all -the values will be fetched from the data using the value accessor, and they will be sorted in -ascending order. - -#### .cols([keys]) -Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all -the values will be fetched from the data using the key accessor, and they will be sorted in -ascending order. - -#### .boxOnClick([handler]) -Gets or sets the handler that fires when an individual cell is clicked in the heatmap. -By default, filtering of the cell will be toggled. - -#### .xAxisOnClick([handler]) -Gets or sets the handler that fires when a column tick is clicked in the x axis. -By default, if any cells in the column are unselected, the whole column will be selected, -otherwise the whole column will be unselected. - -#### .yAxisOnClick([handler]) -Gets or sets the handler that fires when a row tick is clicked in the y axis. -By default, if any cells in the row are unselected, the whole row will be selected, -otherwise the whole row will be unselected. - -## Box Plot - -Includes: [Coordinate Grid Mixin](#coordinate-grid-mixin) - -A box plot is a chart that depicts numerical data via their quartile ranges. - -#### dc.boxPlot(parent[, chartGroup]) -Create a box plot instance and attach it to the given parent element. - -Parameters: -* parent : string | node | selection - any valid -[d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) representing -a dom block element such as a div; or a dom element or d3 selection. -* chartGroup : string (optional) - name of the chart group this chart instance should be placed in. -Interaction with a chart will only trigger events and redraws within the chart's group. - -Returns: -A newly created box plot instance - -```js -// create a box plot under #chart-container1 element using the default global chart group -var boxPlot1 = dc.boxPlot('#chart-container1'); -// create a box plot under #chart-container2 element using chart group A -var boxPlot2 = dc.boxPlot('#chart-container2', 'chartGroupA'); -``` - -#### .boxPadding([padding]) -Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1. -See the [d3 docs](https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands) -for a visual description of how the padding is applied. - -Default: 0.8 - -#### .outerPadding([padding]) -Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts -or on charts with a custom `.boxWidth`. Will pad the width by `padding * barWidth` on each side of the chart. - -Default: 0.5 - -#### .boxWidth(width || function(innerChartWidth, xUnits) { ... }) -Get or set the numerical width of the boxplot box. The width may also be a function taking as -parameters the chart width excluding the right and left margins, as well as the number of x -units. - -#### .tickFormat() -Set the numerical format of the boxplot median, whiskers and quartile labels. Defaults to -integer formatting. -```js -// format ticks to 2 decimal places -chart.tickFormat(d3.format('.2f')); -``` \ No newline at end of file diff --git a/web/docs/docco.css b/web/docs/docco.css deleted file mode 100644 index a2899ac878..0000000000 --- a/web/docs/docco.css +++ /dev/null @@ -1,506 +0,0 @@ -/*--------------------- Typography ----------------------------*/ - -@font-face { - font-family: 'aller-light'; - src: url('http://github.com/public/fonts/aller-light.eot'); - src: url('http://github.com/public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), - url('http://github.com/public/fonts/aller-light.woff') format('woff'), - url('http://github.com/public/fonts/aller-light.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'aller-bold'; - src: url('http://github.com/public/fonts/aller-bold.eot'); - src: url('http://github.com/public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), - url('http://github.com/public/fonts/aller-bold.woff') format('woff'), - url('http://github.com/public/fonts/aller-bold.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'novecento-bold'; - src: url('http://github.com/public/fonts/novecento-bold.eot'); - src: url('http://github.com/public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'), - url('http://github.com/public/fonts/novecento-bold.woff') format('woff'), - url('http://github.com/public/fonts/novecento-bold.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -/*--------------------- Layout ----------------------------*/ -html { height: 100%; } -body { - font-family: "aller-light"; - font-size: 14px; - line-height: 18px; - color: #30404f; - margin: 0; padding: 0; - height:100%; -} -#container { min-height: 100%; } - -a { - color: #000; -} - -b, strong { - font-weight: normal; - font-family: "aller-bold"; -} - -p { - margin: 15px 0 0px; -} - .annotation ul, .annotation ol { - margin: 25px 0; - } - .annotation ul li, .annotation ol li { - font-size: 14px; - line-height: 18px; - margin: 10px 0; - } - -h1, h2, h3, h4, h5, h6 { - color: #112233; - line-height: 1em; - font-weight: normal; - font-family: "novecento-bold"; - text-transform: uppercase; - margin: 30px 0 15px 0; -} - -h1 { - margin-top: 40px; -} - -hr { - border: 0; - background: 1px #ddd; - height: 1px; - margin: 20px 0; -} - -pre, tt, code { - font-size: 12px; line-height: 16px; - font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; - margin: 0; padding: 0; -} - .annotation pre { - display: block; - margin: 0; - padding: 7px 10px; - background: #fcfcfc; - -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - overflow-x: auto; - } - .annotation pre code { - border: 0; - padding: 0; - background: transparent; - } - - -blockquote { - border-left: 5px solid #ccc; - margin: 0; - padding: 1px 0 1px 1em; -} - .sections blockquote p { - font-family: Menlo, Consolas, Monaco, monospace; - font-size: 12px; line-height: 16px; - color: #999; - margin: 10px 0 0; - white-space: pre-wrap; - } - -ul.sections { - list-style: none; - padding:0 0 5px 0;; - margin:0; -} - -/* - Force border-box so that % widths fit the parent - container without overlap because of margin/padding. - - More Info : http://www.quirksmode.org/css/box.html -*/ -ul.sections > li > div { - -moz-box-sizing: border-box; /* firefox */ - -ms-box-sizing: border-box; /* ie */ - -webkit-box-sizing: border-box; /* webkit */ - -khtml-box-sizing: border-box; /* konqueror */ - box-sizing: border-box; /* css3 */ -} - - -/*---------------------- Jump Page -----------------------------*/ -#jump_to, #jump_page { - margin: 0; - background: white; - -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; - -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; - font: 16px Arial; - cursor: pointer; - text-align: right; - list-style: none; -} - -#jump_to a { - text-decoration: none; -} - -#jump_to a.large { - display: none; -} -#jump_to a.small { - font-size: 22px; - font-weight: bold; - color: #676767; -} - -#jump_to, #jump_wrapper { - position: fixed; - right: 0; top: 0; - padding: 10px 15px; - margin:0; -} - -#jump_wrapper { - display: none; - padding:0; -} - -#jump_to:hover #jump_wrapper { - display: block; -} - -#jump_page { - padding: 5px 0 3px; - margin: 0 0 25px 25px; -} - -#jump_page .source { - display: block; - padding: 15px; - text-decoration: none; - border-top: 1px solid #eee; -} - -#jump_page .source:hover { - background: #f5f5ff; -} - -#jump_page .source:first-child { -} - -/*---------------------- Low resolutions (> 320px) ---------------------*/ -@media only screen and (min-width: 320px) { - .pilwrap { display: none; } - - ul.sections > li > div { - display: block; - padding:5px 10px 0 10px; - } - - ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { - padding-left: 30px; - } - - ul.sections > li > div.content { - overflow-x:auto; - -webkit-box-shadow: inset 0 0 5px #e5e5ee; - box-shadow: inset 0 0 5px #e5e5ee; - border: 1px solid #dedede; - margin:5px 10px 5px 10px; - padding-bottom: 5px; - } - - ul.sections > li > div.annotation pre { - margin: 7px 0 7px; - padding-left: 15px; - } - - ul.sections > li > div.annotation p tt, .annotation code { - background: #f8f8ff; - border: 1px solid #dedede; - font-size: 12px; - padding: 0 0.2em; - } -} - -/*---------------------- (> 481px) ---------------------*/ -@media only screen and (min-width: 481px) { - #container { - position: relative; - } - body { - background-color: #F5F5FF; - font-size: 15px; - line-height: 21px; - } - pre, tt, code { - line-height: 18px; - } - p, ul, ol { - margin: 0 0 15px; - } - - - #jump_to { - padding: 5px 10px; - } - #jump_wrapper { - padding: 0; - } - #jump_to, #jump_page { - font: 10px Arial; - text-transform: uppercase; - } - #jump_page .source { - padding: 5px 10px; - } - #jump_to a.large { - display: inline-block; - } - #jump_to a.small { - display: none; - } - - - - #background { - position: absolute; - top: 0; bottom: 0; - width: 350px; - background: #fff; - border-right: 1px solid #e5e5ee; - z-index: -1; - } - - ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { - padding-left: 40px; - } - - ul.sections > li { - white-space: nowrap; - } - - ul.sections > li > div { - display: inline-block; - } - - ul.sections > li > div.annotation { - max-width: 350px; - min-width: 350px; - min-height: 5px; - padding: 13px; - overflow-x: hidden; - white-space: normal; - vertical-align: top; - text-align: left; - } - ul.sections > li > div.annotation pre { - margin: 15px 0 15px; - padding-left: 15px; - } - - ul.sections > li > div.content { - padding: 13px; - vertical-align: top; - border: none; - -webkit-box-shadow: none; - box-shadow: none; - } - - .pilwrap { - position: relative; - display: inline; - } - - .pilcrow { - font: 12px Arial; - text-decoration: none; - color: #454545; - position: absolute; - top: 3px; left: -20px; - padding: 1px 2px; - opacity: 0; - -webkit-transition: opacity 0.2s linear; - } - .for-h1 .pilcrow { - top: 47px; - } - .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { - top: 35px; - } - - ul.sections > li > div.annotation:hover .pilcrow { - opacity: 1; - } -} - -/*---------------------- (> 1025px) ---------------------*/ -@media only screen and (min-width: 1025px) { - - body { - font-size: 16px; - line-height: 24px; - } - - #background { - width: 525px; - } - ul.sections > li > div.annotation { - max-width: 525px; - min-width: 525px; - padding: 10px 25px 1px 50px; - } - ul.sections > li > div.content { - padding: 9px 15px 16px 25px; - } -} - -/*---------------------- Syntax Highlighting -----------------------------*/ - -td.linenos { background-color: #f0f0f0; padding-right: 10px; } -span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } -/* - -github.com style (c) Vasily Polovnyov - -*/ - -pre code { - display: block; padding: 0.5em; - color: #000; - background: #f8f8ff -} - -pre .hljs-comment, -pre .hljs-template_comment, -pre .hljs-diff .hljs-header, -pre .hljs-javadoc { - color: #408080; - font-style: italic -} - -pre .hljs-keyword, -pre .hljs-assignment, -pre .hljs-literal, -pre .hljs-css .hljs-rule .hljs-keyword, -pre .hljs-winutils, -pre .hljs-javascript .hljs-title, -pre .hljs-lisp .hljs-title, -pre .hljs-subst { - color: #954121; - /*font-weight: bold*/ -} - -pre .hljs-number, -pre .hljs-hexcolor { - color: #40a070 -} - -pre .hljs-string, -pre .hljs-tag .hljs-value, -pre .hljs-phpdoc, -pre .hljs-tex .hljs-formula { - color: #219161; -} - -pre .hljs-title, -pre .hljs-id { - color: #19469D; -} -pre .hljs-params { - color: #00F; -} - -pre .hljs-javascript .hljs-title, -pre .hljs-lisp .hljs-title, -pre .hljs-subst { - font-weight: normal -} - -pre .hljs-class .hljs-title, -pre .hljs-haskell .hljs-label, -pre .hljs-tex .hljs-command { - color: #458; - font-weight: bold -} - -pre .hljs-tag, -pre .hljs-tag .hljs-title, -pre .hljs-rules .hljs-property, -pre .hljs-django .hljs-tag .hljs-keyword { - color: #000080; - font-weight: normal -} - -pre .hljs-attribute, -pre .hljs-variable, -pre .hljs-instancevar, -pre .hljs-lisp .hljs-body { - color: #008080 -} - -pre .hljs-regexp { - color: #B68 -} - -pre .hljs-class { - color: #458; - font-weight: bold -} - -pre .hljs-symbol, -pre .hljs-ruby .hljs-symbol .hljs-string, -pre .hljs-ruby .hljs-symbol .hljs-keyword, -pre .hljs-ruby .hljs-symbol .hljs-keymethods, -pre .hljs-lisp .hljs-keyword, -pre .hljs-tex .hljs-special, -pre .hljs-input_number { - color: #990073 -} - -pre .hljs-builtin, -pre .hljs-constructor, -pre .hljs-built_in, -pre .hljs-lisp .hljs-title { - color: #0086b3 -} - -pre .hljs-preprocessor, -pre .hljs-pi, -pre .hljs-doctype, -pre .hljs-shebang, -pre .hljs-cdata { - color: #999; - font-weight: bold -} - -pre .hljs-deletion { - background: #fdd -} - -pre .hljs-addition { - background: #dfd -} - -pre .hljs-diff .hljs-change { - background: #0086b3 -} - -pre .hljs-chunk { - color: #aaa -} - -pre .hljs-tex .hljs-formula { - opacity: 0.5; -} diff --git a/web/docs/stock.html b/web/docs/stock.html deleted file mode 100644 index 85da21716a..0000000000 --- a/web/docs/stock.html +++ /dev/null @@ -1,2499 +0,0 @@ - - - - - dc.js Getting Started and How-To Guide - - - - - -
    -
    - -
      - - - -
    • -
      - - -

      dc.js Getting Started and How-To Guide

      - -
      - -
      'use strict';
      -
      -/* jshint globalstrict: true */
      -/* global dc,d3,crossfilter,colorbrewer */
      - -
    • - - -
    • -
      - -
      - -
      -

      Create Chart Objects

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create chart objects associated with the container elements identified by the css selector. -Note: It is often a good idea to have these objects accessible at the global scope so that they can be modified or -filtered by other page controls.

      - -
      - -
      var gainOrLossChart = dc.pieChart('#gain-loss-chart');
      -var fluctuationChart = dc.barChart('#fluctuation-chart');
      -var quarterChart = dc.pieChart('#quarter-chart');
      -var dayOfWeekChart = dc.rowChart('#day-of-week-chart');
      -var moveChart = dc.lineChart('#monthly-move-chart');
      -var volumeChart = dc.barChart('#monthly-volume-chart');
      -var yearlyBubbleChart = dc.bubbleChart('#yearly-bubble-chart');
      -var nasdaqCount = dc.dataCount('.dc-data-count');
      -var nasdaqTable = dc.dataTable('.dc-data-table');
      - -
    • - - -
    • -
      - -
      - -
      -

      Anchor Div for Charts

      - -
      - -
      /*
      -
      - -
    • - - -
    • -
      - -
      - -
      -

      A div anchor that can be identified by id

      - -
      - -
          <div id='your-chart'></div>
      - -
    • - - -
    • -
      - -
      - -
      -

      Title or anything you want to add above the chart

      - -
      - -
          <div id='chart'><span>Days by Gain or Loss</span></div>
      - -
    • - - -
    • -
      - -
      - -
      -
      .turnOnControls()
      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      If a link with css class reset is present then the chart -will automatically hide/show it based on whether there is a filter -set on the chart (e.g. slice selection for pie chart and brush -selection for bar chart). Enable this with chart.turnOnControls(true)

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      dc.js >=2.1 uses visibility: hidden to hide/show controls without -disrupting the layout. To return the old display: none behavior, -set chart.controlsUseVisibility(false) and use that style instead.

      - -
      - -
          <div id='chart'>
      -       <a class='reset'
      -          href='/service/javascript:myChart.filterAll();dc.redrawAll();'
      -          style='visibility: hidden;'>reset</a>
      -    </div>
      - -
    • - - -
    • -
      - -
      - -
      -

      dc.js will also automatically inject the current filter value into -any html element with its css class set to filter

      - -
      - -
          <div id='chart'>
      -        <span class='reset' style='visibility: hidden;'>
      -          Current filter: <span class='filter'></span>
      -        </span>
      -    </div>
      -*/
      - -
    • - - -
    • -
      - -
      - -
      -

      Load your data

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Data can be loaded through regular means with your -favorite javascript library

      -
      d3.csv('data.csv', function(data) {...});
      -d3.json('data.json', function(data) {...});
      -jQuery.getJson('data.json', function(data){...});
      -
      - -
      - -
      d3.csv('ndx.csv', function (data) {
      - -
    • - - -
    • -
      - -
      - -
      -

      Since its a csv file we need to format the data a bit.

      - -
      - -
          var dateFormat = d3.time.format('%m/%d/%Y');
      -    var numberFormat = d3.format('.2f');
      -
      -    data.forEach(function (d) {
      -        d.dd = dateFormat.parse(d.date);
      -        d.month = d3.time.month(d.dd); // pre-calculate month for better performance
      -        d.close = +d.close; // coerce to number
      -        d.open = +d.open;
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Create Crossfilter Dimensions and Groups

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      See the crossfilter API for reference.

      - -
      - -
          var ndx = crossfilter(data);
      -    var all = ndx.groupAll();
      - -
    • - - -
    • -
      - -
      - -
      -

      Dimension by year

      - -
      - -
          var yearlyDimension = ndx.dimension(function (d) {
      -        return d3.time.year(d.dd).getFullYear();
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Maintain running tallies by year as filters are applied or removed

      - -
      - -
          var yearlyPerformanceGroup = yearlyDimension.group().reduce(
      -        /* callback for when data is added to the current filter results */
      -        function (p, v) {
      -            ++p.count;
      -            p.absGain += v.close - v.open;
      -            p.fluctuation += Math.abs(v.close - v.open);
      -            p.sumIndex += (v.open + v.close) / 2;
      -            p.avgIndex = p.sumIndex / p.count;
      -            p.percentageGain = p.avgIndex ? (p.absGain / p.avgIndex) * 100 : 0;
      -            p.fluctuationPercentage = p.avgIndex ? (p.fluctuation / p.avgIndex) * 100 : 0;
      -            return p;
      -        },
      -        /* callback for when data is removed from the current filter results */
      -        function (p, v) {
      -            --p.count;
      -            p.absGain -= v.close - v.open;
      -            p.fluctuation -= Math.abs(v.close - v.open);
      -            p.sumIndex -= (v.open + v.close) / 2;
      -            p.avgIndex = p.count ? p.sumIndex / p.count : 0;
      -            p.percentageGain = p.avgIndex ? (p.absGain / p.avgIndex) * 100 : 0;
      -            p.fluctuationPercentage = p.avgIndex ? (p.fluctuation / p.avgIndex) * 100 : 0;
      -            return p;
      -        },
      -        /* initialize p */
      -        function () {
      -            return {
      -                count: 0,
      -                absGain: 0,
      -                fluctuation: 0,
      -                fluctuationPercentage: 0,
      -                sumIndex: 0,
      -                avgIndex: 0,
      -                percentageGain: 0
      -            };
      -        }
      -    );
      - -
    • - - -
    • -
      - -
      - -
      -

      Dimension by full date

      - -
      - -
          var dateDimension = ndx.dimension(function (d) {
      -        return d.dd;
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Dimension by month

      - -
      - -
          var moveMonths = ndx.dimension(function (d) {
      -        return d.month;
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Group by total movement within month

      - -
      - -
          var monthlyMoveGroup = moveMonths.group().reduceSum(function (d) {
      -        return Math.abs(d.close - d.open);
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Group by total volume within move, and scale down result

      - -
      - -
          var volumeByMonthGroup = moveMonths.group().reduceSum(function (d) {
      -        return d.volume / 500000;
      -    });
      -    var indexAvgByMonthGroup = moveMonths.group().reduce(
      -        function (p, v) {
      -            ++p.days;
      -            p.total += (v.open + v.close) / 2;
      -            p.avg = Math.round(p.total / p.days);
      -            return p;
      -        },
      -        function (p, v) {
      -            --p.days;
      -            p.total -= (v.open + v.close) / 2;
      -            p.avg = p.days ? Math.round(p.total / p.days) : 0;
      -            return p;
      -        },
      -        function () {
      -            return {days: 0, total: 0, avg: 0};
      -        }
      -    );
      - -
    • - - -
    • -
      - -
      - -
      -

      Create categorical dimension

      - -
      - -
          var gainOrLoss = ndx.dimension(function (d) {
      -        return d.open > d.close ? 'Loss' : 'Gain';
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Produce counts records in the dimension

      - -
      - -
          var gainOrLossGroup = gainOrLoss.group();
      - -
    • - - -
    • -
      - -
      - -
      -

      Determine a histogram of percent changes

      - -
      - -
          var fluctuation = ndx.dimension(function (d) {
      -        return Math.round((d.close - d.open) / d.open * 100);
      -    });
      -    var fluctuationGroup = fluctuation.group();
      - -
    • - - -
    • -
      - -
      - -
      -

      Summarize volume by quarter

      - -
      - -
          var quarter = ndx.dimension(function (d) {
      -        var month = d.dd.getMonth();
      -        if (month <= 2) {
      -            return 'Q1';
      -        } else if (month > 2 && month <= 5) {
      -            return 'Q2';
      -        } else if (month > 5 && month <= 8) {
      -            return 'Q3';
      -        } else {
      -            return 'Q4';
      -        }
      -    });
      -    var quarterGroup = quarter.group().reduceSum(function (d) {
      -        return d.volume;
      -    });
      - -
    • - - -
    • -
      - -
      - -
      -

      Counts per weekday

      - -
      - -
          var dayOfWeek = ndx.dimension(function (d) {
      -        var day = d.dd.getDay();
      -        var name = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
      -        return day + '.' + name[day];
      -    });
      -    var dayOfWeekGroup = dayOfWeek.group();
      - -
    • - - -
    • -
      - -
      - -
      -

      Define Chart Attributes

      -

      Define chart attributes using fluent methods. See the -dc.js API Reference for more information

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Bubble Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a bubble chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with the chart will only trigger redraws -on charts within the same chart group. -
      API: Bubble Chart

      - -
      - -
      -    yearlyBubbleChart /* dc.bubbleChart('#yearly-bubble-chart', 'chartGroup') */
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart width, default = 200

      - -
      - -
              .width(990)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart height, default = 200

      - -
      - -
              .height(250)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart transition duration, default = 750

      - -
      - -
              .transitionDuration(1500)
      -        .margins({top: 10, right: 50, bottom: 30, left: 40})
      -        .dimension(yearlyDimension)
      - -
    • - - -
    • -
      - -
      - -
      -

      The bubble chart expects the groups are reduced to multiple values which are used -to generate x, y, and radius for each key (bubble) in the group

      - -
      - -
              .group(yearlyPerformanceGroup)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color function or array for bubbles: ColorBrewer

      - -
      - -
              .colors(colorbrewer.RdYlGn[9])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color domain to match your data domain if you want to bind data or color

      - -
      - -
              .colorDomain([-500, 500])
      - -
    • - - -
    • -
      - -
      - -
      -
      Accessors
      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Accessor functions are applied to each value returned by the grouping

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      .colorAccessor - the returned value will be passed to the .colors() scale to determine a fill color

      - -
      - -
              .colorAccessor(function (d) {
      -            return d.value.absGain;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      .keyAccessor - the X value will be passed to the .x() scale to determine pixel location

      - -
      - -
              .keyAccessor(function (p) {
      -            return p.value.absGain;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      .valueAccessor - the Y value will be passed to the .y() scale to determine pixel location

      - -
      - -
              .valueAccessor(function (p) {
      -            return p.value.percentageGain;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      .radiusValueAccessor - the value will be passed to the .r() scale to determine radius size; - by default this maps linearly to [0,100]

      - -
      - -
              .radiusValueAccessor(function (p) {
      -            return p.value.fluctuationPercentage;
      -        })
      -        .maxBubbleRelativeSize(0.3)
      -        .x(d3.scale.linear().domain([-2500, 2500]))
      -        .y(d3.scale.linear().domain([-100, 100]))
      -        .r(d3.scale.linear().domain([0, 4000]))
      - -
    • - - -
    • -
      - -
      - -
      -
      Elastic Scaling
      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      .elasticY and .elasticX determine whether the chart should rescale each axis to fit the data.

      - -
      - -
              .elasticY(true)
      -        .elasticX(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      .yAxisPadding and .xAxisPadding add padding to data above and below their max values in the same unit -domains as the Accessors.

      - -
      - -
              .yAxisPadding(100)
      -        .xAxisPadding(500)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) render horizontal grid lines, default=false

      - -
      - -
              .renderHorizontalGridLines(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) render vertical grid lines, default=false

      - -
      - -
              .renderVerticalGridLines(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) render an axis label below the x axis

      - -
      - -
              .xAxisLabel('Index Gain')
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) render a vertical axis lable left of the y axis

      - -
      - -
              .yAxisLabel('Index Gain %')
      - -
    • - - -
    • -
      - -
      - -
      -
      Labels and Titles
      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Labels are displayed on the chart for each bubble. Titles displayed on mouseover. -(optional) whether chart should render labels, default = true

      - -
      - -
              .renderLabel(true)
      -        .label(function (p) {
      -            return p.key;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) whether chart should render titles, default = false

      - -
      - -
              .renderTitle(true)
      -        .title(function (p) {
      -            return [
      -                p.key,
      -                'Index Gain: ' + numberFormat(p.value.absGain),
      -                'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%',
      -                'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'
      -            ].join('\n');
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      Customize Axes

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Set a custom tick format. Both .yAxis() and .xAxis() return an axis object, -so any additional method chaining applies to the axis, not the chart.

      - -
      - -
              .yAxis().tickFormat(function (v) {
      -            return v + '%';
      -        });
      - -
    • - - -
    • -
      - -
      - -
      -

      Pie/Donut Charts

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a pie chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Pie Chart

      - -
      - -
      -    gainOrLossChart /* dc.pieChart('#gain-loss-chart', 'chartGroup') */
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart width, default = 200

      - -
      - -
              .width(180)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart height, default = 200

      - -
      - -
              .height(180)
      - -
    • - - -
    • -
      - -
      - -
      -

      Define pie radius

      - -
      - -
              .radius(80)
      - -
    • - - -
    • -
      - -
      - -
      -

      Set dimension

      - -
      - -
              .dimension(gainOrLoss)
      - -
    • - - -
    • -
      - -
      - -
      -

      Set group

      - -
      - -
              .group(gainOrLossGroup)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) by default pie chart will use group.key as its label but you can overwrite it with a closure.

      - -
      - -
              .label(function (d) {
      -            if (gainOrLossChart.hasFilter() && !gainOrLossChart.hasFilter(d.key)) {
      -                return d.key + '(0%)';
      -            }
      -            var label = d.key;
      -            if (all.value()) {
      -                label += '(' + Math.floor(d.value / all.value() * 100) + '%)';
      -            }
      -            return label;
      -        })
      -    /*
      -
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) whether chart should render labels, default = true

      - -
      - -
              .renderLabel(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) if inner radius is used then a donut chart will be generated instead of pie chart

      - -
      - -
              .innerRadius(40)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart transition duration, default = 350

      - -
      - -
              .transitionDuration(500)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color array for slices

      - -
      - -
              .colors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb'])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color domain to match your data domain if you want to bind data or color

      - -
      - -
              .colorDomain([-1750, 1644])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color value accessor

      - -
      - -
              .colorAccessor(function(d, i){return d.value;})
      -        */;
      -
      -    quarterChart /* dc.pieChart('#quarter-chart', 'chartGroup') */
      -        .width(180)
      -        .height(180)
      -        .radius(80)
      -        .innerRadius(30)
      -        .dimension(quarter)
      -        .group(quarterGroup);
      - -
    • - - -
    • -
      - -
      - -
      -

      Row Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a row chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Row Chart

      - -
      - -
          dayOfWeekChart /* dc.rowChart('#day-of-week-chart', 'chartGroup') */
      -        .width(180)
      -        .height(180)
      -        .margins({top: 20, left: 10, right: 10, bottom: 20})
      -        .group(dayOfWeekGroup)
      -        .dimension(dayOfWeek)
      - -
    • - - -
    • -
      - -
      - -
      -

      Assign colors to each value in the x scale domain

      - -
      - -
              .ordinalColors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb'])
      -        .label(function (d) {
      -            return d.key.split('.')[1];
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      Title sets the row text

      - -
      - -
              .title(function (d) {
      -            return d.value;
      -        })
      -        .elasticX(true)
      -        .xAxis().ticks(4);
      - -
    • - - -
    • -
      - -
      - -
      -

      Bar Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a bar chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Bar Chart

      - -
      - -
          fluctuationChart /* dc.barChart('#volume-month-chart', 'chartGroup') */
      -        .width(420)
      -        .height(180)
      -        .margins({top: 10, right: 50, bottom: 30, left: 40})
      -        .dimension(fluctuation)
      -        .group(fluctuationGroup)
      -        .elasticY(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) whether bar should be center to its x value. Not needed for ordinal chart, default=false

      - -
      - -
              .centerBar(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) set gap between bars manually in px, default=2

      - -
      - -
              .gap(1)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) set filter brush rounding

      - -
      - -
              .round(dc.round.floor)
      -        .alwaysUseRounding(true)
      -        .x(d3.scale.linear().domain([-25, 25]))
      -        .renderHorizontalGridLines(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      Customize the filter displayed in the control span

      - -
      - -
              .filterPrinter(function (filters) {
      -            var filter = filters[0], s = '';
      -            s += numberFormat(filter[0]) + '% -> ' + numberFormat(filter[1]) + '%';
      -            return s;
      -        });
      - -
    • - - -
    • -
      - -
      - -
      -

      Customize axes

      - -
      - -
          fluctuationChart.xAxis().tickFormat(
      -        function (v) { return v + '%'; });
      -    fluctuationChart.yAxis().ticks(5);
      - -
    • - - -
    • -
      - -
      - -
      -

      Stacked Area Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Specify an area chart by using a line chart with .renderArea(true). -
      API: Stack Mixin, -Line Chart

      - -
      - -
          moveChart /* dc.lineChart('#monthly-move-chart', 'chartGroup') */
      -        .renderArea(true)
      -        .width(990)
      -        .height(200)
      -        .transitionDuration(1000)
      -        .margins({top: 30, right: 50, bottom: 25, left: 40})
      -        .dimension(moveMonths)
      -        .mouseZoomable(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      Specify a “range chart” to link its brush extent with the zoom of the current “focus chart”.

      - -
      - -
              .rangeChart(volumeChart)
      -        .x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)]))
      -        .round(d3.time.month.round)
      -        .xUnits(d3.time.months)
      -        .elasticY(true)
      -        .renderHorizontalGridLines(true)
      - -
    • - - -
    • -
      - -
      - -
      -
      Legend
      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Position the legend relative to the chart origin and specify items’ height and separation.

      - -
      - -
              .legend(dc.legend().x(800).y(10).itemHeight(13).gap(5))
      -        .brushOn(false)
      - -
    • - - -
    • -
      - -
      - -
      -

      Add the base layer of the stack with group. The second parameter specifies a series name for use in the -legend. -The .valueAccessor will be used for the base layer

      - -
      - -
              .group(indexAvgByMonthGroup, 'Monthly Index Average')
      -        .valueAccessor(function (d) {
      -            return d.value.avg;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      Stack additional layers with .stack. The first paramenter is a new group. -The second parameter is the series name. The third is a value accessor.

      - -
      - -
              .stack(monthlyMoveGroup, 'Monthly Index Move', function (d) {
      -            return d.value;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      Title can be called by any stack layer.

      - -
      - -
              .title(function (d) {
      -            var value = d.value.avg ? d.value.avg : d.value;
      -            if (isNaN(value)) {
      -                value = 0;
      -            }
      -            return dateFormat(d.key) + '\n' + numberFormat(value);
      -        });
      - -
    • - - -
    • -
      - -
      - -
      -

      Range Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Since this bar chart is specified as “range chart” for the area chart, its brush extent -will always match the zoom of the area chart.

      - -
      - -
          volumeChart.width(990) /* dc.barChart('#monthly-volume-chart', 'chartGroup'); */
      -        .height(40)
      -        .margins({top: 0, right: 50, bottom: 20, left: 40})
      -        .dimension(moveMonths)
      -        .group(volumeByMonthGroup)
      -        .centerBar(true)
      -        .gap(1)
      -        .x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)]))
      -        .round(d3.time.month.round)
      -        .alwaysUseRounding(true)
      -        .xUnits(d3.time.months);
      - -
    • - - -
    • -
      - -
      - -
      -

      Data Count

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a data count widget and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Data Count Widget

      -
      <div class='dc-data-count'>
      - <span class='filter-count'></span>
      - selected out of <span class='total-count'></span> records.
      -</div>
      -
      - -
      - -
      -    nasdaqCount /* dc.dataCount('.dc-data-count', 'chartGroup'); */
      -        .dimension(ndx)
      -        .group(all)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) .html sets different html when some records or all records are selected. -.html replaces everything in the anchor with the html given using the following function. -%filter-count and %total-count are replaced with the values obtained.

      - -
      - -
              .html({
      -            some: '<strong>%filter-count</strong> selected out of <strong>%total-count</strong> records' +
      -                ' | <a href=\'javascript:dc.filterAll(); dc.renderAll();\'>Reset All</a>',
      -            all: 'All records selected. Please click on the graph to apply filters.'
      -        });
      - -
    • - - -
    • -
      - -
      - -
      -

      Data Table

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a data table widget and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Data Table Widget

      -

      You can statically define the headers like in

      -
         <!-- anchor div for data table -->
      -   <div id='data-table'>
      -      <!-- create a custom header -->
      -      <div class='header'>
      -          <span>Date</span>
      -          <span>Open</span>
      -          <span>Close</span>
      -          <span>Change</span>
      -          <span>Volume</span>
      -      </div>
      -      <!-- data rows will filled in here -->
      -   </div>
      -
      -

      or do it programmatically using .columns().

      - -
      - -
      -    nasdaqTable /* dc.dataTable('.dc-data-table', 'chartGroup') */
      -        .dimension(dateDimension)
      - -
    • - - -
    • -
      - -
      - -
      -

      Data table does not use crossfilter group but rather a closure -as a grouping function

      - -
      - -
              .group(function (d) {
      -            var format = d3.format('02d');
      -            return d.dd.getFullYear() + '/' + format((d.dd.getMonth() + 1));
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) max number of records to be shown, default = 25

      - -
      - -
              .size(10)
      - -
    • - - -
    • -
      - -
      - -
      -

      There are several ways to specify the columns; see the data-table documentation. -This code demonstrates generating the column header automatically based on the columns.

      - -
      - -
              .columns([
      - -
    • - - -
    • -
      - -
      - -
      -

      Use the d.date field; capitalized automatically

      - -
      - -
                  'date',
      - -
    • - - -
    • -
      - -
      - -
      -

      Use d.open, d.close

      - -
      - -
                  'open',
      -            'close',
      -            {
      - -
    • - - -
    • -
      - -
      - -
      -

      Specify a custom format for column ‘Change’ by using a label with a function.

      - -
      - -
                      label: 'Change',
      -                format: function (d) {
      -                    return numberFormat(d.close - d.open);
      -                }
      -            },
      - -
    • - - -
    • -
      - -
      - -
      -

      Use d.volume

      - -
      - -
                  'volume'
      -        ])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) sort using the given field, default = function(d){return d;}

      - -
      - -
              .sortBy(function (d) {
      -            return d.dd;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) sort order, default = d3.ascending

      - -
      - -
              .order(d3.ascending)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) custom renderlet to post-process chart using D3

      - -
      - -
              .on('renderlet', function (table) {
      -            table.selectAll('.dc-table-group').classed('info', true);
      -        });
      -
      -    /*
      -
      - -
    • - - -
    • -
      - -
      - -
      -

      Geo Choropleth Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a choropleth chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with such chart will only trigger redraw -on other charts within the same chart group. -
      API: Geo Chroropleth Chart

      - -
      - -
          dc.geoChoroplethChart('#us-chart')
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart width, default 200

      - -
      - -
              .width(990)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart height, default 200

      - -
      - -
              .height(500)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart transition duration, default 1000

      - -
      - -
              .transitionDuration(1000)
      - -
    • - - -
    • -
      - -
      - -
      -

      set crossfilter dimension, dimension key should match the name retrieved in geojson layer

      - -
      - -
              .dimension(states)
      - -
    • - - -
    • -
      - -
      - -
      -

      set crossfilter group

      - -
      - -
              .group(stateRaisedSum)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color function or array for bubbles

      - -
      - -
              .colors(['#ccc', '#E2F2FF','#C4E4FF','#9ED2FF','#81C5FF','#6BBAFF','#51AEFF','#36A2FF','#1E96FF','#0089FF',
      -            '#0061B5'])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color domain to match your data domain if you want to bind data or color

      - -
      - -
              .colorDomain([-5, 200])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color value accessor

      - -
      - -
              .colorAccessor(function(d, i){return d.value;})
      - -
    • - - -
    • -
      - -
      - -
      -

      Project the given geojson. You can call this function multiple times with different geojson feed to generate -multiple layers of geo paths.

      -
        -
      • 1st param - geojson data
      • -
      • 2nd param - name of the layer which will be used to generate css class
      • -
      • 3rd param - (optional) a function used to generate key for geo path, it should match the dimension key -in order for the coloring to work properly
      • -
      - -
      - -
              .overlayGeoJson(statesJson.features, 'state', function(d) {
      -            return d.properties.name;
      -        })
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) closure to generate title for path, default = d.key + ': ' + d.value

      - -
      - -
              .title(function(d) {
      -            return 'State: ' + d.key + '\nTotal Amount Raised: ' + numberFormat(d.value ? d.value : 0) + 'M';
      -        });
      - -
    • - - -
    • -
      - -
      - -
      -

      Bubble Overlay Chart

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Create a overlay bubble chart and use the given css selector as anchor. You can also specify -an optional chart group for this chart to be scoped within. When a chart belongs -to a specific group then any interaction with the chart will only trigger redraw -on charts within the same chart group. -
      API: Bubble Overlay Chart

      - -
      - -
              dc.bubbleOverlay('#bubble-overlay', 'chartGroup')
      - -
    • - - -
    • -
      - -
      - -
      -

      The bubble overlay chart does not generate its own svg element but rather reuses an existing -svg to generate its overlay layer

      - -
      - -
                  .svg(d3.select('#bubble-overlay svg'))
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart width, default = 200

      - -
      - -
                  .width(990)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart height, default = 200

      - -
      - -
                  .height(500)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define chart transition duration, default = 1000

      - -
      - -
                  .transitionDuration(1000)
      - -
    • - - -
    • -
      - -
      - -
      -

      Set crossfilter dimension, dimension key should match the name retrieved in geo json layer

      - -
      - -
                  .dimension(states)
      - -
    • - - -
    • -
      - -
      - -
      -

      Set crossfilter group

      - -
      - -
                  .group(stateRaisedSum)
      - -
    • - - -
    • -
      - -
      - -
      -

      Closure used to retrieve x value from multi-value group

      - -
      - -
                  .keyAccessor(function(p) {return p.value.absGain;})
      - -
    • - - -
    • -
      - -
      - -
      -

      Closure used to retrieve y value from multi-value group

      - -
      - -
                  .valueAccessor(function(p) {return p.value.percentageGain;})
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color function or array for bubbles

      - -
      - -
                  .colors(['#ccc', '#E2F2FF','#C4E4FF','#9ED2FF','#81C5FF','#6BBAFF','#51AEFF','#36A2FF','#1E96FF','#0089FF',
      -                '#0061B5'])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color domain to match your data domain if you want to bind data or color

      - -
      - -
                  .colorDomain([-5, 200])
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) define color value accessor

      - -
      - -
                  .colorAccessor(function(d, i){return d.value;})
      - -
    • - - -
    • -
      - -
      - -
      -

      Closure used to retrieve radius value from multi-value group

      - -
      - -
                  .radiusValueAccessor(function(p) {return p.value.fluctuationPercentage;})
      - -
    • - - -
    • -
      - -
      - -
      -

      set radius scale

      - -
      - -
                  .r(d3.scale.linear().domain([0, 3]))
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) whether chart should render labels, default = true

      - -
      - -
                  .renderLabel(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) closure to generate label per bubble, default = group.key

      - -
      - -
                  .label(function(p) {return p.key.getFullYear();})
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) whether chart should render titles, default = false

      - -
      - -
                  .renderTitle(true)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) closure to generate title per bubble, default = d.key + ': ' + d.value

      - -
      - -
                  .title(function(d) {
      -                return 'Title: ' + d.key;
      -            })
      - -
    • - - -
    • -
      - -
      - -
      -

      add data point to its layer dimension key that matches point name: it will be used to -generate a bubble. Multiple data points can be added to the bubble overlay to generate -multiple bubbles.

      - -
      - -
                  .point('California', 100, 120)
      -            .point('Colorado', 300, 120)
      - -
    • - - -
    • -
      - -
      - -
      -

      (optional) setting debug flag to true will generate a transparent layer on top of -bubble overlay which can be used to obtain relative x,y coordinate for specific -data point, default = false

      - -
      - -
                  .debug(true);
      -    */
      - -
    • - - -
    • -
      - -
      - -
      -

      Rendering

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      simply call .renderAll() to render all charts on the page

      - -
      - -
          dc.renderAll();
      -    /*
      -
      - -
    • - - -
    • -
      - -
      - -
      -

      Or you can render charts belonging to a specific chart group

      - -
      - -
          dc.renderAll('group');
      - -
    • - - -
    • -
      - -
      - -
      -

      Once rendered you can call .redrawAll() to update charts incrementally when the data -changes, without re-rendering everything

      - -
      - -
          dc.redrawAll();
      - -
    • - - -
    • -
      - -
      - -
      -

      Or you can choose to redraw only those charts associated with a specific chart group

      - -
      - -
          dc.redrawAll('group');
      -    */
      -
      -});
      - -
    • - - -
    • -
      - -
      - -
      -

      Versions

      - -
      - -
    • - - -
    • -
      - -
      - -
      -

      Determine the current version of dc with dc.version

      - -
      - -
      d3.selectAll('#version').text(dc.version);
      - -
    • - - -
    • -
      - -
      - -
      -

      Determine latest stable version in the repo via Github API

      - -
      - -
      d3.json('https://api.github.com/repos/dc-js/dc.js/releases/latest', function (error, latestRelease) {
      -    /*jshint camelcase: false */
      -    d3.selectAll('#latest').text(latestRelease.tag_name); /* jscs:disable */
      -});
      - -
    • - -
    -
    - - diff --git a/web/ep/list.js b/web/ep/list.js deleted file mode 100644 index 1c172741e9..0000000000 --- a/web/ep/list.js +++ /dev/null @@ -1,106 +0,0 @@ - -function list (selector,path,data) { - var ndx = crossfilter(data), - all = ndx.groupAll(); - - var pie_group = dc.pieChart(selector + " .group").innerRadius(20).radius(70); - var group = ndx.dimension(function(d) { - if (typeof d.party == "undefined") return ""; - return d.party; - }); - var groupGroup = group.group().reduceSum(function(d) { return 1; }); - - var pie_gender = dc.pieChart(selector + " .gender").radius(70); - var gender = ndx.dimension(function(d) { - if (typeof d.gender_id == "undefined") return ""; - return d.gender; - }); - - var groupGender = gender.group().reduceSum(function(d) { return 1; }); - - var bar_country = dc.barChart(selector + " .country"); - var country = ndx.dimension(function(d) { - if (typeof d.country == "undefined") return ""; - return d.country; - }); - var countryGroup = country.group().reduceSum(function(d) { return 1; }); - - pie_gender - .width(200) - .height(200) - .dimension(gender) - .group(groupGender); - - pie_group - .width(200) - .height(200) - .dimension(group) - .colors(d3.scale.category10()) - .group(groupGroup) - .on('renderlet', function (chart) { - }); - - bar_country - .width(444) - .height(200) - .outerPadding(0) - .gap(1) - .margins({top: 0, right: 0, bottom: 95, left: 30}) - .x(d3.scale.ordinal()) - .xUnits(dc.units.ordinal) - .brushOn(false) - .elasticY(true) - .yAxisLabel("#MEPs") - .dimension(country) - .group(countryGroup); - - bar_country.on("postRender", function(c) {rotateBarChartLabels();} ); - - -function rotateBarChartLabels() { - d3.selectAll(selector+ ' .country .axis.x text') - .style("text-anchor", "end" ) - .attr("transform", function(d) { return "rotate(-90, -4, 9) "; }); -} - - - dc.dataCount(".dc-data-count") - .dimension(ndx) - .group(all); - - dc.dataTable(".dc-data-table") - .dimension(country) - .group(function (d) { - return d.country; - }) - .size(1000) - .columns([ - function (d) { - return d.gender || ""; - }, - function (d) { - return d.first_name || ""; - }, - function (d) { - return d.last_name || ""; - }, - function (d) { - return d.country || ""; - }, - function (d) { - return d.party || ""; - } - ]) - .sortBy(function (d) { - return d.last_name; - }) - .order(d3.ascending) - .on('renderlet', function (table) { - }); - - - - dc.renderAll(); - -} - diff --git a/web/examples/index.html b/web/examples/index.html deleted file mode 100644 index 202fe61724..0000000000 --- a/web/examples/index.html +++ /dev/null @@ -1,64 +0,0 @@ -Index of dc.js examples - - \ No newline at end of file diff --git a/web/examples/stacked-bar.html b/web/examples/stacked-bar.html deleted file mode 100644 index 323b5b464c..0000000000 --- a/web/examples/stacked-bar.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - dc.js - Stacked Bar Example - - - - - - - -
    - -
    - - - - - - -
    - - diff --git a/web/examples/table-pagination.html b/web/examples/table-pagination.html deleted file mode 100644 index a45607e553..0000000000 --- a/web/examples/table-pagination.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - dc.js - Table of Aggregated Data - - - - - - -
    - -
    -
    - Showing - of . - - -
    - - - - - - -
    - - diff --git a/web/js/FileSaver.js b/web/js/FileSaver.js deleted file mode 100644 index 6a3cfc0009..0000000000 --- a/web/js/FileSaver.js +++ /dev/null @@ -1,184 +0,0 @@ -/* FileSaver.js - * A saveAs() FileSaver implementation. - * 1.3.0 - * - * By Eli Grey, http://eligrey.com - * License: MIT - * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md - */ - -/*global self */ -/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ - -/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ - -var saveAs = saveAs || (function(view) { - "use strict"; - // IE <10 is explicitly unsupported - if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { - return; - } - var - doc = view.document - // only get URL when necessary in case Blob.js hasn't overridden it yet - , get_URL = function() { - return view.URL || view.webkitURL || view; - } - , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") - , can_use_save_link = "download" in save_link - , click = function(node) { - var event = new MouseEvent("click"); - node.dispatchEvent(event); - } - , is_safari = /constructor/i.test(view.HTMLElement) - , throw_outside = function(ex) { - (view.setImmediate || view.setTimeout)(function() { - throw ex; - }, 0); - } - , force_saveable_type = "application/octet-stream" - // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to - , arbitrary_revoke_timeout = 1000 * 40 // in ms - , revoke = function(file) { - var revoker = function() { - if (typeof file === "string") { // file is an object URL - get_URL().revokeObjectURL(file); - } else { // file is a File - file.remove(); - } - }; - setTimeout(revoker, arbitrary_revoke_timeout); - } - , dispatch = function(filesaver, event_types, event) { - event_types = [].concat(event_types); - var i = event_types.length; - while (i--) { - var listener = filesaver["on" + event_types[i]]; - if (typeof listener === "function") { - try { - listener.call(filesaver, event || filesaver); - } catch (ex) { - throw_outside(ex); - } - } - } - } - , auto_bom = function(blob) { - // prepend BOM for UTF-8 XML and text/* types (including HTML) - // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF - if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { - return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); - } - return blob; - } - , FileSaver = function(blob, name, no_auto_bom) { - if (!no_auto_bom) { - blob = auto_bom(blob); - } - // First try a.download, then web filesystem, then object URLs - var - filesaver = this - , type = blob.type - , force = type === force_saveable_type - , object_url - , dispatch_all = function() { - dispatch(filesaver, "writestart progress write writeend".split(" ")); - } - // on any filesys errors revert to saving with object URLs - , fs_error = function() { - if (force && is_safari && view.FileReader) { - // Safari doesn't allow downloading of blob urls - var reader = new FileReader(); - reader.onloadend = function() { - var base64Data = reader.result; - view.location.href = "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/)); - filesaver.readyState = filesaver.DONE; - dispatch_all(); - }; - reader.readAsDataURL(blob); - filesaver.readyState = filesaver.INIT; - return; - } - // don't create more object URLs than needed - if (!object_url) { - object_url = get_URL().createObjectURL(blob); - } - if (force) { - view.location.href = object_url; - } else { - var opened = view.open(object_url, "_blank"); - if (!opened) { - // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html - view.location.href = object_url; - } - } - filesaver.readyState = filesaver.DONE; - dispatch_all(); - revoke(object_url); - } - ; - filesaver.readyState = filesaver.INIT; - - if (can_use_save_link) { - object_url = get_URL().createObjectURL(blob); - setTimeout(function() { - save_link.href = object_url; - save_link.download = name; - click(save_link); - dispatch_all(); - revoke(object_url); - filesaver.readyState = filesaver.DONE; - }); - return; - } - - fs_error(); - } - , FS_proto = FileSaver.prototype - , saveAs = function(blob, name, no_auto_bom) { - return new FileSaver(blob, name || blob.name || "download", no_auto_bom); - } - ; - // IE 10+ (native saveAs) - if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { - return function(blob, name, no_auto_bom) { - name = name || blob.name || "download"; - - if (!no_auto_bom) { - blob = auto_bom(blob); - } - return navigator.msSaveOrOpenBlob(blob, name); - }; - } - - FS_proto.abort = function(){}; - FS_proto.readyState = FS_proto.INIT = 0; - FS_proto.WRITING = 1; - FS_proto.DONE = 2; - - FS_proto.error = - FS_proto.onwritestart = - FS_proto.onprogress = - FS_proto.onwrite = - FS_proto.onabort = - FS_proto.onerror = - FS_proto.onwriteend = - null; - - return saveAs; -}( - typeof self !== "undefined" && self - || typeof window !== "undefined" && window - || this.content -)); -// `self` is undefined in Firefox for Android content script context -// while `this` is nsIContentFrameMessageManager -// with an attribute `content` that corresponds to the window - -if (typeof module !== "undefined" && module.exports) { - module.exports.saveAs = saveAs; -} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { - define([], function() { - return saveAs; - }); -} diff --git a/web/js/colorbrewer.js b/web/js/colorbrewer.js deleted file mode 100644 index eca70af967..0000000000 --- a/web/js/colorbrewer.js +++ /dev/null @@ -1 +0,0 @@ -var colorbrewer={YlGn:{3:["#f7fcb9","#addd8e","#31a354"],4:["#ffffcc","#c2e699","#78c679","#238443"],5:["#ffffcc","#c2e699","#78c679","#31a354","#006837"],6:["#ffffcc","#d9f0a3","#addd8e","#78c679","#31a354","#006837"],7:["#ffffcc","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],8:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],9:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"]},YlGnBu:{3:["#edf8b1","#7fcdbb","#2c7fb8"],4:["#ffffcc","#a1dab4","#41b6c4","#225ea8"],5:["#ffffcc","#a1dab4","#41b6c4","#2c7fb8","#253494"],6:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#2c7fb8","#253494"],7:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],8:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],9:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"]},GnBu:{3:["#e0f3db","#a8ddb5","#43a2ca"],4:["#f0f9e8","#bae4bc","#7bccc4","#2b8cbe"],5:["#f0f9e8","#bae4bc","#7bccc4","#43a2ca","#0868ac"],6:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#43a2ca","#0868ac"],7:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],8:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],9:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"]},BuGn:{3:["#e5f5f9","#99d8c9","#2ca25f"],4:["#edf8fb","#b2e2e2","#66c2a4","#238b45"],5:["#edf8fb","#b2e2e2","#66c2a4","#2ca25f","#006d2c"],6:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#2ca25f","#006d2c"],7:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],8:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],9:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"]},PuBuGn:{3:["#ece2f0","#a6bddb","#1c9099"],4:["#f6eff7","#bdc9e1","#67a9cf","#02818a"],5:["#f6eff7","#bdc9e1","#67a9cf","#1c9099","#016c59"],6:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#1c9099","#016c59"],7:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],8:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],9:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"]},PuBu:{3:["#ece7f2","#a6bddb","#2b8cbe"],4:["#f1eef6","#bdc9e1","#74a9cf","#0570b0"],5:["#f1eef6","#bdc9e1","#74a9cf","#2b8cbe","#045a8d"],6:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#2b8cbe","#045a8d"],7:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],8:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],9:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"]},BuPu:{3:["#e0ecf4","#9ebcda","#8856a7"],4:["#edf8fb","#b3cde3","#8c96c6","#88419d"],5:["#edf8fb","#b3cde3","#8c96c6","#8856a7","#810f7c"],6:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8856a7","#810f7c"],7:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],8:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],9:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"]},RdPu:{3:["#fde0dd","#fa9fb5","#c51b8a"],4:["#feebe2","#fbb4b9","#f768a1","#ae017e"],5:["#feebe2","#fbb4b9","#f768a1","#c51b8a","#7a0177"],6:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#c51b8a","#7a0177"],7:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],8:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],9:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"]},PuRd:{3:["#e7e1ef","#c994c7","#dd1c77"],4:["#f1eef6","#d7b5d8","#df65b0","#ce1256"],5:["#f1eef6","#d7b5d8","#df65b0","#dd1c77","#980043"],6:["#f1eef6","#d4b9da","#c994c7","#df65b0","#dd1c77","#980043"],7:["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],8:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],9:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"]},OrRd:{3:["#fee8c8","#fdbb84","#e34a33"],4:["#fef0d9","#fdcc8a","#fc8d59","#d7301f"],5:["#fef0d9","#fdcc8a","#fc8d59","#e34a33","#b30000"],6:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#e34a33","#b30000"],7:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],8:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],9:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"]},YlOrRd:{3:["#ffeda0","#feb24c","#f03b20"],4:["#ffffb2","#fecc5c","#fd8d3c","#e31a1c"],5:["#ffffb2","#fecc5c","#fd8d3c","#f03b20","#bd0026"],6:["#ffffb2","#fed976","#feb24c","#fd8d3c","#f03b20","#bd0026"],7:["#ffffb2","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],8:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],9:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"]},YlOrBr:{3:["#fff7bc","#fec44f","#d95f0e"],4:["#ffffd4","#fed98e","#fe9929","#cc4c02"],5:["#ffffd4","#fed98e","#fe9929","#d95f0e","#993404"],6:["#ffffd4","#fee391","#fec44f","#fe9929","#d95f0e","#993404"],7:["#ffffd4","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],8:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],9:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"]},Purples:{3:["#efedf5","#bcbddc","#756bb1"],4:["#f2f0f7","#cbc9e2","#9e9ac8","#6a51a3"],5:["#f2f0f7","#cbc9e2","#9e9ac8","#756bb1","#54278f"],6:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#756bb1","#54278f"],7:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],8:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],9:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]},Blues:{3:["#deebf7","#9ecae1","#3182bd"],4:["#eff3ff","#bdd7e7","#6baed6","#2171b5"],5:["#eff3ff","#bdd7e7","#6baed6","#3182bd","#08519c"],6:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#3182bd","#08519c"],7:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],8:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],9:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]},Greens:{3:["#e5f5e0","#a1d99b","#31a354"],4:["#edf8e9","#bae4b3","#74c476","#238b45"],5:["#edf8e9","#bae4b3","#74c476","#31a354","#006d2c"],6:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#31a354","#006d2c"],7:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],8:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],9:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"]},Oranges:{3:["#fee6ce","#fdae6b","#e6550d"],4:["#feedde","#fdbe85","#fd8d3c","#d94701"],5:["#feedde","#fdbe85","#fd8d3c","#e6550d","#a63603"],6:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#e6550d","#a63603"],7:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],8:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],9:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"]},Reds:{3:["#fee0d2","#fc9272","#de2d26"],4:["#fee5d9","#fcae91","#fb6a4a","#cb181d"],5:["#fee5d9","#fcae91","#fb6a4a","#de2d26","#a50f15"],6:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#de2d26","#a50f15"],7:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],8:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],9:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"]},Greys:{3:["#f0f0f0","#bdbdbd","#636363"],4:["#f7f7f7","#cccccc","#969696","#525252"],5:["#f7f7f7","#cccccc","#969696","#636363","#252525"],6:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#636363","#252525"],7:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],8:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],9:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"]},PuOr:{3:["#f1a340","#f7f7f7","#998ec3"],4:["#e66101","#fdb863","#b2abd2","#5e3c99"],5:["#e66101","#fdb863","#f7f7f7","#b2abd2","#5e3c99"],6:["#b35806","#f1a340","#fee0b6","#d8daeb","#998ec3","#542788"],7:["#b35806","#f1a340","#fee0b6","#f7f7f7","#d8daeb","#998ec3","#542788"],8:["#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788"],9:["#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788"],10:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],11:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"]},BrBG:{3:["#d8b365","#f5f5f5","#5ab4ac"],4:["#a6611a","#dfc27d","#80cdc1","#018571"],5:["#a6611a","#dfc27d","#f5f5f5","#80cdc1","#018571"],6:["#8c510a","#d8b365","#f6e8c3","#c7eae5","#5ab4ac","#01665e"],7:["#8c510a","#d8b365","#f6e8c3","#f5f5f5","#c7eae5","#5ab4ac","#01665e"],8:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e"],9:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e"],10:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],11:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"]},PRGn:{3:["#af8dc3","#f7f7f7","#7fbf7b"],4:["#7b3294","#c2a5cf","#a6dba0","#008837"],5:["#7b3294","#c2a5cf","#f7f7f7","#a6dba0","#008837"],6:["#762a83","#af8dc3","#e7d4e8","#d9f0d3","#7fbf7b","#1b7837"],7:["#762a83","#af8dc3","#e7d4e8","#f7f7f7","#d9f0d3","#7fbf7b","#1b7837"],8:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837"],9:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837"],10:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],11:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"]},PiYG:{3:["#e9a3c9","#f7f7f7","#a1d76a"],4:["#d01c8b","#f1b6da","#b8e186","#4dac26"],5:["#d01c8b","#f1b6da","#f7f7f7","#b8e186","#4dac26"],6:["#c51b7d","#e9a3c9","#fde0ef","#e6f5d0","#a1d76a","#4d9221"],7:["#c51b7d","#e9a3c9","#fde0ef","#f7f7f7","#e6f5d0","#a1d76a","#4d9221"],8:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221"],9:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221"],10:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],11:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"]},RdBu:{3:["#ef8a62","#f7f7f7","#67a9cf"],4:["#ca0020","#f4a582","#92c5de","#0571b0"],5:["#ca0020","#f4a582","#f7f7f7","#92c5de","#0571b0"],6:["#b2182b","#ef8a62","#fddbc7","#d1e5f0","#67a9cf","#2166ac"],7:["#b2182b","#ef8a62","#fddbc7","#f7f7f7","#d1e5f0","#67a9cf","#2166ac"],8:["#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac"],9:["#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac"],10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"]},RdGy:{3:["#ef8a62","#ffffff","#999999"],4:["#ca0020","#f4a582","#bababa","#404040"],5:["#ca0020","#f4a582","#ffffff","#bababa","#404040"],6:["#b2182b","#ef8a62","#fddbc7","#e0e0e0","#999999","#4d4d4d"],7:["#b2182b","#ef8a62","#fddbc7","#ffffff","#e0e0e0","#999999","#4d4d4d"],8:["#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d"],9:["#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d"],10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"]},RdYlBu:{3:["#fc8d59","#ffffbf","#91bfdb"],4:["#d7191c","#fdae61","#abd9e9","#2c7bb6"],5:["#d7191c","#fdae61","#ffffbf","#abd9e9","#2c7bb6"],6:["#d73027","#fc8d59","#fee090","#e0f3f8","#91bfdb","#4575b4"],7:["#d73027","#fc8d59","#fee090","#ffffbf","#e0f3f8","#91bfdb","#4575b4"],8:["#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4"],9:["#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4"],10:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],11:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"]},Spectral:{3:["#fc8d59","#ffffbf","#99d594"],4:["#d7191c","#fdae61","#abdda4","#2b83ba"],5:["#d7191c","#fdae61","#ffffbf","#abdda4","#2b83ba"],6:["#d53e4f","#fc8d59","#fee08b","#e6f598","#99d594","#3288bd"],7:["#d53e4f","#fc8d59","#fee08b","#ffffbf","#e6f598","#99d594","#3288bd"],8:["#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd"],9:["#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd"],10:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],11:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"]},RdYlGn:{3:["#fc8d59","#ffffbf","#91cf60"],4:["#d7191c","#fdae61","#a6d96a","#1a9641"],5:["#d7191c","#fdae61","#ffffbf","#a6d96a","#1a9641"],6:["#d73027","#fc8d59","#fee08b","#d9ef8b","#91cf60","#1a9850"],7:["#d73027","#fc8d59","#fee08b","#ffffbf","#d9ef8b","#91cf60","#1a9850"],8:["#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850"],9:["#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850"],10:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],11:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"]},Accent:{3:["#7fc97f","#beaed4","#fdc086"],4:["#7fc97f","#beaed4","#fdc086","#ffff99"],5:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0"],6:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f"],7:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17"],8:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"]},Dark2:{3:["#1b9e77","#d95f02","#7570b3"],4:["#1b9e77","#d95f02","#7570b3","#e7298a"],5:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e"],6:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02"],7:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d"],8:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"]},Paired:{3:["#a6cee3","#1f78b4","#b2df8a"],4:["#a6cee3","#1f78b4","#b2df8a","#33a02c"],5:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99"],6:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c"],7:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f"],8:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00"],9:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6"],10:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a"],11:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99"],12:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"]},Pastel1:{3:["#fbb4ae","#b3cde3","#ccebc5"],4:["#fbb4ae","#b3cde3","#ccebc5","#decbe4"],5:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6"],6:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc"],7:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd"],8:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec"],9:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},Pastel2:{3:["#b3e2cd","#fdcdac","#cbd5e8"],4:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4"],5:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9"],6:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae"],7:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc"],8:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"]},Set1:{3:["#e41a1c","#377eb8","#4daf4a"],4:["#e41a1c","#377eb8","#4daf4a","#984ea3"],5:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00"],6:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33"],7:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628"],8:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf"],9:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"]},Set2:{3:["#66c2a5","#fc8d62","#8da0cb"],4:["#66c2a5","#fc8d62","#8da0cb","#e78ac3"],5:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854"],6:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f"],7:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494"],8:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"]},Set3:{3:["#8dd3c7","#ffffb3","#bebada"],4:["#8dd3c7","#ffffb3","#bebada","#fb8072"],5:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3"],6:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462"],7:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69"],8:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5"],9:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9"],10:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd"],11:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5"],12:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"]}}; \ No newline at end of file diff --git a/web/js/crossfilter.js b/web/js/crossfilter.js deleted file mode 100644 index a9b843b24b..0000000000 --- a/web/js/crossfilter.js +++ /dev/null @@ -1,1401 +0,0 @@ -(function(exports){ -crossfilter.version = "1.3.14"; -function crossfilter_identity(d) { - return d; -} -crossfilter.permute = permute; - -function permute(array, index) { - for (var i = 0, n = index.length, copy = new Array(n); i < n; ++i) { - copy[i] = array[index[i]]; - } - return copy; -} -var bisect = crossfilter.bisect = bisect_by(crossfilter_identity); - -bisect.by = bisect_by; - -function bisect_by(f) { - - // Locate the insertion point for x in a to maintain sorted order. The - // arguments lo and hi may be used to specify a subset of the array which - // should be considered; by default the entire array is used. If x is already - // present in a, the insertion point will be before (to the left of) any - // existing entries. The return value is suitable for use as the first - // argument to `array.splice` assuming that a is already sorted. - // - // The returned insertion point i partitions the array a into two halves so - // that all v < x for v in a[lo:i] for the left side and all v >= x for v in - // a[i:hi] for the right side. - function bisectLeft(a, x, lo, hi) { - while (lo < hi) { - var mid = lo + hi >>> 1; - if (f(a[mid]) < x) lo = mid + 1; - else hi = mid; - } - return lo; - } - - // Similar to bisectLeft, but returns an insertion point which comes after (to - // the right of) any existing entries of x in a. - // - // The returned insertion point i partitions the array into two halves so that - // all v <= x for v in a[lo:i] for the left side and all v > x for v in - // a[i:hi] for the right side. - function bisectRight(a, x, lo, hi) { - while (lo < hi) { - var mid = lo + hi >>> 1; - if (x < f(a[mid])) hi = mid; - else lo = mid + 1; - } - return lo; - } - - bisectRight.right = bisectRight; - bisectRight.left = bisectLeft; - return bisectRight; -} -var heap = crossfilter.heap = heap_by(crossfilter_identity); - -heap.by = heap_by; - -function heap_by(f) { - - // Builds a binary heap within the specified array a[lo:hi]. The heap has the - // property such that the parent a[lo+i] is always less than or equal to its - // two children: a[lo+2*i+1] and a[lo+2*i+2]. - function heap(a, lo, hi) { - var n = hi - lo, - i = (n >>> 1) + 1; - while (--i > 0) sift(a, i, n, lo); - return a; - } - - // Sorts the specified array a[lo:hi] in descending order, assuming it is - // already a heap. - function sort(a, lo, hi) { - var n = hi - lo, - t; - while (--n > 0) t = a[lo], a[lo] = a[lo + n], a[lo + n] = t, sift(a, 1, n, lo); - return a; - } - - // Sifts the element a[lo+i-1] down the heap, where the heap is the contiguous - // slice of array a[lo:lo+n]. This method can also be used to update the heap - // incrementally, without incurring the full cost of reconstructing the heap. - function sift(a, i, n, lo) { - var d = a[--lo + i], - x = f(d), - child; - while ((child = i << 1) <= n) { - if (child < n && f(a[lo + child]) > f(a[lo + child + 1])) child++; - if (x <= f(a[lo + child])) break; - a[lo + i] = a[lo + child]; - i = child; - } - a[lo + i] = d; - } - - heap.sort = sort; - return heap; -} -var heapselect = crossfilter.heapselect = heapselect_by(crossfilter_identity); - -heapselect.by = heapselect_by; - -function heapselect_by(f) { - var heap = heap_by(f); - - // Returns a new array containing the top k elements in the array a[lo:hi]. - // The returned array is not sorted, but maintains the heap property. If k is - // greater than hi - lo, then fewer than k elements will be returned. The - // order of elements in a is unchanged by this operation. - function heapselect(a, lo, hi, k) { - var queue = new Array(k = Math.min(hi - lo, k)), - min, - i, - x, - d; - - for (i = 0; i < k; ++i) queue[i] = a[lo++]; - heap(queue, 0, k); - - if (lo < hi) { - min = f(queue[0]); - do { - if (x = f(d = a[lo]) > min) { - queue[0] = d; - min = f(heap(queue, 0, k)[0]); - } - } while (++lo < hi); - } - - return queue; - } - - return heapselect; -} -var insertionsort = crossfilter.insertionsort = insertionsort_by(crossfilter_identity); - -insertionsort.by = insertionsort_by; - -function insertionsort_by(f) { - - function insertionsort(a, lo, hi) { - for (var i = lo + 1; i < hi; ++i) { - for (var j = i, t = a[i], x = f(t); j > lo && f(a[j - 1]) > x; --j) { - a[j] = a[j - 1]; - } - a[j] = t; - } - return a; - } - - return insertionsort; -} -// Algorithm designed by Vladimir Yaroslavskiy. -// Implementation based on the Dart project; see lib/dart/LICENSE for details. - -var quicksort = crossfilter.quicksort = quicksort_by(crossfilter_identity); - -quicksort.by = quicksort_by; - -function quicksort_by(f) { - var insertionsort = insertionsort_by(f); - - function sort(a, lo, hi) { - return (hi - lo < quicksort_sizeThreshold - ? insertionsort - : quicksort)(a, lo, hi); - } - - function quicksort(a, lo, hi) { - // Compute the two pivots by looking at 5 elements. - var sixth = (hi - lo) / 6 | 0, - i1 = lo + sixth, - i5 = hi - 1 - sixth, - i3 = lo + hi - 1 >> 1, // The midpoint. - i2 = i3 - sixth, - i4 = i3 + sixth; - - var e1 = a[i1], x1 = f(e1), - e2 = a[i2], x2 = f(e2), - e3 = a[i3], x3 = f(e3), - e4 = a[i4], x4 = f(e4), - e5 = a[i5], x5 = f(e5); - - var t; - - // Sort the selected 5 elements using a sorting network. - if (x1 > x2) t = e1, e1 = e2, e2 = t, t = x1, x1 = x2, x2 = t; - if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t; - if (x1 > x3) t = e1, e1 = e3, e3 = t, t = x1, x1 = x3, x3 = t; - if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t; - if (x1 > x4) t = e1, e1 = e4, e4 = t, t = x1, x1 = x4, x4 = t; - if (x3 > x4) t = e3, e3 = e4, e4 = t, t = x3, x3 = x4, x4 = t; - if (x2 > x5) t = e2, e2 = e5, e5 = t, t = x2, x2 = x5, x5 = t; - if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t; - if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t; - - var pivot1 = e2, pivotValue1 = x2, - pivot2 = e4, pivotValue2 = x4; - - // e2 and e4 have been saved in the pivot variables. They will be written - // back, once the partitioning is finished. - a[i1] = e1; - a[i2] = a[lo]; - a[i3] = e3; - a[i4] = a[hi - 1]; - a[i5] = e5; - - var less = lo + 1, // First element in the middle partition. - great = hi - 2; // Last element in the middle partition. - - // Note that for value comparison, <, <=, >= and > coerce to a primitive via - // Object.prototype.valueOf; == and === do not, so in order to be consistent - // with natural order (such as for Date objects), we must do two compares. - var pivotsEqual = pivotValue1 <= pivotValue2 && pivotValue1 >= pivotValue2; - if (pivotsEqual) { - - // Degenerated case where the partitioning becomes a dutch national flag - // problem. - // - // [ | < pivot | == pivot | unpartitioned | > pivot | ] - // ^ ^ ^ ^ ^ - // left less k great right - // - // a[left] and a[right] are undefined and are filled after the - // partitioning. - // - // Invariants: - // 1) for x in ]left, less[ : x < pivot. - // 2) for x in [less, k[ : x == pivot. - // 3) for x in ]great, right[ : x > pivot. - for (var k = less; k <= great; ++k) { - var ek = a[k], xk = f(ek); - if (xk < pivotValue1) { - if (k !== less) { - a[k] = a[less]; - a[less] = ek; - } - ++less; - } else if (xk > pivotValue1) { - - // Find the first element <= pivot in the range [k - 1, great] and - // put [:ek:] there. We know that such an element must exist: - // When k == less, then el3 (which is equal to pivot) lies in the - // interval. Otherwise a[k - 1] == pivot and the search stops at k-1. - // Note that in the latter case invariant 2 will be violated for a - // short amount of time. The invariant will be restored when the - // pivots are put into their final positions. - while (true) { - var greatValue = f(a[great]); - if (greatValue > pivotValue1) { - great--; - // This is the only location in the while-loop where a new - // iteration is started. - continue; - } else if (greatValue < pivotValue1) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ek; - break; - } else { - a[k] = a[great]; - a[great--] = ek; - // Note: if great < k then we will exit the outer loop and fix - // invariant 2 (which we just violated). - break; - } - } - } - } - } else { - - // We partition the list into three parts: - // 1. < pivot1 - // 2. >= pivot1 && <= pivot2 - // 3. > pivot2 - // - // During the loop we have: - // [ | < pivot1 | >= pivot1 && <= pivot2 | unpartitioned | > pivot2 | ] - // ^ ^ ^ ^ ^ - // left less k great right - // - // a[left] and a[right] are undefined and are filled after the - // partitioning. - // - // Invariants: - // 1. for x in ]left, less[ : x < pivot1 - // 2. for x in [less, k[ : pivot1 <= x && x <= pivot2 - // 3. for x in ]great, right[ : x > pivot2 - for (var k = less; k <= great; k++) { - var ek = a[k], xk = f(ek); - if (xk < pivotValue1) { - if (k !== less) { - a[k] = a[less]; - a[less] = ek; - } - ++less; - } else { - if (xk > pivotValue2) { - while (true) { - var greatValue = f(a[great]); - if (greatValue > pivotValue2) { - great--; - if (great < k) break; - // This is the only location inside the loop where a new - // iteration is started. - continue; - } else { - // a[great] <= pivot2. - if (greatValue < pivotValue1) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ek; - } else { - // a[great] >= pivot1. - a[k] = a[great]; - a[great--] = ek; - } - break; - } - } - } - } - } - } - - // Move pivots into their final positions. - // We shrunk the list from both sides (a[left] and a[right] have - // meaningless values in them) and now we move elements from the first - // and third partition into these locations so that we can store the - // pivots. - a[lo] = a[less - 1]; - a[less - 1] = pivot1; - a[hi - 1] = a[great + 1]; - a[great + 1] = pivot2; - - // The list is now partitioned into three partitions: - // [ < pivot1 | >= pivot1 && <= pivot2 | > pivot2 ] - // ^ ^ ^ ^ - // left less great right - - // Recursive descent. (Don't include the pivot values.) - sort(a, lo, less - 1); - sort(a, great + 2, hi); - - if (pivotsEqual) { - // All elements in the second partition are equal to the pivot. No - // need to sort them. - return a; - } - - // In theory it should be enough to call _doSort recursively on the second - // partition. - // The Android source however removes the pivot elements from the recursive - // call if the second partition is too large (more than 2/3 of the list). - if (less < i1 && great > i5) { - var lessValue, greatValue; - while ((lessValue = f(a[less])) <= pivotValue1 && lessValue >= pivotValue1) ++less; - while ((greatValue = f(a[great])) <= pivotValue2 && greatValue >= pivotValue2) --great; - - // Copy paste of the previous 3-way partitioning with adaptions. - // - // We partition the list into three parts: - // 1. == pivot1 - // 2. > pivot1 && < pivot2 - // 3. == pivot2 - // - // During the loop we have: - // [ == pivot1 | > pivot1 && < pivot2 | unpartitioned | == pivot2 ] - // ^ ^ ^ - // less k great - // - // Invariants: - // 1. for x in [ *, less[ : x == pivot1 - // 2. for x in [less, k[ : pivot1 < x && x < pivot2 - // 3. for x in ]great, * ] : x == pivot2 - for (var k = less; k <= great; k++) { - var ek = a[k], xk = f(ek); - if (xk <= pivotValue1 && xk >= pivotValue1) { - if (k !== less) { - a[k] = a[less]; - a[less] = ek; - } - less++; - } else { - if (xk <= pivotValue2 && xk >= pivotValue2) { - while (true) { - var greatValue = f(a[great]); - if (greatValue <= pivotValue2 && greatValue >= pivotValue2) { - great--; - if (great < k) break; - // This is the only location inside the loop where a new - // iteration is started. - continue; - } else { - // a[great] < pivot2. - if (greatValue < pivotValue1) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ek; - } else { - // a[great] == pivot1. - a[k] = a[great]; - a[great--] = ek; - } - break; - } - } - } - } - } - } - - // The second partition has now been cleared of pivot elements and looks - // as follows: - // [ * | > pivot1 && < pivot2 | * ] - // ^ ^ - // less great - // Sort the second partition using recursive descent. - - // The second partition looks as follows: - // [ * | >= pivot1 && <= pivot2 | * ] - // ^ ^ - // less great - // Simply sort it by recursive descent. - - return sort(a, less, great + 1); - } - - return sort; -} - -var quicksort_sizeThreshold = 32; -var crossfilter_array8 = crossfilter_arrayUntyped, - crossfilter_array16 = crossfilter_arrayUntyped, - crossfilter_array32 = crossfilter_arrayUntyped, - crossfilter_arrayLengthen = crossfilter_arrayLengthenUntyped, - crossfilter_arrayWiden = crossfilter_arrayWidenUntyped; - -if (typeof Uint8Array !== "undefined") { - crossfilter_array8 = function(n) { return new Uint8Array(n); }; - crossfilter_array16 = function(n) { return new Uint16Array(n); }; - crossfilter_array32 = function(n) { return new Uint32Array(n); }; - - crossfilter_arrayLengthen = function(array, length) { - if (array.length >= length) return array; - var copy = new array.constructor(length); - copy.set(array); - return copy; - }; - - crossfilter_arrayWiden = function(array, width) { - var copy; - switch (width) { - case 16: copy = crossfilter_array16(array.length); break; - case 32: copy = crossfilter_array32(array.length); break; - default: throw new Error("invalid array width!"); - } - copy.set(array); - return copy; - }; -} - -function crossfilter_arrayUntyped(n) { - var array = new Array(n), i = -1; - while (++i < n) array[i] = 0; - return array; -} - -function crossfilter_arrayLengthenUntyped(array, length) { - var n = array.length; - while (n < length) array[n++] = 0; - return array; -} - -function crossfilter_arrayWidenUntyped(array, width) { - if (width > 32) throw new Error("invalid array width!"); - return array; -} -function crossfilter_filterExact(bisect, value) { - return function(values) { - var n = values.length; - return [bisect.left(values, value, 0, n), bisect.right(values, value, 0, n)]; - }; -} - -function crossfilter_filterRange(bisect, range) { - var min = range[0], - max = range[1]; - return function(values) { - var n = values.length; - return [bisect.left(values, min, 0, n), bisect.left(values, max, 0, n)]; - }; -} - -function crossfilter_filterAll(values) { - return [0, values.length]; -} -function crossfilter_null() { - return null; -} -function crossfilter_zero() { - return 0; -} -function crossfilter_reduceIncrement(p) { - return p + 1; -} - -function crossfilter_reduceDecrement(p) { - return p - 1; -} - -function crossfilter_reduceAdd(f) { - return function(p, v) { - return p + +f(v); - }; -} - -function crossfilter_reduceSubtract(f) { - return function(p, v) { - return p - f(v); - }; -} -exports.crossfilter = crossfilter; - -function crossfilter() { - var crossfilter = { - add: add, - remove: removeData, - dimension: dimension, - groupAll: groupAll, - size: size - }; - - var data = [], // the records - n = 0, // the number of records; data.length - m = 0, // a bit mask representing which dimensions are in use - M = 8, // number of dimensions that can fit in `filters` - filters = crossfilter_array8(0), // M bits per record; 1 is filtered out - filterListeners = [], // when the filters change - dataListeners = [], // when data is added - removeDataListeners = []; // when data is removed - - // Adds the specified new records to this crossfilter. - function add(newData) { - var n0 = n, - n1 = newData.length; - - // If there's actually new data to add… - // Merge the new data into the existing data. - // Lengthen the filter bitset to handle the new records. - // Notify listeners (dimensions and groups) that new data is available. - if (n1) { - data = data.concat(newData); - filters = crossfilter_arrayLengthen(filters, n += n1); - dataListeners.forEach(function(l) { l(newData, n0, n1); }); - } - - return crossfilter; - } - - // Removes all records that match the current filters. - function removeData() { - var newIndex = crossfilter_index(n, n), - removed = []; - for (var i = 0, j = 0; i < n; ++i) { - if (filters[i]) newIndex[i] = j++; - else removed.push(i); - } - - // Remove all matching records from groups. - filterListeners.forEach(function(l) { l(0, [], removed); }); - - // Update indexes. - removeDataListeners.forEach(function(l) { l(newIndex); }); - - // Remove old filters and data by overwriting. - for (var i = 0, j = 0, k; i < n; ++i) { - if (k = filters[i]) { - if (i !== j) filters[j] = k, data[j] = data[i]; - ++j; - } - } - data.length = j; - while (n > j) filters[--n] = 0; - } - - // Adds a new dimension with the specified value accessor function. - function dimension(value) { - var dimension = { - filter: filter, - filterExact: filterExact, - filterRange: filterRange, - filterFunction: filterFunction, - filterAll: filterAll, - top: top, - bottom: bottom, - group: group, - groupAll: groupAll, - dispose: dispose, - remove: dispose // for backwards-compatibility - }; - - var one = ~m & -~m, // lowest unset bit as mask, e.g., 00001000 - zero = ~one, // inverted one, e.g., 11110111 - values, // sorted, cached array - index, // value rank ↦ object id - newValues, // temporary array storing newly-added values - newIndex, // temporary array storing newly-added index - sort = quicksort_by(function(i) { return newValues[i]; }), - refilter = crossfilter_filterAll, // for recomputing filter - refilterFunction, // the custom filter function in use - indexListeners = [], // when data is added - dimensionGroups = [], - lo0 = 0, - hi0 = 0; - - // Updating a dimension is a two-stage process. First, we must update the - // associated filters for the newly-added records. Once all dimensions have - // updated their filters, the groups are notified to update. - dataListeners.unshift(preAdd); - dataListeners.push(postAdd); - - removeDataListeners.push(removeData); - - // Incorporate any existing data into this dimension, and make sure that the - // filter bitset is wide enough to handle the new dimension. - m |= one; - if (M >= 32 ? !one : m & -(1 << M)) { - filters = crossfilter_arrayWiden(filters, M <<= 1); - } - preAdd(data, 0, n); - postAdd(data, 0, n); - - // Incorporates the specified new records into this dimension. - // This function is responsible for updating filters, values, and index. - function preAdd(newData, n0, n1) { - - // Permute new values into natural order using a sorted index. - newValues = newData.map(value); - newIndex = sort(crossfilter_range(n1), 0, n1); - newValues = permute(newValues, newIndex); - - // Bisect newValues to determine which new records are selected. - var bounds = refilter(newValues), lo1 = bounds[0], hi1 = bounds[1], i; - if (refilterFunction) { - for (i = 0; i < n1; ++i) { - if (!refilterFunction(newValues[i], i)) filters[newIndex[i] + n0] |= one; - } - } else { - for (i = 0; i < lo1; ++i) filters[newIndex[i] + n0] |= one; - for (i = hi1; i < n1; ++i) filters[newIndex[i] + n0] |= one; - } - - // If this dimension previously had no data, then we don't need to do the - // more expensive merge operation; use the new values and index as-is. - if (!n0) { - values = newValues; - index = newIndex; - lo0 = lo1; - hi0 = hi1; - return; - } - - var oldValues = values, - oldIndex = index, - i0 = 0, - i1 = 0; - - // Otherwise, create new arrays into which to merge new and old. - values = new Array(n); - index = crossfilter_index(n, n); - - // Merge the old and new sorted values, and old and new index. - for (i = 0; i0 < n0 && i1 < n1; ++i) { - if (oldValues[i0] < newValues[i1]) { - values[i] = oldValues[i0]; - index[i] = oldIndex[i0++]; - } else { - values[i] = newValues[i1]; - index[i] = newIndex[i1++] + n0; - } - } - - // Add any remaining old values. - for (; i0 < n0; ++i0, ++i) { - values[i] = oldValues[i0]; - index[i] = oldIndex[i0]; - } - - // Add any remaining new values. - for (; i1 < n1; ++i1, ++i) { - values[i] = newValues[i1]; - index[i] = newIndex[i1] + n0; - } - - // Bisect again to recompute lo0 and hi0. - bounds = refilter(values), lo0 = bounds[0], hi0 = bounds[1]; - } - - // When all filters have updated, notify index listeners of the new values. - function postAdd(newData, n0, n1) { - indexListeners.forEach(function(l) { l(newValues, newIndex, n0, n1); }); - newValues = newIndex = null; - } - - function removeData(reIndex) { - for (var i = 0, j = 0, k; i < n; ++i) { - if (filters[k = index[i]]) { - if (i !== j) values[j] = values[i]; - index[j] = reIndex[k]; - ++j; - } - } - values.length = j; - while (j < n) index[j++] = 0; - - // Bisect again to recompute lo0 and hi0. - var bounds = refilter(values); - lo0 = bounds[0], hi0 = bounds[1]; - } - - // Updates the selected values based on the specified bounds [lo, hi]. - // This implementation is used by all the public filter methods. - function filterIndexBounds(bounds) { - var lo1 = bounds[0], - hi1 = bounds[1]; - - if (refilterFunction) { - refilterFunction = null; - filterIndexFunction(function(d, i) { return lo1 <= i && i < hi1; }); - lo0 = lo1; - hi0 = hi1; - return dimension; - } - - var i, - j, - k, - added = [], - removed = []; - - // Fast incremental update based on previous lo index. - if (lo1 < lo0) { - for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { - filters[k = index[i]] ^= one; - added.push(k); - } - } else if (lo1 > lo0) { - for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { - filters[k = index[i]] ^= one; - removed.push(k); - } - } - - // Fast incremental update based on previous hi index. - if (hi1 > hi0) { - for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { - filters[k = index[i]] ^= one; - added.push(k); - } - } else if (hi1 < hi0) { - for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { - filters[k = index[i]] ^= one; - removed.push(k); - } - } - - lo0 = lo1; - hi0 = hi1; - filterListeners.forEach(function(l) { l(one, added, removed); }); - return dimension; - } - - // Filters this dimension using the specified range, value, or null. - // If the range is null, this is equivalent to filterAll. - // If the range is an array, this is equivalent to filterRange. - // Otherwise, this is equivalent to filterExact. - function filter(range) { - return range == null - ? filterAll() : Array.isArray(range) - ? filterRange(range) : typeof range === "function" - ? filterFunction(range) - : filterExact(range); - } - - // Filters this dimension to select the exact value. - function filterExact(value) { - return filterIndexBounds((refilter = crossfilter_filterExact(bisect, value))(values)); - } - - // Filters this dimension to select the specified range [lo, hi]. - // The lower bound is inclusive, and the upper bound is exclusive. - function filterRange(range) { - return filterIndexBounds((refilter = crossfilter_filterRange(bisect, range))(values)); - } - - // Clears any filters on this dimension. - function filterAll() { - return filterIndexBounds((refilter = crossfilter_filterAll)(values)); - } - - // Filters this dimension using an arbitrary function. - function filterFunction(f) { - refilter = crossfilter_filterAll; - - filterIndexFunction(refilterFunction = f); - - lo0 = 0; - hi0 = n; - - return dimension; - } - - function filterIndexFunction(f) { - var i, - k, - x, - added = [], - removed = []; - - for (i = 0; i < n; ++i) { - if (!(filters[k = index[i]] & one) ^ !!(x = f(values[i], i))) { - if (x) filters[k] &= zero, added.push(k); - else filters[k] |= one, removed.push(k); - } - } - filterListeners.forEach(function(l) { l(one, added, removed); }); - } - - // Returns the top K selected records based on this dimension's order. - // Note: observes this dimension's filter, unlike group and groupAll. - function top(k) { - var array = [], - i = hi0, - j; - - while (--i >= lo0 && k > 0) { - if (!filters[j = index[i]]) { - array.push(data[j]); - --k; - } - } - - return array; - } - - // Returns the bottom K selected records based on this dimension's order. - // Note: observes this dimension's filter, unlike group and groupAll. - function bottom(k) { - var array = [], - i = lo0, - j; - - while (i < hi0 && k > 0) { - if (!filters[j = index[i]]) { - array.push(data[j]); - --k; - } - i++; - } - - return array; - } - - // Adds a new group to this dimension, using the specified key function. - function group(key) { - var group = { - top: top, - all: all, - reduce: reduce, - reduceCount: reduceCount, - reduceSum: reduceSum, - order: order, - orderNatural: orderNatural, - size: size, - dispose: dispose, - remove: dispose // for backwards-compatibility - }; - - // Ensure that this group will be removed when the dimension is removed. - dimensionGroups.push(group); - - var groups, // array of {key, value} - groupIndex, // object id ↦ group id - groupWidth = 8, - groupCapacity = crossfilter_capacity(groupWidth), - k = 0, // cardinality - select, - heap, - reduceAdd, - reduceRemove, - reduceInitial, - update = crossfilter_null, - reset = crossfilter_null, - resetNeeded = true, - groupAll = key === crossfilter_null; - - if (arguments.length < 1) key = crossfilter_identity; - - // The group listens to the crossfilter for when any dimension changes, so - // that it can update the associated reduce values. It must also listen to - // the parent dimension for when data is added, and compute new keys. - filterListeners.push(update); - indexListeners.push(add); - removeDataListeners.push(removeData); - - // Incorporate any existing data into the grouping. - add(values, index, 0, n); - - // Incorporates the specified new values into this group. - // This function is responsible for updating groups and groupIndex. - function add(newValues, newIndex, n0, n1) { - var oldGroups = groups, - reIndex = crossfilter_index(k, groupCapacity), - add = reduceAdd, - initial = reduceInitial, - k0 = k, // old cardinality - i0 = 0, // index of old group - i1 = 0, // index of new record - j, // object id - g0, // old group - x0, // old key - x1, // new key - g, // group to add - x; // key of group to add - - // If a reset is needed, we don't need to update the reduce values. - if (resetNeeded) add = initial = crossfilter_null; - - // Reset the new groups (k is a lower bound). - // Also, make sure that groupIndex exists and is long enough. - groups = new Array(k), k = 0; - groupIndex = k0 > 1 ? crossfilter_arrayLengthen(groupIndex, n) : crossfilter_index(n, groupCapacity); - - // Get the first old key (x0 of g0), if it exists. - if (k0) x0 = (g0 = oldGroups[0]).key; - - // Find the first new key (x1), skipping NaN keys. - while (i1 < n1 && !((x1 = key(newValues[i1])) >= x1)) ++i1; - - // While new keys remain… - while (i1 < n1) { - - // Determine the lesser of the two current keys; new and old. - // If there are no old keys remaining, then always add the new key. - if (g0 && x0 <= x1) { - g = g0, x = x0; - - // Record the new index of the old group. - reIndex[i0] = k; - - // Retrieve the next old key. - if (g0 = oldGroups[++i0]) x0 = g0.key; - } else { - g = {key: x1, value: initial()}, x = x1; - } - - // Add the lesser group. - groups[k] = g; - - // Add any selected records belonging to the added group, while - // advancing the new key and populating the associated group index. - while (!(x1 > x)) { - groupIndex[j = newIndex[i1] + n0] = k; - if (!(filters[j] & zero)) g.value = add(g.value, data[j]); - if (++i1 >= n1) break; - x1 = key(newValues[i1]); - } - - groupIncrement(); - } - - // Add any remaining old groups that were greater than all new keys. - // No incremental reduce is needed; these groups have no new records. - // Also record the new index of the old group. - while (i0 < k0) { - groups[reIndex[i0] = k] = oldGroups[i0++]; - groupIncrement(); - } - - // If we added any new groups before any old groups, - // update the group index of all the old records. - if (k > i0) for (i0 = 0; i0 < n0; ++i0) { - groupIndex[i0] = reIndex[groupIndex[i0]]; - } - - // Modify the update and reset behavior based on the cardinality. - // If the cardinality is less than or equal to one, then the groupIndex - // is not needed. If the cardinality is zero, then there are no records - // and therefore no groups to update or reset. Note that we also must - // change the registered listener to point to the new method. - j = filterListeners.indexOf(update); - if (k > 1) { - update = updateMany; - reset = resetMany; - } else { - if (!k && groupAll) { - k = 1; - groups = [{key: null, value: initial()}]; - } - if (k === 1) { - update = updateOne; - reset = resetOne; - } else { - update = crossfilter_null; - reset = crossfilter_null; - } - groupIndex = null; - } - filterListeners[j] = update; - - // Count the number of added groups, - // and widen the group index as needed. - function groupIncrement() { - if (++k === groupCapacity) { - reIndex = crossfilter_arrayWiden(reIndex, groupWidth <<= 1); - groupIndex = crossfilter_arrayWiden(groupIndex, groupWidth); - groupCapacity = crossfilter_capacity(groupWidth); - } - } - } - - function removeData() { - if (k > 1) { - var oldK = k, - oldGroups = groups, - seenGroups = crossfilter_index(oldK, oldK); - - // Filter out non-matches by copying matching group index entries to - // the beginning of the array. - for (var i = 0, j = 0; i < n; ++i) { - if (filters[i]) { - seenGroups[groupIndex[j] = groupIndex[i]] = 1; - ++j; - } - } - - // Reassemble groups including only those groups that were referred - // to by matching group index entries. Note the new group index in - // seenGroups. - groups = [], k = 0; - for (i = 0; i < oldK; ++i) { - if (seenGroups[i]) { - seenGroups[i] = k++; - groups.push(oldGroups[i]); - } - } - - if (k > 1) { - // Reindex the group index using seenGroups to find the new index. - for (var i = 0; i < j; ++i) groupIndex[i] = seenGroups[groupIndex[i]]; - } else { - groupIndex = null; - } - filterListeners[filterListeners.indexOf(update)] = k > 1 - ? (reset = resetMany, update = updateMany) - : k === 1 ? (reset = resetOne, update = updateOne) - : reset = update = crossfilter_null; - } else if (k === 1) { - if (groupAll) return; - for (var i = 0; i < n; ++i) if (filters[i]) return; - groups = [], k = 0; - filterListeners[filterListeners.indexOf(update)] = - update = reset = crossfilter_null; - } - } - - // Reduces the specified selected or deselected records. - // This function is only used when the cardinality is greater than 1. - function updateMany(filterOne, added, removed) { - if (filterOne === one || resetNeeded) return; - - var i, - k, - n, - g; - - // Add the added values. - for (i = 0, n = added.length; i < n; ++i) { - if (!(filters[k = added[i]] & zero)) { - g = groups[groupIndex[k]]; - g.value = reduceAdd(g.value, data[k]); - } - } - - // Remove the removed values. - for (i = 0, n = removed.length; i < n; ++i) { - if ((filters[k = removed[i]] & zero) === filterOne) { - g = groups[groupIndex[k]]; - g.value = reduceRemove(g.value, data[k]); - } - } - } - - // Reduces the specified selected or deselected records. - // This function is only used when the cardinality is 1. - function updateOne(filterOne, added, removed) { - if (filterOne === one || resetNeeded) return; - - var i, - k, - n, - g = groups[0]; - - // Add the added values. - for (i = 0, n = added.length; i < n; ++i) { - if (!(filters[k = added[i]] & zero)) { - g.value = reduceAdd(g.value, data[k]); - } - } - - // Remove the removed values. - for (i = 0, n = removed.length; i < n; ++i) { - if ((filters[k = removed[i]] & zero) === filterOne) { - g.value = reduceRemove(g.value, data[k]); - } - } - } - - // Recomputes the group reduce values from scratch. - // This function is only used when the cardinality is greater than 1. - function resetMany() { - var i, - g; - - // Reset all group values. - for (i = 0; i < k; ++i) { - groups[i].value = reduceInitial(); - } - - // Add any selected records. - for (i = 0; i < n; ++i) { - if (!(filters[i] & zero)) { - g = groups[groupIndex[i]]; - g.value = reduceAdd(g.value, data[i]); - } - } - } - - // Recomputes the group reduce values from scratch. - // This function is only used when the cardinality is 1. - function resetOne() { - var i, - g = groups[0]; - - // Reset the singleton group values. - g.value = reduceInitial(); - - // Add any selected records. - for (i = 0; i < n; ++i) { - if (!(filters[i] & zero)) { - g.value = reduceAdd(g.value, data[i]); - } - } - } - - // Returns the array of group values, in the dimension's natural order. - function all() { - if (resetNeeded) reset(), resetNeeded = false; - return groups; - } - - // Returns a new array containing the top K group values, in reduce order. - function top(k) { - var top = select(all(), 0, groups.length, k); - return heap.sort(top, 0, top.length); - } - - // Sets the reduce behavior for this group to use the specified functions. - // This method lazily recomputes the reduce values, waiting until needed. - function reduce(add, remove, initial) { - reduceAdd = add; - reduceRemove = remove; - reduceInitial = initial; - resetNeeded = true; - return group; - } - - // A convenience method for reducing by count. - function reduceCount() { - return reduce(crossfilter_reduceIncrement, crossfilter_reduceDecrement, crossfilter_zero); - } - - // A convenience method for reducing by sum(value). - function reduceSum(value) { - return reduce(crossfilter_reduceAdd(value), crossfilter_reduceSubtract(value), crossfilter_zero); - } - - // Sets the reduce order, using the specified accessor. - function order(value) { - select = heapselect_by(valueOf); - heap = heap_by(valueOf); - function valueOf(d) { return value(d.value); } - return group; - } - - // A convenience method for natural ordering by reduce value. - function orderNatural() { - return order(crossfilter_identity); - } - - // Returns the cardinality of this group, irrespective of any filters. - function size() { - return k; - } - - // Removes this group and associated event listeners. - function dispose() { - var i = filterListeners.indexOf(update); - if (i >= 0) filterListeners.splice(i, 1); - i = indexListeners.indexOf(add); - if (i >= 0) indexListeners.splice(i, 1); - i = removeDataListeners.indexOf(removeData); - if (i >= 0) removeDataListeners.splice(i, 1); - return group; - } - - return reduceCount().orderNatural(); - } - - // A convenience function for generating a singleton group. - function groupAll() { - var g = group(crossfilter_null), all = g.all; - delete g.all; - delete g.top; - delete g.order; - delete g.orderNatural; - delete g.size; - g.value = function() { return all()[0].value; }; - return g; - } - - // Removes this dimension and associated groups and event listeners. - function dispose() { - dimensionGroups.forEach(function(group) { group.dispose(); }); - var i = dataListeners.indexOf(preAdd); - if (i >= 0) dataListeners.splice(i, 1); - i = dataListeners.indexOf(postAdd); - if (i >= 0) dataListeners.splice(i, 1); - i = removeDataListeners.indexOf(removeData); - if (i >= 0) removeDataListeners.splice(i, 1); - m &= zero; - return filterAll(); - } - - return dimension; - } - - // A convenience method for groupAll on a dummy dimension. - // This implementation can be optimized since it always has cardinality 1. - function groupAll() { - var group = { - reduce: reduce, - reduceCount: reduceCount, - reduceSum: reduceSum, - value: value, - dispose: dispose, - remove: dispose // for backwards-compatibility - }; - - var reduceValue, - reduceAdd, - reduceRemove, - reduceInitial, - resetNeeded = true; - - // The group listens to the crossfilter for when any dimension changes, so - // that it can update the reduce value. It must also listen to the parent - // dimension for when data is added. - filterListeners.push(update); - dataListeners.push(add); - - // For consistency; actually a no-op since resetNeeded is true. - add(data, 0, n); - - // Incorporates the specified new values into this group. - function add(newData, n0) { - var i; - - if (resetNeeded) return; - - // Add the added values. - for (i = n0; i < n; ++i) { - if (!filters[i]) { - reduceValue = reduceAdd(reduceValue, data[i]); - } - } - } - - // Reduces the specified selected or deselected records. - function update(filterOne, added, removed) { - var i, - k, - n; - - if (resetNeeded) return; - - // Add the added values. - for (i = 0, n = added.length; i < n; ++i) { - if (!filters[k = added[i]]) { - reduceValue = reduceAdd(reduceValue, data[k]); - } - } - - // Remove the removed values. - for (i = 0, n = removed.length; i < n; ++i) { - if (filters[k = removed[i]] === filterOne) { - reduceValue = reduceRemove(reduceValue, data[k]); - } - } - } - - // Recomputes the group reduce value from scratch. - function reset() { - var i; - - reduceValue = reduceInitial(); - - for (i = 0; i < n; ++i) { - if (!filters[i]) { - reduceValue = reduceAdd(reduceValue, data[i]); - } - } - } - - // Sets the reduce behavior for this group to use the specified functions. - // This method lazily recomputes the reduce value, waiting until needed. - function reduce(add, remove, initial) { - reduceAdd = add; - reduceRemove = remove; - reduceInitial = initial; - resetNeeded = true; - return group; - } - - // A convenience method for reducing by count. - function reduceCount() { - return reduce(crossfilter_reduceIncrement, crossfilter_reduceDecrement, crossfilter_zero); - } - - // A convenience method for reducing by sum(value). - function reduceSum(value) { - return reduce(crossfilter_reduceAdd(value), crossfilter_reduceSubtract(value), crossfilter_zero); - } - - // Returns the computed reduce value. - function value() { - if (resetNeeded) reset(), resetNeeded = false; - return reduceValue; - } - - // Removes this group and associated event listeners. - function dispose() { - var i = filterListeners.indexOf(update); - if (i >= 0) filterListeners.splice(i); - i = dataListeners.indexOf(add); - if (i >= 0) dataListeners.splice(i); - return group; - } - - return reduceCount(); - } - - // Returns the number of records in this crossfilter, irrespective of any filters. - function size() { - return n; - } - - return arguments.length - ? add(arguments[0]) - : crossfilter; -} - -// Returns an array of size n, big enough to store ids up to m. -function crossfilter_index(n, m) { - return (m < 0x101 - ? crossfilter_array8 : m < 0x10001 - ? crossfilter_array16 - : crossfilter_array32)(n); -} - -// Constructs a new array of size n, with sequential values from 0 to n - 1. -function crossfilter_range(n) { - var range = crossfilter_index(n, n); - for (var i = -1; ++i < n;) range[i] = i; - return range; -} - -function crossfilter_capacity(w) { - return w === 8 - ? 0x100 : w === 16 - ? 0x10000 - : 0x100000000; -} -})(typeof exports !== 'undefined' && exports || this); diff --git a/web/js/d3.js b/web/js/d3.js deleted file mode 100644 index aded45c440..0000000000 --- a/web/js/d3.js +++ /dev/null @@ -1,9554 +0,0 @@ -!function() { - var d3 = { - version: "3.5.17" - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = this.document; - function d3_documentElement(node) { - return node && (node.ownerDocument || node.document || node).documentElement; - } - function d3_window(node) { - return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); - } - if (d3_document) { - try { - d3_array(d3_document.documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - } - if (!Date.now) Date.now = function() { - return +new Date(); - }; - if (d3_document) { - try { - d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - } - d3.ascending = d3_ascending; - function d3_ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - function d3_number(x) { - return x === null ? NaN : +x; - } - function d3_numeric(x) { - return !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = +array[i])) s += a; - } else { - while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - d3.mean = function(array, f) { - var s = 0, n = array.length, a, i = -1, j = n; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; - } - if (j) return s / j; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - var numbers = [], n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); - } - if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); - }; - d3.variance = function(array, f) { - var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) { - if (d3_numeric(a = d3_number(array[i]))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } else { - while (++i < n) { - if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } - if (j > 1) return s / (j - 1); - }; - d3.deviation = function() { - var v = d3.variance.apply(this, arguments); - return v ? Math.sqrt(v) : v; - }; - function d3_bisector(compare) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - } - var d3_bisect = d3_bisector(d3_ascending); - d3.bisectLeft = d3_bisect.left; - d3.bisect = d3.bisectRight = d3_bisect.right; - d3.bisector = function(f) { - return d3_bisector(f.length === 1 ? function(d, x) { - return d3_ascending(f(d), x); - } : f); - }; - d3.shuffle = function(array, i0, i1) { - if ((m = arguments.length) < 3) { - i1 = array.length; - if (m < 2) i0 = 0; - } - var m = i1 - i0, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.transpose = function(matrix) { - if (!(n = matrix.length)) return []; - for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { - for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { - row[j] = matrix[j][i]; - } - } - return transpose; - }; - function d3_transposeLength(d) { - return d.length; - } - d3.zip = function() { - return d3.transpose(arguments); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } - d3.map = function(object, f) { - var map = new d3_Map(); - if (object instanceof d3_Map) { - object.forEach(function(key, value) { - map.set(key, value); - }); - } else if (Array.isArray(object)) { - var i = -1, n = object.length, o; - if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); - } else { - for (var key in object) map.set(key, object[key]); - } - return map; - }; - function d3_Map() { - this._ = Object.create(null); - } - var d3_map_proto = "__proto__", d3_map_zero = "\x00"; - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this._[d3_map_escape(key)]; - }, - set: function(key, value) { - return this._[d3_map_escape(key)] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - for (var key in this._) values.push(this._[key]); - return values; - }, - entries: function() { - var entries = []; - for (var key in this._) entries.push({ - key: d3_map_unescape(key), - value: this._[key] - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); - } - }); - function d3_map_escape(key) { - return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; - } - function d3_map_unescape(key) { - return (key += "")[0] === d3_map_zero ? key.slice(1) : key; - } - function d3_map_has(key) { - return d3_map_escape(key) in this._; - } - function d3_map_remove(key) { - return (key = d3_map_escape(key)) in this._ && delete this._[key]; - } - function d3_map_keys() { - var keys = []; - for (var key in this._) keys.push(d3_map_unescape(key)); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this._) ++size; - return size; - } - function d3_map_empty() { - for (var key in this._) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() { - this._ = Object.create(null); - } - d3_class(d3_Set, { - has: d3_map_has, - add: function(key) { - this._[d3_map_escape(key += "")] = true; - return key; - }, - remove: d3_map_remove, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key)); - } - }); - d3.behavior = {}; - function d3_identity(d) { - return d; - } - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.slice(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.slice(i + 1); - type = type.slice(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatches = function(n, s) { - var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; - d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - return d3_selectMatches(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = Sizzle; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3.select(d3_document.documentElement); - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: d3_nsXhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return (name + "").trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) { - var node = this.node(); - return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); - } - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - function create() { - var document = this.ownerDocument, namespace = this.namespaceURI; - return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); - } - function createNS() { - return this.ownerDocument.createElementNS(name.space, name.local); - } - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(d3_selectionRemove); - }; - function d3_selectionRemove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; - for (i = -1; ++i < n; ) { - if (node = group[i]) { - if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues[i] = keyValue; - } - } - for (i = -1; ++i < m; ) { - if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } else if (node !== true) { - updateNodes[i] = node; - node.__data__ = nodeData; - } - nodeByKeyValue.set(keyValue, true); - } - for (i = -1; ++i < n; ) { - if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3_ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - d3_selection_each(this, function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3.select = function(node) { - var group; - if (typeof node === "string") { - group = [ d3_select(node, d3_document) ]; - group.parentNode = d3_document.documentElement; - } else { - group = [ node ]; - group.parentNode = d3_documentElement(node); - } - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group; - if (typeof nodes === "string") { - group = d3_array(d3_selectAll(nodes, d3_document)); - group.parentNode = d3_document.documentElement; - } else { - group = d3_array(nodes); - group.parentNode = null; - } - return d3_selection([ group ]); - }; - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.slice(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - if (d3_document) { - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - } - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect, d3_event_dragId = 0; - function d3_event_dragSuppress(node) { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect == null) { - d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); - } - if (d3_event_dragSelect) { - var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - var off = function() { - w.on(click, null); - }; - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0) { - var window = d3_window(container); - if (window.scrollX || window.scrollY) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touch = function(container, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; - if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return d3_mousePoint(container, touch); - } - } - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function dragstart(id, position, subject, move, end) { - return function() { - var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); - if (origin) { - dragOffset = origin.apply(that, arguments); - dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; - } else { - dragOffset = [ 0, 0 ]; - } - dispatch({ - type: "dragstart" - }); - function moved() { - var position1 = position(parent, dragId), dx, dy; - if (!position1) return; - dx = position1[0] - position0[0]; - dy = position1[1] - position0[1]; - dragged |= dx | dy; - position0 = position1; - dispatch({ - type: "drag", - x: position1[0] + dragOffset[0], - y: position1[1] + dragOffset[1], - dx: dx, - dy: dy - }); - } - function ended() { - if (!position(parent, dragId)) return; - dragSubject.on(move + dragName, null).on(end + dragName, null); - dragRestore(dragged); - dispatch({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - function d3_behavior_dragTouchId() { - return d3.event.changedTouches[0].identifier; - } - d3.touches = function(container, touches) { - if (arguments.length < 2) touches = d3_eventSource().touches; - return touches ? d3_array(touches).map(function(touch) { - var point = d3_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; - }; - var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; - function d3_sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; - if (d2 < ε2) { - S = Math.log(w1 / w0) / ρ; - i = function(t) { - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; - }; - } else { - var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / ρ; - i = function(t) { - var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - }; - } - i.duration = S * 1e3; - return i; - }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - if (!d3_behavior_zoomWheel) { - d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - } - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var dispatch = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(dispatch); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(dispatch); - }; - }).each("interrupt.zoom", function() { - zoomended(dispatch); - }).each("end.zoom", function() { - zoomended(dispatch); - }); - } else { - this.__chart__ = view; - zoomstarted(dispatch); - zoomed(dispatch); - zoomended(dispatch); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: null - }; - scaleTo(+_); - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.duration = function(_) { - if (!arguments.length) return duration; - duration = +_; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function zoomTo(that, p, l, k) { - that.__chart__ = { - x: view.x, - y: view.y, - k: view.k - }; - scaleTo(Math.pow(2, k)); - translateTo(center0 = p, l); - that = d3.select(that); - if (duration > 0) that = that.transition().duration(duration); - that.call(zoom.event); - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(dispatch) { - if (!zooming++) dispatch({ - type: "zoomstart" - }); - } - function zoomed(dispatch) { - rescale(); - dispatch({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); - } - function zoomended(dispatch) { - if (!--zooming) dispatch({ - type: "zoomend" - }), center0 = null; - } - function mousedowned() { - var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); - d3_selection_interrupt.call(that); - zoomstarted(dispatch); - function moved() { - dragged = 1; - translateTo(d3.mouse(that), location0); - zoomed(dispatch); - } - function ended() { - subject.on(mousemove, null).on(mouseup, null); - dragRestore(dragged); - zoomended(dispatch); - } - } - function touchstarted() { - var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); - started(); - zoomstarted(dispatch); - subject.on(mousedown, null).on(touchstart, started); - function relocate() { - var touches = d3.touches(that); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; - } - function started() { - var target = d3.event.target; - d3.select(target).on(touchmove, moved).on(touchend, ended); - targets.push(target); - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0]; - zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); - d3_eventPreventDefault(); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } - } - function moved() { - var touches = d3.touches(that), p0, l0, p1, l1; - d3_selection_interrupt.call(that); - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(dispatch); - } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - d3.selectAll(targets).on(zoomName, null); - subject.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(dispatch); - } - } - function mousewheeled() { - var dispatch = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), - translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(dispatch); - }, 50); - d3_eventPreventDefault(); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(center0, translate0); - zoomed(dispatch); - } - function dblclicked() { - var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; - zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; - d3.color = d3_color; - function d3_color() {} - d3_color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.hsl = d3_hsl; - function d3_hsl(h, s, l) { - return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); - } - var d3_hslPrototype = d3_hsl.prototype = new d3_color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, k * this.l); - }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); - }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = d3_hcl; - function d3_hcl(h, c, l) { - return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); - } - var d3_hclPrototype = d3_hcl.prototype = new d3_color(); - d3_hclPrototype.brighter = function(k) { - return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); - }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = d3_lab; - function d3_lab(l, a, b) { - return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_lab.prototype = new d3_color(); - d3_labPrototype.brighter = function(k) { - return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); - }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = d3_rgb; - function d3_rgb(r, g, b) { - return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); - } - function d3_rgbNumber(value) { - return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; - } - var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return new d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_rgb(k * this.r, k * this.g, k * this.b); - }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); - }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); - }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - var r = 0, g = 0, b = 0, m1, m2, color; - m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } - } - } - if (color = d3_rgb_names.get(format)) { - return rgb(color.r, color.g, color.b); - } - if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { - if (format.length === 4) { - r = (color & 3840) >> 4; - r = r >> 4 | r; - g = color & 240; - g = g >> 4 | g; - b = color & 15; - b = b << 4 | b; - } else if (format.length === 7) { - r = (color & 16711680) >> 16; - g = (color & 65280) >> 8; - b = color & 255; - } - } - return rgb(r, g, b); - } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; - } - return new d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - rebeccapurple: 6697881, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; - } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } - } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - function d3_xhrHasResponse(request) { - var type = request.responseType; - return type && type !== "text" ? request.response : request.responseText; - } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.slice(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.slice(j, I - k); - } - return text.slice(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && (a = f(a, n++)) == null) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } - }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); - }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); - }; - d3.timer = function() { - d3_timer.apply(this, arguments); - }; - function d3_timer(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - return timer; - } - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); - }; - function d3_timer_mark() { - var now = Date.now(), timer = d3_timer_queueHead; - while (timer) { - if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; - timer = timer.n; - } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.c) { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; - } else { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } - } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value = +value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { - var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - exponent = false; - - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - var fullSuffix = suffix; - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - fullSuffix = unit.symbol + suffix; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before, after; - if (i < 0) { - var j = exponent ? value.lastIndexOf("e") : -1; - if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); - } else { - before = value.substring(0, i); - after = locale_decimal + value.substring(i + 1); - } - if (!zfill && comma) before = formatGroup(before, Infinity); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; - }; - }; - } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); - } - }); - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); - } - }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; - } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; - } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } - } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; - } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; - } - }; - } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); - }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); - }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.slice(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; - } - } - string.push(template.slice(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; - } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; - } - } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; - }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); - }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; - } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); - } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); - } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); - } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; - } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; - } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); - }; - } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) - }; - }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; - } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); - } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); - } - }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); - } - }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); - } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } - }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; - } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; - } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; - } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; - } - function compareRanges(a, b) { - return a[0] - b[0]; - } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; - } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; - } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; - }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; - } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); - } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (polygonStarted) listener.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); - } - function ringStart() { - ringListener.lineStart(); - ring = []; - } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - if (n > 0) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); - } - return; - } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); - } - return clip; - }; - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; - } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; - } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); - polarAngle += antimeridian ? dλ + sdλ * τ : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } - } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; - } - } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1; - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; - } - } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; - } - } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy - }; - return line; - }; - } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } - }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); - } - listener.polygonEnd(); - } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; - } - } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); - } - } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); - } - clip.point = point; - if (v_) listener.lineEnd(); - } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - return clip; - }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); - } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; - } - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); - }; - return p; - } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; - } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); - }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; - } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; - } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); - }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); - } - }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); - }; - } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; - } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; - }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x + pointRadius, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - context.closePath(); - } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); - } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); - } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; - } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); - } - return resample; - } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } - } - } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; - } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); - } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); - }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); - }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; - } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); - } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); - } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); - } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; - } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; - } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; - } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; - } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; - } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); - }; - } - function d3_source(d) { - return d.source; - } - function d3_target(d) { - return d.target; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; - } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; - }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); - }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; - } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; - }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, - point: d3_noop, - lineStart: d3_geo_lengthLineStart, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; - }; - function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; - } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; - }; - return azimuthal; - } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - if (F > 0) { - if (φ < -halfπ + ε) φ = -halfπ + ε; - } else { - if (φ > halfπ - ε) φ = halfπ - ε; - } - var ρ = F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; - } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; - } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); - } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; - } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return rotate([ 0, 0, 90 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; - } - function d3_geom_pointY(d) { - return d[1]; - } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); - } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; - }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; - } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - c = d; - } - if (closed) subject.push(subject[0]); - a = b; - } - return subject; - }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); - } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; - } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; - } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); - } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; - } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; - } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; - } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; - } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; - } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; - } - } - } - } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; - } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; - } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; - } - } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; - } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } - } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } - } - } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; - } - } - } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; - } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; - } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; - } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; - } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; - } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; - } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; - } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; - } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; - } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges - }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; - } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); - } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); - }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); - } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } - return quadtree(points); - } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = xm; else x2 = xm; - if (below) y1 = ym; else y2 = ym; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - root.find = function(point) { - return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); - }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; - }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null - }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { - var minDistance2 = Infinity, closestPoint; - (function find(node, x1, y1, x2, y2) { - if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; - if (point = node.point) { - var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; - if (distance2 < minDistance2) { - var distance = Math.sqrt(minDistance2 = distance2); - x0 = x - distance, y0 = y - distance; - x3 = x + distance, y3 = y + distance; - closestPoint = point; - } - } - var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; - for (var i = below << 1 | right, j = i + 4; i < j; ++i) { - if (node = children[i & 3]) switch (i & 3) { - case 0: - find(node, x1, y1, xm, ym); - break; - - case 1: - find(node, xm, y1, x2, ym); - break; - - case 2: - find(node, x1, ym, xm, y2); - break; - - case 3: - find(node, xm, ym, x2, y2); - break; - } - } - })(root, x0, y0, x3, y3); - return closestPoint; - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); - }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; - } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - a = +a, b = +b; - return function(t) { - return a * (1 - t) + b * t; - }; - } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; - a = a + "", b = b + ""; - while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { - if ((bs = bm.index) > bi) { - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { - if (s[i]) s[i] += bm; else s[++i] = bm; - } else { - s[++i] = null; - q.push({ - i: i, - x: d3_interpolateNumber(am, bm) - }); - } - bi = d3_interpolate_numberB.lastIndex; - } - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { - return b(t) + ""; - }) : function() { - return b; - } : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; - } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; - }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); - } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); - }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); - } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); - }; - } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; - }; - } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; - }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; - }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; - } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; - }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; - } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; - } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; - } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransformPop(s) { - return s.length ? s.pop() + "," : ""; - } - function d3_interpolateTranslate(ta, tb, s, q) { - if (ta[0] !== tb[0] || ta[1] !== tb[1]) { - var i = s.push("translate(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } - } - function d3_interpolateRotate(ra, rb, s, q) { - if (ra !== rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); - } - } - function d3_interpolateSkew(wa, wb, s, q) { - if (wa !== wb) { - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); - } - } - function d3_interpolateScale(ka, kb, s, q) { - if (ka[0] !== kb[0] || ka[1] !== kb[1]) { - var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] !== 1 || kb[1] !== 1) { - s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); - } - } - function d3_interpolateTransform(a, b) { - var s = [], q = []; - a = d3.transform(a), b = d3.transform(b); - d3_interpolateTranslate(a.translate, b.translate, s, q); - d3_interpolateRotate(a.rotate, b.rotate, s, q); - d3_interpolateSkew(a.skew, b.skew, s, q); - d3_interpolateScale(a.scale, b.scale, s, q); - a = b = null; - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - function d3_uninterpolateNumber(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return (x - a) / b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return Math.max(0, Math.min(1, (x - a) / b)); - }; - } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; - }; - }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; - } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; - } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); - } - return sharedNode; - } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: groupSums[di] - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } - } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); - }); - } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - force.tick = function() { - if ((alpha *= .99) < .005) { - timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha - }); - }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; - }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) { - alpha = x; - } else { - timer.c = null, timer.t = NaN, timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - } - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - timer = d3_timer(force.tick); - } - return force; - }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, l = candidates.length, x; - while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); - }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); - }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; - } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; - } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; - } - } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; - } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; - } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function hierarchy(root) { - var stack = [ root ], nodes = [], node; - root.depth = 0; - while ((node = stack.pop()) != null) { - nodes.push(node); - if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { - var n, childs, child; - while (--n >= 0) { - stack.push(child = childs[n]); - child.parent = node; - child.depth = node.depth + 1; - } - if (value) node.value = 0; - node.children = childs; - } else { - if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; - delete node.children; - } - } - d3_layout_hierarchyVisitAfter(root, function(node) { - var childs, parent; - if (sort && (childs = node.children)) childs.sort(sort); - if (value && (parent = node.parent)) parent.value += node.value; - }); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - if (value) { - d3_layout_hierarchyVisitBefore(root, function(node) { - if (node.children) node.value = 0; - }); - d3_layout_hierarchyVisitAfter(root, function(node) { - var parent; - if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; - if (parent = node.parent) parent.value += node.value; - }); - } - return root; - }; - return hierarchy; - }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; - } - function d3_layout_hierarchyVisitBefore(node, callback) { - var nodes = [ node ]; - while ((node = nodes.pop()) != null) { - callback(node); - if ((children = node.children) && (n = children.length)) { - var n, children; - while (--n >= 0) nodes.push(children[n]); - } - } - } - function d3_layout_hierarchyVisitAfter(node, callback) { - var nodes = [ node ], nodes2 = []; - while ((node = nodes.pop()) != null) { - nodes2.push(node); - if ((children = node.children) && (n = children.length)) { - var i = -1, n, children; - while (++i < n) nodes.push(children[i]); - } - } - while ((node = nodes2.pop()) != null) { - callback(node); - } - } - function d3_layout_hierarchyChildren(d) { - return d.children; - } - function d3_layout_hierarchyValue(d) { - return d.value; - } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; - } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); - } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; - } - } - } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; - } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; - } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; - }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; - function pie(data) { - var n = data.length, values = data.map(function(d, i) { - return +value.call(pie, d, i); - }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - index.forEach(function(i) { - arcs[i] = { - data: data[i], - value: v = values[i], - startAngle: a, - endAngle: a += v * k + pa, - padAngle: p - }; - }); - return arcs; - } - pie.value = function(_) { - if (!arguments.length) return value; - value = _; - return pie; - }; - pie.sort = function(_) { - if (!arguments.length) return sort; - sort = _; - return pie; - }; - pie.startAngle = function(_) { - if (!arguments.length) return startAngle; - startAngle = _; - return pie; - }; - pie.endAngle = function(_) { - if (!arguments.length) return endAngle; - endAngle = _; - return pie; - }; - pie.padAngle = function(_) { - if (!arguments.length) return padAngle; - padAngle = _; - return pie; - }; - return pie; - }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - if (!(n = data.length)) return data; - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var m = series[0].length, n, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); - } - } - return data; - } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; - } - function d3_layout_stackY(d) { - return d.y; - } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; - } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); - } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; - } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; - } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; - } - } - return j; - } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); - } - function d3_layout_stackSum(p, d) { - return p + d[1]; - } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); - } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; - } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; - } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); - }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; - } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; - } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } - } - } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; - } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); - } - } - } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); - d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; - d3_layout_hierarchyVisitBefore(root1, secondWalk); - if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { - var left = root0, right = root0, bottom = root0; - d3_layout_hierarchyVisitBefore(root0, function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); - d3_layout_hierarchyVisitBefore(root0, function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - return nodes; - } - function wrapTree(root0) { - var root1 = { - A: null, - children: [ root0 ] - }, queue = [ root1 ], node1; - while ((node1 = queue.pop()) != null) { - for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { - queue.push((children[i] = child = { - _: children[i], - parent: node1, - children: (child = children[i].children) && child.slice() || [], - A: null, - a: null, - z: 0, - m: 0, - c: 0, - s: 0, - t: null, - i: i - }).a = child); - } - } - return root1.children[0]; - } - function firstWalk(v) { - var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; - if (children.length) { - d3_layout_treeShift(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - function apportion(v, w, ancestor) { - if (w) { - var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !d3_layout_treeRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - function sizeNode(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null ? sizeNode : null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) == null ? null : sizeNode; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); - }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(v) { - var children = v.children; - return children.length ? children[0] : v.t; - } - function d3_layout_treeRight(v) { - var children = v.children, n; - return (n = children.length) ? children[n - 1] : v.t; - } - function d3_layout_treeMove(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; - } - function d3_layout_treeShift(v) { - var shift = 0, change = 0, children = v.children, i = children.length, w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } - } - function d3_layout_treeAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; - } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_hierarchyVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; - }); - return nodes; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; - }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; - }; - return d3_layout_hierarchyRebind(cluster, hierarchy); - }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; - } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; - } - } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; - } - children.forEach(squarify); - } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; - } - } - children.forEach(stickify); - } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); - } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = root.y = 0; - if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; - }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; - }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; - } - }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); - } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; - } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; - } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; - } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity - }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); - }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - return domain; - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - if (format) { - var match = d3_format_re.exec(format); - match.shift(); - if (match[8] === "s") { - var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); - if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); - match[8] = "f"; - format = d3.format(match.join("")); - return function(d) { - return format(prefix.scale(d)) + prefix.symbol; - }; - } - if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); - format = match.join(""); - } else { - format = ",." + d3_scale_linearPrecision(range[2]) + "f"; - } - return d3.format(format); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); - }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); - } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); - } - return ticks; - }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(1, base * n / scale.ticks().length); - return function(d) { - var i = d / pow(Math.round(log(d))); - if (i * base < base - .5) i *= base; - return i <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, - 0) : (stop - start) / (domain.length - 1 + padding); - range = steps(start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; - }; - scale.rangeRoundPoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), - 0) : (stop - start) / (domain.length - 1 + padding) | 0; - range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); - rangeBand = 0; - ranger = { - t: "rangeRoundPoints", - a: arguments - }; - return scale; - }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; - }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; - }; - scale.rangeBand = function() { - return rangeBand; - }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); - }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); - } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); - }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; - } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - function d3_zero() { - return 0; - } - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; - function arc() { - var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; - if (r1 < r0) rc = r1, r1 = r0, r0 = rc; - if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; - var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; - if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { - rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); - if (!cw) p1 *= -1; - if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); - if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); - } - if (r1) { - x0 = r1 * Math.cos(a0 + p1); - y0 = r1 * Math.sin(a0 + p1); - x1 = r1 * Math.cos(a1 - p1); - y1 = r1 * Math.sin(a1 - p1); - var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; - if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { - var h1 = (a0 + a1) / 2; - x0 = r1 * Math.cos(h1); - y0 = r1 * Math.sin(h1); - x1 = y1 = null; - } - } else { - x0 = y0 = 0; - } - if (r0) { - x2 = r0 * Math.cos(a1 - p0); - y2 = r0 * Math.sin(a1 - p0); - x3 = r0 * Math.cos(a0 + p0); - y3 = r0 * Math.sin(a0 + p0); - var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; - if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { - var h0 = (a0 + a1) / 2; - x2 = r0 * Math.cos(h0); - y2 = r0 * Math.sin(h0); - x3 = y3 = null; - } - } else { - x2 = y2 = 0; - } - if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { - cr = r0 < r1 ^ cw ? 0 : 1; - var rc1 = rc, rc0 = rc; - if (da < π) { - var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); - rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); - } - if (x1 != null) { - var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); - if (rc === rc1) { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); - } else { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); - } - } else { - path.push("M", x0, ",", y0); - } - if (x3 != null) { - var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); - if (rc === rc0) { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } else { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } - } else { - path.push("L", x2, ",", y2); - } - } else { - path.push("M", x0, ",", y0); - if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); - path.push("L", x2, ",", y2); - if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); - } - path.push("Z"); - return path.join(""); - } - function circleSegment(r1, cw) { - return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; - } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.cornerRadius = function(v) { - if (!arguments.length) return cornerRadius; - cornerRadius = d3_functor(v); - return arc; - }; - arc.padRadius = function(v) { - if (!arguments.length) return padRadius; - padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.padAngle = function(v) { - if (!arguments.length) return padAngle; - padAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcAuto = "auto"; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_arcPadAngle(d) { - return d && d.padAngle; - } - function d3_svg_arcSweep(x0, y0, x1, y1) { - return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; - } - function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { - var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; - } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; - }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.length > 1 ? points.join("L") : points + "Z"; - } - function d3_svg_lineLinearClosed(points) { - return points.join("L") + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); - } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); - } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - } - } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; - } - return path; - } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); - } - return tangents; - } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - points.pop(); - path.push("L", pi); - return path.join(""); - } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); - } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; - } - m[i] = d; - return m; - } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); - } - return tangents; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] - halfπ; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; - } - } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; - } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - return area; - } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; - } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; - } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; - }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; - } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; - } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - d3_selectionPrototype.transition = function(name) { - var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id); - }; - d3_selectionPrototype.interrupt = function(name) { - return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); - }; - var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); - function d3_selection_interruptNS(ns) { - return function() { - var lock, activeId, active; - if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { - active.timer.c = null; - active.timer.t = NaN; - if (--lock.count) delete lock[activeId]; else delete this[ns]; - lock.active += .5; - active.event && active.event.interrupt.call(this, this.__data__, active.index); - } - }; - } - function d3_transition(groups, ns, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.namespace = ns; - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection, name) { - return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); - }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, ns, id, node[ns][id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node[ns][id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.namespace, this.id); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) return this.node()[ns][id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node[ns][id].tween.remove(name); - } : function(node) { - node[ns][id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id, ns = groups.namespace; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node[ns][id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); - } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); - }); - } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); - }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); - }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; - }; - } - d3_transitionPrototype.remove = function() { - var ns = this.namespace; - return this.each("end.transition", function() { - var p; - if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node[ns][id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].delay; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node[ns][id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].duration; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node[ns][id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - try { - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node[ns][id]; - type.call(node, node.__data__, i, j); - }); - } finally { - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } - } else { - d3_selection_each(this, function(node) { - var transition = node[ns][id]; - (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = node[ns][id0]; - d3_transitionNode(node, i, ns, id1, { - time: transition.time, - ease: transition.ease, - delay: transition.delay + transition.duration, - duration: transition.duration - }); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id1); - }; - function d3_transitionNamespace(name) { - return name == null ? "__transition__" : "__transition_" + name + "__"; - } - function d3_transitionNode(node, i, ns, id, inherit) { - var lock = node[ns] || (node[ns] = { - active: 0, - count: 0 - }), transition = lock[id], time, timer, duration, ease, tweens; - function schedule(elapsed) { - var delay = transition.delay; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - } - function start(elapsed) { - var activeId = lock.active, active = lock[activeId]; - if (active) { - active.timer.c = null; - active.timer.t = NaN; - --lock.count; - delete lock[activeId]; - active.event && active.event.interrupt.call(node, node.__data__, active.index); - } - for (var cancelId in lock) { - if (+cancelId < id) { - var cancel = lock[cancelId]; - cancel.timer.c = null; - cancel.timer.t = NaN; - --lock.count; - delete lock[cancelId]; - } - } - timer.c = tick; - d3_timer(function() { - if (timer.c && tick(elapsed || 1)) { - timer.c = null; - timer.t = NaN; - } - return 1; - }, 0, time); - lock.active = id; - transition.event && transition.event.start.call(node, node.__data__, i); - tweens = []; - transition.tween.forEach(function(key, value) { - if (value = value.call(node, node.__data__, i)) { - tweens.push(value); - } - }); - ease = transition.ease; - duration = transition.duration; - } - function tick(elapsed) { - var t = elapsed / duration, e = ease(t), n = tweens.length; - while (n > 0) { - tweens[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, node.__data__, i); - if (--lock.count) delete lock[id]; else delete node[ns]; - return 1; - } - } - if (!transition) { - time = inherit.time; - timer = d3_timer(schedule, 0, time); - transition = lock[id] = { - tween: new d3_Map(), - time: time, - timer: timer, - delay: inherit.delay, - duration: inherit.duration, - ease: inherit.ease, - index: i - }; - inherit = null; - ++lock.count; - } - } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; - if (orient === "bottom" || orient === "top") { - tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; - text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); - } else { - tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; - text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); - pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); - } - lineEnter.attr(y2, sign * innerTickSize); - textEnter.attr(y1, sign * tickSpacing); - lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); - textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1, scale0); - } - tickEnter.call(tickTransform, scale0, scale1); - tickUpdate.call(tickTransform, scale1, scale1); - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = d3_array(arguments); - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; - }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; - }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function() { - return arguments.length && axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x0, x1) { - selection.attr("transform", function(d) { - var v0 = x0(d); - return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; - }); - } - function d3_svg_axisY(selection, y0, y1) { - selection.attr("transform", function(d) { - var v0 = y0(d); - return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; - }); - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } - } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; - } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; - } else { - max = position; - } - } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; - } - } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } - } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; - }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; - }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; - }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; - }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; - }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; - } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; - } - } : interval)); - }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); - } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); - }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; - }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; - }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; -}(); \ No newline at end of file diff --git a/web/js/dc.js b/web/js/dc.js deleted file mode 100644 index 31d92324f8..0000000000 --- a/web/js/dc.js +++ /dev/null @@ -1,10850 +0,0 @@ -/*! - * dc 2.1.0-dev - * http://dc-js.github.io/dc.js/ - * Copyright 2012-2016 Nick Zhu & the dc.js Developers - * https://github.com/dc-js/dc.js/blob/master/AUTHORS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function() { function _dc(d3, crossfilter) { -'use strict'; - -/** - * The entire dc.js library is scoped under the **dc** name space. It does not introduce - * anything else into the global name space. - * - * Most `dc` functions are designed to allow function chaining, meaning they return the current chart - * instance whenever it is appropriate. The getter forms of functions do not participate in function - * chaining because they return values that are not the chart, although some, - * such as {@link dc.baseMixin#svg .svg} and {@link dc.coordinateGridMixin#xAxis .xAxis}, - * return values that are themselves chainable d3 objects. - * @namespace dc - * @version 2.1.0-dev - * @example - * // Example chaining - * chart.width(300) - * .height(300) - * .filter('sunday'); - */ -/*jshint -W079*/ -var dc = { - version: '2.1.0-dev', - constants: { - CHART_CLASS: 'dc-chart', - DEBUG_GROUP_CLASS: 'debug', - STACK_CLASS: 'stack', - DESELECTED_CLASS: 'deselected', - SELECTED_CLASS: 'selected', - NODE_INDEX_NAME: '__index__', - GROUP_INDEX_NAME: '__group_index__', - DEFAULT_CHART_GROUP: '__default_chart_group__', - EVENT_DELAY: 40, - NEGLIGIBLE_NUMBER: 1e-10 - }, - _renderlet: null -}; -/*jshint +W079*/ - -/** - * The dc.chartRegistry object maintains sets of all instantiated dc.js charts under named groups - * and the default group. - * - * A chart group often corresponds to a crossfilter instance. It specifies - * the set of charts which should be updated when a filter changes on one of the charts or when the - * global functions {@link dc.filterAll dc.filterAll}, {@link dc.refocusAll dc.refocusAll}, - * {@link dc.renderAll dc.renderAll}, {@link dc.redrawAll dc.redrawAll}, or chart functions - * {@link dc.baseMixin#renderGroup baseMixin.renderGroup}, - * {@link dc.baseMixin#redrawGroup baseMixin.redrawGroup} are called. - * - * @namespace chartRegistry - * @memberof dc - * @type {{has, register, deregister, clear, list}} - */ -dc.chartRegistry = (function () { - // chartGroup:string => charts:array - var _chartMap = {}; - - function initializeChartGroup (group) { - if (!group) { - group = dc.constants.DEFAULT_CHART_GROUP; - } - - if (!_chartMap[group]) { - _chartMap[group] = []; - } - - return group; - } - - return { - /** - * Determine if a given chart instance resides in any group in the registry. - * @method has - * @memberof dc.chartRegistry - * @param {Object} chart dc.js chart instance - * @returns {Boolean} - */ - has: function (chart) { - for (var e in _chartMap) { - if (_chartMap[e].indexOf(chart) >= 0) { - return true; - } - } - return false; - }, - - /** - * Add given chart instance to the given group, creating the group if necessary. - * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. - * @method register - * @memberof dc.chartRegistry - * @param {Object} chart dc.js chart instance - * @param {String} [group] Group name - */ - register: function (chart, group) { - group = initializeChartGroup(group); - _chartMap[group].push(chart); - }, - - /** - * Remove given chart instance from the given group, creating the group if necessary. - * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. - * @method deregister - * @memberof dc.chartRegistry - * @param {Object} chart dc.js chart instance - * @param {String} [group] Group name - */ - deregister: function (chart, group) { - group = initializeChartGroup(group); - for (var i = 0; i < _chartMap[group].length; i++) { - if (_chartMap[group][i].anchorName() === chart.anchorName()) { - _chartMap[group].splice(i, 1); - break; - } - } - }, - - /** - * Clear given group if one is provided, otherwise clears all groups. - * @method clear - * @memberof dc.chartRegistry - * @param {String} group Group name - */ - clear: function (group) { - if (group) { - delete _chartMap[group]; - } else { - _chartMap = {}; - } - }, - - /** - * Get an array of each chart instance in the given group. - * If no group is provided, the charts in the default group are returned. - * @method list - * @memberof dc.chartRegistry - * @param {String} [group] Group name - * @returns {Array} - */ - list: function (group) { - group = initializeChartGroup(group); - return _chartMap[group]; - } - }; -})(); - -/** - * Add given chart instance to the given group, creating the group if necessary. - * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. - * @memberof dc - * @method registerChart - * @param {Object} chart dc.js chart instance - * @param {String} [group] Group name - */ -dc.registerChart = function (chart, group) { - dc.chartRegistry.register(chart, group); -}; - -/** - * Remove given chart instance from the given group, creating the group if necessary. - * If no group is provided, the default group `dc.constants.DEFAULT_CHART_GROUP` will be used. - * @memberof dc - * @method deregisterChart - * @param {Object} chart dc.js chart instance - * @param {String} [group] Group name - */ -dc.deregisterChart = function (chart, group) { - dc.chartRegistry.deregister(chart, group); -}; - -/** - * Determine if a given chart instance resides in any group in the registry. - * @memberof dc - * @method hasChart - * @param {Object} chart dc.js chart instance - * @returns {Boolean} - */ -dc.hasChart = function (chart) { - return dc.chartRegistry.has(chart); -}; - -/** - * Clear given group if one is provided, otherwise clears all groups. - * @memberof dc - * @method deregisterAllCharts - * @param {String} group Group name - */ -dc.deregisterAllCharts = function (group) { - dc.chartRegistry.clear(group); -}; - -/** - * Clear all filters on all charts within the given chart group. If the chart group is not given then - * only charts that belong to the default chart group will be reset. - * @memberof dc - * @method filterAll - * @param {String} [group] - */ -dc.filterAll = function (group) { - var charts = dc.chartRegistry.list(group); - for (var i = 0; i < charts.length; ++i) { - charts[i].filterAll(); - } -}; - -/** - * Reset zoom level / focus on all charts that belong to the given chart group. If the chart group is - * not given then only charts that belong to the default chart group will be reset. - * @memberof dc - * @method refocusAll - * @param {String} [group] - */ -dc.refocusAll = function (group) { - var charts = dc.chartRegistry.list(group); - for (var i = 0; i < charts.length; ++i) { - if (charts[i].focus) { - charts[i].focus(); - } - } -}; - -/** - * Re-render all charts belong to the given chart group. If the chart group is not given then only - * charts that belong to the default chart group will be re-rendered. - * @memberof dc - * @method renderAll - * @param {String} [group] - */ -dc.renderAll = function (group) { - var charts = dc.chartRegistry.list(group); - for (var i = 0; i < charts.length; ++i) { - charts[i].render(); - } - - if (dc._renderlet !== null) { - dc._renderlet(group); - } -}; - -/** - * Redraw all charts belong to the given chart group. If the chart group is not given then only charts - * that belong to the default chart group will be re-drawn. Redraw is different from re-render since - * when redrawing dc tries to update the graphic incrementally, using transitions, instead of starting - * from scratch. - * @memberof dc - * @method redrawAll - * @param {String} [group] - */ -dc.redrawAll = function (group) { - var charts = dc.chartRegistry.list(group); - for (var i = 0; i < charts.length; ++i) { - charts[i].redraw(); - } - - if (dc._renderlet !== null) { - dc._renderlet(group); - } -}; - -/** - * If this boolean is set truthy, all transitions will be disabled, and changes to the charts will happen - * immediately - * @memberof dc - * @method disableTransitions - * @type {Boolean} - * @default false - */ -dc.disableTransitions = false; - -dc.transition = function (selections, duration, callback, name) { - if (duration <= 0 || duration === undefined || dc.disableTransitions) { - return selections; - } - - var s = selections - .transition(name) - .duration(duration); - - if (typeof(callback) === 'function') { - callback(s); - } - - return s; -}; - -/* somewhat silly, but to avoid duplicating logic */ -dc.optionalTransition = function (enable, duration, callback, name) { - if (enable) { - return function (selection) { - return dc.transition(selection, duration, callback, name); - }; - } else { - return function (selection) { - return selection; - }; - } -}; - -// See http://stackoverflow.com/a/20773846 -dc.afterTransition = function (transition, callback) { - if (transition.empty() || !transition.duration) { - callback.call(transition); - } else { - var n = 0; - transition - .each(function () { ++n; }) - .each('end', function () { - if (!--n) { - callback.call(transition); - } - }); - } -}; - -/** - * @namespace units - * @memberof dc - * @type {{}} - */ -dc.units = {}; - -/** - * The default value for {@link dc.coordinateGridMixin#xUnits .xUnits} for the - * {@link dc.coordinateGridMixin Coordinate Grid Chart} and should - * be used when the x values are a sequence of integers. - * It is a function that counts the number of integers in the range supplied in its start and end parameters. - * @method integers - * @memberof dc.units - * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits} - * @example - * chart.xUnits(dc.units.integers) // already the default - * @param {Number} start - * @param {Number} end - * @return {Number} - */ -dc.units.integers = function (start, end) { - return Math.abs(end - start); -}; - -/** - * This argument can be passed to the {@link dc.coordinateGridMixin#xUnits .xUnits} function of the to - * specify ordinal units for the x axis. Usually this parameter is used in combination with passing - * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales d3.scale.ordinal} to - * {@link dc.coordinateGridMixin#x .x}. - * It just returns the domain passed to it, which for ordinal charts is an array of all values. - * @method ordinal - * @memberof dc.units - * @see {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales d3.scale.ordinal} - * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits} - * @see {@link dc.coordinateGridMixin#x coordinateGridMixin.x} - * @example - * chart.xUnits(dc.units.ordinal) - * .x(d3.scale.ordinal()) - * @param {*} start - * @param {*} end - * @param {Array} domain - * @return {Array} - */ -dc.units.ordinal = function (start, end, domain) { - return domain; -}; - -/** - * @namespace fp - * @memberof dc.units - * @type {{}} - */ -dc.units.fp = {}; -/** - * This function generates an argument for the {@link dc.coordinateGridMixin Coordinate Grid Chart} - * {@link dc.coordinateGridMixin#xUnits .xUnits} function specifying that the x values are floating-point - * numbers with the given precision. - * The returned function determines how many values at the given precision will fit into the range - * supplied in its start and end parameters. - * @method precision - * @memberof dc.units.fp - * @see {@link dc.coordinateGridMixin#xUnits coordinateGridMixin.xUnits} - * @example - * // specify values (and ticks) every 0.1 units - * chart.xUnits(dc.units.fp.precision(0.1) - * // there are 500 units between 0.5 and 1 if the precision is 0.001 - * var thousandths = dc.units.fp.precision(0.001); - * thousandths(0.5, 1.0) // returns 500 - * @param {Number} precision - * @return {Function} start-end unit function - */ -dc.units.fp.precision = function (precision) { - var _f = function (s, e) { - var d = Math.abs((e - s) / _f.resolution); - if (dc.utils.isNegligible(d - Math.floor(d))) { - return Math.floor(d); - } else { - return Math.ceil(d); - } - }; - _f.resolution = precision; - return _f; -}; - -dc.round = {}; -dc.round.floor = function (n) { - return Math.floor(n); -}; -dc.round.ceil = function (n) { - return Math.ceil(n); -}; -dc.round.round = function (n) { - return Math.round(n); -}; - -dc.override = function (obj, functionName, newFunction) { - var existingFunction = obj[functionName]; - obj['_' + functionName] = existingFunction; - obj[functionName] = newFunction; -}; - -dc.renderlet = function (_) { - if (!arguments.length) { - return dc._renderlet; - } - dc._renderlet = _; - return dc; -}; - -dc.instanceOfChart = function (o) { - return o instanceof Object && o.__dcFlag__ && true; -}; - -dc.errors = {}; - -dc.errors.Exception = function (msg) { - var _msg = msg || 'Unexpected internal error'; - - this.message = _msg; - - this.toString = function () { - return _msg; - }; - this.stack = (new Error()).stack; -}; -dc.errors.Exception.prototype = Object.create(Error.prototype); -dc.errors.Exception.prototype.constructor = dc.errors.Exception; - -dc.errors.InvalidStateException = function () { - dc.errors.Exception.apply(this, arguments); -}; - -dc.errors.InvalidStateException.prototype = Object.create(dc.errors.Exception.prototype); -dc.errors.InvalidStateException.prototype.constructor = dc.errors.InvalidStateException; - -dc.errors.BadArgumentException = function () { - dc.errors.Exception.apply(this, arguments); -}; - -dc.errors.BadArgumentException.prototype = Object.create(dc.errors.Exception.prototype); -dc.errors.BadArgumentException.prototype.constructor = dc.errors.BadArgumentException; - -/** - * The default date format for dc.js - * @name dateFormat - * @memberof dc - * @type {Function} - * @default d3.time.format('%m/%d/%Y') - */ -dc.dateFormat = d3.time.format('%m/%d/%Y'); - -/** - * @namespace printers - * @memberof dc - * @type {{}} - */ -dc.printers = {}; - -/** - * Converts a list of filters into a readable string - * @method filters - * @memberof dc.printers - * @param {Array} filters - * @returns {String} - */ -dc.printers.filters = function (filters) { - var s = ''; - - for (var i = 0; i < filters.length; ++i) { - if (i > 0) { - s += ', '; - } - s += dc.printers.filter(filters[i]); - } - - return s; -}; - -/** - * Converts a filter into a readable string - * @method filter - * @memberof dc.printers - * @param {dc.filters|any|Array} filter - * @returns {String} - */ -dc.printers.filter = function (filter) { - var s = ''; - - if (typeof filter !== 'undefined' && filter !== null) { - if (filter instanceof Array) { - if (filter.length >= 2) { - s = '[' + dc.utils.printSingleValue(filter[0]) + ' -> ' + dc.utils.printSingleValue(filter[1]) + ']'; - } else if (filter.length >= 1) { - s = dc.utils.printSingleValue(filter[0]); - } - } else { - s = dc.utils.printSingleValue(filter); - } - } - - return s; -}; - -/** - * Returns a function that given a string property name, can be used to pluck the property off an object. A function - * can be passed as the second argument to also alter the data being returned. This can be a useful shorthand method to create - * accessor functions. - * @method pluck - * @memberof dc - * @example - * var xPluck = dc.pluck('x'); - * var objA = {x: 1}; - * xPluck(objA) // 1 - * @example - * var xPosition = dc.pluck('x', function (x, i) { - * // `this` is the original datum, - * // `x` is the x property of the datum, - * // `i` is the position in the array - * return this.radius + x; - * }); - * dc.selectAll('.circle').data(...).x(xPosition); - * @param {String} n - * @param {Function} [f] - * @returns {Function} - */ -dc.pluck = function (n, f) { - if (!f) { - return function (d) { return d[n]; }; - } - return function (d, i) { return f.call(d, d[n], i); }; -}; - -/** - * @namespace utils - * @memberof dc - * @type {{}} - */ -dc.utils = {}; - -/** - * Print a single value filter - * @method printSingleValue - * @memberof dc.utils - * @param {any} filter - * @returns {String} - */ -dc.utils.printSingleValue = function (filter) { - var s = '' + filter; - - if (filter instanceof Date) { - s = dc.dateFormat(filter); - } else if (typeof(filter) === 'string') { - s = filter; - } else if (dc.utils.isFloat(filter)) { - s = dc.utils.printSingleValue.fformat(filter); - } else if (dc.utils.isInteger(filter)) { - s = Math.round(filter); - } - - return s; -}; -dc.utils.printSingleValue.fformat = d3.format('.2f'); - -/** - * Arbitrary add one value to another. - * @method add - * @memberof dc.utils - * @todo - * These assume than any string r is a percentage (whether or not it includes %). - * They also generate strange results if l is a string. - * @param {String|Date|Number} l - * @param {Number} r - * @returns {String|Date|Number} - */ -dc.utils.add = function (l, r) { - if (typeof r === 'string') { - r = r.replace('%', ''); - } - - if (l instanceof Date) { - if (typeof r === 'string') { - r = +r; - } - var d = new Date(); - d.setTime(l.getTime()); - d.setDate(l.getDate() + r); - return d; - } else if (typeof r === 'string') { - var percentage = (+r / 100); - return l > 0 ? l * (1 + percentage) : l * (1 - percentage); - } else { - return l + r; - } -}; - -/** - * Arbitrary subtract one value from another. - * @method subtract - * @memberof dc.utils - * @todo - * These assume than any string r is a percentage (whether or not it includes %). - * They also generate strange results if l is a string. - * @param {String|Date|Number} l - * @param {Number} r - * @returns {String|Date|Number} - */ -dc.utils.subtract = function (l, r) { - if (typeof r === 'string') { - r = r.replace('%', ''); - } - - if (l instanceof Date) { - if (typeof r === 'string') { - r = +r; - } - var d = new Date(); - d.setTime(l.getTime()); - d.setDate(l.getDate() - r); - return d; - } else if (typeof r === 'string') { - var percentage = (+r / 100); - return l < 0 ? l * (1 + percentage) : l * (1 - percentage); - } else { - return l - r; - } -}; - -/** - * Is the value a number? - * @method isNumber - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isNumber = function (n) { - return n === +n; -}; - -/** - * Is the value a float? - * @method isFloat - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isFloat = function (n) { - return n === +n && n !== (n | 0); -}; - -/** - * Is the value an integer? - * @method isInteger - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isInteger = function (n) { - return n === +n && n === (n | 0); -}; - -/** - * Is the value very close to zero? - * @method isNegligible - * @memberof dc.utils - * @param {any} n - * @returns {Boolean} - */ -dc.utils.isNegligible = function (n) { - return !dc.utils.isNumber(n) || (n < dc.constants.NEGLIGIBLE_NUMBER && n > -dc.constants.NEGLIGIBLE_NUMBER); -}; - -/** - * Ensure the value is no greater or less than the min/max values. If it is return the boundary value. - * @method clamp - * @memberof dc.utils - * @param {any} val - * @param {any} min - * @param {any} max - * @returns {any} - */ -dc.utils.clamp = function (val, min, max) { - return val < min ? min : (val > max ? max : val); -}; - -/** - * Using a simple static counter, provide a unique integer id. - * @method uniqueId - * @memberof dc.utils - * @returns {Number} - */ -var _idCounter = 0; -dc.utils.uniqueId = function () { - return ++_idCounter; -}; - -/** - * Convert a name to an ID. - * @method nameToId - * @memberof dc.utils - * @param {String} name - * @returns {String} - */ -dc.utils.nameToId = function (name) { - return name.toLowerCase().replace(/[\s]/g, '_').replace(/[\.']/g, ''); -}; - -/** - * Append or select an item on a parent element - * @method appendOrSelect - * @memberof dc.utils - * @param {d3.selection} parent - * @param {String} selector - * @param {String} tag - * @returns {d3.selection} - */ -dc.utils.appendOrSelect = function (parent, selector, tag) { - tag = tag || selector; - var element = parent.select(selector); - if (element.empty()) { - element = parent.append(tag); - } - return element; -}; - -/** - * Return the number if the value is a number; else 0. - * @method safeNumber - * @memberof dc.utils - * @param {Number|any} n - * @returns {Number} - */ -dc.utils.safeNumber = function (n) { return dc.utils.isNumber(+n) ? +n : 0;}; - -dc.logger = {}; - -dc.logger.enableDebugLog = false; - -dc.logger.warn = function (msg) { - if (console) { - if (console.warn) { - console.warn(msg); - } else if (console.log) { - console.log(msg); - } - } - - return dc.logger; -}; - -dc.logger.debug = function (msg) { - if (dc.logger.enableDebugLog && console) { - if (console.debug) { - console.debug(msg); - } else if (console.log) { - console.log(msg); - } - } - - return dc.logger; -}; - -dc.logger.deprecate = function (fn, msg) { - // Allow logging of deprecation - var warned = false; - function deprecated () { - if (!warned) { - dc.logger.warn(msg); - warned = true; - } - return fn.apply(this, arguments); - } - return deprecated; -}; - -dc.events = { - current: null -}; - -/** - * This function triggers a throttled event function with a specified delay (in milli-seconds). Events - * that are triggered repetitively due to user interaction such brush dragging might flood the library - * and invoke more renders than can be executed in time. Using this function to wrap your event - * function allows the library to smooth out the rendering by throttling events and only responding to - * the most recent event. - * @name events.trigger - * @memberof dc - * @example - * chart.on('renderlet', function(chart) { - * // smooth the rendering through event throttling - * dc.events.trigger(function(){ - * // focus some other chart to the range selected by user on this chart - * someOtherChart.focus(chart.filter()); - * }); - * }) - * @param {Function} closure - * @param {Number} [delay] - */ -dc.events.trigger = function (closure, delay) { - if (!delay) { - closure(); - return; - } - - dc.events.current = closure; - - setTimeout(function () { - if (closure === dc.events.current) { - closure(); - } - }, delay); -}; - -/** - * The dc.js filters are functions which are passed into crossfilter to chose which records will be - * accumulated to produce values for the charts. In the crossfilter model, any filters applied on one - * dimension will affect all the other dimensions but not that one. dc always applies a filter - * function to the dimension; the function combines multiple filters and if any of them accept a - * record, it is filtered in. - * - * These filter constructors are used as appropriate by the various charts to implement brushing. We - * mention below which chart uses which filter. In some cases, many instances of a filter will be added. - * - * Each of the dc.js filters is an object with the following properties: - * * `isFiltered` - a function that returns true if a value is within the filter - * * `filterType` - a string identifying the filter, here the name of the constructor - * - * Currently these filter objects are also arrays, but this is not a requirement. Custom filters - * can be used as long as they have the properties above. - * @namespace filters - * @memberof dc - * @type {{}} - */ -dc.filters = {}; - -/** - * RangedFilter is a filter which accepts keys between `low` and `high`. It is used to implement X - * axis brushing for the {@link dc.coordinateGridMixin coordinate grid charts}. - * - * Its `filterType` is 'RangedFilter' - * @name RangedFilter - * @memberof dc.filters - * @param {Number} low - * @param {Number} high - * @return {Array} - * @constructor - */ -dc.filters.RangedFilter = function (low, high) { - var range = new Array(low, high); - range.isFiltered = function (value) { - return value >= this[0] && value < this[1]; - }; - range.filterType = 'RangedFilter'; - - return range; -}; - -/** - * TwoDimensionalFilter is a filter which accepts a single two-dimensional value. It is used by the - * {@link dc.heatMap heat map chart} to include particular cells as they are clicked. (Rows and columns are - * filtered by filtering all the cells in the row or column.) - * - * Its `filterType` is 'TwoDimensionalFilter' - * @name TwoDimensionalFilter - * @memberof dc.filters - * @param {Array} filter - * @return {Array} - * @constructor - */ -dc.filters.TwoDimensionalFilter = function (filter) { - if (filter === null) { return null; } - - var f = filter; - f.isFiltered = function (value) { - return value.length && value.length === f.length && - value[0] === f[0] && value[1] === f[1]; - }; - f.filterType = 'TwoDimensionalFilter'; - - return f; -}; - -/** - * The RangedTwoDimensionalFilter allows filtering all values which fit within a rectangular - * region. It is used by the {@link dc.scatterPlot scatter plot} to implement rectangular brushing. - * - * It takes two two-dimensional points in the form `[[x1,y1],[x2,y2]]`, and normalizes them so that - * `x1 <= x2` and `y1 <= y2`. It then returns a filter which accepts any points which are in the - * rectangular range including the lower values but excluding the higher values. - * - * If an array of two values are given to the RangedTwoDimensionalFilter, it interprets the values as - * two x coordinates `x1` and `x2` and returns a filter which accepts any points for which `x1 <= x < - * x2`. - * - * Its `filterType` is 'RangedTwoDimensionalFilter' - * @name RangedTwoDimensionalFilter - * @memberof dc.filters - * @param {Array>} filter - * @return {Array>} - * @constructor - */ -dc.filters.RangedTwoDimensionalFilter = function (filter) { - if (filter === null) { return null; } - - var f = filter; - var fromBottomLeft; - - if (f[0] instanceof Array) { - fromBottomLeft = [ - [Math.min(filter[0][0], filter[1][0]), Math.min(filter[0][1], filter[1][1])], - [Math.max(filter[0][0], filter[1][0]), Math.max(filter[0][1], filter[1][1])] - ]; - } else { - fromBottomLeft = [[filter[0], -Infinity], [filter[1], Infinity]]; - } - - f.isFiltered = function (value) { - var x, y; - - if (value instanceof Array) { - if (value.length !== 2) { - return false; - } - x = value[0]; - y = value[1]; - } else { - x = value; - y = fromBottomLeft[0][1]; - } - - return x >= fromBottomLeft[0][0] && x < fromBottomLeft[1][0] && - y >= fromBottomLeft[0][1] && y < fromBottomLeft[1][1]; - }; - f.filterType = 'RangedTwoDimensionalFilter'; - - return f; -}; - -/** - * `dc.baseMixin` is an abstract functional object representing a basic `dc` chart object - * for all chart and widget implementations. Methods from the {@link #dc.baseMixin dc.baseMixin} are inherited - * and available on all chart implementations in the `dc` library. - * @name baseMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.baseMixin} - */ -dc.baseMixin = function (_chart) { - _chart.__dcFlag__ = dc.utils.uniqueId(); - - var _dimension; - var _group; - - var _anchor; - var _root; - var _svg; - var _isChild; - - var _minWidth = 200; - var _defaultWidthCalc = function (element) { - var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; - return (width && width > _minWidth) ? width : _minWidth; - }; - var _widthCalc = _defaultWidthCalc; - - var _minHeight = 200; - var _defaultHeightCalc = function (element) { - var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; - return (height && height > _minHeight) ? height : _minHeight; - }; - var _heightCalc = _defaultHeightCalc; - var _width, _height; - - var _keyAccessor = dc.pluck('key'); - var _valueAccessor = dc.pluck('value'); - var _label = dc.pluck('key'); - - var _ordering = dc.pluck('key'); - var _orderSort; - - var _renderLabel = false; - - var _title = function (d) { - return _chart.keyAccessor()(d) + ': ' + _chart.valueAccessor()(d); - }; - var _renderTitle = true; - var _controlsUseVisibility = false; - - var _transitionDuration = 750; - - var _filterPrinter = dc.printers.filters; - - var _mandatoryAttributes = ['dimension', 'group']; - - var _chartGroup = dc.constants.DEFAULT_CHART_GROUP; - - var _listeners = d3.dispatch( - 'preRender', - 'postRender', - 'preRedraw', - 'postRedraw', - 'filtered', - 'zoomed', - 'renderlet', - 'pretransition'); - - var _legend; - var _commitHandler; - - var _filters = []; - var _filterHandler = function (dimension, filters) { - if (filters.length === 0) { - dimension.filter(null); - } else if (filters.length === 1 && !filters[0].isFiltered) { - // single value and not a function-based filter - dimension.filterExact(filters[0]); - } else if (filters.length === 1 && filters[0].filterType === 'RangedFilter') { - // single range-based filter - dimension.filterRange(filters[0]); - } else { - dimension.filterFunction(function (d) { - for (var i = 0; i < filters.length; i++) { - var filter = filters[i]; - if (filter.isFiltered && filter.isFiltered(d)) { - return true; - } else if (filter <= d && filter >= d) { - return true; - } - } - return false; - }); - } - return filters; - }; - - var _data = function (group) { - return group.all(); - }; - - /** - * Set or get the height attribute of a chart. The height is applied to the SVGElement generated by - * the chart when rendered (or re-rendered). If a value is given, then it will be used to calculate - * the new height and the chart returned for method chaining. The value can either be a numeric, a - * function, or falsy. If no value is specified then the value of the current height attribute will - * be returned. - * - * By default, without an explicit height being given, the chart will select the width of its - * anchor element. If that isn't possible it defaults to 200 (provided by the - * {@link dc.baseMixin#minHeight minHeight} property). Setting the value falsy will return - * the chart to the default behavior. - * @method height - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#minHeight minHeight} - * @example - * // Default height - * chart.height(function (element) { - * var height = element && element.getBoundingClientRect && element.getBoundingClientRect().height; - * return (height && height > chart.minHeight()) ? height : chart.minHeight(); - * }); - * - * chart.height(250); // Set the chart's height to 250px; - * chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function - * chart.height(null); // reset the height to the default auto calculation - * @param {Number|Function} [height] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.height = function (height) { - if (!arguments.length) { - if (!dc.utils.isNumber(_height)) { - // only calculate once - _height = _heightCalc(_root.node()); - } - return _height; - } - _heightCalc = d3.functor(height || _defaultHeightCalc); - _height = undefined; - return _chart; - }; - - /** - * Set or get the width attribute of a chart. - * @method width - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#height height} - * @see {@link dc.baseMixin#minWidth minWidth} - * @example - * // Default width - * chart.width(function (element) { - * var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width; - * return (width && width > chart.minWidth()) ? width : chart.minWidth(); - * }); - * @param {Number|Function} [width] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.width = function (width) { - if (!arguments.length) { - if (!dc.utils.isNumber(_width)) { - // only calculate once - _width = _widthCalc(_root.node()); - } - return _width; - } - _widthCalc = d3.functor(width || _defaultWidthCalc); - _width = undefined; - return _chart; - }; - - /** - * Set or get the minimum width attribute of a chart. This only has effect when used with the default - * {@link dc.baseMixin#width width} function. - * @method minWidth - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#width width} - * @param {Number} [minWidth=200] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.minWidth = function (minWidth) { - if (!arguments.length) { - return _minWidth; - } - _minWidth = minWidth; - return _chart; - }; - - /** - * Set or get the minimum height attribute of a chart. This only has effect when used with the default - * {@link dc.baseMixin#height height} function. - * @method minHeight - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#height height} - * @param {Number} [minHeight=200] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.minHeight = function (minHeight) { - if (!arguments.length) { - return _minHeight; - } - _minHeight = minHeight; - return _chart; - }; - - /** - * **mandatory** - * - * Set or get the dimension attribute of a chart. In `dc`, a dimension can be any valid [crossfilter - * dimension](https://github.com/square/crossfilter/wiki/API-Reference#wiki-dimension). - * - * If a value is given, then it will be used as the new dimension. If no value is specified then - * the current dimension will be returned. - * @method dimension - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension crossfilter.dimension} - * @example - * var index = crossfilter([]); - * var dimension = index.dimension(dc.pluck('key')); - * chart.dimension(dimension); - * @param {crossfilter.dimension} [dimension] - * @return {crossfilter.dimension} - * @return {dc.baseMixin} - */ - _chart.dimension = function (dimension) { - if (!arguments.length) { - return _dimension; - } - _dimension = dimension; - _chart.expireCache(); - return _chart; - }; - - /** - * Set the data callback or retrieve the chart's data set. The data callback is passed the chart's - * group and by default will return - * {@link https://github.com/square/crossfilter/wiki/API-Reference#group_all group.all}. - * This behavior may be modified to, for instance, return only the top 5 groups. - * @method data - * @memberof dc.baseMixin - * @instance - * @example - * // Default data function - * chart.data(function (group) { return group.all(); }); - * - * chart.data(function (group) { return group.top(5); }); - * @param {Function} [callback] - * @return {*} - * @return {dc.baseMixin} - */ - _chart.data = function (callback) { - if (!arguments.length) { - return _data.call(_chart, _group); - } - _data = d3.functor(callback); - _chart.expireCache(); - return _chart; - }; - - /** - * **mandatory** - * - * Set or get the group attribute of a chart. In `dc` a group is a - * {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter group}. - * Usually the group should be created from the particular dimension associated with the same chart. If a value is - * given, then it will be used as the new group. - * - * If no value specified then the current group will be returned. - * If `name` is specified then it will be used to generate legend label. - * @method group - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} - * @example - * var index = crossfilter([]); - * var dimension = index.dimension(dc.pluck('key')); - * chart.dimension(dimension); - * chart.group(dimension.group(crossfilter.reduceSum())); - * @param {crossfilter.group} [group] - * @param {String} [name] - * @return {crossfilter.group} - * @return {dc.baseMixin} - */ - _chart.group = function (group, name) { - if (!arguments.length) { - return _group; - } - _group = group; - _chart._groupName = name; - _chart.expireCache(); - return _chart; - }; - - /** - * Get or set an accessor to order ordinal dimensions. The chart uses - * {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by} - * to sort elements; this accessor returns the value to order on. - * @method ordering - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#quicksort_by crossfilter.quicksort.by} - * @example - * // Default ordering accessor - * _chart.ordering(dc.pluck('key')); - * @param {Function} [orderFunction] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.ordering = function (orderFunction) { - if (!arguments.length) { - return _ordering; - } - _ordering = orderFunction; - _orderSort = crossfilter.quicksort.by(_ordering); - _chart.expireCache(); - return _chart; - }; - - _chart._computeOrderedGroups = function (data) { - var dataCopy = data.slice(0); - - if (dataCopy.length <= 1) { - return dataCopy; - } - - if (!_orderSort) { - _orderSort = crossfilter.quicksort.by(_ordering); - } - - return _orderSort(dataCopy, 0, dataCopy.length); - }; - - /** - * Clear all filters associated with this chart - * - * The same can be achieved by calling {@link dc.baseMixin#filter chart.filter(null)}. - * @method filterAll - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.filterAll = function () { - return _chart.filter(null); - }; - - /** - * Execute d3 single selection in the chart's scope using the given selector and return the d3 - * selection. - * - * This function is **not chainable** since it does not return a chart instance; however the d3 - * selection result can be chained to d3 function calls. - * @method select - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection} - * @example - * // Similar to: - * d3.select('#chart-id').select(selector); - * @return {d3.selection} - */ - _chart.select = function (s) { - return _root.select(s); - }; - - /** - * Execute in scope d3 selectAll using the given selector and return d3 selection result. - * - * This function is **not chainable** since it does not return a chart instance; however the d3 - * selection result can be chained to d3 function calls. - * @method selectAll - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Selections d3.selection} - * @example - * // Similar to: - * d3.select('#chart-id').selectAll(selector); - * @return {d3.selection} - */ - _chart.selectAll = function (s) { - return _root ? _root.selectAll(s) : null; - }; - - /** - * Set the root SVGElement to either be an existing chart's root; or any valid [d3 single - * selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying a dom - * block element such as a div; or a dom element or d3 selection. Optionally registers the chart - * within the chartGroup. This class is called internally on chart initialization, but be called - * again to relocate the chart. However, it will orphan any previously created SVGElements. - * @method anchor - * @memberof dc.baseMixin - * @instance - * @param {anchorChart|anchorSelector|anchorNode} [parent] - * @param {String} [chartGroup] - * @return {String|node|d3.selection} - * @return {dc.baseMixin} - */ - _chart.anchor = function (parent, chartGroup) { - if (!arguments.length) { - return _anchor; - } - if (dc.instanceOfChart(parent)) { - _anchor = parent.anchor(); - _root = parent.root(); - _isChild = true; - } else if (parent) { - if (parent.select && parent.classed) { // detect d3 selection - _anchor = parent.node(); - } else { - _anchor = parent; - } - _root = d3.select(_anchor); - _root.classed(dc.constants.CHART_CLASS, true); - dc.registerChart(_chart, chartGroup); - _isChild = false; - } else { - throw new dc.errors.BadArgumentException('parent must be defined'); - } - _chartGroup = chartGroup; - return _chart; - }; - - /** - * Returns the DOM id for the chart's anchored location. - * @method anchorName - * @memberof dc.baseMixin - * @instance - * @return {String} - */ - _chart.anchorName = function () { - var a = _chart.anchor(); - if (a && a.id) { - return a.id; - } - if (a && a.replace) { - return a.replace('#', ''); - } - return 'dc-chart' + _chart.chartID(); - }; - - /** - * Returns the root element where a chart resides. Usually it will be the parent div element where - * the SVGElement was created. You can also pass in a new root element however this is usually handled by - * dc internally. Resetting the root element on a chart outside of dc internals may have - * unexpected consequences. - * @method root - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement HTMLElement} - * @param {HTMLElement} [rootElement] - * @return {HTMLElement} - * @return {dc.baseMixin} - */ - _chart.root = function (rootElement) { - if (!arguments.length) { - return _root; - } - _root = rootElement; - return _chart; - }; - - /** - * Returns the top SVGElement for this specific chart. You can also pass in a new SVGElement, - * however this is usually handled by dc internally. Resetting the SVGElement on a chart outside - * of dc internals may have unexpected consequences. - * @method svg - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} - * @param {SVGElement|d3.selection} [svgElement] - * @return {SVGElement|d3.selection} - * @return {dc.baseMixin} - */ - _chart.svg = function (svgElement) { - if (!arguments.length) { - return _svg; - } - _svg = svgElement; - return _chart; - }; - - /** - * Remove the chart's SVGElements from the dom and recreate the container SVGElement. - * @method resetSvg - * @memberof dc.baseMixin - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SVGElement SVGElement} - * @return {SVGElement} - */ - _chart.resetSvg = function () { - _chart.select('svg').remove(); - return generateSvg(); - }; - - function sizeSvg () { - if (_svg) { - _svg - .attr('width', _chart.width()) - .attr('height', _chart.height()); - } - } - - function generateSvg () { - _svg = _chart.root().append('svg'); - sizeSvg(); - return _svg; - } - - /** - * Set or get the filter printer function. The filter printer function is used to generate human - * friendly text for filter value(s) associated with the chart instance. By default dc charts use a - * default filter printer `dc.printers.filter` that provides simple printing support for both - * single value and ranged filters. - * @method filterPrinter - * @memberof dc.baseMixin - * @instance - * @param {Function} [filterPrinterFunction=dc.printers.filter] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.filterPrinter = function (filterPrinterFunction) { - if (!arguments.length) { - return _filterPrinter; - } - _filterPrinter = filterPrinterFunction; - return _chart; - }; - - /** - * If set, use the `visibility` attribute instead of the `display` attribute for showing/hiding - * chart reset and filter controls, for less disruption to the layout. - * @method controlsUseVisibility - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [controlsUseVisibility=false] - * @return {Boolean} - * @return {dc.baseMixin} - **/ - _chart.controlsUseVisibility = function (useVisibility) { - if (!arguments.length) { - return _controlsUseVisibility; - } - _controlsUseVisibility = useVisibility; - return _chart; - }; - - /** - * Turn on optional control elements within the root element. dc currently supports the - * following html control elements. - * * root.selectAll('.reset') - elements are turned on if the chart has an active filter. This type - * of control element is usually used to store a reset link to allow user to reset filter on a - * certain chart. This element will be turned off automatically if the filter is cleared. - * * root.selectAll('.filter') elements are turned on if the chart has an active filter. The text - * content of this element is then replaced with the current filter value using the filter printer - * function. This type of element will be turned off automatically if the filter is cleared. - * @method turnOnControls - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.turnOnControls = function () { - if (_root) { - var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display'; - _chart.selectAll('.reset').style(attribute, null); - _chart.selectAll('.filter').text(_filterPrinter(_chart.filters())).style(attribute, null); - } - return _chart; - }; - - /** - * Turn off optional control elements within the root element. - * @method turnOffControls - * @memberof dc.baseMixin - * @see {@link dc.baseMixin#turnOnControls turnOnControls} - * @instance - * @return {dc.baseMixin} - */ - _chart.turnOffControls = function () { - if (_root) { - var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display'; - var value = _chart.controlsUseVisibility() ? 'hidden' : 'none'; - _chart.selectAll('.reset').style(attribute, value); - _chart.selectAll('.filter').style(attribute, value).text(_chart.filter()); - } - return _chart; - }; - - /** - * Set or get the animation transition duration (in milliseconds) for this chart instance. - * @method transitionDuration - * @memberof dc.baseMixin - * @instance - * @param {Number} [duration=750] - * @return {Number} - * @return {dc.baseMixin} - */ - _chart.transitionDuration = function (duration) { - if (!arguments.length) { - return _transitionDuration; - } - _transitionDuration = duration; - return _chart; - }; - - _chart._mandatoryAttributes = function (_) { - if (!arguments.length) { - return _mandatoryAttributes; - } - _mandatoryAttributes = _; - return _chart; - }; - - function checkForMandatoryAttributes (a) { - if (!_chart[a] || !_chart[a]()) { - throw new dc.errors.InvalidStateException('Mandatory attribute chart.' + a + - ' is missing on chart[#' + _chart.anchorName() + ']'); - } - } - - /** - * Invoking this method will force the chart to re-render everything from scratch. Generally it - * should only be used to render the chart for the first time on the page or if you want to make - * sure everything is redrawn from scratch instead of relying on the default incremental redrawing - * behaviour. - * @method render - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.render = function () { - _height = _width = undefined; // force recalculate - _listeners.preRender(_chart); - - if (_mandatoryAttributes) { - _mandatoryAttributes.forEach(checkForMandatoryAttributes); - } - - var result = _chart._doRender(); - - if (_legend) { - _legend.render(); - } - - _chart._activateRenderlets('postRender'); - - return result; - }; - - _chart._activateRenderlets = function (event) { - _listeners.pretransition(_chart); - if (_chart.transitionDuration() > 0 && _svg) { - _svg.transition().duration(_chart.transitionDuration()) - .each('end', function () { - _listeners.renderlet(_chart); - if (event) { - _listeners[event](_chart); - } - }); - } else { - _listeners.renderlet(_chart); - if (event) { - _listeners[event](_chart); - } - } - }; - - /** - * Calling redraw will cause the chart to re-render data changes incrementally. If there is no - * change in the underlying data dimension then calling this method will have no effect on the - * chart. Most chart interaction in dc will automatically trigger this method through internal - * events (in particular {@link dc.redrawAll dc.redrawAll}); therefore, you only need to - * manually invoke this function if data is manipulated outside of dc's control (for example if - * data is loaded in the background using - * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add}. - * @method redraw - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.redraw = function () { - sizeSvg(); - _listeners.preRedraw(_chart); - - var result = _chart._doRedraw(); - - if (_legend) { - _legend.render(); - } - - _chart._activateRenderlets('postRedraw'); - - return result; - }; - - /** - * Gets/sets the commit handler. If the chart has a commit handler, the handler will be called when - * the chart's filters have changed, in order to send the filter data asynchronously to a server. - * - * Unlike other functions in dc.js, the commit handler is asynchronous. It takes two arguments: - * a flag indicating whether this is a render (true) or a redraw (false), and a callback to be - * triggered once the commit is filtered. The callback has the standard node.js continuation signature - * with error first and result second. - * @method commitHandler - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.commitHandler = function (commitHandler) { - if (!arguments.length) { - return _commitHandler; - } - _commitHandler = commitHandler; - return _chart; - }; - - /** - * Redraws all charts in the same group as this chart, typically in reaction to a filter - * change. If the chart has a {@link dc.baseMixin.commitFilter commitHandler}, it will - * be executed and waited for. - * @method redrawGroup - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.redrawGroup = function () { - if (_commitHandler) { - _commitHandler(false, function (error, result) { - if (error) { - console.log(error); - } else { - dc.redrawAll(_chart.chartGroup()); - } - }); - } else { - dc.redrawAll(_chart.chartGroup()); - } - return _chart; - }; - - /** - * Renders all charts in the same group as this chart. If the chart has a - * {@link dc.baseMixin.commitFilter commitHandler}, it will be executed and waited for - * @method renderGroup - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.renderGroup = function () { - if (_commitHandler) { - _commitHandler(false, function (error, result) { - if (error) { - console.log(error); - } else { - dc.renderAll(_chart.chartGroup()); - } - }); - } else { - dc.renderAll(_chart.chartGroup()); - } - return _chart; - }; - - _chart._invokeFilteredListener = function (f) { - if (f !== undefined) { - _listeners.filtered(_chart, f); - } - }; - - _chart._invokeZoomedListener = function () { - _listeners.zoomed(_chart); - }; - - var _hasFilterHandler = function (filters, filter) { - if (filter === null || typeof(filter) === 'undefined') { - return filters.length > 0; - } - return filters.some(function (f) { - return filter <= f && filter >= f; - }); - }; - - /** - * Set or get the has-filter handler. The has-filter handler is a function that checks to see if - * the chart's current filters (first argument) include a specific filter (second argument). Using a custom has-filter handler allows - * you to change the way filters are checked for and replaced. - * @method hasFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default has-filter handler - * chart.hasFilterHandler(function (filters, filter) { - * if (filter === null || typeof(filter) === 'undefined') { - * return filters.length > 0; - * } - * return filters.some(function (f) { - * return filter <= f && filter >= f; - * }); - * }); - * - * // custom filter handler (no-op) - * chart.hasFilterHandler(function(filters, filter) { - * return false; - * }); - * @param {Function} [hasFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.hasFilterHandler = function (hasFilterHandler) { - if (!arguments.length) { - return _hasFilterHandler; - } - _hasFilterHandler = hasFilterHandler; - return _chart; - }; - - /** - * Check whether any active filter or a specific filter is associated with particular chart instance. - * This function is **not chainable**. - * @method hasFilter - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#hasFilterHandler hasFilterHandler} - * @param {*} [filter] - * @return {Boolean} - */ - _chart.hasFilter = function (filter) { - return _hasFilterHandler(_filters, filter); - }; - - var _removeFilterHandler = function (filters, filter) { - for (var i = 0; i < filters.length; i++) { - if (filters[i] <= filter && filters[i] >= filter) { - filters.splice(i, 1); - break; - } - } - return filters; - }; - - /** - * Set or get the remove filter handler. The remove filter handler is a function that removes a - * filter from the chart's current filters. Using a custom remove filter handler allows you to - * change how filters are removed or perform additional work when removing a filter, e.g. when - * using a filter server other than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method removeFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default remove filter handler - * chart.removeFilterHandler(function (filters, filter) { - * for (var i = 0; i < filters.length; i++) { - * if (filters[i] <= filter && filters[i] >= filter) { - * filters.splice(i, 1); - * break; - * } - * } - * return filters; - * }); - * - * // custom filter handler (no-op) - * chart.removeFilterHandler(function(filters, filter) { - * return filters; - * }); - * @param {Function} [removeFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.removeFilterHandler = function (removeFilterHandler) { - if (!arguments.length) { - return _removeFilterHandler; - } - _removeFilterHandler = removeFilterHandler; - return _chart; - }; - - var _addFilterHandler = function (filters, filter) { - filters.push(filter); - return filters; - }; - - /** - * Set or get the add filter handler. The add filter handler is a function that adds a filter to - * the chart's filter list. Using a custom add filter handler allows you to change the way filters - * are added or perform additional work when adding a filter, e.g. when using a filter server other - * than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method addFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default add filter handler - * chart.addFilterHandler(function (filters, filter) { - * filters.push(filter); - * return filters; - * }); - * - * // custom filter handler (no-op) - * chart.addFilterHandler(function(filters, filter) { - * return filters; - * }); - * @param {Function} [addFilterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.addFilterHandler = function (addFilterHandler) { - if (!arguments.length) { - return _addFilterHandler; - } - _addFilterHandler = addFilterHandler; - return _chart; - }; - - var _resetFilterHandler = function (filters) { - return []; - }; - - /** - * Set or get the reset filter handler. The reset filter handler is a function that resets the - * chart's filter list by returning a new list. Using a custom reset filter handler allows you to - * change the way filters are reset, or perform additional work when resetting the filters, - * e.g. when using a filter server other than crossfilter. - * - * The handler should return a new or modified array as the result. - * @method resetFilterHandler - * @memberof dc.baseMixin - * @instance - * @example - * // default remove filter handler - * function (filters) { - * return []; - * } - * - * // custom filter handler (no-op) - * chart.resetFilterHandler(function(filters) { - * return filters; - * }); - * @param {Function} [resetFilterHandler] - * @return {dc.baseMixin} - */ - _chart.resetFilterHandler = function (resetFilterHandler) { - if (!arguments.length) { - return _resetFilterHandler; - } - _resetFilterHandler = resetFilterHandler; - return _chart; - }; - - function applyFilters (filters) { - if (_chart.dimension() && _chart.dimension().filter) { - var fs = _filterHandler(_chart.dimension(), filters); - if (fs) { - filters = fs; - } - } - return filters; - } - - /** - * Replace the chart filter. This is equivalent to calling `chart.filter(null).filter(filter)` - * - * @method replaceFilter - * @memberof dc.baseMixin - * @instance - * @param {*} [filter] - * @return {dc.baseMixin} - **/ - _chart.replaceFilter = function (filter) { - _filters = _resetFilterHandler(_filters); - _chart.filter(filter); - }; - - /** - * Filter the chart by the given parameter, or return the current filter if no input parameter - * is given. - * - * The filter parameter can take one of these forms: - * * A single value: the value will be toggled (added if it is not present in the current - * filters, removed if it is present) - * * An array containing a single array of values (`[[value,value,value]]`): each value is - * toggled - * * When appropriate for the chart, a {@link dc.filters dc filter object} such as - * * {@link dc.filters.RangedFilter `dc.filters.RangedFilter`} for the - * {@link dc.coordinateGridMixin dc.coordinateGridMixin} charts - * * {@link dc.filters.TwoDimensionalFilter `dc.filters.TwoDimensionalFilter`} for the - * {@link dc.heatMap heat map} - * * {@link dc.filters.RangedTwoDimensionalFilter `dc.filters.RangedTwoDimensionalFilter`} - * for the {@link dc.scatterPlot scatter plot} - * * `null`: the filter will be reset using the - * {@link dc.baseMixin#resetFilterHandler resetFilterHandler} - * - * Note that this is always a toggle (even when it doesn't make sense for the filter type). If - * you wish to replace the current filter, either call `chart.filter(null)` first, or - * equivalently, call {@link dc.baseMixin#replaceFilter `chart.replaceFilter(filter)`} instead. - * - * Each toggle is executed by checking if the value is already present using the - * {@link dc.baseMixin#hasFilterHandler hasFilterHandler}; if it is not present, it is added - * using the {@link dc.baseMixin#addFilterHandler addFilterHandler}; if it is already present, - * it is removed using the {@link dc.baseMixin#removeFilterHandler removeFilterHandler}. - * - * Once the filters array has been updated, the filters are applied to the - * crossfilter dimension, using the {@link dc.baseMixin#filterHandler filterHandler}. - * - * Once you have set the filters, call {@link dc.baseMixin#redrawGroup `chart.redrawGroup()`} - * (or {@link dc.redrawAll `dc.redrawAll()`}) to redraw the chart's group. - * @method filter - * @memberof dc.baseMixin - * @instance - * @see {@link dc.baseMixin#addFilterHandler addFilterHandler} - * @see {@link dc.baseMixin#removeFilterHandler removeFilterHandler} - * @see {@link dc.baseMixin#resetFilterHandler resetFilterHandler} - * @see {@link dc.baseMixin#filterHandler filterHandler} - * @example - * // filter by a single string - * chart.filter('Sunday'); - * // filter by a single age - * chart.filter(18); - * // filter by a set of states - * chart.filter([['MA', 'TX', 'ND', 'WA']]); - * // filter by range -- note the use of dc.filters.RangedFilter, which is different - * // from the syntax for filtering a crossfilter dimension directly, dimension.filter([15,20]) - * chart.filter(dc.filters.RangedFilter(15,20)); - * @param {*} [filter] - * @return {dc.baseMixin} - */ - _chart.filter = function (filter) { - if (!arguments.length) { - return _filters.length > 0 ? _filters[0] : null; - } - var filters = _filters; - if (filter instanceof Array && filter[0] instanceof Array && !filter.isFiltered) { - // toggle each filter - filter[0].forEach(function (f) { - if (_hasFilterHandler(filters, f)) { - filters = _removeFilterHandler(filters, f); - } else { - filters = _addFilterHandler(filters, f); - } - }); - } else if (filter === null) { - filters = _resetFilterHandler(filters); - } else { - if (_hasFilterHandler(filters, filter)) { - filters = _removeFilterHandler(filters, filter); - } else { - filters = _addFilterHandler(filters, filter); - } - } - _filters = applyFilters(filters); - _chart._invokeFilteredListener(filter); - - if (_root !== null && _chart.hasFilter()) { - _chart.turnOnControls(); - } else { - _chart.turnOffControls(); - } - - return _chart; - }; - - /** - * Returns all current filters. This method does not perform defensive cloning of the internal - * filter array before returning, therefore any modification of the returned array will effect the - * chart's internal filter storage. - * @method filters - * @memberof dc.baseMixin - * @instance - * @return {Array<*>} - */ - _chart.filters = function () { - return _filters; - }; - - _chart.highlightSelected = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, true); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, false); - }; - - _chart.fadeDeselected = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, false); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, true); - }; - - _chart.resetHighlight = function (e) { - d3.select(e).classed(dc.constants.SELECTED_CLASS, false); - d3.select(e).classed(dc.constants.DESELECTED_CLASS, false); - }; - - /** - * This function is passed to d3 as the onClick handler for each chart. The default behavior is to - * filter on the clicked datum (passed to the callback) and redraw the chart group. - * @method onClick - * @memberof dc.baseMixin - * @instance - * @param {*} datum - */ - _chart.onClick = function (datum) { - var filter = _chart.keyAccessor()(datum); - dc.events.trigger(function () { - _chart.filter(filter); - _chart.redrawGroup(); - }); - }; - - /** - * Set or get the filter handler. The filter handler is a function that performs the filter action - * on a specific dimension. Using a custom filter handler allows you to perform additional logic - * before or after filtering. - * @method filterHandler - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#dimension_filter crossfilter.dimension.filter} - * @example - * // default filter handler - * chart.filterHandler(function (dimension, filters) { - * dimension.filter(null); - * if (filters.length === 0) { - * dimension.filter(null); - * } else { - * dimension.filterFunction(function (d) { - * for (var i = 0; i < filters.length; i++) { - * var filter = filters[i]; - * if (filter.isFiltered && filter.isFiltered(d)) { - * return true; - * } else if (filter <= d && filter >= d) { - * return true; - * } - * } - * return false; - * }); - * } - * return filters; - * }); - * - * // custom filter handler - * chart.filterHandler(function(dimension, filter){ - * var newFilter = filter + 10; - * dimension.filter(newFilter); - * return newFilter; // set the actual filter value to the new value - * }); - * @param {Function} [filterHandler] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.filterHandler = function (filterHandler) { - if (!arguments.length) { - return _filterHandler; - } - _filterHandler = filterHandler; - return _chart; - }; - - // abstract function stub - _chart._doRender = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - _chart._doRedraw = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - _chart.legendables = function () { - // do nothing in base, should be overridden by sub-function - return []; - }; - - _chart.legendHighlight = function () { - // do nothing in base, should be overridden by sub-function - }; - - _chart.legendReset = function () { - // do nothing in base, should be overridden by sub-function - }; - - _chart.legendToggle = function () { - // do nothing in base, should be overriden by sub-function - }; - - _chart.isLegendableHidden = function () { - // do nothing in base, should be overridden by sub-function - return false; - }; - - /** - * Set or get the key accessor function. The key accessor function is used to retrieve the key - * value from the crossfilter group. Key values are used differently in different charts, for - * example keys correspond to slices in a pie chart and x axis positions in a grid coordinate chart. - * @method keyAccessor - * @memberof dc.baseMixin - * @instance - * @example - * // default key accessor - * chart.keyAccessor(function(d) { return d.key; }); - * // custom key accessor for a multi-value crossfilter reduction - * chart.keyAccessor(function(p) { return p.value.absGain; }); - * @param {Function} [keyAccessor] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.keyAccessor = function (keyAccessor) { - if (!arguments.length) { - return _keyAccessor; - } - _keyAccessor = keyAccessor; - return _chart; - }; - - /** - * Set or get the value accessor function. The value accessor function is used to retrieve the - * value from the crossfilter group. Group values are used differently in different charts, for - * example values correspond to slice sizes in a pie chart and y axis positions in a grid - * coordinate chart. - * @method valueAccessor - * @memberof dc.baseMixin - * @instance - * @example - * // default value accessor - * chart.valueAccessor(function(d) { return d.value; }); - * // custom value accessor for a multi-value crossfilter reduction - * chart.valueAccessor(function(p) { return p.value.percentageGain; }); - * @param {Function} [valueAccessor] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.valueAccessor = function (valueAccessor) { - if (!arguments.length) { - return _valueAccessor; - } - _valueAccessor = valueAccessor; - return _chart; - }; - - /** - * Set or get the label function. The chart class will use this function to render labels for each - * child element in the chart, e.g. slices in a pie chart or bubbles in a bubble chart. Not every - * chart supports the label function, for example line chart does not use this function - * at all. By default, enables labels; pass false for the second parameter if this is not desired. - * @method label - * @memberof dc.baseMixin - * @instance - * @example - * // default label function just return the key - * chart.label(function(d) { return d.key; }); - * // label function has access to the standard d3 data binding and can get quite complicated - * chart.label(function(d) { return d.data.key + '(' + Math.floor(d.data.value / all.value() * 100) + '%)'; }); - * @param {Function} [labelFunction] - * @param {Boolean} [enableLabels=true] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.label = function (labelFunction, enableLabels) { - if (!arguments.length) { - return _label; - } - _label = labelFunction; - if ((enableLabels === undefined) || enableLabels) { - _renderLabel = true; - } - return _chart; - }; - - /** - * Turn on/off label rendering - * @method renderLabel - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [renderLabel=false] - * @return {Boolean} - * @return {dc.baseMixin} - */ - _chart.renderLabel = function (renderLabel) { - if (!arguments.length) { - return _renderLabel; - } - _renderLabel = renderLabel; - return _chart; - }; - - /** - * Set or get the title function. The chart class will use this function to render the SVGElement title - * (usually interpreted by browser as tooltips) for each child element in the chart, e.g. a slice - * in a pie chart or a bubble in a bubble chart. Almost every chart supports the title function; - * however in grid coordinate charts you need to turn off the brush in order to see titles, because - * otherwise the brush layer will block tooltip triggering. - * @method title - * @memberof dc.baseMixin - * @instance - * @example - * // default title function shows "key: value" - * chart.title(function(d) { return d.key + ': ' + d.value; }); - * // title function has access to the standard d3 data binding and can get quite complicated - * chart.title(function(p) { - * return p.key.getFullYear() - * + '\n' - * + 'Index Gain: ' + numberFormat(p.value.absGain) + '\n' - * + 'Index Gain in Percentage: ' + numberFormat(p.value.percentageGain) + '%\n' - * + 'Fluctuation / Index Ratio: ' + numberFormat(p.value.fluctuationPercentage) + '%'; - * }); - * @param {Function} [titleFunction] - * @return {Function} - * @return {dc.baseMixin} - */ - _chart.title = function (titleFunction) { - if (!arguments.length) { - return _title; - } - _title = titleFunction; - return _chart; - }; - - /** - * Turn on/off title rendering, or return the state of the render title flag if no arguments are - * given. - * @method renderTitle - * @memberof dc.baseMixin - * @instance - * @param {Boolean} [renderTitle=true] - * @return {Boolean} - * @return {dc.baseMixin} - */ - _chart.renderTitle = function (renderTitle) { - if (!arguments.length) { - return _renderTitle; - } - _renderTitle = renderTitle; - return _chart; - }; - - /** - * A renderlet is similar to an event listener on rendering event. Multiple renderlets can be added - * to an individual chart. Each time a chart is rerendered or redrawn the renderlets are invoked - * right after the chart finishes its transitions, giving you a way to modify the SVGElements. - * Renderlet functions take the chart instance as the only input parameter and you can - * use the dc API or use raw d3 to achieve pretty much any effect. - * - * Use {@link dc.baseMixin#on on} with a 'renderlet' prefix. - * Generates a random key for the renderlet, which makes it hard to remove. - * @method renderlet - * @memberof dc.baseMixin - * @instance - * @deprecated - * @example - * // do this instead of .renderlet(function(chart) { ... }) - * chart.on("renderlet", function(chart){ - * // mix of dc API and d3 manipulation - * chart.select('g.y').style('display', 'none'); - * // its a closure so you can also access other chart variable available in the closure scope - * moveChart.filter(chart.filter()); - * }); - * @param {Function} renderletFunction - * @return {dc.baseMixin} - */ - _chart.renderlet = dc.logger.deprecate(function (renderletFunction) { - _chart.on('renderlet.' + dc.utils.uniqueId(), renderletFunction); - return _chart; - }, 'chart.renderlet has been deprecated. Please use chart.on("renderlet.", renderletFunction)'); - - /** - * Get or set the chart group to which this chart belongs. Chart groups are rendered or redrawn - * together since it is expected they share the same underlying crossfilter data set. - * @method chartGroup - * @memberof dc.baseMixin - * @instance - * @param {String} [chartGroup] - * @return {String} - * @return {dc.baseMixin} - */ - _chart.chartGroup = function (chartGroup) { - if (!arguments.length) { - return _chartGroup; - } - if (!_isChild) { - dc.deregisterChart(_chart, _chartGroup); - } - _chartGroup = chartGroup; - if (!_isChild) { - dc.registerChart(_chart, _chartGroup); - } - return _chart; - }; - - /** - * Expire the internal chart cache. dc charts cache some data internally on a per chart basis to - * speed up rendering and avoid unnecessary calculation; however it might be useful to clear the - * cache if you have changed state which will affect rendering. For example if you invoke the - * {@link https://github.com/square/crossfilter/wiki/API-Reference#crossfilter_add crossfilter.add} - * function or reset group or dimension after rendering it is a good idea to - * clear the cache to make sure charts are rendered properly. - * @method expireCache - * @memberof dc.baseMixin - * @instance - * @return {dc.baseMixin} - */ - _chart.expireCache = function () { - // do nothing in base, should be overridden by sub-function - return _chart; - }; - - /** - * Attach a dc.legend widget to this chart. The legend widget will automatically draw legend labels - * based on the color setting and names associated with each group. - * @method legend - * @memberof dc.baseMixin - * @instance - * @example - * chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) - * @param {dc.legend} [legend] - * @return {dc.legend} - * @return {dc.baseMixin} - */ - _chart.legend = function (legend) { - if (!arguments.length) { - return _legend; - } - _legend = legend; - _legend.parent(_chart); - return _chart; - }; - - /** - * Returns the internal numeric ID of the chart. - * @method chartID - * @memberof dc.baseMixin - * @instance - * @return {String} - */ - _chart.chartID = function () { - return _chart.__dcFlag__; - }; - - /** - * Set chart options using a configuration object. Each key in the object will cause the method of - * the same name to be called with the value to set that attribute for the chart. - * @method options - * @memberof dc.baseMixin - * @instance - * @example - * chart.options({dimension: myDimension, group: myGroup}); - * @param {{}} opts - * @return {dc.baseMixin} - */ - _chart.options = function (opts) { - var applyOptions = [ - 'anchor', - 'group', - 'xAxisLabel', - 'yAxisLabel', - 'stack', - 'title', - 'point', - 'getColor', - 'overlayGeoJson' - ]; - - for (var o in opts) { - if (typeof(_chart[o]) === 'function') { - if (opts[o] instanceof Array && applyOptions.indexOf(o) !== -1) { - _chart[o].apply(_chart, opts[o]); - } else { - _chart[o].call(_chart, opts[o]); - } - } else { - dc.logger.debug('Not a valid option setter name: ' + o); - } - } - return _chart; - }; - - /** - * All dc chart instance supports the following listeners. - * Supports the following events: - * * `renderlet` - This listener function will be invoked after transitions after redraw and render. Replaces the - * deprecated {@link dc.baseMixin#renderlet renderlet} method. - * * `pretransition` - Like `.on('renderlet', ...)` but the event is fired before transitions start. - * * `preRender` - This listener function will be invoked before chart rendering. - * * `postRender` - This listener function will be invoked after chart finish rendering including - * all renderlets' logic. - * * `preRedraw` - This listener function will be invoked before chart redrawing. - * * `postRedraw` - This listener function will be invoked after chart finish redrawing - * including all renderlets' logic. - * * `filtered` - This listener function will be invoked after a filter is applied, added or removed. - * * `zoomed` - This listener function will be invoked after a zoom is triggered. - * @method on - * @memberof dc.baseMixin - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Internals#dispatch_on d3.dispatch.on} - * @example - * .on('renderlet', function(chart, filter){...}) - * .on('pretransition', function(chart, filter){...}) - * .on('preRender', function(chart){...}) - * .on('postRender', function(chart){...}) - * .on('preRedraw', function(chart){...}) - * .on('postRedraw', function(chart){...}) - * .on('filtered', function(chart, filter){...}) - * .on('zoomed', function(chart, filter){...}) - * @param {String} event - * @param {Function} listener - * @return {dc.baseMixin} - */ - _chart.on = function (event, listener) { - _listeners.on(event, listener); - return _chart; - }; - - return _chart; -}; - -/** - * Margin is a mixin that provides margin utility functions for both the Row Chart and Coordinate Grid - * Charts. - * @name marginMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.marginMixin} - */ -dc.marginMixin = function (_chart) { - var _margin = {top: 10, right: 50, bottom: 30, left: 30}; - - /** - * Get or set the margins for a particular coordinate grid chart instance. The margins is stored as - * an associative Javascript array. - * @method margins - * @memberof dc.marginMixin - * @instance - * @example - * var leftMargin = chart.margins().left; // 30 by default - * chart.margins().left = 50; - * leftMargin = chart.margins().left; // now 50 - * @param {{top: Number, right: Number, left: Number, bottom: Number}} [margins={top: 10, right: 50, bottom: 30, left: 30}] - * @return {{top: Number, right: Number, left: Number, bottom: Number}} - * @return {dc.marginMixin} - */ - _chart.margins = function (margins) { - if (!arguments.length) { - return _margin; - } - _margin = margins; - return _chart; - }; - - _chart.effectiveWidth = function () { - return _chart.width() - _chart.margins().left - _chart.margins().right; - }; - - _chart.effectiveHeight = function () { - return _chart.height() - _chart.margins().top - _chart.margins().bottom; - }; - - return _chart; -}; - -/** - * The Color Mixin is an abstract chart functional class providing universal coloring support - * as a mix-in for any concrete chart implementation. - * @name colorMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.colorMixin} - */ -dc.colorMixin = function (_chart) { - var _colors = d3.scale.category20c(); - var _defaultAccessor = true; - - var _colorAccessor = function (d) { return _chart.keyAccessor()(d); }; - - /** - * Retrieve current color scale or set a new color scale. This methods accepts any function that - * operates like a d3 scale. - * @method colors - * @memberof dc.colorMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale} - * @example - * // alternate categorical scale - * chart.colors(d3.scale.category20b()); - * // ordinal scale - * chart.colors(d3.scale.ordinal().range(['red','green','blue'])); - * // convenience method, the same as above - * chart.ordinalColors(['red','green','blue']); - * // set a linear scale - * chart.linearColors(["#4575b4", "#ffffbf", "#a50026"]); - * @param {d3.scale} [colorScale=d3.scale.category20c()] - * @return {d3.scale} - * @return {dc.colorMixin} - */ - _chart.colors = function (colorScale) { - if (!arguments.length) { - return _colors; - } - if (colorScale instanceof Array) { - _colors = d3.scale.quantize().range(colorScale); // deprecated legacy support, note: this fails for ordinal domains - } else { - _colors = d3.functor(colorScale); - } - return _chart; - }; - - /** - * Convenience method to set the color scale to - * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#ordinal d3.scale.ordinal} with - * range `r`. - * @method ordinalColors - * @memberof dc.colorMixin - * @instance - * @param {Array} r - * @return {dc.colorMixin} - */ - _chart.ordinalColors = function (r) { - return _chart.colors(d3.scale.ordinal().range(r)); - }; - - /** - * Convenience method to set the color scale to an Hcl interpolated linear scale with range `r`. - * @method linearColors - * @memberof dc.colorMixin - * @instance - * @param {Array} r - * @return {dc.colorMixin} - */ - _chart.linearColors = function (r) { - return _chart.colors(d3.scale.linear() - .range(r) - .interpolate(d3.interpolateHcl)); - }; - - /** - * Set or the get color accessor function. This function will be used to map a data point in a - * crossfilter group to a color value on the color scale. The default function uses the key - * accessor. - * @method colorAccessor - * @memberof dc.colorMixin - * @instance - * @example - * // default index based color accessor - * .colorAccessor(function (d, i){return i;}) - * // color accessor for a multi-value crossfilter reduction - * .colorAccessor(function (d){return d.value.absGain;}) - * @param {Function} [colorAccessor] - * @return {Function} - * @return {dc.colorMixin} - */ - _chart.colorAccessor = function (colorAccessor) { - if (!arguments.length) { - return _colorAccessor; - } - _colorAccessor = colorAccessor; - _defaultAccessor = false; - return _chart; - }; - - // what is this? - _chart.defaultColorAccessor = function () { - return _defaultAccessor; - }; - - /** - * Set or get the current domain for the color mapping function. The domain must be supplied as an - * array. - * - * Note: previously this method accepted a callback function. Instead you may use a custom scale - * set by {@link dc.colorMixin#colors .colors}. - * @method colorDomain - * @memberof dc.colorMixin - * @instance - * @param {Array} [domain] - * @return {Array} - * @return {dc.colorMixin} - */ - _chart.colorDomain = function (domain) { - if (!arguments.length) { - return _colors.domain(); - } - _colors.domain(domain); - return _chart; - }; - - /** - * Set the domain by determining the min and max values as retrieved by - * {@link dc.colorMixin#colorAccessor .colorAccessor} over the chart's dataset. - * @method calculateColorDomain - * @memberof dc.colorMixin - * @instance - * @return {dc.colorMixin} - */ - _chart.calculateColorDomain = function () { - var newDomain = [d3.min(_chart.data(), _chart.colorAccessor()), - d3.max(_chart.data(), _chart.colorAccessor())]; - _colors.domain(newDomain); - return _chart; - }; - - /** - * Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. - * @method getColor - * @memberof dc.colorMixin - * @instance - * @param {*} d - * @param {Number} [i] - * @return {String} - */ - _chart.getColor = function (d, i) { - return _colors(_colorAccessor.call(this, d, i)); - }; - - /** - * Get the color for the datum d and counter i. This is used internally by charts to retrieve a color. - * @method colorCalculator - * @memberof dc.colorMixin - * @instance - * @param {*} [colorCalculator] - * @return {*} - */ - _chart.colorCalculator = function (colorCalculator) { - if (!arguments.length) { - return _chart.getColor; - } - _chart.getColor = colorCalculator; - return _chart; - }; - - return _chart; -}; - -/** - * Coordinate Grid is an abstract base chart designed to support a number of coordinate grid based - * concrete chart types, e.g. bar chart, line chart, and bubble chart. - * @name coordinateGridMixin - * @memberof dc - * @mixin - * @mixes dc.colorMixin - * @mixes dc.marginMixin - * @mixes dc.baseMixin - * @param {Object} _chart - * @return {dc.coordinateGridMixin} - */ -dc.coordinateGridMixin = function (_chart) { - var GRID_LINE_CLASS = 'grid-line'; - var HORIZONTAL_CLASS = 'horizontal'; - var VERTICAL_CLASS = 'vertical'; - var Y_AXIS_LABEL_CLASS = 'y-axis-label'; - var X_AXIS_LABEL_CLASS = 'x-axis-label'; - var DEFAULT_AXIS_LABEL_PADDING = 12; - - _chart = dc.colorMixin(dc.marginMixin(dc.baseMixin(_chart))); - - _chart.colors(d3.scale.category10()); - _chart._mandatoryAttributes().push('x'); - - function zoomHandler () { - _refocused = true; - if (_zoomOutRestrict) { - _chart.x().domain(constrainRange(_chart.x().domain(), _xOriginalDomain)); - if (_rangeChart) { - _chart.x().domain(constrainRange(_chart.x().domain(), _rangeChart.x().domain())); - } - } - - var domain = _chart.x().domain(); - var domFilter = dc.filters.RangedFilter(domain[0], domain[1]); - - _chart.replaceFilter(domFilter); - _chart.rescale(); - _chart.redraw(); - - if (_rangeChart && !rangesEqual(_chart.filter(), _rangeChart.filter())) { - dc.events.trigger(function () { - _rangeChart.replaceFilter(domFilter); - _rangeChart.redraw(); - }); - } - - _chart._invokeZoomedListener(); - - dc.events.trigger(function () { - _chart.redrawGroup(); - }, dc.constants.EVENT_DELAY); - - _refocused = !rangesEqual(domain, _xOriginalDomain); - } - - var _parent; - var _g; - var _chartBodyG; - - var _x; - var _xOriginalDomain; - var _xAxis = d3.svg.axis().orient('bottom'); - var _xUnits = dc.units.integers; - var _xAxisPadding = 0; - var _xElasticity = false; - var _xAxisLabel; - var _xAxisLabelPadding = 0; - var _lastXDomain; - - var _y; - var _yAxis = d3.svg.axis().orient('left'); - var _yAxisPadding = 0; - var _yElasticity = false; - var _yAxisLabel; - var _yAxisLabelPadding = 0; - - var _brush = d3.svg.brush(); - var _brushOn = true; - var _round; - - var _renderHorizontalGridLine = false; - var _renderVerticalGridLine = false; - - var _refocused = false, _resizing = false; - var _unitCount; - - var _zoomScale = [1, Infinity]; - var _zoomOutRestrict = true; - - var _zoom = d3.behavior.zoom().on('zoom', zoomHandler); - var _nullZoom = d3.behavior.zoom().on('zoom', null); - var _hasBeenMouseZoomable = false; - - var _rangeChart; - var _focusChart; - - var _mouseZoomable = false; - var _clipPadding = 0; - - var _outerRangeBandPadding = 0.5; - var _rangeBandPadding = 0; - - var _useRightYAxis = false; - - /** - * When changing the domain of the x or y scale, it is necessary to tell the chart to recalculate - * and redraw the axes. (`.rescale()` is called automatically when the x or y scale is replaced - * with {@link dc.coordinateGridMixin+x .x()} or {@link dc.coordinateGridMixin#y .y()}, and has - * no effect on elastic scales.) - * @method rescale - * @memberof dc.coordinateGridMixin - * @instance - * @return {dc.coordinateGridMixin} - */ - _chart.rescale = function () { - _unitCount = undefined; - _resizing = true; - return _chart; - }; - - _chart.resizing = function () { - return _resizing; - }; - - /** - * Get or set the range selection chart associated with this instance. Setting the range selection - * chart using this function will automatically update its selection brush when the current chart - * zooms in. In return the given range chart will also automatically attach this chart as its focus - * chart hence zoom in when range brush updates. - * - * Usually the range and focus charts will share a dimension. The range chart will set the zoom - * boundaries for the focus chart, so its dimension values must be compatible with the domain of - * the focus chart. - * - * See the [Nasdaq 100 Index](http://dc-js.github.com/dc.js/) example for this effect in action. - * @method rangeChart - * @memberof dc.coordinateGridMixin - * @instance - * @param {dc.coordinateGridMixin} [rangeChart] - * @return {dc.coordinateGridMixin} - */ - _chart.rangeChart = function (rangeChart) { - if (!arguments.length) { - return _rangeChart; - } - _rangeChart = rangeChart; - _rangeChart.focusChart(_chart); - return _chart; - }; - - /** - * Get or set the scale extent for mouse zooms. - * @method zoomScale - * @memberof dc.coordinateGridMixin - * @instance - * @param {Array} [extent=[1, Infinity]] - * @return {Array} - * @return {dc.coordinateGridMixin} - */ - _chart.zoomScale = function (extent) { - if (!arguments.length) { - return _zoomScale; - } - _zoomScale = extent; - return _chart; - }; - - /** - * Get or set the zoom restriction for the chart. If true limits the zoom to origional domain of the chart. - * @method zoomOutRestrict - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [zoomOutRestrict=true] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.zoomOutRestrict = function (zoomOutRestrict) { - if (!arguments.length) { - return _zoomOutRestrict; - } - _zoomScale[0] = zoomOutRestrict ? 1 : 0; - _zoomOutRestrict = zoomOutRestrict; - return _chart; - }; - - _chart._generateG = function (parent) { - if (parent === undefined) { - _parent = _chart.svg(); - } else { - _parent = parent; - } - - var href = window.location.href.split('#')[0]; - - _g = _parent.append('g'); - - _chartBodyG = _g.append('g').attr('class', 'chart-body') - .attr('transform', 'translate(' + _chart.margins().left + ', ' + _chart.margins().top + ')') - .attr('clip-path', 'url('http://github.com/+%20href%20+%20'#'%20+%20getClipPathId() + ')'); - - return _g; - }; - - /** - * Get or set the root g element. This method is usually used to retrieve the g element in order to - * overlay custom svg drawing programatically. **Caution**: The root g element is usually generated - * by dc.js internals, and resetting it might produce unpredictable result. - * @method g - * @memberof dc.coordinateGridMixin - * @instance - * @param {SVGElement} [gElement] - * @return {SVGElement} - * @return {dc.coordinateGridMixin} - */ - _chart.g = function (gElement) { - if (!arguments.length) { - return _g; - } - _g = gElement; - return _chart; - }; - - /** - * Set or get mouse zoom capability flag (default: false). When turned on the chart will be - * zoomable using the mouse wheel. If the range selector chart is attached zooming will also update - * the range selection brush on the associated range selector chart. - * @method mouseZoomable - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [mouseZoomable=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.mouseZoomable = function (mouseZoomable) { - if (!arguments.length) { - return _mouseZoomable; - } - _mouseZoomable = mouseZoomable; - return _chart; - }; - - /** - * Retrieve the svg group for the chart body. - * @method chartBodyG - * @memberof dc.coordinateGridMixin - * @instance - * @param {SVGElement} [chartBodyG] - * @return {SVGElement} - */ - _chart.chartBodyG = function (chartBodyG) { - if (!arguments.length) { - return _chartBodyG; - } - _chartBodyG = chartBodyG; - return _chart; - }; - - /** - * **mandatory** - * - * Get or set the x scale. The x scale can be any d3 - * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale} or - * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales ordinal scale}. - * @method x - * @memberof dc.coordinateGridMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale} - * @example - * // set x to a linear scale - * chart.x(d3.scale.linear().domain([-2500, 2500])) - * // set x to a time scale to generate histogram - * chart.x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2012, 11, 31)])) - * @param {d3.scale} [xScale] - * @return {d3.scale} - * @return {dc.coordinateGridMixin} - */ - _chart.x = function (xScale) { - if (!arguments.length) { - return _x; - } - _x = xScale; - _xOriginalDomain = _x.domain(); - _chart.rescale(); - return _chart; - }; - - _chart.xOriginalDomain = function () { - return _xOriginalDomain; - }; - - /** - * Set or get the xUnits function. The coordinate grid chart uses the xUnits function to calculate - * the number of data projections on x axis such as the number of bars for a bar chart or the - * number of dots for a line chart. This function is expected to return a Javascript array of all - * data points on x axis, or the number of points on the axis. [d3 time range functions - * d3.time.days, d3.time.months, and - * d3.time.years](https://github.com/mbostock/d3/wiki/Time-Intervals#aliases) are all valid xUnits - * function. dc.js also provides a few units function, see the {@link dc.utils Utilities} section for - * a list of built-in units functions. The default xUnits function is dc.units.integers. - * @method xUnits - * @memberof dc.coordinateGridMixin - * @instance - * @todo Add docs for utilities - * @example - * // set x units to count days - * chart.xUnits(d3.time.days); - * // set x units to count months - * chart.xUnits(d3.time.months); - * - * // A custom xUnits function can be used as long as it follows the following interface: - * // units in integer - * function(start, end, xDomain) { - * // simply calculates how many integers in the domain - * return Math.abs(end - start); - * }; - * - * // fixed units - * function(start, end, xDomain) { - * // be aware using fixed units will disable the focus/zoom ability on the chart - * return 1000; - * @param {Function} [xUnits] - * @return {Function} - * @return {dc.coordinateGridMixin} - */ - _chart.xUnits = function (xUnits) { - if (!arguments.length) { - return _xUnits; - } - _xUnits = xUnits; - return _chart; - }; - - /** - * Set or get the x axis used by a particular coordinate grid chart instance. This function is most - * useful when x axis customization is required. The x axis in dc.js is an instance of a [d3 - * axis object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis); therefore it supports any - * valid d3 axis manipulation. **Caution**: The x axis is usually generated internally by dc; - * resetting it may cause unexpected results. - * @method xAxis - * @memberof dc.coordinateGridMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis} - * @example - * // customize x axis tick format - * chart.xAxis().tickFormat(function(v) {return v + '%';}); - * // customize x axis tick values - * chart.xAxis().tickValues([0, 100, 200, 300]); - * @param {d3.svg.axis} [xAxis=d3.svg.axis().orient('bottom')] - * @return {d3.svg.axis} - * @return {dc.coordinateGridMixin} - */ - _chart.xAxis = function (xAxis) { - if (!arguments.length) { - return _xAxis; - } - _xAxis = xAxis; - return _chart; - }; - - /** - * Turn on/off elastic x axis behavior. If x axis elasticity is turned on, then the grid chart will - * attempt to recalculate the x axis range whenever a redraw event is triggered. - * @method elasticX - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [elasticX=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.elasticX = function (elasticX) { - if (!arguments.length) { - return _xElasticity; - } - _xElasticity = elasticX; - return _chart; - }; - - /** - * Set or get x axis padding for the elastic x axis. The padding will be added to both end of the x - * axis if elasticX is turned on; otherwise it is ignored. - * - * padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to - * number or date x axes. When padding a date axis, an integer represents number of days being padded - * and a percentage string will be treated the same as an integer. - * @method xAxisPadding - * @memberof dc.coordinateGridMixin - * @instance - * @param {Number|String} [padding=0] - * @return {Number|String} - * @return {dc.coordinateGridMixin} - */ - _chart.xAxisPadding = function (padding) { - if (!arguments.length) { - return _xAxisPadding; - } - _xAxisPadding = padding; - return _chart; - }; - - /** - * Returns the number of units displayed on the x axis using the unit measure configured by - * .xUnits. - * @method xUnitCount - * @memberof dc.coordinateGridMixin - * @instance - * @return {Number} - */ - _chart.xUnitCount = function () { - if (_unitCount === undefined) { - var units = _chart.xUnits()(_chart.x().domain()[0], _chart.x().domain()[1], _chart.x().domain()); - - if (units instanceof Array) { - _unitCount = units.length; - } else { - _unitCount = units; - } - } - - return _unitCount; - }; - - /** - * Gets or sets whether the chart should be drawn with a right axis instead of a left axis. When - * used with a chart in a composite chart, allows both left and right Y axes to be shown on a - * chart. - * @method useRightYAxis - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [useRightYAxis=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.useRightYAxis = function (useRightYAxis) { - if (!arguments.length) { - return _useRightYAxis; - } - _useRightYAxis = useRightYAxis; - return _chart; - }; - - /** - * Returns true if the chart is using ordinal xUnits ({@link dc.units.ordinal dc.units.ordinal}, or false - * otherwise. Most charts behave differently with ordinal data and use the result of this method to - * trigger the appropriate logic. - * @method isOrdinal - * @memberof dc.coordinateGridMixin - * @instance - * @return {Boolean} - */ - _chart.isOrdinal = function () { - return _chart.xUnits() === dc.units.ordinal; - }; - - _chart._useOuterPadding = function () { - return true; - }; - - _chart._ordinalXDomain = function () { - var groups = _chart._computeOrderedGroups(_chart.data()); - return groups.map(_chart.keyAccessor()); - }; - - function compareDomains (d1, d2) { - return !d1 || !d2 || d1.length !== d2.length || - d1.some(function (elem, i) { return (elem && d2[i]) ? elem.toString() !== d2[i].toString() : elem === d2[i]; }); - } - - function prepareXAxis (g, render) { - if (!_chart.isOrdinal()) { - if (_chart.elasticX()) { - _x.domain([_chart.xAxisMin(), _chart.xAxisMax()]); - } - } else { // _chart.isOrdinal() - if (_chart.elasticX() || _x.domain().length === 0) { - _x.domain(_chart._ordinalXDomain()); - } - } - - // has the domain changed? - var xdom = _x.domain(); - if (render || compareDomains(_lastXDomain, xdom)) { - _chart.rescale(); - } - _lastXDomain = xdom; - - // please can't we always use rangeBands for bar charts? - if (_chart.isOrdinal()) { - _x.rangeBands([0, _chart.xAxisLength()], _rangeBandPadding, - _chart._useOuterPadding() ? _outerRangeBandPadding : 0); - } else { - _x.range([0, _chart.xAxisLength()]); - } - - _xAxis = _xAxis.scale(_chart.x()); - - renderVerticalGridLines(g); - } - - _chart.renderXAxis = function (g) { - var axisXG = g.selectAll('g.x'); - - if (axisXG.empty()) { - axisXG = g.append('g') - .attr('class', 'axis x') - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart._xAxisY() + ')'); - } - - var axisXLab = g.selectAll('text.' + X_AXIS_LABEL_CLASS); - if (axisXLab.empty() && _chart.xAxisLabel()) { - axisXLab = g.append('text') - .attr('class', X_AXIS_LABEL_CLASS) - .attr('transform', 'translate(' + (_chart.margins().left + _chart.xAxisLength() / 2) + ',' + - (_chart.height() - _xAxisLabelPadding) + ')') - .attr('text-anchor', 'middle'); - } - if (_chart.xAxisLabel() && axisXLab.text() !== _chart.xAxisLabel()) { - axisXLab.text(_chart.xAxisLabel()); - } - - dc.transition(axisXG, _chart.transitionDuration()) - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart._xAxisY() + ')') - .call(_xAxis); - dc.transition(axisXLab, _chart.transitionDuration()) - .attr('transform', 'translate(' + (_chart.margins().left + _chart.xAxisLength() / 2) + ',' + - (_chart.height() - _xAxisLabelPadding) + ')'); - }; - - function renderVerticalGridLines (g) { - var gridLineG = g.selectAll('g.' + VERTICAL_CLASS); - - if (_renderVerticalGridLine) { - if (gridLineG.empty()) { - gridLineG = g.insert('g', ':first-child') - .attr('class', GRID_LINE_CLASS + ' ' + VERTICAL_CLASS) - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')'); - } - - var ticks = _xAxis.tickValues() ? _xAxis.tickValues() : - (typeof _x.ticks === 'function' ? _x.ticks(_xAxis.ticks()[0]) : _x.domain()); - - var lines = gridLineG.selectAll('line') - .data(ticks); - - // enter - var linesGEnter = lines.enter() - .append('line') - .attr('x1', function (d) { - return _x(d); - }) - .attr('y1', _chart._xAxisY() - _chart.margins().top) - .attr('x2', function (d) { - return _x(d); - }) - .attr('y2', 0) - .attr('opacity', 0); - dc.transition(linesGEnter, _chart.transitionDuration()) - .attr('opacity', 1); - - // update - dc.transition(lines, _chart.transitionDuration()) - .attr('x1', function (d) { - return _x(d); - }) - .attr('y1', _chart._xAxisY() - _chart.margins().top) - .attr('x2', function (d) { - return _x(d); - }) - .attr('y2', 0); - - // exit - lines.exit().remove(); - } else { - gridLineG.selectAll('line').remove(); - } - } - - _chart._xAxisY = function () { - return (_chart.height() - _chart.margins().bottom); - }; - - _chart.xAxisLength = function () { - return _chart.effectiveWidth(); - }; - - /** - * Set or get the x axis label. If setting the label, you may optionally include additional padding to - * the margin to make room for the label. By default the padded is set to 12 to accomodate the text height. - * @method xAxisLabel - * @memberof dc.coordinateGridMixin - * @instance - * @param {String} [labelText] - * @param {Number} [padding=12] - * @return {String} - */ - _chart.xAxisLabel = function (labelText, padding) { - if (!arguments.length) { - return _xAxisLabel; - } - _xAxisLabel = labelText; - _chart.margins().bottom -= _xAxisLabelPadding; - _xAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding; - _chart.margins().bottom += _xAxisLabelPadding; - return _chart; - }; - - _chart._prepareYAxis = function (g) { - if (_y === undefined || _chart.elasticY()) { - if (_y === undefined) { - _y = d3.scale.linear(); - } - var min = _chart.yAxisMin() || 0, - max = _chart.yAxisMax() || 0; - _y.domain([min, max]).rangeRound([_chart.yAxisHeight(), 0]); - } - - _y.range([_chart.yAxisHeight(), 0]); - _yAxis = _yAxis.scale(_y); - - if (_useRightYAxis) { - _yAxis.orient('right'); - } - - _chart._renderHorizontalGridLinesForAxis(g, _y, _yAxis); - }; - - _chart.renderYAxisLabel = function (axisClass, text, rotation, labelXPosition) { - labelXPosition = labelXPosition || _yAxisLabelPadding; - - var axisYLab = _chart.g().selectAll('text.' + Y_AXIS_LABEL_CLASS + '.' + axisClass + '-label'); - var labelYPosition = (_chart.margins().top + _chart.yAxisHeight() / 2); - if (axisYLab.empty() && text) { - axisYLab = _chart.g().append('text') - .attr('transform', 'translate(' + labelXPosition + ',' + labelYPosition + '),rotate(' + rotation + ')') - .attr('class', Y_AXIS_LABEL_CLASS + ' ' + axisClass + '-label') - .attr('text-anchor', 'middle') - .text(text); - } - if (text && axisYLab.text() !== text) { - axisYLab.text(text); - } - dc.transition(axisYLab, _chart.transitionDuration()) - .attr('transform', 'translate(' + labelXPosition + ',' + labelYPosition + '),rotate(' + rotation + ')'); - }; - - _chart.renderYAxisAt = function (axisClass, axis, position) { - var axisYG = _chart.g().selectAll('g.' + axisClass); - if (axisYG.empty()) { - axisYG = _chart.g().append('g') - .attr('class', 'axis ' + axisClass) - .attr('transform', 'translate(' + position + ',' + _chart.margins().top + ')'); - } - - dc.transition(axisYG, _chart.transitionDuration()) - .attr('transform', 'translate(' + position + ',' + _chart.margins().top + ')') - .call(axis); - }; - - _chart.renderYAxis = function () { - var axisPosition = _useRightYAxis ? (_chart.width() - _chart.margins().right) : _chart._yAxisX(); - _chart.renderYAxisAt('y', _yAxis, axisPosition); - var labelPosition = _useRightYAxis ? (_chart.width() - _yAxisLabelPadding) : _yAxisLabelPadding; - var rotation = _useRightYAxis ? 90 : -90; - _chart.renderYAxisLabel('y', _chart.yAxisLabel(), rotation, labelPosition); - }; - - _chart._renderHorizontalGridLinesForAxis = function (g, scale, axis) { - var gridLineG = g.selectAll('g.' + HORIZONTAL_CLASS); - - if (_renderHorizontalGridLine) { - var ticks = axis.tickValues() ? axis.tickValues() : scale.ticks(axis.ticks()[0]); - - if (gridLineG.empty()) { - gridLineG = g.insert('g', ':first-child') - .attr('class', GRID_LINE_CLASS + ' ' + HORIZONTAL_CLASS) - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')'); - } - - var lines = gridLineG.selectAll('line') - .data(ticks); - - // enter - var linesGEnter = lines.enter() - .append('line') - .attr('x1', 1) - .attr('y1', function (d) { - return scale(d); - }) - .attr('x2', _chart.xAxisLength()) - .attr('y2', function (d) { - return scale(d); - }) - .attr('opacity', 0); - dc.transition(linesGEnter, _chart.transitionDuration()) - .attr('opacity', 1); - - // update - dc.transition(lines, _chart.transitionDuration()) - .attr('x1', 1) - .attr('y1', function (d) { - return scale(d); - }) - .attr('x2', _chart.xAxisLength()) - .attr('y2', function (d) { - return scale(d); - }); - - // exit - lines.exit().remove(); - } else { - gridLineG.selectAll('line').remove(); - } - }; - - _chart._yAxisX = function () { - return _chart.useRightYAxis() ? _chart.width() - _chart.margins().right : _chart.margins().left; - }; - - /** - * Set or get the y axis label. If setting the label, you may optionally include additional padding - * to the margin to make room for the label. By default the padded is set to 12 to accomodate the - * text height. - * @method yAxisLabel - * @memberof dc.coordinateGridMixin - * @instance - * @param {String} [labelText] - * @param {Number} [padding=12] - * @return {String} - * @return {dc.coordinateGridMixin} - */ - _chart.yAxisLabel = function (labelText, padding) { - if (!arguments.length) { - return _yAxisLabel; - } - _yAxisLabel = labelText; - _chart.margins().left -= _yAxisLabelPadding; - _yAxisLabelPadding = (padding === undefined) ? DEFAULT_AXIS_LABEL_PADDING : padding; - _chart.margins().left += _yAxisLabelPadding; - return _chart; - }; - - /** - * Get or set the y scale. The y scale is typically automatically determined by the chart implementation. - * @method y - * @memberof dc.coordinateGridMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale} - * @param {d3.scale} [yScale] - * @return {d3.scale} - * @return {dc.coordinateGridMixin} - */ - _chart.y = function (yScale) { - if (!arguments.length) { - return _y; - } - _y = yScale; - _chart.rescale(); - return _chart; - }; - - /** - * Set or get the y axis used by the coordinate grid chart instance. This function is most useful - * when y axis customization is required. The y axis in dc.js is simply an instance of a [d3 axis - * object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis); therefore it supports any - * valid d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc; - * resetting it may cause unexpected results. - * @method yAxis - * @memberof dc.coordinateGridMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis} - * @example - * // customize y axis tick format - * chart.yAxis().tickFormat(function(v) {return v + '%';}); - * // customize y axis tick values - * chart.yAxis().tickValues([0, 100, 200, 300]); - * @param {d3.svg.axis} [yAxis=d3.svg.axis().orient('left')] - * @return {d3.svg.axis} - * @return {dc.coordinateGridMixin} - */ - _chart.yAxis = function (yAxis) { - if (!arguments.length) { - return _yAxis; - } - _yAxis = yAxis; - return _chart; - }; - - /** - * Turn on/off elastic y axis behavior. If y axis elasticity is turned on, then the grid chart will - * attempt to recalculate the y axis range whenever a redraw event is triggered. - * @method elasticY - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [elasticY=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.elasticY = function (elasticY) { - if (!arguments.length) { - return _yElasticity; - } - _yElasticity = elasticY; - return _chart; - }; - - /** - * Turn on/off horizontal grid lines. - * @method renderHorizontalGridLines - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [renderHorizontalGridLines=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.renderHorizontalGridLines = function (renderHorizontalGridLines) { - if (!arguments.length) { - return _renderHorizontalGridLine; - } - _renderHorizontalGridLine = renderHorizontalGridLines; - return _chart; - }; - - /** - * Turn on/off vertical grid lines. - * @method renderVerticalGridLines - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [renderVerticalGridLines=false] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.renderVerticalGridLines = function (renderVerticalGridLines) { - if (!arguments.length) { - return _renderVerticalGridLine; - } - _renderVerticalGridLine = renderVerticalGridLines; - return _chart; - }; - - /** - * Calculates the minimum x value to display in the chart. Includes xAxisPadding if set. - * @method xAxisMin - * @memberof dc.coordinateGridMixin - * @instance - * @return {*} - */ - _chart.xAxisMin = function () { - var min = d3.min(_chart.data(), function (e) { - return _chart.keyAccessor()(e); - }); - return dc.utils.subtract(min, _xAxisPadding); - }; - - /** - * Calculates the maximum x value to display in the chart. Includes xAxisPadding if set. - * @method xAxisMax - * @memberof dc.coordinateGridMixin - * @instance - * @return {*} - */ - _chart.xAxisMax = function () { - var max = d3.max(_chart.data(), function (e) { - return _chart.keyAccessor()(e); - }); - return dc.utils.add(max, _xAxisPadding); - }; - - /** - * Calculates the minimum y value to display in the chart. Includes yAxisPadding if set. - * @method yAxisMin - * @memberof dc.coordinateGridMixin - * @instance - * @return {*} - */ - _chart.yAxisMin = function () { - var min = d3.min(_chart.data(), function (e) { - return _chart.valueAccessor()(e); - }); - return dc.utils.subtract(min, _yAxisPadding); - }; - - /** - * Calculates the maximum y value to display in the chart. Includes yAxisPadding if set. - * @method yAxisMax - * @memberof dc.coordinateGridMixin - * @instance - * @return {*} - */ - _chart.yAxisMax = function () { - var max = d3.max(_chart.data(), function (e) { - return _chart.valueAccessor()(e); - }); - return dc.utils.add(max, _yAxisPadding); - }; - - /** - * Set or get y axis padding for the elastic y axis. The padding will be added to the top and - * bottom of the y axis if elasticY is turned on; otherwise it is ignored. - * - * Padding can be an integer or percentage in string (e.g. '10%'). Padding can be applied to - * number or date axes. When padding a date axis, an integer represents number of days being padded - * and a percentage string will be treated the same as an integer. - * @method yAxisPadding - * @memberof dc.coordinateGridMixin - * @instance - * @param {Number|String} [padding=0] - * @return {Number} - * @return {dc.coordinateGridMixin} - */ - _chart.yAxisPadding = function (padding) { - if (!arguments.length) { - return _yAxisPadding; - } - _yAxisPadding = padding; - return _chart; - }; - - _chart.yAxisHeight = function () { - return _chart.effectiveHeight(); - }; - - /** - * Set or get the rounding function used to quantize the selection when brushing is enabled. - * @method round - * @memberof dc.coordinateGridMixin - * @instance - * @example - * // set x unit round to by month, this will make sure range selection brush will - * // select whole months - * chart.round(d3.time.month.round); - * @param {Function} [round] - * @return {Function} - * @return {dc.coordinateGridMixin} - */ - _chart.round = function (round) { - if (!arguments.length) { - return _round; - } - _round = round; - return _chart; - }; - - _chart._rangeBandPadding = function (_) { - if (!arguments.length) { - return _rangeBandPadding; - } - _rangeBandPadding = _; - return _chart; - }; - - _chart._outerRangeBandPadding = function (_) { - if (!arguments.length) { - return _outerRangeBandPadding; - } - _outerRangeBandPadding = _; - return _chart; - }; - - dc.override(_chart, 'filter', function (_) { - if (!arguments.length) { - return _chart._filter(); - } - - _chart._filter(_); - - if (_) { - _chart.brush().extent(_); - } else { - _chart.brush().clear(); - } - - return _chart; - }); - - _chart.brush = function (_) { - if (!arguments.length) { - return _brush; - } - _brush = _; - return _chart; - }; - - function brushHeight () { - return _chart._xAxisY() - _chart.margins().top; - } - - _chart.renderBrush = function (g) { - if (_brushOn) { - _brush.on('brush', _chart._brushing); - _brush.on('brushstart', _chart._disableMouseZoom); - _brush.on('brushend', configureMouseZoom); - - var gBrush = g.append('g') - .attr('class', 'brush') - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')') - .call(_brush.x(_chart.x())); - _chart.setBrushY(gBrush, false); - _chart.setHandlePaths(gBrush); - - if (_chart.hasFilter()) { - _chart.redrawBrush(g, false); - } - } - }; - - _chart.setHandlePaths = function (gBrush) { - gBrush.selectAll('.resize').append('path').attr('d', _chart.resizeHandlePath); - }; - - _chart.setBrushY = function (gBrush) { - gBrush.selectAll('rect') - .attr('height', brushHeight()); - gBrush.selectAll('.resize path') - .attr('d', _chart.resizeHandlePath); - }; - - _chart.extendBrush = function () { - var extent = _brush.extent(); - if (_chart.round()) { - extent[0] = extent.map(_chart.round())[0]; - extent[1] = extent.map(_chart.round())[1]; - - _g.select('.brush') - .call(_brush.extent(extent)); - } - return extent; - }; - - _chart.brushIsEmpty = function (extent) { - return _brush.empty() || !extent || extent[1] <= extent[0]; - }; - - _chart._brushing = function () { - var extent = _chart.extendBrush(); - - _chart.redrawBrush(_g, false); - - if (_chart.brushIsEmpty(extent)) { - dc.events.trigger(function () { - _chart.filter(null); - _chart.redrawGroup(); - }, dc.constants.EVENT_DELAY); - } else { - var rangedFilter = dc.filters.RangedFilter(extent[0], extent[1]); - - dc.events.trigger(function () { - _chart.replaceFilter(rangedFilter); - _chart.redrawGroup(); - }, dc.constants.EVENT_DELAY); - } - }; - - _chart.redrawBrush = function (g, doTransition) { - if (_brushOn) { - if (_chart.filter() && _chart.brush().empty()) { - _chart.brush().extent(_chart.filter()); - } - - var gBrush = dc.optionalTransition(doTransition, _chart.transitionDuration())(g.select('g.brush')); - _chart.setBrushY(gBrush); - gBrush.call(_chart.brush() - .x(_chart.x()) - .extent(_chart.brush().extent())); - } - - _chart.fadeDeselectedArea(); - }; - - _chart.fadeDeselectedArea = function () { - // do nothing, sub-chart should override this function - }; - - // borrowed from Crossfilter example - _chart.resizeHandlePath = function (d) { - var e = +(d === 'e'), x = e ? 1 : -1, y = brushHeight() / 3; - return 'M' + (0.5 * x) + ',' + y + - 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + - 'V' + (2 * y - 6) + - 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y) + - 'Z' + - 'M' + (2.5 * x) + ',' + (y + 8) + - 'V' + (2 * y - 8) + - 'M' + (4.5 * x) + ',' + (y + 8) + - 'V' + (2 * y - 8); - }; - - function getClipPathId () { - return _chart.anchorName().replace(/[ .#=\[\]]/g, '-') + '-clip'; - } - - /** - * Get or set the padding in pixels for the clip path. Once set padding will be applied evenly to - * the top, left, right, and bottom when the clip path is generated. If set to zero, the clip area - * will be exactly the chart body area minus the margins. - * @method clipPadding - * @memberof dc.coordinateGridMixin - * @instance - * @param {Number} [padding=5] - * @return {Number} - * @return {dc.coordinateGridMixin} - */ - _chart.clipPadding = function (padding) { - if (!arguments.length) { - return _clipPadding; - } - _clipPadding = padding; - return _chart; - }; - - function generateClipPath () { - var defs = dc.utils.appendOrSelect(_parent, 'defs'); - // cannot select elements; bug in WebKit, must select by id - // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I - var id = getClipPathId(); - var chartBodyClip = dc.utils.appendOrSelect(defs, '#' + id, 'clipPath').attr('id', id); - - var padding = _clipPadding * 2; - - dc.utils.appendOrSelect(chartBodyClip, 'rect') - .attr('width', _chart.xAxisLength() + padding) - .attr('height', _chart.yAxisHeight() + padding) - .attr('transform', 'translate(-' + _clipPadding + ', -' + _clipPadding + ')'); - } - - _chart._preprocessData = function () {}; - - _chart._doRender = function () { - _chart.resetSvg(); - - _chart._preprocessData(); - - _chart._generateG(); - generateClipPath(); - - drawChart(true); - - configureMouseZoom(); - - return _chart; - }; - - _chart._doRedraw = function () { - _chart._preprocessData(); - - drawChart(false); - generateClipPath(); - - return _chart; - }; - - function drawChart (render) { - if (_chart.isOrdinal()) { - _brushOn = false; - } - - prepareXAxis(_chart.g(), render); - _chart._prepareYAxis(_chart.g()); - - _chart.plotData(); - - if (_chart.elasticX() || _resizing || render) { - _chart.renderXAxis(_chart.g()); - } - - if (_chart.elasticY() || _resizing || render) { - _chart.renderYAxis(_chart.g()); - } - - if (render) { - _chart.renderBrush(_chart.g(), false); - } else { - _chart.redrawBrush(_chart.g(), _resizing); - } - _chart.fadeDeselectedArea(); - _resizing = false; - } - - function configureMouseZoom () { - if (_mouseZoomable) { - _chart._enableMouseZoom(); - } else if (_hasBeenMouseZoomable) { - _chart._disableMouseZoom(); - } - } - - _chart._enableMouseZoom = function () { - _hasBeenMouseZoomable = true; - _zoom.x(_chart.x()) - .scaleExtent(_zoomScale) - .size([_chart.width(), _chart.height()]) - .duration(_chart.transitionDuration()); - _chart.root().call(_zoom); - }; - - _chart._disableMouseZoom = function () { - _chart.root().call(_nullZoom); - }; - - function constrainRange (range, constraint) { - var constrainedRange = []; - constrainedRange[0] = d3.max([range[0], constraint[0]]); - constrainedRange[1] = d3.min([range[1], constraint[1]]); - return constrainedRange; - } - - /** - * Zoom this chart to focus on the given range. The given range should be an array containing only - * 2 elements (`[start, end]`) defining a range in the x domain. If the range is not given or set - * to null, then the zoom will be reset. _For focus to work elasticX has to be turned off; - * otherwise focus will be ignored. - * @method focus - * @memberof dc.coordinateGridMixin - * @instance - * @example - * chart.on('renderlet', function(chart) { - * // smooth the rendering through event throttling - * dc.events.trigger(function(){ - * // focus some other chart to the range selected by user on this chart - * someOtherChart.focus(chart.filter()); - * }); - * }) - * @param {Array} [range] - */ - _chart.focus = function (range) { - if (hasRangeSelected(range)) { - _chart.x().domain(range); - } else { - _chart.x().domain(_xOriginalDomain); - } - - _zoom.x(_chart.x()); - zoomHandler(); - }; - - _chart.refocused = function () { - return _refocused; - }; - - _chart.focusChart = function (c) { - if (!arguments.length) { - return _focusChart; - } - _focusChart = c; - _chart.on('filtered', function (chart) { - if (!chart.filter()) { - dc.events.trigger(function () { - _focusChart.x().domain(_focusChart.xOriginalDomain()); - }); - } else if (!rangesEqual(chart.filter(), _focusChart.filter())) { - dc.events.trigger(function () { - _focusChart.focus(chart.filter()); - }); - } - }); - return _chart; - }; - - function rangesEqual (range1, range2) { - if (!range1 && !range2) { - return true; - } else if (!range1 || !range2) { - return false; - } else if (range1.length === 0 && range2.length === 0) { - return true; - } else if (range1[0].valueOf() === range2[0].valueOf() && - range1[1].valueOf() === range2[1].valueOf()) { - return true; - } - return false; - } - - /** - * Turn on/off the brush-based range filter. When brushing is on then user can drag the mouse - * across a chart with a quantitative scale to perform range filtering based on the extent of the - * brush, or click on the bars of an ordinal bar chart or slices of a pie chart to filter and - * un-filter them. However turning on the brush filter will disable other interactive elements on - * the chart such as highlighting, tool tips, and reference lines. Zooming will still be possible - * if enabled, but only via scrolling (panning will be disabled.) - * @method brushOn - * @memberof dc.coordinateGridMixin - * @instance - * @param {Boolean} [brushOn=true] - * @return {Boolean} - * @return {dc.coordinateGridMixin} - */ - _chart.brushOn = function (brushOn) { - if (!arguments.length) { - return _brushOn; - } - _brushOn = brushOn; - return _chart; - }; - - function hasRangeSelected (range) { - return range instanceof Array && range.length > 1; - } - - return _chart; -}; - -/** - * Stack Mixin is an mixin that provides cross-chart support of stackability using d3.layout.stack. - * @name stackMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.stackMixin} - */ -dc.stackMixin = function (_chart) { - - function prepareValues (layer, layerIdx) { - var valAccessor = layer.accessor || _chart.valueAccessor(); - layer.name = String(layer.name || layerIdx); - layer.values = layer.group.all().map(function (d, i) { - return { - x: _chart.keyAccessor()(d, i), - y: layer.hidden ? null : valAccessor(d, i), - data: d, - layer: layer.name, - hidden: layer.hidden - }; - }); - - layer.values = layer.values.filter(domainFilter()); - return layer.values; - } - - var _stackLayout = d3.layout.stack() - .values(prepareValues); - - var _stack = []; - var _titles = {}; - - var _hidableStacks = false; - - function domainFilter () { - if (!_chart.x()) { - return d3.functor(true); - } - var xDomain = _chart.x().domain(); - if (_chart.isOrdinal()) { - // TODO #416 - //var domainSet = d3.set(xDomain); - return function () { - return true; //domainSet.has(p.x); - }; - } - if (_chart.elasticX()) { - return function () { return true; }; - } - return function (p) { - //return true; - return p.x >= xDomain[0] && p.x <= xDomain[xDomain.length - 1]; - }; - } - - /** - * Stack a new crossfilter group onto this chart with an optional custom value accessor. All stacks - * in the same chart will share the same key accessor and therefore the same set of keys. - * - * For example, in a stacked bar chart, the bars of each stack will be positioned using the same set - * of keys on the x axis, while stacked vertically. If name is specified then it will be used to - * generate the legend label. - * @method stack - * @memberof dc.stackMixin - * @instance - * @see {@link https://github.com/square/crossfilter/wiki/API-Reference#group-map-reduce crossfilter.group} - * @example - * // stack group using default accessor - * chart.stack(valueSumGroup) - * // stack group using custom accessor - * .stack(avgByDayGroup, function(d){return d.value.avgByDay;}); - * @param {crossfilter.group} group - * @param {String} [name] - * @param {Function} [accessor] - * @return {Array<{group: crossfilter.group, name: String, accessor: Function}>} - * @return {dc.stackMixin} - */ - _chart.stack = function (group, name, accessor) { - if (!arguments.length) { - return _stack; - } - - if (arguments.length <= 2) { - accessor = name; - } - - var layer = {group: group}; - if (typeof name === 'string') { - layer.name = name; - } - if (typeof accessor === 'function') { - layer.accessor = accessor; - } - _stack.push(layer); - - return _chart; - }; - - dc.override(_chart, 'group', function (g, n, f) { - if (!arguments.length) { - return _chart._group(); - } - _stack = []; - _titles = {}; - _chart.stack(g, n); - if (f) { - _chart.valueAccessor(f); - } - return _chart._group(g, n); - }); - - /** - * Allow named stacks to be hidden or shown by clicking on legend items. - * This does not affect the behavior of hideStack or showStack. - * @method hidableStacks - * @memberof dc.stackMixin - * @instance - * @param {Boolean} [hidableStacks=false] - * @return {Boolean} - * @return {dc.stackMixin} - */ - _chart.hidableStacks = function (hidableStacks) { - if (!arguments.length) { - return _hidableStacks; - } - _hidableStacks = hidableStacks; - return _chart; - }; - - function findLayerByName (n) { - var i = _stack.map(dc.pluck('name')).indexOf(n); - return _stack[i]; - } - - /** - * Hide all stacks on the chart with the given name. - * The chart must be re-rendered for this change to appear. - * @method hideStack - * @memberof dc.stackMixin - * @instance - * @param {String} stackName - * @return {dc.stackMixin} - */ - _chart.hideStack = function (stackName) { - var layer = findLayerByName(stackName); - if (layer) { - layer.hidden = true; - } - return _chart; - }; - - /** - * Show all stacks on the chart with the given name. - * The chart must be re-rendered for this change to appear. - * @method showStack - * @memberof dc.stackMixin - * @instance - * @param {String} stackName - * @return {dc.stackMixin} - */ - _chart.showStack = function (stackName) { - var layer = findLayerByName(stackName); - if (layer) { - layer.hidden = false; - } - return _chart; - }; - - _chart.getValueAccessorByIndex = function (index) { - return _stack[index].accessor || _chart.valueAccessor(); - }; - - _chart.yAxisMin = function () { - var min = d3.min(flattenStack(), function (p) { - return (p.y < 0) ? (p.y + p.y0) : p.y0; - }); - - return dc.utils.subtract(min, _chart.yAxisPadding()); - - }; - - _chart.yAxisMax = function () { - var max = d3.max(flattenStack(), function (p) { - return (p.y > 0) ? (p.y + p.y0) : p.y0; - }); - - return dc.utils.add(max, _chart.yAxisPadding()); - }; - - function flattenStack () { - var valueses = _chart.data().map(function (layer) { return layer.values; }); - return Array.prototype.concat.apply([], valueses); - } - - _chart.xAxisMin = function () { - var min = d3.min(flattenStack(), dc.pluck('x')); - return dc.utils.subtract(min, _chart.xAxisPadding()); - }; - - _chart.xAxisMax = function () { - var max = d3.max(flattenStack(), dc.pluck('x')); - return dc.utils.add(max, _chart.xAxisPadding()); - }; - - /** - * Set or get the title function. Chart class will use this function to render svg title (usually interpreted by - * browser as tooltips) for each child element in the chart, i.e. a slice in a pie chart or a bubble in a bubble chart. - * Almost every chart supports title function however in grid coordinate chart you need to turn off brush in order to - * use title otherwise the brush layer will block tooltip trigger. - * - * If the first argument is a stack name, the title function will get or set the title for that stack. If stackName - * is not provided, the first stack is implied. - * @method title - * @memberof dc.stackMixin - * @instance - * @example - * // set a title function on 'first stack' - * chart.title('first stack', function(d) { return d.key + ': ' + d.value; }); - * // get a title function from 'second stack' - * var secondTitleFunction = chart.title('second stack'); - * @param {String} [stackName] - * @param {Function} [titleAccessor] - * @return {String} - * @return {dc.stackMixin} - */ - dc.override(_chart, 'title', function (stackName, titleAccessor) { - if (!stackName) { - return _chart._title(); - } - - if (typeof stackName === 'function') { - return _chart._title(stackName); - } - if (stackName === _chart._groupName && typeof titleAccessor === 'function') { - return _chart._title(titleAccessor); - } - - if (typeof titleAccessor !== 'function') { - return _titles[stackName] || _chart._title(); - } - - _titles[stackName] = titleAccessor; - - return _chart; - }); - - /** - * Gets or sets the stack layout algorithm, which computes a baseline for each stack and - * propagates it to the next - * @method stackLayout - * @memberof dc.stackMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Stack-Layout d3.layout.stack} - * @param {Function} [stack=d3.layout.stack] - * @return {Function} - * @return {dc.stackMixin} - */ - _chart.stackLayout = function (stack) { - if (!arguments.length) { - return _stackLayout; - } - _stackLayout = stack; - if (_stackLayout.values() === d3.layout.stack().values()) { - _stackLayout.values(prepareValues); - } - return _chart; - }; - - function visability (l) { - return !l.hidden; - } - - _chart.data(function () { - var layers = _stack.filter(visability); - return layers.length ? _chart.stackLayout()(layers) : []; - }); - - _chart._ordinalXDomain = function () { - var flat = flattenStack().map(dc.pluck('data')); - var ordered = _chart._computeOrderedGroups(flat); - return ordered.map(_chart.keyAccessor()); - }; - - _chart.colorAccessor(function (d) { - var layer = this.layer || this.name || d.name || d.layer; - return layer; - }); - - _chart.legendables = function () { - return _stack.map(function (layer, i) { - return { - chart: _chart, - name: layer.name, - hidden: layer.hidden || false, - color: _chart.getColor.call(layer, layer.values, i) - }; - }); - }; - - _chart.isLegendableHidden = function (d) { - var layer = findLayerByName(d.name); - return layer ? layer.hidden : false; - }; - - _chart.legendToggle = function (d) { - if (_hidableStacks) { - if (_chart.isLegendableHidden(d)) { - _chart.showStack(d.name); - } else { - _chart.hideStack(d.name); - } - //_chart.redraw(); - _chart.renderGroup(); - } - }; - - return _chart; -}; - -/** - * Cap is a mixin that groups small data elements below a _cap_ into an *others* grouping for both the - * Row and Pie Charts. - * - * The top ordered elements in the group up to the cap amount will be kept in the chart, and the rest - * will be replaced with an *others* element, with value equal to the sum of the replaced values. The - * keys of the elements below the cap limit are recorded in order to filter by those keys when the - * others* element is clicked. - * @name capMixin - * @memberof dc - * @mixin - * @param {Object} _chart - * @return {dc.capMixin} - */ -dc.capMixin = function (_chart) { - - var _cap = Infinity; - - var _othersLabel = 'Others'; - - var _othersGrouper = function (topRows) { - var topRowsSum = d3.sum(topRows, _chart.valueAccessor()), - allRows = _chart.group().all(), - allRowsSum = d3.sum(allRows, _chart.valueAccessor()), - topKeys = topRows.map(_chart.keyAccessor()), - allKeys = allRows.map(_chart.keyAccessor()), - topSet = d3.set(topKeys), - others = allKeys.filter(function (d) {return !topSet.has(d);}); - if (allRowsSum > topRowsSum) { - return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]); - } - return topRows; - }; - - _chart.cappedKeyAccessor = function (d, i) { - if (d.others) { - return d.key; - } - return _chart.keyAccessor()(d, i); - }; - - _chart.cappedValueAccessor = function (d, i) { - if (d.others) { - return d.value; - } - return _chart.valueAccessor()(d, i); - }; - - _chart.data(function (group) { - if (_cap === Infinity) { - return _chart._computeOrderedGroups(group.all()); - } else { - var topRows = group.top(_cap); // ordered by crossfilter group order (default value) - topRows = _chart._computeOrderedGroups(topRows); // re-order using ordering (default key) - if (_othersGrouper) { - return _othersGrouper(topRows); - } - return topRows; - } - }); - - /** - * Get or set the count of elements to that will be included in the cap. - * @method cap - * @memberof dc.capMixin - * @instance - * @param {Number} [count=Infinity] - * @return {Number} - * @return {dc.capMixin} - */ - _chart.cap = function (count) { - if (!arguments.length) { - return _cap; - } - _cap = count; - return _chart; - }; - - /** - * Get or set the label for *Others* slice when slices cap is specified - * @method othersLabel - * @memberof dc.capMixin - * @instance - * @param {String} [label="Others"] - * @return {String} - * @return {dc.capMixin} - */ - _chart.othersLabel = function (label) { - if (!arguments.length) { - return _othersLabel; - } - _othersLabel = label; - return _chart; - }; - - /** - * Get or set the grouper function that will perform the insertion of data for the *Others* slice - * if the slices cap is specified. If set to a falsy value, no others will be added. By default the - * grouper function computes the sum of all values below the cap. - * @method othersGrouper - * @memberof dc.capMixin - * @instance - * @example - * // Default others grouper - * chart.othersGrouper(function (topRows) { - * var topRowsSum = d3.sum(topRows, _chart.valueAccessor()), - * allRows = _chart.group().all(), - * allRowsSum = d3.sum(allRows, _chart.valueAccessor()), - * topKeys = topRows.map(_chart.keyAccessor()), - * allKeys = allRows.map(_chart.keyAccessor()), - * topSet = d3.set(topKeys), - * others = allKeys.filter(function (d) {return !topSet.has(d);}); - * if (allRowsSum > topRowsSum) { - * return topRows.concat([{'others': others, 'key': _othersLabel, 'value': allRowsSum - topRowsSum}]); - * } - * return topRows; - * }); - * // Custom others grouper - * chart.othersGrouper(function (data) { - * // compute the value for others, presumably the sum of all values below the cap - * var othersSum = yourComputeOthersValueLogic(data) - * - * // the keys are needed to properly filter when the others element is clicked - * var othersKeys = yourComputeOthersKeysArrayLogic(data); - * - * // add the others row to the dataset - * data.push({'key': 'Others', 'value': othersSum, 'others': othersKeys }); - * - * return data; - * }); - * @param {Function} [grouperFunction] - * @return {Function} - * @return {dc.capMixin} - */ - _chart.othersGrouper = function (grouperFunction) { - if (!arguments.length) { - return _othersGrouper; - } - _othersGrouper = grouperFunction; - return _chart; - }; - - dc.override(_chart, 'onClick', function (d) { - if (d.others) { - _chart.filter([d.others]); - } - _chart._onClick(d); - }); - - return _chart; -}; - -/** - * This Mixin provides reusable functionalities for any chart that needs to visualize data using bubbles. - * @name bubbleMixin - * @memberof dc - * @mixin - * @mixes dc.colorMixin - * @param {Object} _chart - * @return {dc.bubbleMixin} - */ -dc.bubbleMixin = function (_chart) { - var _maxBubbleRelativeSize = 0.3; - var _minRadiusWithLabel = 10; - - _chart.BUBBLE_NODE_CLASS = 'node'; - _chart.BUBBLE_CLASS = 'bubble'; - _chart.MIN_RADIUS = 10; - - _chart = dc.colorMixin(_chart); - - _chart.renderLabel(true); - - _chart.data(function (group) { - return group.top(Infinity); - }); - - var _r = d3.scale.linear().domain([0, 100]); - - var _rValueAccessor = function (d) { - return d.r; - }; - - /** - * Get or set the bubble radius scale. By default the bubble chart uses - * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales#linear d3.scale.linear().domain([0, 100])} - * as its radius scale. - * @method r - * @memberof dc.bubbleMixin - * @instance - * @see {@link http://github.com/mbostock/d3/wiki/Scales d3.scale} - * @param {d3.scale} [bubbleRadiusScale=d3.scale.linear().domain([0, 100])] - * @return {d3.scale} - * @return {dc.bubbleMixin} - */ - _chart.r = function (bubbleRadiusScale) { - if (!arguments.length) { - return _r; - } - _r = bubbleRadiusScale; - return _chart; - }; - - /** - * Get or set the radius value accessor function. If set, the radius value accessor function will - * be used to retrieve a data value for each bubble. The data retrieved then will be mapped using - * the r scale to the actual bubble radius. This allows you to encode a data dimension using bubble - * size. - * @method radiusValueAccessor - * @memberof dc.bubbleMixin - * @instance - * @param {Function} [radiusValueAccessor] - * @return {Function} - * @return {dc.bubbleMixin} - */ - _chart.radiusValueAccessor = function (radiusValueAccessor) { - if (!arguments.length) { - return _rValueAccessor; - } - _rValueAccessor = radiusValueAccessor; - return _chart; - }; - - _chart.rMin = function () { - var min = d3.min(_chart.data(), function (e) { - return _chart.radiusValueAccessor()(e); - }); - return min; - }; - - _chart.rMax = function () { - var max = d3.max(_chart.data(), function (e) { - return _chart.radiusValueAccessor()(e); - }); - return max; - }; - - _chart.bubbleR = function (d) { - var value = _chart.radiusValueAccessor()(d); - var r = _chart.r()(value); - if (isNaN(r) || value <= 0) { - r = 0; - } - return r; - }; - - var labelFunction = function (d) { - return _chart.label()(d); - }; - - var shouldLabel = function (d) { - return (_chart.bubbleR(d) > _minRadiusWithLabel); - }; - - var labelOpacity = function (d) { - return shouldLabel(d) ? 1 : 0; - }; - - var labelPointerEvent = function (d) { - return shouldLabel(d) ? 'all' : 'none'; - }; - - _chart._doRenderLabel = function (bubbleGEnter) { - if (_chart.renderLabel()) { - var label = bubbleGEnter.select('text'); - - if (label.empty()) { - label = bubbleGEnter.append('text') - .attr('text-anchor', 'middle') - .attr('dy', '.3em') - .on('click', _chart.onClick); - } - - label - .attr('opacity', 0) - .attr('pointer-events', labelPointerEvent) - .text(labelFunction); - dc.transition(label, _chart.transitionDuration()) - .attr('opacity', labelOpacity); - } - }; - - _chart.doUpdateLabels = function (bubbleGEnter) { - if (_chart.renderLabel()) { - var labels = bubbleGEnter.selectAll('text') - .attr('pointer-events', labelPointerEvent) - .text(labelFunction); - dc.transition(labels, _chart.transitionDuration()) - .attr('opacity', labelOpacity); - } - }; - - var titleFunction = function (d) { - return _chart.title()(d); - }; - - _chart._doRenderTitles = function (g) { - if (_chart.renderTitle()) { - var title = g.select('title'); - - if (title.empty()) { - g.append('title').text(titleFunction); - } - } - }; - - _chart.doUpdateTitles = function (g) { - if (_chart.renderTitle()) { - g.selectAll('title').text(titleFunction); - } - }; - - /** - * Get or set the minimum radius. This will be used to initialize the radius scale's range. - * @method minRadius - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [radius=10] - * @return {Number} - * @return {dc.bubbleMixin} - */ - _chart.minRadius = function (radius) { - if (!arguments.length) { - return _chart.MIN_RADIUS; - } - _chart.MIN_RADIUS = radius; - return _chart; - }; - - /** - * Get or set the minimum radius for label rendering. If a bubble's radius is less than this value - * then no label will be rendered. - * @method minRadiusWithLabel - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [radius=10] - * @return {Number} - * @return {dc.bubbleMixin} - */ - - _chart.minRadiusWithLabel = function (radius) { - if (!arguments.length) { - return _minRadiusWithLabel; - } - _minRadiusWithLabel = radius; - return _chart; - }; - - /** - * Get or set the maximum relative size of a bubble to the length of x axis. This value is useful - * when the difference in radius between bubbles is too great. - * @method maxBubbleRelativeSize - * @memberof dc.bubbleMixin - * @instance - * @param {Number} [relativeSize=0.3] - * @return {Number} - * @return {dc.bubbleMixin} - */ - _chart.maxBubbleRelativeSize = function (relativeSize) { - if (!arguments.length) { - return _maxBubbleRelativeSize; - } - _maxBubbleRelativeSize = relativeSize; - return _chart; - }; - - _chart.fadeDeselectedArea = function () { - if (_chart.hasFilter()) { - _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function (d) { - if (_chart.isSelectedNode(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.selectAll('g.' + _chart.BUBBLE_NODE_CLASS).each(function () { - _chart.resetHighlight(this); - }); - } - }; - - _chart.isSelectedNode = function (d) { - return _chart.hasFilter(d.key); - }; - - _chart.onClick = function (d) { - var filter = d.key; - dc.events.trigger(function () { - _chart.filter(filter); - _chart.redrawGroup(); - }); - }; - - return _chart; -}; - -/** - * The pie chart implementation is usually used to visualize a small categorical distribution. The pie - * chart uses keyAccessor to determine the slices, and valueAccessor to calculate the size of each - * slice relative to the sum of all values. Slices are ordered by {@link dc.baseMixin#ordering ordering} - * which defaults to sorting by key. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * @class pieChart - * @memberof dc - * @mixes dc.capMixin - * @mixes dc.colorMixin - * @mixes dc.baseMixin - * @example - * // create a pie chart under #chart-container1 element using the default global chart group - * var chart1 = dc.pieChart('#chart-container1'); - * // create a pie chart under #chart-container2 element using chart group A - * var chart2 = dc.pieChart('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.pieChart} - */ -dc.pieChart = function (parent, chartGroup) { - var DEFAULT_MIN_ANGLE_FOR_LABEL = 0.5; - - var _sliceCssClass = 'pie-slice'; - var _labelCssClass = 'pie-label'; - var _sliceGroupCssClass = 'pie-slice-group'; - var _labelGroupCssClass = 'pie-label-group'; - var _emptyCssClass = 'empty-chart'; - var _emptyTitle = 'empty'; - - var _radius, - _givenRadius, // specified radius, if any - _innerRadius = 0, - _externalRadiusPadding = 0; - - var _g; - var _cx; - var _cy; - var _minAngleForLabel = DEFAULT_MIN_ANGLE_FOR_LABEL; - var _externalLabelRadius; - var _drawPaths = false; - var _chart = dc.capMixin(dc.colorMixin(dc.baseMixin({}))); - - _chart.colorAccessor(_chart.cappedKeyAccessor); - - _chart.title(function (d) { - return _chart.cappedKeyAccessor(d) + ': ' + _chart.cappedValueAccessor(d); - }); - - /** - * Get or set the maximum number of slices the pie chart will generate. The top slices are determined by - * value from high to low. Other slices exeeding the cap will be rolled up into one single *Others* slice. - * @method slicesCap - * @memberof dc.pieChart - * @instance - * @param {Number} [cap] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.slicesCap = _chart.cap; - - _chart.label(_chart.cappedKeyAccessor); - _chart.renderLabel(true); - - _chart.transitionDuration(350); - - _chart._doRender = function () { - _chart.resetSvg(); - - _g = _chart.svg() - .append('g') - .attr('transform', 'translate(' + _chart.cx() + ',' + _chart.cy() + ')'); - - _g.append('g').attr('class', _sliceGroupCssClass); - _g.append('g').attr('class', _labelGroupCssClass); - - drawChart(); - - return _chart; - }; - - function drawChart () { - // set radius on basis of chart dimension if missing - _radius = _givenRadius ? _givenRadius : d3.min([_chart.width(), _chart.height()]) / 2; - - var arc = buildArcs(); - - var pie = pieLayout(); - var pieData; - // if we have data... - if (d3.sum(_chart.data(), _chart.valueAccessor())) { - pieData = pie(_chart.data()); - _g.classed(_emptyCssClass, false); - } else { - // otherwise we'd be getting NaNs, so override - // note: abuse others for its ignoring the value accessor - pieData = pie([{key: _emptyTitle, value: 1, others: [_emptyTitle]}]); - _g.classed(_emptyCssClass, true); - } - - if (_g) { - var slices = _g.select('g.' + _sliceGroupCssClass) - .selectAll('g.' + _sliceCssClass) - .data(pieData); - - var labels = _g.select('g.' + _labelGroupCssClass) - .selectAll('text.' + _labelCssClass) - .data(pieData); - - createElements(slices, labels, arc, pieData); - - updateElements(pieData, arc); - - removeElements(slices, labels); - - highlightFilter(); - - dc.transition(_g, _chart.transitionDuration()) - .attr('transform', 'translate(' + _chart.cx() + ',' + _chart.cy() + ')'); - } - } - - function createElements (slices, labels, arc, pieData) { - var slicesEnter = createSliceNodes(slices); - - createSlicePath(slicesEnter, arc); - - createTitles(slicesEnter); - - createLabels(labels, pieData, arc); - } - - function createSliceNodes (slices) { - var slicesEnter = slices - .enter() - .append('g') - .attr('class', function (d, i) { - return _sliceCssClass + ' _' + i; - }); - return slicesEnter; - } - - function createSlicePath (slicesEnter, arc) { - var slicePath = slicesEnter.append('path') - .attr('fill', fill) - .on('click', onClick) - .attr('d', function (d, i) { - return safeArc(d, i, arc); - }); - - dc.transition(slicePath, _chart.transitionDuration(), function (s) { - s.attrTween('d', tweenPie); - }); - } - - function createTitles (slicesEnter) { - if (_chart.renderTitle()) { - slicesEnter.append('title').text(function (d) { - return _chart.title()(d.data); - }); - } - } - - _chart._applyLabelText = function (labels) { - labels - .text(function (d) { - var data = d.data; - if ((sliceHasNoData(data) || sliceTooSmall(d)) && !isSelectedSlice(d)) { - return ''; - } - return _chart.label()(d.data); - }); - }; - - function positionLabels (labels, arc) { - _chart._applyLabelText(labels); - dc.transition(labels, _chart.transitionDuration()) - .attr('transform', function (d) { - return labelPosition(d, arc); - }) - .attr('text-anchor', 'middle'); - } - - function highlightSlice (i, whether) { - _chart.select('g.pie-slice._' + i) - .classed('highlight', whether); - } - - function createLabels (labels, pieData, arc) { - if (_chart.renderLabel()) { - var labelsEnter = labels - .enter() - .append('text') - .attr('class', function (d, i) { - var classes = _sliceCssClass + ' ' + _labelCssClass + ' _' + i; - if (_externalLabelRadius) { - classes += ' external'; - } - return classes; - }) - .on('click', onClick) - .on('mouseover', function (d, i) { - highlightSlice(i, true); - }) - .on('mouseout', function (d, i) { - highlightSlice(i, false); - }); - positionLabels(labelsEnter, arc); - if (_externalLabelRadius && _drawPaths) { - updateLabelPaths(pieData, arc); - } - } - } - - function updateLabelPaths (pieData, arc) { - var polyline = _g.selectAll('polyline.' + _sliceCssClass) - .data(pieData); - - polyline - .enter() - .append('polyline') - .attr('class', function (d, i) { - return 'pie-path _' + i + ' ' + _sliceCssClass; - }) - .on('click', onClick) - .on('mouseover', function (d, i) { - highlightSlice(i, true); - }) - .on('mouseout', function (d, i) { - highlightSlice(i, false); - }); - - polyline.exit().remove(); - var arc2 = d3.svg.arc() - .outerRadius(_radius - _externalRadiusPadding + _externalLabelRadius) - .innerRadius(_radius - _externalRadiusPadding); - var transition = dc.transition(polyline, _chart.transitionDuration()); - // this is one rare case where d3.selection differs from d3.transition - if (transition.attrTween) { - transition - .attrTween('points', function (d) { - this._current = this._current || d; - var interpolate = d3.interpolate(this._current, d); - this._current = interpolate(0); - return function (t) { - var d2 = interpolate(t); - return [arc.centroid(d2), arc2.centroid(d2)]; - }; - }); - } else { - transition.attr('points', function (d) { - return [arc.centroid(d), arc2.centroid(d)]; - }); - } - transition.style('visibility', function (d) { - return d.endAngle - d.startAngle < 0.0001 ? 'hidden' : 'visible'; - }); - - } - - function updateElements (pieData, arc) { - updateSlicePaths(pieData, arc); - updateLabels(pieData, arc); - updateTitles(pieData); - } - - function updateSlicePaths (pieData, arc) { - var slicePaths = _g.selectAll('g.' + _sliceCssClass) - .data(pieData) - .select('path') - .attr('d', function (d, i) { - return safeArc(d, i, arc); - }); - dc.transition(slicePaths, _chart.transitionDuration(), - function (s) { - s.attrTween('d', tweenPie); - }).attr('fill', fill); - } - - function updateLabels (pieData, arc) { - if (_chart.renderLabel()) { - var labels = _g.selectAll('text.' + _labelCssClass) - .data(pieData); - positionLabels(labels, arc); - if (_externalLabelRadius && _drawPaths) { - updateLabelPaths(pieData, arc); - } - } - } - - function updateTitles (pieData) { - if (_chart.renderTitle()) { - _g.selectAll('g.' + _sliceCssClass) - .data(pieData) - .select('title') - .text(function (d) { - return _chart.title()(d.data); - }); - } - } - - function removeElements (slices, labels) { - slices.exit().remove(); - labels.exit().remove(); - } - - function highlightFilter () { - if (_chart.hasFilter()) { - _chart.selectAll('g.' + _sliceCssClass).each(function (d) { - if (isSelectedSlice(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.selectAll('g.' + _sliceCssClass).each(function () { - _chart.resetHighlight(this); - }); - } - } - - /** - * Get or set the external radius padding of the pie chart. This will force the radius of the - * pie chart to become smaller or larger depending on the value. - * @method externalRadiusPadding - * @memberof dc.pieChart - * @instance - * @param {Number} [externalRadiusPadding=0] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.externalRadiusPadding = function (externalRadiusPadding) { - if (!arguments.length) { - return _externalRadiusPadding; - } - _externalRadiusPadding = externalRadiusPadding; - return _chart; - }; - - /** - * Get or set the inner radius of the pie chart. If the inner radius is greater than 0px then the - * pie chart will be rendered as a doughnut chart. - * @method innerRadius - * @memberof dc.pieChart - * @instance - * @param {Number} [innerRadius=0] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.innerRadius = function (innerRadius) { - if (!arguments.length) { - return _innerRadius; - } - _innerRadius = innerRadius; - return _chart; - }; - - /** - * Get or set the outer radius. If the radius is not set, it will be half of the minimum of the - * chart width and height. - * @method radius - * @memberof dc.pieChart - * @instance - * @param {Number} [radius] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.radius = function (radius) { - if (!arguments.length) { - return _givenRadius; - } - _givenRadius = radius; - return _chart; - }; - - /** - * Get or set center x coordinate position. Default is center of svg. - * @method cx - * @memberof dc.pieChart - * @instance - * @param {Number} [cx] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.cx = function (cx) { - if (!arguments.length) { - return (_cx || _chart.width() / 2); - } - _cx = cx; - return _chart; - }; - - /** - * Get or set center y coordinate position. Default is center of svg. - * @method cy - * @memberof dc.pieChart - * @instance - * @param {Number} [cy] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.cy = function (cy) { - if (!arguments.length) { - return (_cy || _chart.height() / 2); - } - _cy = cy; - return _chart; - }; - - function buildArcs () { - return d3.svg.arc() - .outerRadius(_radius - _externalRadiusPadding) - .innerRadius(_innerRadius); - } - - function isSelectedSlice (d) { - return _chart.hasFilter(_chart.cappedKeyAccessor(d.data)); - } - - _chart._doRedraw = function () { - drawChart(); - return _chart; - }; - - /** - * Get or set the minimal slice angle for label rendering. Any slice with a smaller angle will not - * display a slice label. - * @method minAngleForLabel - * @memberof dc.pieChart - * @instance - * @param {Number} [minAngleForLabel=0.5] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.minAngleForLabel = function (minAngleForLabel) { - if (!arguments.length) { - return _minAngleForLabel; - } - _minAngleForLabel = minAngleForLabel; - return _chart; - }; - - function pieLayout () { - return d3.layout.pie().sort(null).value(_chart.cappedValueAccessor); - } - - function sliceTooSmall (d) { - var angle = (d.endAngle - d.startAngle); - return isNaN(angle) || angle < _minAngleForLabel; - } - - function sliceHasNoData (d) { - return _chart.cappedValueAccessor(d) === 0; - } - - function tweenPie (b) { - b.innerRadius = _innerRadius; - var current = this._current; - if (isOffCanvas(current)) { - current = {startAngle: 0, endAngle: 0}; - } else { - // only interpolate startAngle & endAngle, not the whole data object - current = {startAngle: current.startAngle, endAngle: current.endAngle}; - } - var i = d3.interpolate(current, b); - this._current = i(0); - return function (t) { - return safeArc(i(t), 0, buildArcs()); - }; - } - - function isOffCanvas (current) { - return !current || isNaN(current.startAngle) || isNaN(current.endAngle); - } - - function fill (d, i) { - return _chart.getColor(d.data, i); - } - - function onClick (d, i) { - if (_g.attr('class') !== _emptyCssClass) { - _chart.onClick(d.data, i); - } - } - - function safeArc (d, i, arc) { - var path = arc(d, i); - if (path.indexOf('NaN') >= 0) { - path = 'M0,0'; - } - return path; - } - - /** - * Title to use for the only slice when there is no data. - * @method emptyTitle - * @memberof dc.pieChart - * @instance - * @param {String} [title] - * @return {String} - * @return {dc.pieChart} - */ - _chart.emptyTitle = function (title) { - if (arguments.length === 0) { - return _emptyTitle; - } - _emptyTitle = title; - return _chart; - }; - - /** - * Position slice labels offset from the outer edge of the chart - * - * The given argument sets the radial offset. - * @method externalLabels - * @memberof dc.pieChart - * @instance - * @param {Number} [externalLabelRadius] - * @return {Number} - * @return {dc.pieChart} - */ - _chart.externalLabels = function (externalLabelRadius) { - if (arguments.length === 0) { - return _externalLabelRadius; - } else if (externalLabelRadius) { - _externalLabelRadius = externalLabelRadius; - } else { - _externalLabelRadius = undefined; - } - - return _chart; - }; - - /** - * Get or set whether to draw lines from pie slices to their labels. - * - * @method drawPaths - * @memberof dc.pieChart - * @instance - * @param {Boolean} [drawPaths] - * @return {Boolean} - * @return {dc.pieChart} - */ - _chart.drawPaths = function (drawPaths) { - if (arguments.length === 0) { - return _drawPaths; - } - _drawPaths = drawPaths; - return _chart; - }; - - function labelPosition (d, arc) { - var centroid; - if (_externalLabelRadius) { - centroid = d3.svg.arc() - .outerRadius(_radius - _externalRadiusPadding + _externalLabelRadius) - .innerRadius(_radius - _externalRadiusPadding + _externalLabelRadius) - .centroid(d); - } else { - centroid = arc.centroid(d); - } - if (isNaN(centroid[0]) || isNaN(centroid[1])) { - return 'translate(0,0)'; - } else { - return 'translate(' + centroid + ')'; - } - } - - _chart.legendables = function () { - return _chart.data().map(function (d, i) { - var legendable = {name: d.key, data: d.value, others: d.others, chart: _chart}; - legendable.color = _chart.getColor(d, i); - return legendable; - }); - }; - - _chart.legendHighlight = function (d) { - highlightSliceFromLegendable(d, true); - }; - - _chart.legendReset = function (d) { - highlightSliceFromLegendable(d, false); - }; - - _chart.legendToggle = function (d) { - _chart.onClick({key: d.name, others: d.others}); - }; - - function highlightSliceFromLegendable (legendable, highlighted) { - _chart.selectAll('g.pie-slice').each(function (d) { - if (legendable.name === d.data.key) { - d3.select(this).classed('highlight', highlighted); - } - }); - } - - return _chart.anchor(parent, chartGroup); -}; - -/** - * Concrete bar chart/histogram implementation. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class barChart - * @memberof dc - * @mixes dc.stackMixin - * @mixes dc.coordinateGridMixin - * @example - * // create a bar chart under #chart-container1 element using the default global chart group - * var chart1 = dc.barChart('#chart-container1'); - * // create a bar chart under #chart-container2 element using chart group A - * var chart2 = dc.barChart('#chart-container2', 'chartGroupA'); - * // create a sub-chart under a composite parent chart - * var chart3 = dc.barChart(compositeChart); - * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} - * specifying a dom block element such as a div; or a dom element or d3 selection. If the bar - * chart is a sub-chart in a {@link dc.compositeChart Composite Chart} then pass in the parent - * composite chart instance instead. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.barChart} - */ -dc.barChart = function (parent, chartGroup) { - var MIN_BAR_WIDTH = 1; - var DEFAULT_GAP_BETWEEN_BARS = 2; - var LABEL_PADDING = 3; - - var _chart = dc.stackMixin(dc.coordinateGridMixin({})); - - var _gap = DEFAULT_GAP_BETWEEN_BARS; - var _centerBar = false; - var _alwaysUseRounding = false; - - var _barWidth; - - dc.override(_chart, 'rescale', function () { - _chart._rescale(); - _barWidth = undefined; - return _chart; - }); - - dc.override(_chart, 'render', function () { - if (_chart.round() && _centerBar && !_alwaysUseRounding) { - dc.logger.warn('By default, brush rounding is disabled if bars are centered. ' + - 'See dc.js bar chart API documentation for details.'); - } - - return _chart._render(); - }); - - _chart.label(function (d) { - return dc.utils.printSingleValue(d.y0 + d.y); - }, false); - - _chart.plotData = function () { - var layers = _chart.chartBodyG().selectAll('g.stack') - .data(_chart.data()); - - calculateBarWidth(); - - layers - .enter() - .append('g') - .attr('class', function (d, i) { - return 'stack ' + '_' + i; - }); - - var last = layers.size() - 1; - layers.each(function (d, i) { - var layer = d3.select(this); - - renderBars(layer, i, d); - - if (_chart.renderLabel() && last === i) { - renderLabels(layer, i, d); - } - }); - }; - - function barHeight (d) { - return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0))); - } - - function renderLabels (layer, layerIndex, d) { - var labels = layer.selectAll('text.barLabel') - .data(d.values, dc.pluck('x')); - - labels.enter() - .append('text') - .attr('class', 'barLabel') - .attr('text-anchor', 'middle'); - - if (_chart.isOrdinal()) { - labels.on('click', _chart.onClick); - labels.attr('cursor', 'pointer'); - } - - dc.transition(labels, _chart.transitionDuration()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - if (!_centerBar) { - x += _barWidth / 2; - } - return dc.utils.safeNumber(x); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0); - - if (d.y < 0) { - y -= barHeight(d); - } - - return dc.utils.safeNumber(y - LABEL_PADDING); - }) - .text(function (d) { - return _chart.label()(d); - }); - - dc.transition(labels.exit(), _chart.transitionDuration()) - .attr('height', 0) - .remove(); - } - - function renderBars (layer, layerIndex, d) { - var bars = layer.selectAll('rect.bar') - .data(d.values, dc.pluck('x')); - - var enter = bars.enter() - .append('rect') - .attr('class', 'bar') - .attr('fill', dc.pluck('data', _chart.getColor)) - .attr('y', _chart.yAxisHeight()) - .attr('height', 0); - - if (_chart.renderTitle()) { - enter.append('title').text(dc.pluck('data', _chart.title(d.name))); - } - - if (_chart.isOrdinal()) { - bars.on('click', _chart.onClick); - } - - dc.transition(bars, _chart.transitionDuration()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - if (_centerBar) { - x -= _barWidth / 2; - } - if (_chart.isOrdinal() && _gap !== undefined) { - x += _gap / 2; - } - return dc.utils.safeNumber(x); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0); - - if (d.y < 0) { - y -= barHeight(d); - } - - return dc.utils.safeNumber(y); - }) - .attr('width', _barWidth) - .attr('height', function (d) { - return barHeight(d); - }) - .attr('fill', dc.pluck('data', _chart.getColor)) - .select('title').text(dc.pluck('data', _chart.title(d.name))); - - dc.transition(bars.exit(), _chart.transitionDuration()) - .attr('x', function (d) { return _chart.x()(d.x); }) - .attr('width', _barWidth * 0.9) - .remove(); - } - - function calculateBarWidth () { - if (_barWidth === undefined) { - var numberOfBars = _chart.xUnitCount(); - - // please can't we always use rangeBands for bar charts? - if (_chart.isOrdinal() && _gap === undefined) { - _barWidth = Math.floor(_chart.x().rangeBand()); - } else if (_gap) { - _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); - } else { - _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); - } - - if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) { - _barWidth = MIN_BAR_WIDTH; - } - } - } - - _chart.fadeDeselectedArea = function () { - var bars = _chart.chartBodyG().selectAll('rect.bar'); - var extent = _chart.brush().extent(); - - if (_chart.isOrdinal()) { - if (_chart.hasFilter()) { - bars.classed(dc.constants.SELECTED_CLASS, function (d) { - return _chart.hasFilter(d.x); - }); - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return !_chart.hasFilter(d.x); - }); - } else { - bars.classed(dc.constants.SELECTED_CLASS, false); - bars.classed(dc.constants.DESELECTED_CLASS, false); - } - } else { - if (!_chart.brushIsEmpty(extent)) { - var start = extent[0]; - var end = extent[1]; - - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return d.x < start || d.x >= end; - }); - } else { - bars.classed(dc.constants.DESELECTED_CLASS, false); - } - } - }; - - /** - * Whether the bar chart will render each bar centered around the data position on the x-axis. - * @method centerBar - * @memberof dc.barChart - * @instance - * @param {Boolean} [centerBar=false] - * @return {Boolean} - * @return {dc.barChart} - */ - _chart.centerBar = function (centerBar) { - if (!arguments.length) { - return _centerBar; - } - _centerBar = centerBar; - return _chart; - }; - - dc.override(_chart, 'onClick', function (d) { - _chart._onClick(d.data); - }); - - /** - * Get or set the spacing between bars as a fraction of bar size. Valid values are between 0-1. - * Setting this value will also remove any previously set {@link dc.barChart#gap gap}. See the - * {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs} - * for a visual description of how the padding is applied. - * @method barPadding - * @memberof dc.barChart - * @instance - * @param {Number} [barPadding=0] - * @return {Number} - * @return {dc.barChart} - */ - _chart.barPadding = function (barPadding) { - if (!arguments.length) { - return _chart._rangeBandPadding(); - } - _chart._rangeBandPadding(barPadding); - _gap = undefined; - return _chart; - }; - - _chart._useOuterPadding = function () { - return _gap === undefined; - }; - - /** - * Get or set the outer padding on an ordinal bar chart. This setting has no effect on non-ordinal charts. - * Will pad the width by `padding * barWidth` on each side of the chart. - * @method outerPadding - * @memberof dc.barChart - * @instance - * @param {Number} [padding=0.5] - * @return {Number} - * @return {dc.barChart} - */ - _chart.outerPadding = _chart._outerRangeBandPadding; - - /** - * Manually set fixed gap (in px) between bars instead of relying on the default auto-generated - * gap. By default the bar chart implementation will calculate and set the gap automatically - * based on the number of data points and the length of the x axis. - * @method gap - * @memberof dc.barChart - * @instance - * @param {Number} [gap=2] - * @return {Number} - * @return {dc.barChart} - */ - _chart.gap = function (gap) { - if (!arguments.length) { - return _gap; - } - _gap = gap; - return _chart; - }; - - _chart.extendBrush = function () { - var extent = _chart.brush().extent(); - if (_chart.round() && (!_centerBar || _alwaysUseRounding)) { - extent[0] = extent.map(_chart.round())[0]; - extent[1] = extent.map(_chart.round())[1]; - - _chart.chartBodyG().select('.brush') - .call(_chart.brush().extent(extent)); - } - - return extent; - }; - - /** - * Set or get whether rounding is enabled when bars are centered. If false, using - * rounding with centered bars will result in a warning and rounding will be ignored. This flag - * has no effect if bars are not {@link dc.barChart#centerBar centered}. - * When using standard d3.js rounding methods, the brush often doesn't align correctly with - * centered bars since the bars are offset. The rounding function must add an offset to - * compensate, such as in the following example. - * @method alwaysUseRounding - * @memberof dc.barChart - * @instance - * @example - * chart.round(function(n) { return Math.floor(n) + 0.5; }); - * @param {Boolean} [alwaysUseRounding=false] - * @return {Boolean} - * @return {dc.barChart} - */ - _chart.alwaysUseRounding = function (alwaysUseRounding) { - if (!arguments.length) { - return _alwaysUseRounding; - } - _alwaysUseRounding = alwaysUseRounding; - return _chart; - }; - - function colorFilter (color, inv) { - return function () { - var item = d3.select(this); - var match = item.attr('fill') === color; - return inv ? !match : match; - }; - } - - _chart.legendHighlight = function (d) { - if (!_chart.isLegendableHidden(d)) { - _chart.g().selectAll('rect.bar') - .classed('highlight', colorFilter(d.color)) - .classed('fadeout', colorFilter(d.color, true)); - } - }; - - _chart.legendReset = function () { - _chart.g().selectAll('rect.bar') - .classed('highlight', false) - .classed('fadeout', false); - }; - - dc.override(_chart, 'xAxisMax', function () { - var max = this._xAxisMax(); - if ('resolution' in _chart.xUnits()) { - var res = _chart.xUnits().resolution; - max += res; - } - return max; - }); - - return _chart.anchor(parent, chartGroup); -}; - -/** - * Concrete line/area chart implementation. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class lineChart - * @memberof dc - * @mixes dc.stackMixin - * @mixes dc.coordinateGridMixin - * @example - * // create a line chart under #chart-container1 element using the default global chart group - * var chart1 = dc.lineChart('#chart-container1'); - * // create a line chart under #chart-container2 element using chart group A - * var chart2 = dc.lineChart('#chart-container2', 'chartGroupA'); - * // create a sub-chart under a composite parent chart - * var chart3 = dc.lineChart(compositeChart); - * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} - * specifying a dom block element such as a div; or a dom element or d3 selection. If the line - * chart is a sub-chart in a {@link dc.compositeChart Composite Chart} then pass in the parent - * composite chart instance instead. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.lineChart} - */ -dc.lineChart = function (parent, chartGroup) { - var DEFAULT_DOT_RADIUS = 5; - var TOOLTIP_G_CLASS = 'dc-tooltip'; - var DOT_CIRCLE_CLASS = 'dot'; - var Y_AXIS_REF_LINE_CLASS = 'yRef'; - var X_AXIS_REF_LINE_CLASS = 'xRef'; - var DEFAULT_DOT_OPACITY = 1e-6; - var LABEL_PADDING = 3; - - var _chart = dc.stackMixin(dc.coordinateGridMixin({})); - var _renderArea = false; - var _dotRadius = DEFAULT_DOT_RADIUS; - var _dataPointRadius = null; - var _dataPointFillOpacity = DEFAULT_DOT_OPACITY; - var _dataPointStrokeOpacity = DEFAULT_DOT_OPACITY; - var _interpolate = 'linear'; - var _tension = 0.7; - var _defined; - var _dashStyle; - var _xyTipsOn = true; - - _chart.transitionDuration(500); - _chart._rangeBandPadding(1); - - _chart.plotData = function () { - var chartBody = _chart.chartBodyG(); - var layersList = chartBody.selectAll('g.stack-list'); - - if (layersList.empty()) { - layersList = chartBody.append('g').attr('class', 'stack-list'); - } - - var layers = layersList.selectAll('g.stack').data(_chart.data()); - - var layersEnter = layers - .enter() - .append('g') - .attr('class', function (d, i) { - return 'stack ' + '_' + i; - }); - - drawLine(layersEnter, layers); - - drawArea(layersEnter, layers); - - drawDots(chartBody, layers); - - if (_chart.renderLabel()) { - drawLabels(layers); - } - }; - - /** - * Gets or sets the interpolator to use for lines drawn, by string name, allowing e.g. step - * functions, splines, and cubic interpolation. This is passed to - * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate} and - * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate}, - * where you can find a complete list of valid arguments - * @method interpolate - * @memberof dc.lineChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate} - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate} - * @param {String} [interpolate='linear'] - * @return {String} - * @return {dc.lineChart} - */ - _chart.interpolate = function (interpolate) { - if (!arguments.length) { - return _interpolate; - } - _interpolate = interpolate; - return _chart; - }; - - /** - * Gets or sets the tension to use for lines drawn, in the range 0 to 1. - * This parameter further customizes the interpolation behavior. It is passed to - * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_tension d3.svg.line.tension} and - * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_tension d3.svg.area.tension}. - * @method tension - * @memberof dc.lineChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate d3.svg.line.interpolate} - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#area_interpolate d3.svg.area.interpolate} - * @param {Number} [tension=0.7] - * @return {Number} - * @return {dc.lineChart} - */ - _chart.tension = function (tension) { - if (!arguments.length) { - return _tension; - } - _tension = tension; - return _chart; - }; - - /** - * Gets or sets a function that will determine discontinuities in the line which should be - * skipped: the path will be broken into separate subpaths if some points are undefined. - * This function is passed to - * {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_defined d3.svg.line.defined} - * - * Note: crossfilter will sometimes coerce nulls to 0, so you may need to carefully write - * custom reduce functions to get this to work, depending on your data. See - * https://github.com/dc-js/dc.js/issues/615#issuecomment-49089248 - * @method defined - * @memberof dc.lineChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#line_defined d3.svg.line.defined} - * @param {Function} [defined] - * @return {Function} - * @return {dc.lineChart} - */ - _chart.defined = function (defined) { - if (!arguments.length) { - return _defined; - } - _defined = defined; - return _chart; - }; - - /** - * Set the line's d3 dashstyle. This value becomes the 'stroke-dasharray' of line. Defaults to empty - * array (solid line). - * @method dashStyle - * @memberof dc.lineChart - * @instance - * @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray stroke-dasharray} - * @example - * // create a Dash Dot Dot Dot - * chart.dashStyle([3,1,1,1]); - * @param {Array} [dashStyle=[]] - * @return {Array} - * @return {dc.lineChart} - */ - _chart.dashStyle = function (dashStyle) { - if (!arguments.length) { - return _dashStyle; - } - _dashStyle = dashStyle; - return _chart; - }; - - /** - * Get or set render area flag. If the flag is set to true then the chart will render the area - * beneath each line and the line chart effectively becomes an area chart. - * @method renderArea - * @memberof dc.lineChart - * @instance - * @param {Boolean} [renderArea=false] - * @return {Boolean} - * @return {dc.lineChart} - */ - _chart.renderArea = function (renderArea) { - if (!arguments.length) { - return _renderArea; - } - _renderArea = renderArea; - return _chart; - }; - - function colors (d, i) { - return _chart.getColor.call(d, d.values, i); - } - - function drawLine (layersEnter, layers) { - var line = d3.svg.line() - .x(function (d) { - return _chart.x()(d.x); - }) - .y(function (d) { - return _chart.y()(d.y + d.y0); - }) - .interpolate(_interpolate) - .tension(_tension); - if (_defined) { - line.defined(_defined); - } - - var path = layersEnter.append('path') - .attr('class', 'line') - .attr('stroke', colors); - if (_dashStyle) { - path.attr('stroke-dasharray', _dashStyle); - } - - dc.transition(layers.select('path.line'), _chart.transitionDuration()) - //.ease('linear') - .attr('stroke', colors) - .attr('d', function (d) { - return safeD(line(d.values)); - }); - } - - function drawArea (layersEnter, layers) { - if (_renderArea) { - var area = d3.svg.area() - .x(function (d) { - return _chart.x()(d.x); - }) - .y(function (d) { - return _chart.y()(d.y + d.y0); - }) - .y0(function (d) { - return _chart.y()(d.y0); - }) - .interpolate(_interpolate) - .tension(_tension); - if (_defined) { - area.defined(_defined); - } - - layersEnter.append('path') - .attr('class', 'area') - .attr('fill', colors) - .attr('d', function (d) { - return safeD(area(d.values)); - }); - - dc.transition(layers.select('path.area'), _chart.transitionDuration()) - //.ease('linear') - .attr('fill', colors) - .attr('d', function (d) { - return safeD(area(d.values)); - }); - } - } - - function safeD (d) { - return (!d || d.indexOf('NaN') >= 0) ? 'M0,0' : d; - } - - function drawDots (chartBody, layers) { - if (!_chart.brushOn() && _chart.xyTipsOn()) { - var tooltipListClass = TOOLTIP_G_CLASS + '-list'; - var tooltips = chartBody.select('g.' + tooltipListClass); - - if (tooltips.empty()) { - tooltips = chartBody.append('g').attr('class', tooltipListClass); - } - - layers.each(function (d, layerIndex) { - var points = d.values; - if (_defined) { - points = points.filter(_defined); - } - - var g = tooltips.select('g.' + TOOLTIP_G_CLASS + '._' + layerIndex); - if (g.empty()) { - g = tooltips.append('g').attr('class', TOOLTIP_G_CLASS + ' _' + layerIndex); - } - - createRefLines(g); - - var dots = g.selectAll('circle.' + DOT_CIRCLE_CLASS) - .data(points, dc.pluck('x')); - - dots.enter() - .append('circle') - .attr('class', DOT_CIRCLE_CLASS) - .attr('r', getDotRadius()) - .style('fill-opacity', _dataPointFillOpacity) - .style('stroke-opacity', _dataPointStrokeOpacity) - .attr('fill', _chart.getColor) - .on('mousemove', function () { - var dot = d3.select(this); - showDot(dot); - showRefLines(dot, g); - }) - .on('mouseout', function () { - var dot = d3.select(this); - hideDot(dot); - hideRefLines(g); - }); - - dots.call(renderTitle, d); - - dc.transition(dots, _chart.transitionDuration()) - .attr('cx', function (d) { - return dc.utils.safeNumber(_chart.x()(d.x)); - }) - .attr('cy', function (d) { - return dc.utils.safeNumber(_chart.y()(d.y + d.y0)); - }) - .attr('fill', _chart.getColor); - - dots.exit().remove(); - }); - } - } - - _chart.label(function (d) { - return dc.utils.printSingleValue(d.y0 + d.y); - }, false); - - function drawLabels (layers) { - layers.each(function (d, layerIndex) { - var layer = d3.select(this); - var labels = layer.selectAll('text.lineLabel') - .data(d.values, dc.pluck('x')); - - labels.enter() - .append('text') - .attr('class', 'lineLabel') - .attr('text-anchor', 'middle'); - - dc.transition(labels, _chart.transitionDuration()) - .attr('x', function (d) { - return dc.utils.safeNumber(_chart.x()(d.x)); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0) - LABEL_PADDING; - return dc.utils.safeNumber(y); - }) - .text(function (d) { - return _chart.label()(d); - }); - - dc.transition(labels.exit(), _chart.transitionDuration()) - .attr('height', 0) - .remove(); - }); - } - - function createRefLines (g) { - var yRefLine = g.select('path.' + Y_AXIS_REF_LINE_CLASS).empty() ? - g.append('path').attr('class', Y_AXIS_REF_LINE_CLASS) : g.select('path.' + Y_AXIS_REF_LINE_CLASS); - yRefLine.style('display', 'none').attr('stroke-dasharray', '5,5'); - - var xRefLine = g.select('path.' + X_AXIS_REF_LINE_CLASS).empty() ? - g.append('path').attr('class', X_AXIS_REF_LINE_CLASS) : g.select('path.' + X_AXIS_REF_LINE_CLASS); - xRefLine.style('display', 'none').attr('stroke-dasharray', '5,5'); - } - - function showDot (dot) { - dot.style('fill-opacity', 0.8); - dot.style('stroke-opacity', 0.8); - dot.attr('r', _dotRadius); - return dot; - } - - function showRefLines (dot, g) { - var x = dot.attr('cx'); - var y = dot.attr('cy'); - var yAxisX = (_chart._yAxisX() - _chart.margins().left); - var yAxisRefPathD = 'M' + yAxisX + ' ' + y + 'L' + (x) + ' ' + (y); - var xAxisRefPathD = 'M' + x + ' ' + _chart.yAxisHeight() + 'L' + x + ' ' + y; - g.select('path.' + Y_AXIS_REF_LINE_CLASS).style('display', '').attr('d', yAxisRefPathD); - g.select('path.' + X_AXIS_REF_LINE_CLASS).style('display', '').attr('d', xAxisRefPathD); - } - - function getDotRadius () { - return _dataPointRadius || _dotRadius; - } - - function hideDot (dot) { - dot.style('fill-opacity', _dataPointFillOpacity) - .style('stroke-opacity', _dataPointStrokeOpacity) - .attr('r', getDotRadius()); - } - - function hideRefLines (g) { - g.select('path.' + Y_AXIS_REF_LINE_CLASS).style('display', 'none'); - g.select('path.' + X_AXIS_REF_LINE_CLASS).style('display', 'none'); - } - - function renderTitle (dot, d) { - if (_chart.renderTitle()) { - dot.selectAll('title').remove(); - dot.append('title').text(dc.pluck('data', _chart.title(d.name))); - } - } - - /** - * Turn on/off the mouseover behavior of an individual data point which renders a circle and x/y axis - * dashed lines back to each respective axis. This is ignored if the chart - * {@link dc.coordinateGridMixin#brushOn brush} is on - * @method xyTipsOn - * @memberof dc.lineChart - * @instance - * @param {Boolean} [xyTipsOn=false] - * @return {Boolean} - * @return {dc.lineChart} - */ - _chart.xyTipsOn = function (xyTipsOn) { - if (!arguments.length) { - return _xyTipsOn; - } - _xyTipsOn = xyTipsOn; - return _chart; - }; - - /** - * Get or set the radius (in px) for dots displayed on the data points. - * @method dotRadius - * @memberof dc.lineChart - * @instance - * @param {Number} [dotRadius=5] - * @return {Number} - * @return {dc.lineChart} - */ - _chart.dotRadius = function (dotRadius) { - if (!arguments.length) { - return _dotRadius; - } - _dotRadius = dotRadius; - return _chart; - }; - - /** - * Always show individual dots for each datapoint. - * If `options` is falsy, it disables data point rendering. - * - * If no `options` are provided, the current `options` values are instead returned. - * @method renderDataPoints - * @memberof dc.lineChart - * @instance - * @example - * chart.renderDataPoints({radius: 2, fillOpacity: 0.8, strokeOpacity: 0.8}) - * @param {{fillOpacity: Number, strokeOpacity: Number, radius: Number}} [options={fillOpacity: 0.8, strokeOpacity: 0.8, radius: 2}] - * @return {{fillOpacity: Number, strokeOpacity: Number, radius: Number}} - * @return {dc.lineChart} - */ - _chart.renderDataPoints = function (options) { - if (!arguments.length) { - return { - fillOpacity: _dataPointFillOpacity, - strokeOpacity: _dataPointStrokeOpacity, - radius: _dataPointRadius - }; - } else if (!options) { - _dataPointFillOpacity = DEFAULT_DOT_OPACITY; - _dataPointStrokeOpacity = DEFAULT_DOT_OPACITY; - _dataPointRadius = null; - } else { - _dataPointFillOpacity = options.fillOpacity || 0.8; - _dataPointStrokeOpacity = options.strokeOpacity || 0.8; - _dataPointRadius = options.radius || 2; - } - return _chart; - }; - - function colorFilter (color, dashstyle, inv) { - return function () { - var item = d3.select(this); - var match = (item.attr('stroke') === color && - item.attr('stroke-dasharray') === ((dashstyle instanceof Array) ? - dashstyle.join(',') : null)) || item.attr('fill') === color; - return inv ? !match : match; - }; - } - - _chart.legendHighlight = function (d) { - if (!_chart.isLegendableHidden(d)) { - _chart.g().selectAll('path.line, path.area') - .classed('highlight', colorFilter(d.color, d.dashstyle)) - .classed('fadeout', colorFilter(d.color, d.dashstyle, true)); - } - }; - - _chart.legendReset = function () { - _chart.g().selectAll('path.line, path.area') - .classed('highlight', false) - .classed('fadeout', false); - }; - - dc.override(_chart, 'legendables', function () { - var legendables = _chart._legendables(); - if (!_dashStyle) { - return legendables; - } - return legendables.map(function (l) { - l.dashstyle = _dashStyle; - return l; - }); - }); - - return _chart.anchor(parent, chartGroup); -}; - -/** - * The data count widget is a simple widget designed to display the number of records selected by the - * current filters out of the total number of records in the data set. Once created the data count widget - * will automatically update the text content of the following elements under the parent element. - * - * Note: this widget works best for the specific case of showing the number of records out of a - * total. If you want a more general-purpose numeric display, please use the - * {@link dc.numberDisplay} widget instead. - * - * '.total-count' - total number of records - * '.filter-count' - number of records matched by the current filters - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * @class dataCount - * @memberof dc - * @mixes dc.baseMixin - * @example - * var ndx = crossfilter(data); - * var all = ndx.groupAll(); - * - * dc.dataCount('.dc-data-count') - * .dimension(ndx) - * .group(all); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.dataCount} - */ -dc.dataCount = function (parent, chartGroup) { - var _formatNumber = d3.format(',d'); - var _chart = dc.baseMixin({}); - var _html = {some: '', all: ''}; - - /** - * Gets or sets an optional object specifying HTML templates to use depending how many items are - * selected. The text `%total-count` will replaced with the total number of records, and the text - * `%filter-count` will be replaced with the number of selected records. - * - all: HTML template to use if all items are selected - * - some: HTML template to use if not all items are selected - * @method html - * @memberof dc.dataCount - * @instance - * @example - * counter.html({ - * some: '%filter-count out of %total-count records selected', - * all: 'All records selected. Click on charts to apply filters' - * }) - * @param {{some:String, all: String}} [options] - * @return {{some:String, all: String}} - * @return {dc.dataCount} - */ - _chart.html = function (options) { - if (!arguments.length) { - return _html; - } - if (options.all) { - _html.all = options.all; - } - if (options.some) { - _html.some = options.some; - } - return _chart; - }; - - /** - * Gets or sets an optional function to format the filter count and total count. - * @method formatNumber - * @memberof dc.dataCount - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format} - * @example - * counter.formatNumber(d3.format('.2g')) - * @param {Function} [formatter=d3.format('.2g')] - * @return {Function} - * @return {dc.dataCount} - */ - _chart.formatNumber = function (formatter) { - if (!arguments.length) { - return _formatNumber; - } - _formatNumber = formatter; - return _chart; - }; - - _chart._doRender = function () { - var tot = _chart.dimension().size(), - val = _chart.group().value(); - var all = _formatNumber(tot); - var selected = _formatNumber(val); - - if ((tot === val) && (_html.all !== '')) { - _chart.root().html(_html.all.replace('%total-count', all).replace('%filter-count', selected)); - } else if (_html.some !== '') { - _chart.root().html(_html.some.replace('%total-count', all).replace('%filter-count', selected)); - } else { - _chart.selectAll('.total-count').text(all); - _chart.selectAll('.filter-count').text(selected); - } - return _chart; - }; - - _chart._doRedraw = function () { - return _chart._doRender(); - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * The data table is a simple widget designed to list crossfilter focused data set (rows being - * filtered) in a good old tabular fashion. - * - * Note: Unlike other charts, the data table (and data grid chart) use the group attribute as a - * keying function for {@link https://github.com/mbostock/d3/wiki/Arrays#-nest nesting} the data - * together in groups. Do not pass in a crossfilter group as this will not work. - * - * Another interesting feature of the data table is that you can pass a crossfilter group to the `dimension`, as - * long as you specify the {@link dc.dataTable#order order} as `d3.descending`, since the data - * table will use `dimension.top()` to fetch the data in that case, and the method is equally - * supported on the crossfilter group as the crossfilter dimension. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.io/dc.js/examples/table-on-aggregated-data.html dataTable on a crossfilter group} - * ({@link https://github.com/dc-js/dc.js/blob/develop/web/examples/table-on-aggregated-data.html source}) - * @class dataTable - * @memberof dc - * @mixes dc.baseMixin - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.dataTable} - */ -dc.dataTable = function (parent, chartGroup) { - var LABEL_CSS_CLASS = 'dc-table-label'; - var ROW_CSS_CLASS = 'dc-table-row'; - var COLUMN_CSS_CLASS = 'dc-table-column'; - var GROUP_CSS_CLASS = 'dc-table-group'; - var HEAD_CSS_CLASS = 'dc-table-head'; - - var _chart = dc.baseMixin({}); - - var _size = 25; - var _columns = []; - var _sortBy = function (d) { - return d; - }; - var _order = d3.ascending; - var _beginSlice = 0; - var _endSlice; - var _showGroups = true; - - _chart._doRender = function () { - _chart.selectAll('tbody').remove(); - - renderRows(renderGroups()); - - return _chart; - }; - - _chart._doColumnValueFormat = function (v, d) { - return ((typeof v === 'function') ? - v(d) : // v as function - ((typeof v === 'string') ? - d[v] : // v is field name string - v.format(d) // v is Object, use fn (element 2) - ) - ); - }; - - _chart._doColumnHeaderFormat = function (d) { - // if 'function', convert to string representation - // show a string capitalized - // if an object then display its label string as-is. - return (typeof d === 'function') ? - _chart._doColumnHeaderFnToString(d) : - ((typeof d === 'string') ? - _chart._doColumnHeaderCapitalize(d) : String(d.label)); - }; - - _chart._doColumnHeaderCapitalize = function (s) { - // capitalize - return s.charAt(0).toUpperCase() + s.slice(1); - }; - - _chart._doColumnHeaderFnToString = function (f) { - // columnString(f) { - var s = String(f); - var i1 = s.indexOf('return '); - if (i1 >= 0) { - var i2 = s.lastIndexOf(';'); - if (i2 >= 0) { - s = s.substring(i1 + 7, i2); - var i3 = s.indexOf('numberFormat'); - if (i3 >= 0) { - s = s.replace('numberFormat', ''); - } - } - } - return s; - }; - - function renderGroups () { - // The 'original' example uses all 'functions'. - // If all 'functions' are used, then don't remove/add a header, and leave - // the html alone. This preserves the functionality of earlier releases. - // A 2nd option is a string representing a field in the data. - // A third option is to supply an Object such as an array of 'information', and - // supply your own _doColumnHeaderFormat and _doColumnValueFormat functions to - // create what you need. - var bAllFunctions = true; - _columns.forEach(function (f) { - bAllFunctions = bAllFunctions & (typeof f === 'function'); - }); - - if (!bAllFunctions) { - // ensure one thead - var thead = _chart.selectAll('thead').data([0]); - thead.enter().append('thead'); - thead.exit().remove(); - - // with one tr - var headrow = thead.selectAll('tr').data([0]); - headrow.enter().append('tr'); - headrow.exit().remove(); - - // with a th for each column - var headcols = headrow.selectAll('th') - .data(_columns); - headcols.enter().append('th'); - headcols.exit().remove(); - - headcols - .attr('class', HEAD_CSS_CLASS) - .html(function (d) { - return (_chart._doColumnHeaderFormat(d)); - - }); - } - - var groups = _chart.root().selectAll('tbody') - .data(nestEntries(), function (d) { - return _chart.keyAccessor()(d); - }); - - var rowGroup = groups - .enter() - .append('tbody'); - - if (_showGroups === true) { - rowGroup - .append('tr') - .attr('class', GROUP_CSS_CLASS) - .append('td') - .attr('class', LABEL_CSS_CLASS) - .attr('colspan', _columns.length) - .html(function (d) { - return _chart.keyAccessor()(d); - }); - } - - groups.exit().remove(); - - return rowGroup; - } - - function nestEntries () { - var entries; - if (_order === d3.ascending) { - entries = _chart.dimension().bottom(_size); - } else { - entries = _chart.dimension().top(_size); - } - - return d3.nest() - .key(_chart.group()) - .sortKeys(_order) - .entries(entries.sort(function (a, b) { - return _order(_sortBy(a), _sortBy(b)); - }).slice(_beginSlice, _endSlice)); - } - - function renderRows (groups) { - var rows = groups.order() - .selectAll('tr.' + ROW_CSS_CLASS) - .data(function (d) { - return d.values; - }); - - var rowEnter = rows.enter() - .append('tr') - .attr('class', ROW_CSS_CLASS); - - _columns.forEach(function (v, i) { - rowEnter.append('td') - .attr('class', COLUMN_CSS_CLASS + ' _' + i) - .html(function (d) { - return _chart._doColumnValueFormat(v, d); - }); - }); - - rows.exit().remove(); - - return rows; - } - - _chart._doRedraw = function () { - return _chart._doRender(); - }; - - /** - * Get or set the table size which determines the number of rows displayed by the widget. - * @method size - * @memberof dc.dataTable - * @instance - * @param {Number} [size=25] - * @return {Number} - * @return {dc.dataTable} - */ - _chart.size = function (size) { - if (!arguments.length) { - return _size; - } - _size = size; - return _chart; - }; - - /** - * Get or set the index of the beginning slice which determines which entries get displayed - * by the widget. Useful when implementing pagination. - * - * Note: the sortBy function will determine how the rows are ordered for pagination purposes. - - * See the {@link http://dc-js.github.io/dc.js/examples/table-pagination.html table pagination example} - * to see how to implement the pagination user interface using `beginSlice` and `endSlice`. - * @method beginSlice - * @memberof dc.dataTable - * @instance - * @param {Number} [beginSlice=0] - * @return {Number} - * @return {dc.dataTable} - */ - _chart.beginSlice = function (beginSlice) { - if (!arguments.length) { - return _beginSlice; - } - _beginSlice = beginSlice; - return _chart; - }; - - /** - * Get or set the index of the end slice which determines which entries get displayed by the - * widget. Useful when implementing pagination. See {@link dc.dataTable#beginSlice `beginSlice`} for more information. - * @method endSlice - * @memberof dc.dataTable - * @instance - * @param {Number|undefined} [endSlice=undefined] - * @return {Number} - * @return {dc.dataTable} - */ - _chart.endSlice = function (endSlice) { - if (!arguments.length) { - return _endSlice; - } - _endSlice = endSlice; - return _chart; - }; - - /** - * Get or set column functions. The data table widget supports several methods of specifying the - * columns to display. - * - * The original method uses an array of functions to generate dynamic columns. Column functions - * are simple javascript functions with only one input argument `d` which represents a row in - * the data set. The return value of these functions will be used to generate the content for - * each cell. However, this method requires the HTML for the table to have a fixed set of column - * headers. - * - *
    chart.columns([
    -     *     function(d) { return d.date; },
    -     *     function(d) { return d.open; },
    -     *     function(d) { return d.close; },
    -     *     function(d) { return numberFormat(d.close - d.open); },
    -     *     function(d) { return d.volume; }
    -     * ]);
    -     * 
    - * - * In the second method, you can list the columns to read from the data without specifying it as - * a function, except where necessary (ie, computed columns). Note the data element name is - * capitalized when displayed in the table header. You can also mix in functions as necessary, - * using the third `{label, format}` form, as shown below. - * - *
    chart.columns([
    -     *     "date",    // d["date"], ie, a field accessor; capitalized automatically
    -     *     "open",    // ...
    -     *     "close",   // ...
    -     *     {
    -     *         label: "Change",
    -     *         format: function (d) {
    -     *             return numberFormat(d.close - d.open);
    -     *         }
    -     *     },
    -     *     "volume"   // d["volume"], ie, a field accessor; capitalized automatically
    -     * ]);
    -     * 
    - * - * In the third example, we specify all fields using the `{label, format}` method: - *
    chart.columns([
    -     *     {
    -     *         label: "Date",
    -     *         format: function (d) { return d.date; }
    -     *     },
    -     *     {
    -     *         label: "Open",
    -     *         format: function (d) { return numberFormat(d.open); }
    -     *     },
    -     *     {
    -     *         label: "Close",
    -     *         format: function (d) { return numberFormat(d.close); }
    -     *     },
    -     *     {
    -     *         label: "Change",
    -     *         format: function (d) { return numberFormat(d.close - d.open); }
    -     *     },
    -     *     {
    -     *         label: "Volume",
    -     *         format: function (d) { return d.volume; }
    -     *     }
    -     * ]);
    -     * 
    - * - * You may wish to override the dataTable functions `_doColumnHeaderCapitalize` and - * `_doColumnHeaderFnToString`, which are used internally to translate the column information or - * function into a displayed header. The first one is used on the "string" column specifier; the - * second is used to transform a stringified function into something displayable. For the Stock - * example, the function for Change becomes the table header **d.close - d.open**. - * - * Finally, you can even specify a completely different form of column definition. To do this, - * override `_chart._doColumnHeaderFormat` and `_chart._doColumnValueFormat` Be aware that - * fields without numberFormat specification will be displayed just as they are stored in the - * data, unformatted. - * @method columns - * @memberof dc.dataTable - * @instance - * @param {Array} [columns=[]] - * @return {Array}} - * @return {dc.dataTable} - */ - _chart.columns = function (columns) { - if (!arguments.length) { - return _columns; - } - _columns = columns; - return _chart; - }; - - /** - * Get or set sort-by function. This function works as a value accessor at row level and returns a - * particular field to be sorted by. Default value: identity function - * @method sortBy - * @memberof dc.dataTable - * @instance - * @example - * chart.sortBy(function(d) { - * return d.date; - * }); - * @param {Function} [sortBy] - * @return {Function} - * @return {dc.dataTable} - */ - _chart.sortBy = function (sortBy) { - if (!arguments.length) { - return _sortBy; - } - _sortBy = sortBy; - return _chart; - }; - - /** - * Get or set sort order. If the order is `d3.ascending`, the data table will use - * `dimension().bottom()` to fetch the data; otherwise it will use `dimension().top()` - * @method order - * @memberof dc.dataTable - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * chart.order(d3.descending); - * @param {Function} [order=d3.ascending] - * @return {Function} - * @return {dc.dataTable} - */ - _chart.order = function (order) { - if (!arguments.length) { - return _order; - } - _order = order; - return _chart; - }; - - /** - * Get or set if group rows will be shown. - * - * The .group() getter-setter must be provided in either case. - * @method showGroups - * @memberof dc.dataTable - * @instance - * @example - * chart - * .group([value], [name]) - * .showGroups(true|false); - * @param {Boolean} [showGroups=true] - * @return {Boolean} - * @return {dc.dataTable} - */ - _chart.showGroups = function (showGroups) { - if (!arguments.length) { - return _showGroups; - } - _showGroups = showGroups; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * Data grid is a simple widget designed to list the filtered records, providing - * a simple way to define how the items are displayed. - * - * Note: Unlike other charts, the data grid chart (and data table) use the group attribute as a keying function - * for {@link https://github.com/mbostock/d3/wiki/Arrays#-nest nesting} the data together in groups. - * Do not pass in a crossfilter group as this will not work. - * - * Examples: - * - {@link http://europarl.me/dc.js/web/ep/index.html List of members of the european parliament} - * @class dataGrid - * @memberof dc - * @mixes dc.baseMixin - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.dataGrid} - */ -dc.dataGrid = function (parent, chartGroup) { - var LABEL_CSS_CLASS = 'dc-grid-label'; - var ITEM_CSS_CLASS = 'dc-grid-item'; - var GROUP_CSS_CLASS = 'dc-grid-group'; - var GRID_CSS_CLASS = 'dc-grid-top'; - - var _chart = dc.baseMixin({}); - - var _size = 999; // shouldn't be needed, but you might - var _html = function (d) { return 'you need to provide an html() handling param: ' + JSON.stringify(d); }; - var _sortBy = function (d) { - return d; - }; - var _order = d3.ascending; - var _beginSlice = 0, _endSlice; - - var _htmlGroup = function (d) { - return '

    ' + - _chart.keyAccessor()(d) + '

    '; - }; - - _chart._doRender = function () { - _chart.selectAll('div.' + GRID_CSS_CLASS).remove(); - - renderItems(renderGroups()); - - return _chart; - }; - - function renderGroups () { - var groups = _chart.root().selectAll('div.' + GRID_CSS_CLASS) - .data(nestEntries(), function (d) { - return _chart.keyAccessor()(d); - }); - - var itemGroup = groups - .enter() - .append('div') - .attr('class', GRID_CSS_CLASS); - - if (_htmlGroup) { - itemGroup - .html(function (d) { - return _htmlGroup(d); - }); - } - - groups.exit().remove(); - return itemGroup; - } - - function nestEntries () { - var entries = _chart.dimension().top(_size); - - return d3.nest() - .key(_chart.group()) - .sortKeys(_order) - .entries(entries.sort(function (a, b) { - return _order(_sortBy(a), _sortBy(b)); - }).slice(_beginSlice, _endSlice)); - } - - function renderItems (groups) { - var items = groups.order() - .selectAll('div.' + ITEM_CSS_CLASS) - .data(function (d) { - return d.values; - }); - - items.enter() - .append('div') - .attr('class', ITEM_CSS_CLASS) - .html(function (d) { - return _html(d); - }); - - items.exit().remove(); - - return items; - } - - _chart._doRedraw = function () { - return _chart._doRender(); - }; - - /** - * Get or set the index of the beginning slice which determines which entries get displayed by the widget. - * Useful when implementing pagination. - * @method beginSlice - * @memberof dc.dataGrid - * @instance - * @param {Number} [beginSlice=0] - * @return {Number} - * @return {dc.dataGrid} - */ - _chart.beginSlice = function (beginSlice) { - if (!arguments.length) { - return _beginSlice; - } - _beginSlice = beginSlice; - return _chart; - }; - - /** - * Get or set the index of the end slice which determines which entries get displayed by the widget - * Useful when implementing pagination. - * @method endSlice - * @memberof dc.dataGrid - * @instance - * @param {Number} [endSlice] - * @return {Number} - * @return {dc.dataGrid} - */ - _chart.endSlice = function (endSlice) { - if (!arguments.length) { - return _endSlice; - } - _endSlice = endSlice; - return _chart; - }; - - /** - * Get or set the grid size which determines the number of items displayed by the widget. - * @method size - * @memberof dc.dataGrid - * @instance - * @param {Number} [size=999] - * @return {Number} - * @return {dc.dataGrid} - */ - _chart.size = function (size) { - if (!arguments.length) { - return _size; - } - _size = size; - return _chart; - }; - - /** - * Get or set the function that formats an item. The data grid widget uses a - * function to generate dynamic html. Use your favourite templating engine or - * generate the string directly. - * @method html - * @memberof dc.dataGrid - * @instance - * @example - * chart.html(function (d) { return '
    '+data.exampleString+'
    ';}); - * @param {Function} [html] - * @return {Function} - * @return {dc.dataGrid} - */ - _chart.html = function (html) { - if (!arguments.length) { - return _html; - } - _html = html; - return _chart; - }; - - /** - * Get or set the function that formats a group label. - * @method htmlGroup - * @memberof dc.dataGrid - * @instance - * @example - * chart.htmlGroup (function (d) { return '

    '.d.key . 'with ' . d.values.length .' items

    '}); - * @param {Function} [htmlGroup] - * @return {Function} - * @return {dc.dataGrid} - */ - _chart.htmlGroup = function (htmlGroup) { - if (!arguments.length) { - return _htmlGroup; - } - _htmlGroup = htmlGroup; - return _chart; - }; - - /** - * Get or set sort-by function. This function works as a value accessor at the item - * level and returns a particular field to be sorted. - * @method sortBy - * @memberof dc.dataGrid - * @instance - * @example - * chart.sortBy(function(d) { - * return d.date; - * }); - * @param {Function} [sortByFunction] - * @return {Function} - * @return {dc.dataGrid} - */ - _chart.sortBy = function (sortByFunction) { - if (!arguments.length) { - return _sortBy; - } - _sortBy = sortByFunction; - return _chart; - }; - - /** - * Get or set sort order function. - * @method order - * @memberof dc.dataGrid - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * chart.order(d3.descending); - * @param {Function} [order=d3.ascending] - * @return {Function} - * @return {dc.dataGrid} - */ - _chart.order = function (order) { - if (!arguments.length) { - return _order; - } - _order = order; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * A concrete implementation of a general purpose bubble chart that allows data visualization using the - * following dimensions: - * - x axis position - * - y axis position - * - bubble radius - * - color - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/vc/index.html US Venture Capital Landscape 2011} - * @class bubbleChart - * @memberof dc - * @mixes dc.bubbleMixin - * @mixes dc.coordinateGridMixin - * @example - * // create a bubble chart under #chart-container1 element using the default global chart group - * var bubbleChart1 = dc.bubbleChart('#chart-container1'); - * // create a bubble chart under #chart-container2 element using chart group A - * var bubbleChart2 = dc.bubbleChart('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.bubbleChart} - */ -dc.bubbleChart = function (parent, chartGroup) { - var _chart = dc.bubbleMixin(dc.coordinateGridMixin({})); - - var _elasticRadius = false; - var _sortBubbleSize = false; - - _chart.transitionDuration(750); - - var bubbleLocator = function (d) { - return 'translate(' + (bubbleX(d)) + ',' + (bubbleY(d)) + ')'; - }; - - /** - * Turn on or off the elastic bubble radius feature, or return the value of the flag. If this - * feature is turned on, then bubble radii will be automatically rescaled to fit the chart better. - * @method elasticRadius - * @memberof dc.bubbleChart - * @instance - * @param {Boolean} [elasticRadius=false] - * @return {Boolean} - * @return {dc.bubbleChart} - */ - _chart.elasticRadius = function (elasticRadius) { - if (!arguments.length) { - return _elasticRadius; - } - _elasticRadius = elasticRadius; - return _chart; - }; - - /** - * Turn on or off the bubble sorting feature, or return the value of the flag. If enabled, - * bubbles will be sorted by their radius, with smaller bubbles in front. - * @method sortBubbleSize - * @memberof dc.bubbleChart - * @instance - * @param {Boolean} [sortBubbleSize=false] - * @return {Boolean} - * @return {dc.bubbleChart} - */ - _chart.sortBubbleSize = function (sortBubbleSize) { - if (!arguments.length) { - return _sortBubbleSize; - } - _sortBubbleSize = sortBubbleSize; - return _chart; - }; - - _chart.plotData = function () { - if (_elasticRadius) { - _chart.r().domain([_chart.rMin(), _chart.rMax()]); - } - - _chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]); - - var data = _chart.data(); - if (_sortBubbleSize) { - // sort descending so smaller bubbles are on top - var radiusAccessor = _chart.radiusValueAccessor(); - data.sort(function (a, b) { return d3.descending(radiusAccessor(a), radiusAccessor(b)); }); - } - var bubbleG = _chart.chartBodyG().selectAll('g.' + _chart.BUBBLE_NODE_CLASS) - .data(data, function (d) { return d.key; }); - if (_sortBubbleSize) { - // Call order here to update dom order based on sort - bubbleG.order(); - } - - renderNodes(bubbleG); - - updateNodes(bubbleG); - - removeNodes(bubbleG); - - _chart.fadeDeselectedArea(); - }; - - function renderNodes (bubbleG) { - var bubbleGEnter = bubbleG.enter().append('g'); - - bubbleGEnter - .attr('class', _chart.BUBBLE_NODE_CLASS) - .attr('transform', bubbleLocator) - .append('circle').attr('class', function (d, i) { - return _chart.BUBBLE_CLASS + ' _' + i; - }) - .on('click', _chart.onClick) - .attr('fill', _chart.getColor) - .attr('r', 0); - dc.transition(bubbleG, _chart.transitionDuration()) - .selectAll('circle.' + _chart.BUBBLE_CLASS) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('opacity', function (d) { - return (_chart.bubbleR(d) > 0) ? 1 : 0; - }); - - _chart._doRenderLabel(bubbleGEnter); - - _chart._doRenderTitles(bubbleGEnter); - } - - function updateNodes (bubbleG) { - dc.transition(bubbleG, _chart.transitionDuration()) - .attr('transform', bubbleLocator) - .selectAll('circle.' + _chart.BUBBLE_CLASS) - .attr('fill', _chart.getColor) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('opacity', function (d) { - return (_chart.bubbleR(d) > 0) ? 1 : 0; - }); - - _chart.doUpdateLabels(bubbleG); - _chart.doUpdateTitles(bubbleG); - } - - function removeNodes (bubbleG) { - bubbleG.exit().remove(); - } - - function bubbleX (d) { - var x = _chart.x()(_chart.keyAccessor()(d)); - if (isNaN(x)) { - x = 0; - } - return x; - } - - function bubbleY (d) { - var y = _chart.y()(_chart.valueAccessor()(d)); - if (isNaN(y)) { - y = 0; - } - return y; - } - - _chart.renderBrush = function () { - // override default x axis brush from parent chart - }; - - _chart.redrawBrush = function () { - // override default x axis brush from parent chart - _chart.fadeDeselectedArea(); - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * Composite charts are a special kind of chart that render multiple charts on the same Coordinate - * Grid. You can overlay (compose) different bar/line/area charts in a single composite chart to - * achieve some quite flexible charting effects. - * @class compositeChart - * @memberof dc - * @mixes dc.coordinateGridMixin - * @example - * // create a composite chart under #chart-container1 element using the default global chart group - * var compositeChart1 = dc.compositeChart('#chart-container1'); - * // create a composite chart under #chart-container2 element using chart group A - * var compositeChart2 = dc.compositeChart('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.compositeChart} - */ -dc.compositeChart = function (parent, chartGroup) { - - var SUB_CHART_CLASS = 'sub'; - var DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING = 12; - - var _chart = dc.coordinateGridMixin({}); - var _children = []; - - var _childOptions = {}; - - var _shareColors = false, - _shareTitle = true, - _alignYAxes = false; - - var _rightYAxis = d3.svg.axis(), - _rightYAxisLabel = 0, - _rightYAxisLabelPadding = DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING, - _rightY, - _rightAxisGridLines = false; - - _chart._mandatoryAttributes([]); - _chart.transitionDuration(500); - - dc.override(_chart, '_generateG', function () { - var g = this.__generateG(); - - for (var i = 0; i < _children.length; ++i) { - var child = _children[i]; - - generateChildG(child, i); - - if (!child.dimension()) { - child.dimension(_chart.dimension()); - } - if (!child.group()) { - child.group(_chart.group()); - } - - child.chartGroup(_chart.chartGroup()); - child.svg(_chart.svg()); - child.xUnits(_chart.xUnits()); - child.transitionDuration(_chart.transitionDuration()); - child.brushOn(_chart.brushOn()); - child.renderTitle(_chart.renderTitle()); - child.elasticX(_chart.elasticX()); - } - - return g; - }); - - _chart._brushing = function () { - var extent = _chart.extendBrush(); - var brushIsEmpty = _chart.brushIsEmpty(extent); - - for (var i = 0; i < _children.length; ++i) { - _children[i].replaceFilter(brushIsEmpty ? null : extent); - } - }; - - _chart._prepareYAxis = function () { - var left = (leftYAxisChildren().length !== 0); - var right = (rightYAxisChildren().length !== 0); - var ranges = calculateYAxisRanges(left, right); - - if (left) { prepareLeftYAxis(ranges); } - if (right) { prepareRightYAxis(ranges); } - - if (leftYAxisChildren().length > 0 && !_rightAxisGridLines) { - _chart._renderHorizontalGridLinesForAxis(_chart.g(), _chart.y(), _chart.yAxis()); - } else if (rightYAxisChildren().length > 0) { - _chart._renderHorizontalGridLinesForAxis(_chart.g(), _rightY, _rightYAxis); - } - }; - - _chart.renderYAxis = function () { - if (leftYAxisChildren().length !== 0) { - _chart.renderYAxisAt('y', _chart.yAxis(), _chart.margins().left); - _chart.renderYAxisLabel('y', _chart.yAxisLabel(), -90); - } - - if (rightYAxisChildren().length !== 0) { - _chart.renderYAxisAt('yr', _chart.rightYAxis(), _chart.width() - _chart.margins().right); - _chart.renderYAxisLabel('yr', _chart.rightYAxisLabel(), 90, _chart.width() - _rightYAxisLabelPadding); - } - }; - - function calculateYAxisRanges (left, right) { - var lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax; - var ranges; - - if (left) { - lyAxisMin = yAxisMin(); - lyAxisMax = yAxisMax(); - } - - if (right) { - ryAxisMin = rightYAxisMin(); - ryAxisMax = rightYAxisMax(); - } - - if (_chart.alignYAxes() && left && right) { - ranges = alignYAxisRanges(lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax); - } - - return ranges || { - lyAxisMin: lyAxisMin, - lyAxisMax: lyAxisMax, - ryAxisMin: ryAxisMin, - ryAxisMax: ryAxisMax - }; - } - - function alignYAxisRanges (lyAxisMin, lyAxisMax, ryAxisMin, ryAxisMax) { - // since the two series will share a zero, each Y is just a multiple - // of the other. and the ratio should be the ratio of the ranges of the - // input data, so that they come out the same height. so we just min/max - - // note: both ranges already include zero due to the stack mixin (#667) - // if #667 changes, we can reconsider whether we want data height or - // height from zero to be equal. and it will be possible for the axes - // to be aligned but not visible. - var extentRatio = (ryAxisMax - ryAxisMin) / (lyAxisMax - lyAxisMin); - - return { - lyAxisMin: Math.min(lyAxisMin, ryAxisMin / extentRatio), - lyAxisMax: Math.max(lyAxisMax, ryAxisMax / extentRatio), - ryAxisMin: Math.min(ryAxisMin, lyAxisMin * extentRatio), - ryAxisMax: Math.max(ryAxisMax, lyAxisMax * extentRatio) - }; - } - - function prepareRightYAxis (ranges) { - var needDomain = _chart.rightY() === undefined || _chart.elasticY(), - needRange = needDomain || _chart.resizing(); - if (_chart.rightY() === undefined) { - _chart.rightY(d3.scale.linear()); - } - if (needDomain) { - _chart.rightY().domain([ranges.ryAxisMin, ranges.ryAxisMax]); - } - if (needRange) { - _chart.rightY().rangeRound([_chart.yAxisHeight(), 0]); - } - - _chart.rightY().range([_chart.yAxisHeight(), 0]); - _chart.rightYAxis(_chart.rightYAxis().scale(_chart.rightY())); - - _chart.rightYAxis().orient('right'); - } - - function prepareLeftYAxis (ranges) { - var needDomain = _chart.y() === undefined || _chart.elasticY(), - needRange = needDomain || _chart.resizing(); - if (_chart.y() === undefined) { - _chart.y(d3.scale.linear()); - } - if (needDomain) { - _chart.y().domain([ranges.lyAxisMin, ranges.lyAxisMax]); - } - if (needRange) { - _chart.y().rangeRound([_chart.yAxisHeight(), 0]); - } - - _chart.y().range([_chart.yAxisHeight(), 0]); - _chart.yAxis(_chart.yAxis().scale(_chart.y())); - - _chart.yAxis().orient('left'); - } - - function generateChildG (child, i) { - child._generateG(_chart.g()); - child.g().attr('class', SUB_CHART_CLASS + ' _' + i); - } - - _chart.plotData = function () { - for (var i = 0; i < _children.length; ++i) { - var child = _children[i]; - - if (!child.g()) { - generateChildG(child, i); - } - - if (_shareColors) { - child.colors(_chart.colors()); - } - - child.x(_chart.x()); - - child.xAxis(_chart.xAxis()); - - if (child.useRightYAxis()) { - child.y(_chart.rightY()); - child.yAxis(_chart.rightYAxis()); - } else { - child.y(_chart.y()); - child.yAxis(_chart.yAxis()); - } - - child.plotData(); - - child._activateRenderlets(); - } - }; - - /** - * Get or set whether to draw gridlines from the right y axis. Drawing from the left y axis is the - * default behavior. This option is only respected when subcharts with both left and right y-axes - * are present. - * @method useRightAxisGridLines - * @memberof dc.compositeChart - * @instance - * @param {Boolean} [useRightAxisGridLines=false] - * @return {Boolean} - * @return {dc.compositeChart} - */ - _chart.useRightAxisGridLines = function (useRightAxisGridLines) { - if (!arguments) { - return _rightAxisGridLines; - } - - _rightAxisGridLines = useRightAxisGridLines; - return _chart; - }; - - /** - * Get or set chart-specific options for all child charts. This is equivalent to calling - * {@link dc.baseMixin#options .options} on each child chart. - * @method childOptions - * @memberof dc.compositeChart - * @instance - * @param {Object} [childOptions] - * @return {Object} - * @return {dc.compositeChart} - */ - _chart.childOptions = function (childOptions) { - if (!arguments.length) { - return _childOptions; - } - _childOptions = childOptions; - _children.forEach(function (child) { - child.options(_childOptions); - }); - return _chart; - }; - - _chart.fadeDeselectedArea = function () { - for (var i = 0; i < _children.length; ++i) { - var child = _children[i]; - child.brush(_chart.brush()); - child.fadeDeselectedArea(); - } - }; - - /** - * Set or get the right y axis label. - * @method rightYAxisLabel - * @memberof dc.compositeChart - * @instance - * @param {String} [rightYAxisLabel] - * @param {Number} [padding] - * @return {String} - * @return {dc.compositeChart} - */ - _chart.rightYAxisLabel = function (rightYAxisLabel, padding) { - if (!arguments.length) { - return _rightYAxisLabel; - } - _rightYAxisLabel = rightYAxisLabel; - _chart.margins().right -= _rightYAxisLabelPadding; - _rightYAxisLabelPadding = (padding === undefined) ? DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING : padding; - _chart.margins().right += _rightYAxisLabelPadding; - return _chart; - }; - - /** - * Combine the given charts into one single composite coordinate grid chart. - * @method compose - * @memberof dc.compositeChart - * @instance - * @example - * moveChart.compose([ - * // when creating sub-chart you need to pass in the parent chart - * dc.lineChart(moveChart) - * .group(indexAvgByMonthGroup) // if group is missing then parent's group will be used - * .valueAccessor(function (d){return d.value.avg;}) - * // most of the normal functions will continue to work in a composed chart - * .renderArea(true) - * .stack(monthlyMoveGroup, function (d){return d.value;}) - * .title(function (d){ - * var value = d.value.avg?d.value.avg:d.value; - * if(isNaN(value)) value = 0; - * return dateFormat(d.key) + '\n' + numberFormat(value); - * }), - * dc.barChart(moveChart) - * .group(volumeByMonthGroup) - * .centerBar(true) - * ]); - * @param {Array} [subChartArray] - * @return {dc.compositeChart} - */ - _chart.compose = function (subChartArray) { - _children = subChartArray; - _children.forEach(function (child) { - child.height(_chart.height()); - child.width(_chart.width()); - child.margins(_chart.margins()); - - if (_shareTitle) { - child.title(_chart.title()); - } - - child.options(_childOptions); - }); - return _chart; - }; - - /** - * Returns the child charts which are composed into the composite chart. - * @method children - * @memberof dc.compositeChart - * @instance - * @return {Array} - */ - _chart.children = function () { - return _children; - }; - - /** - * Get or set color sharing for the chart. If set, the {@link dc.colorMixin#colors .colors()} value from this chart - * will be shared with composed children. Additionally if the child chart implements - * Stackable and has not set a custom .colorAccessor, then it will generate a color - * specific to its order in the composition. - * @method shareColors - * @memberof dc.compositeChart - * @instance - * @param {Boolean} [shareColors=false] - * @return {Boolean} - * @return {dc.compositeChart} - */ - _chart.shareColors = function (shareColors) { - if (!arguments.length) { - return _shareColors; - } - _shareColors = shareColors; - return _chart; - }; - - /** - * Get or set title sharing for the chart. If set, the {@link dc.baseMixin#title .title()} value from - * this chart will be shared with composed children. - * @method shareTitle - * @memberof dc.compositeChart - * @instance - * @param {Boolean} [shareTitle=true] - * @return {Boolean} - * @return {dc.compositeChart} - */ - _chart.shareTitle = function (shareTitle) { - if (!arguments.length) { - return _shareTitle; - } - _shareTitle = shareTitle; - return _chart; - }; - - /** - * Get or set the y scale for the right axis. The right y scale is typically automatically - * generated by the chart implementation. - * @method rightY - * @memberof dc.compositeChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Scales d3.scale} - * @param {d3.scale} [yScale] - * @return {d3.scale} - * @return {dc.compositeChart} - */ - _chart.rightY = function (yScale) { - if (!arguments.length) { - return _rightY; - } - _rightY = yScale; - _chart.rescale(); - return _chart; - }; - - /** - * Get or set alignment between left and right y axes. A line connecting '0' on both y axis - * will be parallel to x axis. This only has effect when {@link #dc.coordinateGridMixin+elasticY elasticY} is true. - * @method alignYAxes - * @memberof dc.compositeChart - * @instance - * @param {Boolean} [alignYAxes=false] - * @return {Chart} - */ - _chart.alignYAxes = function (alignYAxes) { - if (!arguments.length) { - return _alignYAxes; - } - _alignYAxes = alignYAxes; - _chart.rescale(); - return _chart; - }; - - function leftYAxisChildren () { - return _children.filter(function (child) { - return !child.useRightYAxis(); - }); - } - - function rightYAxisChildren () { - return _children.filter(function (child) { - return child.useRightYAxis(); - }); - } - - function getYAxisMin (charts) { - return charts.map(function (c) { - return c.yAxisMin(); - }); - } - - delete _chart.yAxisMin; - function yAxisMin () { - return d3.min(getYAxisMin(leftYAxisChildren())); - } - - function rightYAxisMin () { - return d3.min(getYAxisMin(rightYAxisChildren())); - } - - function getYAxisMax (charts) { - return charts.map(function (c) { - return c.yAxisMax(); - }); - } - - delete _chart.yAxisMax; - function yAxisMax () { - return dc.utils.add(d3.max(getYAxisMax(leftYAxisChildren())), _chart.yAxisPadding()); - } - - function rightYAxisMax () { - return dc.utils.add(d3.max(getYAxisMax(rightYAxisChildren())), _chart.yAxisPadding()); - } - - function getAllXAxisMinFromChildCharts () { - return _children.map(function (c) { - return c.xAxisMin(); - }); - } - - dc.override(_chart, 'xAxisMin', function () { - return dc.utils.subtract(d3.min(getAllXAxisMinFromChildCharts()), _chart.xAxisPadding()); - }); - - function getAllXAxisMaxFromChildCharts () { - return _children.map(function (c) { - return c.xAxisMax(); - }); - } - - dc.override(_chart, 'xAxisMax', function () { - return dc.utils.add(d3.max(getAllXAxisMaxFromChildCharts()), _chart.xAxisPadding()); - }); - - _chart.legendables = function () { - return _children.reduce(function (items, child) { - if (_shareColors) { - child.colors(_chart.colors()); - } - items.push.apply(items, child.legendables()); - return items; - }, []); - }; - - _chart.legendHighlight = function (d) { - for (var j = 0; j < _children.length; ++j) { - var child = _children[j]; - child.legendHighlight(d); - } - }; - - _chart.legendReset = function (d) { - for (var j = 0; j < _children.length; ++j) { - var child = _children[j]; - child.legendReset(d); - } - }; - - _chart.legendToggle = function () { - console.log('composite should not be getting legendToggle itself'); - }; - - /** - * Set or get the right y axis used by the composite chart. This function is most useful when y - * axis customization is required. The y axis in dc.js is an instance of a [d3 axis - * object](https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-_axis) therefore it supports any valid - * d3 axis manipulation. **Caution**: The y axis is usually generated internally by dc; - * resetting it may cause unexpected results. - * @method rightYAxis - * @memberof dc.compositeChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Axes d3.svg.axis} - * @example - * // customize y axis tick format - * chart.rightYAxis().tickFormat(function (v) {return v + '%';}); - * // customize y axis tick values - * chart.rightYAxis().tickValues([0, 100, 200, 300]); - * @param {d3.svg.axis} [rightYAxis] - * @return {d3.svg.axis} - * @return {dc.compositeChart} - */ - _chart.rightYAxis = function (rightYAxis) { - if (!arguments.length) { - return _rightYAxis; - } - _rightYAxis = rightYAxis; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * A series chart is a chart that shows multiple series of data overlaid on one chart, where the - * series is specified in the data. It is a specialization of Composite Chart and inherits all - * composite features other than recomposing the chart. - * - * Examples: - * - {@link http://dc-js.github.io/dc.js/examples/series.html Series Chart} - * @class seriesChart - * @memberof dc - * @mixes dc.compositeChart - * @example - * // create a series chart under #chart-container1 element using the default global chart group - * var seriesChart1 = dc.seriesChart("#chart-container1"); - * // create a series chart under #chart-container2 element using chart group A - * var seriesChart2 = dc.seriesChart("#chart-container2", "chartGroupA"); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.seriesChart} - */ -dc.seriesChart = function (parent, chartGroup) { - var _chart = dc.compositeChart(parent, chartGroup); - - function keySort (a, b) { - return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b)); - } - - var _charts = {}; - var _chartFunction = dc.lineChart; - var _seriesAccessor; - var _seriesSort = d3.ascending; - var _valueSort = keySort; - - _chart._mandatoryAttributes().push('seriesAccessor', 'chart'); - _chart.shareColors(true); - - _chart._preprocessData = function () { - var keep = []; - var childrenChanged; - var nester = d3.nest().key(_seriesAccessor); - if (_seriesSort) { - nester.sortKeys(_seriesSort); - } - if (_valueSort) { - nester.sortValues(_valueSort); - } - var nesting = nester.entries(_chart.data()); - var children = - nesting.map(function (sub, i) { - var subChart = _charts[sub.key] || _chartFunction.call(_chart, _chart, chartGroup, sub.key, i); - if (!_charts[sub.key]) { - childrenChanged = true; - } - _charts[sub.key] = subChart; - keep.push(sub.key); - return subChart - .dimension(_chart.dimension()) - .group({all: d3.functor(sub.values)}, sub.key) - .keyAccessor(_chart.keyAccessor()) - .valueAccessor(_chart.valueAccessor()) - .brushOn(_chart.brushOn()); - }); - // this works around the fact compositeChart doesn't really - // have a removal interface - Object.keys(_charts) - .filter(function (c) {return keep.indexOf(c) === -1;}) - .forEach(function (c) { - clearChart(c); - childrenChanged = true; - }); - _chart._compose(children); - if (childrenChanged && _chart.legend()) { - _chart.legend().render(); - } - }; - - function clearChart (c) { - if (_charts[c].g()) { - _charts[c].g().remove(); - } - delete _charts[c]; - } - - function resetChildren () { - Object.keys(_charts).map(clearChart); - _charts = {}; - } - - /** - * Get or set the chart function, which generates the child charts. - * @method chart - * @memberof dc.seriesChart - * @instance - * @example - * // put interpolation on the line charts used for the series - * chart.chart(function(c) { return dc.lineChart(c).interpolate('basis'); }) - * // do a scatter series chart - * chart.chart(dc.scatterPlot) - * @param {Function} [chartFunction=dc.lineChart] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.chart = function (chartFunction) { - if (!arguments.length) { - return _chartFunction; - } - _chartFunction = chartFunction; - resetChildren(); - return _chart; - }; - - /** - * **mandatory** - * - * Get or set accessor function for the displayed series. Given a datum, this function - * should return the series that datum belongs to. - * @method seriesAccessor - * @memberof dc.seriesChart - * @instance - * @example - * // simple series accessor - * chart.seriesAccessor(function(d) { return "Expt: " + d.key[0]; }) - * @param {Function} [accessor] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.seriesAccessor = function (accessor) { - if (!arguments.length) { - return _seriesAccessor; - } - _seriesAccessor = accessor; - resetChildren(); - return _chart; - }; - - /** - * Get or set a function to sort the list of series by, given series values. - * @method seriesSort - * @memberof dc.seriesChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * chart.seriesSort(d3.descending); - * @param {Function} [sortFunction=d3.ascending] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.seriesSort = function (sortFunction) { - if (!arguments.length) { - return _seriesSort; - } - _seriesSort = sortFunction; - resetChildren(); - return _chart; - }; - - /** - * Get or set a function to sort each series values by. By default this is the key accessor which, - * for example, will ensure a lineChart series connects its points in increasing key/x order, - * rather than haphazardly. - * @method valueSort - * @memberof dc.seriesChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_ascending d3.ascending} - * @see {@link https://github.com/mbostock/d3/wiki/Arrays#d3_descending d3.descending} - * @example - * // Default value sort - * _chart.valueSort(function keySort (a, b) { - * return d3.ascending(_chart.keyAccessor()(a), _chart.keyAccessor()(b)); - * }); - * @param {Function} [sortFunction] - * @return {Function} - * @return {dc.seriesChart} - */ - _chart.valueSort = function (sortFunction) { - if (!arguments.length) { - return _valueSort; - } - _valueSort = sortFunction; - resetChildren(); - return _chart; - }; - - // make compose private - _chart._compose = _chart.compose; - delete _chart.compose; - - return _chart; -}; - -/** - * The geo choropleth chart is designed as an easy way to create a crossfilter driven choropleth map - * from GeoJson data. This chart implementation was inspired by - * {@link http://bl.ocks.org/4060606 the great d3 choropleth example}. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/vc/index.html US Venture Capital Landscape 2011} - * @class geoChoroplethChart - * @memberof dc - * @mixes dc.colorMixin - * @mixes dc.baseMixin - * @example - * // create a choropleth chart under '#us-chart' element using the default global chart group - * var chart1 = dc.geoChoroplethChart('#us-chart'); - * // create a choropleth chart under '#us-chart2' element using chart group A - * var chart2 = dc.compositeChart('#us-chart2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.geoChoroplethChart} - */ -dc.geoChoroplethChart = function (parent, chartGroup) { - var _chart = dc.colorMixin(dc.baseMixin({})); - - _chart.colorAccessor(function (d) { - return d || 0; - }); - - var _geoPath = d3.geo.path(); - var _projectionFlag; - - var _geoJsons = []; - - _chart._doRender = function () { - _chart.resetSvg(); - for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) { - var states = _chart.svg().append('g') - .attr('class', 'layer' + layerIndex); - - var regionG = states.selectAll('g.' + geoJson(layerIndex).name) - .data(geoJson(layerIndex).data) - .enter() - .append('g') - .attr('class', geoJson(layerIndex).name); - - regionG - .append('path') - .attr('fill', 'white') - .attr('d', _geoPath); - - regionG.append('title'); - - plotData(layerIndex); - } - _projectionFlag = false; - }; - - function plotData (layerIndex) { - var data = generateLayeredData(); - - if (isDataLayer(layerIndex)) { - var regionG = renderRegionG(layerIndex); - - renderPaths(regionG, layerIndex, data); - - renderTitle(regionG, layerIndex, data); - } - } - - function generateLayeredData () { - var data = {}; - var groupAll = _chart.data(); - for (var i = 0; i < groupAll.length; ++i) { - data[_chart.keyAccessor()(groupAll[i])] = _chart.valueAccessor()(groupAll[i]); - } - return data; - } - - function isDataLayer (layerIndex) { - return geoJson(layerIndex).keyAccessor; - } - - function renderRegionG (layerIndex) { - var regionG = _chart.svg() - .selectAll(layerSelector(layerIndex)) - .classed('selected', function (d) { - return isSelected(layerIndex, d); - }) - .classed('deselected', function (d) { - return isDeselected(layerIndex, d); - }) - .attr('class', function (d) { - var layerNameClass = geoJson(layerIndex).name; - var regionClass = dc.utils.nameToId(geoJson(layerIndex).keyAccessor(d)); - var baseClasses = layerNameClass + ' ' + regionClass; - if (isSelected(layerIndex, d)) { - baseClasses += ' selected'; - } - if (isDeselected(layerIndex, d)) { - baseClasses += ' deselected'; - } - return baseClasses; - }); - return regionG; - } - - function layerSelector (layerIndex) { - return 'g.layer' + layerIndex + ' g.' + geoJson(layerIndex).name; - } - - function isSelected (layerIndex, d) { - return _chart.hasFilter() && _chart.hasFilter(getKey(layerIndex, d)); - } - - function isDeselected (layerIndex, d) { - return _chart.hasFilter() && !_chart.hasFilter(getKey(layerIndex, d)); - } - - function getKey (layerIndex, d) { - return geoJson(layerIndex).keyAccessor(d); - } - - function geoJson (index) { - return _geoJsons[index]; - } - - function renderPaths (regionG, layerIndex, data) { - var paths = regionG - .select('path') - .attr('fill', function () { - var currentFill = d3.select(this).attr('fill'); - if (currentFill) { - return currentFill; - } - return 'none'; - }) - .on('click', function (d) { - return _chart.onClick(d, layerIndex); - }); - - dc.transition(paths, _chart.transitionDuration()).attr('fill', function (d, i) { - return _chart.getColor(data[geoJson(layerIndex).keyAccessor(d)], i); - }); - } - - _chart.onClick = function (d, layerIndex) { - var selectedRegion = geoJson(layerIndex).keyAccessor(d); - dc.events.trigger(function () { - _chart.filter(selectedRegion); - _chart.redrawGroup(); - }); - }; - - function renderTitle (regionG, layerIndex, data) { - if (_chart.renderTitle()) { - regionG.selectAll('title').text(function (d) { - var key = getKey(layerIndex, d); - var value = data[key]; - return _chart.title()({key: key, value: value}); - }); - } - } - - _chart._doRedraw = function () { - for (var layerIndex = 0; layerIndex < _geoJsons.length; ++layerIndex) { - plotData(layerIndex); - if (_projectionFlag) { - _chart.svg().selectAll('g.' + geoJson(layerIndex).name + ' path').attr('d', _geoPath); - } - } - _projectionFlag = false; - }; - - /** - * **mandatory** - * - * Use this function to insert a new GeoJson map layer. This function can be invoked multiple times - * if you have multiple GeoJson data layers to render on top of each other. If you overlay multiple - * layers with the same name the new overlay will override the existing one. - * @method overlayGeoJson - * @memberof dc.geoChoroplethChart - * @instance - * @see {@link http://geojson.org/ GeoJSON} - * @see {@link https://github.com/mbostock/topojson/wiki TopoJSON} - * @see {@link https://github.com/mbostock/topojson/wiki/API-Reference#feature topojson.feature} - * @example - * // insert a layer for rendering US states - * chart.overlayGeoJson(statesJson.features, 'state', function(d) { - * return d.properties.name; - * }); - * @param {geoJson} json - a geojson feed - * @param {String} name - name of the layer - * @param {Function} keyAccessor - accessor function used to extract 'key' from the GeoJson data. The key extracted by - * this function should match the keys returned by the crossfilter groups. - * @return {dc.geoChoroplethChart} - */ - _chart.overlayGeoJson = function (json, name, keyAccessor) { - for (var i = 0; i < _geoJsons.length; ++i) { - if (_geoJsons[i].name === name) { - _geoJsons[i].data = json; - _geoJsons[i].keyAccessor = keyAccessor; - return _chart; - } - } - _geoJsons.push({name: name, data: json, keyAccessor: keyAccessor}); - return _chart; - }; - - /** - * Set custom geo projection function. See the available [d3 geo projection - * functions](https://github.com/mbostock/d3/wiki/Geo-Projections). - * @method projection - * @memberof dc.geoChoroplethChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Geo-Projections d3.geo.projection} - * @see {@link https://github.com/d3/d3-geo-projection Extended d3.geo.projection} - * @param {d3.projection} [projection=d3.geo.albersUsa()] - * @return {dc.geoChoroplethChart} - */ - _chart.projection = function (projection) { - _geoPath.projection(projection); - _projectionFlag = true; - return _chart; - }; - - /** - * Returns all GeoJson layers currently registered with this chart. The returned array is a - * reference to this chart's internal data structure, so any modification to this array will also - * modify this chart's internal registration. - * @method geoJsons - * @memberof dc.geoChoroplethChart - * @instance - * @return {Array<{name:String, data: Object, accessor: Function}>} - */ - _chart.geoJsons = function () { - return _geoJsons; - }; - - /** - * Returns the {@link https://github.com/mbostock/d3/wiki/Geo-Paths#path d3.geo.path} object used to - * render the projection and features. Can be useful for figuring out the bounding box of the - * feature set and thus a way to calculate scale and translation for the projection. - * @method geoPath - * @memberof dc.geoChoroplethChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Geo-Paths#path d3.geo.path} - * @return {d3.geo.path} - */ - _chart.geoPath = function () { - return _geoPath; - }; - - /** - * Remove a GeoJson layer from this chart by name - * @method removeGeoJson - * @memberof dc.geoChoroplethChart - * @instance - * @param {String} name - * @return {dc.geoChoroplethChart} - */ - _chart.removeGeoJson = function (name) { - var geoJsons = []; - - for (var i = 0; i < _geoJsons.length; ++i) { - var layer = _geoJsons[i]; - if (layer.name !== name) { - geoJsons.push(layer); - } - } - - _geoJsons = geoJsons; - - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * The bubble overlay chart is quite different from the typical bubble chart. With the bubble overlay - * chart you can arbitrarily place bubbles on an existing svg or bitmap image, thus changing the - * typical x and y positioning while retaining the capability to visualize data using bubble radius - * and coloring. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class bubbleOverlay - * @memberof dc - * @mixes dc.bubbleMixin - * @mixes dc.baseMixin - * @example - * // create a bubble overlay chart on top of the '#chart-container1 svg' element using the default global chart group - * var bubbleChart1 = dc.bubbleOverlayChart('#chart-container1').svg(d3.select('#chart-container1 svg')); - * // create a bubble overlay chart on top of the '#chart-container2 svg' element using chart group A - * var bubbleChart2 = dc.compositeChart('#chart-container2', 'chartGroupA').svg(d3.select('#chart-container2 svg')); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.bubbleOverlay} - */ -dc.bubbleOverlay = function (parent, chartGroup) { - var BUBBLE_OVERLAY_CLASS = 'bubble-overlay'; - var BUBBLE_NODE_CLASS = 'node'; - var BUBBLE_CLASS = 'bubble'; - - /** - * **mandatory** - * - * Set the underlying svg image element. Unlike other dc charts this chart will not generate a svg - * element; therefore the bubble overlay chart will not work if this function is not invoked. If the - * underlying image is a bitmap, then an empty svg will need to be created on top of the image. - * @method svg - * @memberof dc.bubbleOverlay - * @instance - * @example - * // set up underlying svg element - * chart.svg(d3.select('#chart svg')); - * @param {SVGElement|d3.selection} [imageElement] - * @return {dc.bubbleOverlay} - */ - var _chart = dc.bubbleMixin(dc.baseMixin({})); - var _g; - var _points = []; - - _chart.transitionDuration(750); - - _chart.radiusValueAccessor(function (d) { - return d.value; - }); - - /** - * **mandatory** - * - * Set up a data point on the overlay. The name of a data point should match a specific 'key' among - * data groups generated using keyAccessor. If a match is found (point name <-> data group key) - * then a bubble will be generated at the position specified by the function. x and y - * value specified here are relative to the underlying svg. - * @method point - * @memberof dc.bubbleOverlay - * @instance - * @param {String} name - * @param {Number} x - * @param {Number} y - * @return {dc.bubbleOverlay} - */ - _chart.point = function (name, x, y) { - _points.push({name: name, x: x, y: y}); - return _chart; - }; - - _chart._doRender = function () { - _g = initOverlayG(); - - _chart.r().range([_chart.MIN_RADIUS, _chart.width() * _chart.maxBubbleRelativeSize()]); - - initializeBubbles(); - - _chart.fadeDeselectedArea(); - - return _chart; - }; - - function initOverlayG () { - _g = _chart.select('g.' + BUBBLE_OVERLAY_CLASS); - if (_g.empty()) { - _g = _chart.svg().append('g').attr('class', BUBBLE_OVERLAY_CLASS); - } - return _g; - } - - function initializeBubbles () { - var data = mapData(); - - _points.forEach(function (point) { - var nodeG = getNodeG(point, data); - - var circle = nodeG.select('circle.' + BUBBLE_CLASS); - - if (circle.empty()) { - circle = nodeG.append('circle') - .attr('class', BUBBLE_CLASS) - .attr('r', 0) - .attr('fill', _chart.getColor) - .on('click', _chart.onClick); - } - - dc.transition(circle, _chart.transitionDuration()) - .attr('r', function (d) { - return _chart.bubbleR(d); - }); - - _chart._doRenderLabel(nodeG); - - _chart._doRenderTitles(nodeG); - }); - } - - function mapData () { - var data = {}; - _chart.data().forEach(function (datum) { - data[_chart.keyAccessor()(datum)] = datum; - }); - return data; - } - - function getNodeG (point, data) { - var bubbleNodeClass = BUBBLE_NODE_CLASS + ' ' + dc.utils.nameToId(point.name); - - var nodeG = _g.select('g.' + dc.utils.nameToId(point.name)); - - if (nodeG.empty()) { - nodeG = _g.append('g') - .attr('class', bubbleNodeClass) - .attr('transform', 'translate(' + point.x + ',' + point.y + ')'); - } - - nodeG.datum(data[point.name]); - - return nodeG; - } - - _chart._doRedraw = function () { - updateBubbles(); - - _chart.fadeDeselectedArea(); - - return _chart; - }; - - function updateBubbles () { - var data = mapData(); - - _points.forEach(function (point) { - var nodeG = getNodeG(point, data); - - var circle = nodeG.select('circle.' + BUBBLE_CLASS); - - dc.transition(circle, _chart.transitionDuration()) - .attr('r', function (d) { - return _chart.bubbleR(d); - }) - .attr('fill', _chart.getColor); - - _chart.doUpdateLabels(nodeG); - - _chart.doUpdateTitles(nodeG); - }); - } - - _chart.debug = function (flag) { - if (flag) { - var debugG = _chart.select('g.' + dc.constants.DEBUG_GROUP_CLASS); - - if (debugG.empty()) { - debugG = _chart.svg() - .append('g') - .attr('class', dc.constants.DEBUG_GROUP_CLASS); - } - - var debugText = debugG.append('text') - .attr('x', 10) - .attr('y', 20); - - debugG - .append('rect') - .attr('width', _chart.width()) - .attr('height', _chart.height()) - .on('mousemove', function () { - var position = d3.mouse(debugG.node()); - var msg = position[0] + ', ' + position[1]; - debugText.text(msg); - }); - } else { - _chart.selectAll('.debug').remove(); - } - - return _chart; - }; - - _chart.anchor(parent, chartGroup); - - return _chart; -}; - -/** - * Concrete row chart implementation. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * @class rowChart - * @memberof dc - * @mixes dc.capMixin - * @mixes dc.marginMixin - * @mixes dc.colorMixin - * @mixes dc.baseMixin - * @example - * // create a row chart under #chart-container1 element using the default global chart group - * var chart1 = dc.rowChart('#chart-container1'); - * // create a row chart under #chart-container2 element using chart group A - * var chart2 = dc.rowChart('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.rowChart} - */ -dc.rowChart = function (parent, chartGroup) { - - var _g; - - var _labelOffsetX = 10; - var _labelOffsetY = 15; - var _hasLabelOffsetY = false; - var _dyOffset = '0.35em'; // this helps center labels https://github.com/mbostock/d3/wiki/SVG-Shapes#svg_text - var _titleLabelOffsetX = 2; - - var _gap = 5; - - var _fixedBarHeight = false; - var _rowCssClass = 'row'; - var _titleRowCssClass = 'titlerow'; - var _renderTitleLabel = false; - - var _chart = dc.capMixin(dc.marginMixin(dc.colorMixin(dc.baseMixin({})))); - - var _x; - - var _elasticX; - - var _xAxis = d3.svg.axis().orient('bottom'); - - var _rowData; - - _chart.rowsCap = _chart.cap; - - function calculateAxisScale () { - if (!_x || _elasticX) { - var extent = d3.extent(_rowData, _chart.cappedValueAccessor); - if (extent[0] > 0) { - extent[0] = 0; - } - if (extent[1] < 0) { - extent[1] = 0; - } - _x = d3.scale.linear().domain(extent) - .range([0, _chart.effectiveWidth()]); - } - _xAxis.scale(_x); - } - - function drawAxis () { - var axisG = _g.select('g.axis'); - - calculateAxisScale(); - - if (axisG.empty()) { - axisG = _g.append('g').attr('class', 'axis'); - } - axisG.attr('transform', 'translate(0, ' + _chart.effectiveHeight() + ')'); - - dc.transition(axisG, _chart.transitionDuration()) - .call(_xAxis); - } - - _chart._doRender = function () { - _chart.resetSvg(); - - _g = _chart.svg() - .append('g') - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')'); - - drawChart(); - - return _chart; - }; - - _chart.title(function (d) { - return _chart.cappedKeyAccessor(d) + ': ' + _chart.cappedValueAccessor(d); - }); - - _chart.label(_chart.cappedKeyAccessor); - - /** - * Gets or sets the x scale. The x scale can be any d3 - * {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale} - * @method x - * @memberof dc.rowChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Quantitative-Scales quantitive scale} - * @param {d3.scale} [scale] - * @return {d3.scale} - * @return {dc.rowChart} - */ - _chart.x = function (scale) { - if (!arguments.length) { - return _x; - } - _x = scale; - return _chart; - }; - - function drawGridLines () { - _g.selectAll('g.tick') - .select('line.grid-line') - .remove(); - - _g.selectAll('g.tick') - .append('line') - .attr('class', 'grid-line') - .attr('x1', 0) - .attr('y1', 0) - .attr('x2', 0) - .attr('y2', function () { - return -_chart.effectiveHeight(); - }); - } - - function drawChart () { - _rowData = _chart.data(); - - drawAxis(); - drawGridLines(); - - var rows = _g.selectAll('g.' + _rowCssClass) - .data(_rowData); - - createElements(rows); - removeElements(rows); - updateElements(rows); - } - - function createElements (rows) { - var rowEnter = rows.enter() - .append('g') - .attr('class', function (d, i) { - return _rowCssClass + ' _' + i; - }); - - rowEnter.append('rect').attr('width', 0); - - createLabels(rowEnter); - } - - function removeElements (rows) { - rows.exit().remove(); - } - - function rootValue () { - var root = _x(0); - return (root === -Infinity || root !== root) ? _x(1) : root; - } - - function updateElements (rows) { - var n = _rowData.length; - - var height; - if (!_fixedBarHeight) { - height = (_chart.effectiveHeight() - (n + 1) * _gap) / n; - } else { - height = _fixedBarHeight; - } - - // vertically align label in center unless they override the value via property setter - if (!_hasLabelOffsetY) { - _labelOffsetY = height / 2; - } - - var rect = rows.attr('transform', function (d, i) { - return 'translate(0,' + ((i + 1) * _gap + i * height) + ')'; - }).select('rect') - .attr('height', height) - .attr('fill', _chart.getColor) - .on('click', onClick) - .classed('deselected', function (d) { - return (_chart.hasFilter()) ? !isSelectedRow(d) : false; - }) - .classed('selected', function (d) { - return (_chart.hasFilter()) ? isSelectedRow(d) : false; - }); - - dc.transition(rect, _chart.transitionDuration()) - .attr('width', function (d) { - return Math.abs(rootValue() - _x(_chart.valueAccessor()(d))); - }) - .attr('transform', translateX); - - createTitles(rows); - updateLabels(rows); - } - - function createTitles (rows) { - if (_chart.renderTitle()) { - rows.selectAll('title').remove(); - rows.append('title').text(_chart.title()); - } - } - - function createLabels (rowEnter) { - if (_chart.renderLabel()) { - rowEnter.append('text') - .on('click', onClick); - } - if (_chart.renderTitleLabel()) { - rowEnter.append('text') - .attr('class', _titleRowCssClass) - .on('click', onClick); - } - } - - function updateLabels (rows) { - if (_chart.renderLabel()) { - var lab = rows.select('text') - .attr('x', _labelOffsetX) - .attr('y', _labelOffsetY) - .attr('dy', _dyOffset) - .on('click', onClick) - .attr('class', function (d, i) { - return _rowCssClass + ' _' + i; - }) - .text(function (d) { - return _chart.label()(d); - }); - dc.transition(lab, _chart.transitionDuration()) - .attr('transform', translateX); - } - if (_chart.renderTitleLabel()) { - var titlelab = rows.select('.' + _titleRowCssClass) - .attr('x', _chart.effectiveWidth() - _titleLabelOffsetX) - .attr('y', _labelOffsetY) - .attr('dy', _dyOffset) - .attr('text-anchor', 'end') - .on('click', onClick) - .attr('class', function (d, i) { - return _titleRowCssClass + ' _' + i ; - }) - .text(function (d) { - return _chart.title()(d); - }); - dc.transition(titlelab, _chart.transitionDuration()) - .attr('transform', translateX); - } - } - - /** - * Turn on/off Title label rendering (values) using SVG style of text-anchor 'end' - * @method renderTitleLabel - * @memberof dc.rowChart - * @instance - * @param {Boolean} [renderTitleLabel=false] - * @return {Boolean} - * @return {dc.rowChart} - */ - _chart.renderTitleLabel = function (renderTitleLabel) { - if (!arguments.length) { - return _renderTitleLabel; - } - _renderTitleLabel = renderTitleLabel; - return _chart; - }; - - function onClick (d) { - _chart.onClick(d); - } - - function translateX (d) { - var x = _x(_chart.cappedValueAccessor(d)), - x0 = rootValue(), - s = x > x0 ? x0 : x; - return 'translate(' + s + ',0)'; - } - - _chart._doRedraw = function () { - drawChart(); - return _chart; - }; - - /** - * Get the x axis for the row chart instance. Note: not settable for row charts. - * See the {@link https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis d3 axis object} - * documention for more information. - * @method xAxis - * @memberof dc.rowChart - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-axis d3.svg.axis} - * @example - * // customize x axis tick format - * chart.xAxis().tickFormat(function (v) {return v + '%';}); - * // customize x axis tick values - * chart.xAxis().tickValues([0, 100, 200, 300]); - * @return {d3.svg.axis} - */ - _chart.xAxis = function () { - return _xAxis; - }; - - /** - * Get or set the fixed bar height. Default is [false] which will auto-scale bars. - * For example, if you want to fix the height for a specific number of bars (useful in TopN charts) - * you could fix height as follows (where count = total number of bars in your TopN and gap is - * your vertical gap space). - * @method fixedBarHeight - * @memberof dc.rowChart - * @instance - * @example - * chart.fixedBarHeight( chartheight - (count + 1) * gap / count); - * @param {Boolean|Number} [fixedBarHeight=false] - * @return {Boolean|Number} - * @return {dc.rowChart} - */ - _chart.fixedBarHeight = function (fixedBarHeight) { - if (!arguments.length) { - return _fixedBarHeight; - } - _fixedBarHeight = fixedBarHeight; - return _chart; - }; - - /** - * Get or set the vertical gap space between rows on a particular row chart instance - * @method gap - * @memberof dc.rowChart - * @instance - * @param {Number} [gap=5] - * @return {Number} - * @return {dc.rowChart} - */ - _chart.gap = function (gap) { - if (!arguments.length) { - return _gap; - } - _gap = gap; - return _chart; - }; - - /** - * Get or set the elasticity on x axis. If this attribute is set to true, then the x axis will rescle to auto-fit the - * data range when filtered. - * @method elasticX - * @memberof dc.rowChart - * @instance - * @param {Boolean} [elasticX] - * @return {Boolean} - * @return {dc.rowChart} - */ - _chart.elasticX = function (elasticX) { - if (!arguments.length) { - return _elasticX; - } - _elasticX = elasticX; - return _chart; - }; - - /** - * Get or set the x offset (horizontal space to the top left corner of a row) for labels on a particular row chart. - * @method labelOffsetX - * @memberof dc.rowChart - * @instance - * @param {Number} [labelOffsetX=10] - * @return {Number} - * @return {dc.rowChart} - */ - _chart.labelOffsetX = function (labelOffsetX) { - if (!arguments.length) { - return _labelOffsetX; - } - _labelOffsetX = labelOffsetX; - return _chart; - }; - - /** - * Get or set the y offset (vertical space to the top left corner of a row) for labels on a particular row chart. - * @method labelOffsetY - * @memberof dc.rowChart - * @instance - * @param {Number} [labelOffsety=15] - * @return {Number} - * @return {dc.rowChart} - */ - _chart.labelOffsetY = function (labelOffsety) { - if (!arguments.length) { - return _labelOffsetY; - } - _labelOffsetY = labelOffsety; - _hasLabelOffsetY = true; - return _chart; - }; - - /** - * Get of set the x offset (horizontal space between right edge of row and right edge or text. - * @method titleLabelOffsetX - * @memberof dc.rowChart - * @instance - * @param {Number} [titleLabelOffsetX=2] - * @return {Number} - * @return {dc.rowChart} - */ - _chart.titleLabelOffsetX = function (titleLabelOffsetX) { - if (!arguments.length) { - return _titleLabelOffsetX; - } - _titleLabelOffsetX = titleLabelOffsetX; - return _chart; - }; - - function isSelectedRow (d) { - return _chart.hasFilter(_chart.cappedKeyAccessor(d)); - } - - return _chart.anchor(parent, chartGroup); -}; - -/** - * Legend is a attachable widget that can be added to other dc charts to render horizontal legend - * labels. - * - * Examples: - * - {@link http://dc-js.github.com/dc.js/ Nasdaq 100 Index} - * - {@link http://dc-js.github.com/dc.js/crime/index.html Canadian City Crime Stats} - * @class legend - * @memberof dc - * @example - * chart.legend(dc.legend().x(400).y(10).itemHeight(13).gap(5)) - * @return {dc.legend} - */ -dc.legend = function () { - var LABEL_GAP = 2; - - var _legend = {}, - _parent, - _x = 0, - _y = 0, - _itemHeight = 12, - _gap = 5, - _horizontal = false, - _legendWidth = 560, - _itemWidth = 70, - _autoItemWidth = false, - _legendText = dc.pluck('name'); - - var _g; - - _legend.parent = function (p) { - if (!arguments.length) { - return _parent; - } - _parent = p; - return _legend; - }; - - _legend.render = function () { - _parent.svg().select('g.dc-legend').remove(); - _g = _parent.svg().append('g') - .attr('class', 'dc-legend') - .attr('transform', 'translate(' + _x + ',' + _y + ')'); - var legendables = _parent.legendables(); - - var itemEnter = _g.selectAll('g.dc-legend-item') - .data(legendables) - .enter() - .append('g') - .attr('class', 'dc-legend-item') - .on('mouseover', function (d) { - _parent.legendHighlight(d); - }) - .on('mouseout', function (d) { - _parent.legendReset(d); - }) - .on('click', function (d) { - d.chart.legendToggle(d); - }); - - _g.selectAll('g.dc-legend-item') - .classed('fadeout', function (d) { - return d.chart.isLegendableHidden(d); - }); - - if (legendables.some(dc.pluck('dashstyle'))) { - itemEnter - .append('line') - .attr('x1', 0) - .attr('y1', _itemHeight / 2) - .attr('x2', _itemHeight) - .attr('y2', _itemHeight / 2) - .attr('stroke-width', 2) - .attr('stroke-dasharray', dc.pluck('dashstyle')) - .attr('stroke', dc.pluck('color')); - } else { - itemEnter - .append('rect') - .attr('width', _itemHeight) - .attr('height', _itemHeight) - .attr('fill', function (d) {return d ? d.color : 'blue';}); - } - - itemEnter.append('text') - .text(_legendText) - .attr('x', _itemHeight + LABEL_GAP) - .attr('y', function () { - return _itemHeight / 2 + (this.clientHeight ? this.clientHeight : 13) / 2 - 2; - }); - - var _cumulativeLegendTextWidth = 0; - var row = 0; - itemEnter.attr('transform', function (d, i) { - if (_horizontal) { - var translateBy = 'translate(' + _cumulativeLegendTextWidth + ',' + row * legendItemHeight() + ')'; - var itemWidth = _autoItemWidth === true ? this.getBBox().width + _gap : _itemWidth; - - if ((_cumulativeLegendTextWidth + itemWidth) >= _legendWidth) { - ++row ; - _cumulativeLegendTextWidth = 0 ; - } else { - _cumulativeLegendTextWidth += itemWidth; - } - return translateBy; - } else { - return 'translate(0,' + i * legendItemHeight() + ')'; - } - }); - }; - - function legendItemHeight () { - return _gap + _itemHeight; - } - - /** - * Set or get x coordinate for legend widget. - * @method x - * @memberof dc.legend - * @instance - * @param {Number} [x=0] - * @return {Number} - * @return {dc.legend} - */ - _legend.x = function (x) { - if (!arguments.length) { - return _x; - } - _x = x; - return _legend; - }; - - /** - * Set or get y coordinate for legend widget. - * @method y - * @memberof dc.legend - * @instance - * @param {Number} [y=0] - * @return {Number} - * @return {dc.legend} - */ - _legend.y = function (y) { - if (!arguments.length) { - return _y; - } - _y = y; - return _legend; - }; - - /** - * Set or get gap between legend items. - * @method gap - * @memberof dc.legend - * @instance - * @param {Number} [gap=5] - * @return {Number} - * @return {dc.legend} - */ - _legend.gap = function (gap) { - if (!arguments.length) { - return _gap; - } - _gap = gap; - return _legend; - }; - - /** - * Set or get legend item height. - * @method itemHeight - * @memberof dc.legend - * @instance - * @param {Number} [itemHeight=12] - * @return {Number} - * @return {dc.legend} - */ - _legend.itemHeight = function (itemHeight) { - if (!arguments.length) { - return _itemHeight; - } - _itemHeight = itemHeight; - return _legend; - }; - - /** - * Position legend horizontally instead of vertically. - * @method horizontal - * @memberof dc.legend - * @instance - * @param {Boolean} [horizontal=false] - * @return {Boolean} - * @return {dc.legend} - */ - _legend.horizontal = function (horizontal) { - if (!arguments.length) { - return _horizontal; - } - _horizontal = horizontal; - return _legend; - }; - - /** - * Maximum width for horizontal legend. - * @method legendWidth - * @memberof dc.legend - * @instance - * @param {Number} [legendWidth=500] - * @return {Number} - * @return {dc.legend} - */ - _legend.legendWidth = function (legendWidth) { - if (!arguments.length) { - return _legendWidth; - } - _legendWidth = legendWidth; - return _legend; - }; - - /** - * legendItem width for horizontal legend. - * @method itemWidth - * @memberof dc.legend - * @instance - * @param {Number} [itemWidth=70] - * @return {Number} - * @return {dc.legend} - */ - _legend.itemWidth = function (itemWidth) { - if (!arguments.length) { - return _itemWidth; - } - _itemWidth = itemWidth; - return _legend; - }; - - /** - * Turn automatic width for legend items on or off. If true, {@link dc.legend#itemWidth itemWidth} is ignored. - * This setting takes into account {@link dc.legend#gap gap}. - * @method autoItemWidth - * @memberof dc.legend - * @instance - * @param {Boolean} [autoItemWidth=false] - * @return {Boolean} - * @return {dc.legend} - */ - _legend.autoItemWidth = function (autoItemWidth) { - if (!arguments.length) { - return _autoItemWidth; - } - _autoItemWidth = autoItemWidth; - return _legend; - }; - - /** - * Set or get the legend text function. The legend widget uses this function to render the legend - * text for each item. If no function is specified the legend widget will display the names - * associated with each group. - * @method legendText - * @memberof dc.legend - * @instance - * @param {Function} [legendText] - * @return {Function} - * @return {dc.legend} - * @example - * // default legendText - * legend.legendText(dc.pluck('name')) - * - * // create numbered legend items - * chart.legend(dc.legend().legendText(function(d, i) { return i + '. ' + d.name; })) - * - * // create legend displaying group counts - * chart.legend(dc.legend().legendText(function(d) { return d.name + ': ' d.data; })) - **/ - _legend.legendText = function (legendText) { - if (!arguments.length) { - return _legendText; - } - _legendText = legendText; - return _legend; - }; - - return _legend; -}; - -/** - * A scatter plot chart - * - * Examples: - * - {@link http://dc-js.github.io/dc.js/examples/scatter.html Scatter Chart} - * - {@link http://dc-js.github.io/dc.js/examples/multi-scatter.html Multi-Scatter Chart} - * @class scatterPlot - * @memberof dc - * @mixes dc.coordinateGridMixin - * @example - * // create a scatter plot under #chart-container1 element using the default global chart group - * var chart1 = dc.scatterPlot('#chart-container1'); - * // create a scatter plot under #chart-container2 element using chart group A - * var chart2 = dc.scatterPlot('#chart-container2', 'chartGroupA'); - * // create a sub-chart under a composite parent chart - * var chart3 = dc.scatterPlot(compositeChart); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.scatterPlot} - */ -dc.scatterPlot = function (parent, chartGroup) { - var _chart = dc.coordinateGridMixin({}); - var _symbol = d3.svg.symbol(); - - var _existenceAccessor = function (d) { return d.value; }; - - var originalKeyAccessor = _chart.keyAccessor(); - _chart.keyAccessor(function (d) { return originalKeyAccessor(d)[0]; }); - _chart.valueAccessor(function (d) { return originalKeyAccessor(d)[1]; }); - _chart.colorAccessor(function () { return _chart._groupName; }); - - var _locator = function (d) { - return 'translate(' + _chart.x()(_chart.keyAccessor()(d)) + ',' + - _chart.y()(_chart.valueAccessor()(d)) + ')'; - }; - - var _highlightedSize = 7; - var _symbolSize = 5; - var _excludedSize = 3; - var _excludedColor = null; - var _excludedOpacity = 1.0; - var _emptySize = 0; - var _filtered = []; - - _symbol.size(function (d, i) { - if (!_existenceAccessor(d)) { - return _emptySize; - } else if (_filtered[i]) { - return Math.pow(_symbolSize, 2); - } else { - return Math.pow(_excludedSize, 2); - } - }); - - dc.override(_chart, '_filter', function (filter) { - if (!arguments.length) { - return _chart.__filter(); - } - - return _chart.__filter(dc.filters.RangedTwoDimensionalFilter(filter)); - }); - - _chart.plotData = function () { - var symbols = _chart.chartBodyG().selectAll('path.symbol') - .data(_chart.data()); - - symbols - .enter() - .append('path') - .attr('class', 'symbol') - .attr('opacity', 0) - .attr('fill', _chart.getColor) - .attr('transform', _locator); - - symbols.each(function (d, i) { - _filtered[i] = !_chart.filter() || _chart.filter().isFiltered([d.key[0], d.key[1]]); - }); - - dc.transition(symbols, _chart.transitionDuration()) - .attr('opacity', function (d, i) { - return !_existenceAccessor(d) ? 0 : - _filtered[i] ? 1 : _chart.excludedOpacity(); - }) - .attr('fill', function (d, i) { - return _chart.excludedColor() && !_filtered[i] ? - _chart.excludedColor() : - _chart.getColor(d); - }) - .attr('transform', _locator) - .attr('d', _symbol); - - dc.transition(symbols.exit(), _chart.transitionDuration()) - .attr('opacity', 0).remove(); - }; - - /** - * Get or set the existence accessor. If a point exists, it is drawn with - * {@link dc.scatterPlot#symbolSize symbolSize} radius and - * opacity 1; if it does not exist, it is drawn with - * {@link dc.scatterPlot#emptySize emptySize} radius and opacity 0. By default, - * the existence accessor checks if the reduced value is truthy. - * @method existenceAccessor - * @memberof dc.scatterPlot - * @instance - * @see {@link dc.scatterPlot#symbolSize symbolSize} - * @see {@link dc.scatterPlot#emptySize emptySize} - * @example - * // default accessor - * chart.existenceAccessor(function (d) { return d.value; }); - * @param {Function} [accessor] - * @return {Function} - * @return {dc.scatterPlot} - */ - _chart.existenceAccessor = function (accessor) { - if (!arguments.length) { - return _existenceAccessor; - } - _existenceAccessor = accessor; - return this; - }; - - /** - * Get or set the symbol type used for each point. By default the symbol is a circle. - * Type can be a constant or an accessor. - * @method symbol - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_type d3.svg.symbol().type()} - * @example - * // Circle type - * chart.symbol('circle'); - * // Square type - * chart.symbol('square'); - * @param {String|Function} [type='circle'] - * @return {String|Function} - * @return {dc.scatterPlot} - */ - _chart.symbol = function (type) { - if (!arguments.length) { - return _symbol.type(); - } - _symbol.type(type); - return _chart; - }; - - /** - * Set or get radius for symbols. - * @method symbolSize - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [symbolSize=3] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.symbolSize = function (symbolSize) { - if (!arguments.length) { - return _symbolSize; - } - _symbolSize = symbolSize; - return _chart; - }; - - /** - * Set or get radius for highlighted symbols. - * @method highlightedSize - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [highlightedSize=5] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.highlightedSize = function (highlightedSize) { - if (!arguments.length) { - return _highlightedSize; - } - _highlightedSize = highlightedSize; - return _chart; - }; - - /** - * Set or get size for symbols excluded from this chart's filter. If null, no - * special size is applied for symbols based on their filter status - * @method excludedSize - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [excludedSize=null] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.excludedSize = function (excludedSize) { - if (!arguments.length) { - return _excludedSize; - } - _excludedSize = excludedSize; - return _chart; - }; - - /** - * Set or get color for symbols excluded from this chart's filter. If null, no - * special color is applied for symbols based on their filter status - * @method excludedColor - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [excludedColor=null] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.excludedColor = function (excludedColor) { - if (!arguments.length) { - return _excludedColor; - } - _excludedColor = excludedColor; - return _chart; - }; - - /** - * Set or get opacity for symbols excluded from this chart's filter. - * @method excludedOpacity - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [excludedOpacity=1.0] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.excludedOpacity = function (excludedOpacity) { - if (!arguments.length) { - return _excludedOpacity; - } - _excludedOpacity = excludedOpacity; - return _chart; - }; - - /** - * Set or get radius for symbols when the group is empty. - * @method emptySize - * @memberof dc.scatterPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol_size d3.svg.symbol().size()} - * @param {Number} [emptySize=0] - * @return {Number} - * @return {dc.scatterPlot} - */ - _chart.hiddenSize = _chart.emptySize = function (emptySize) { - if (!arguments.length) { - return _emptySize; - } - _emptySize = emptySize; - return _chart; - }; - - _chart.legendables = function () { - return [{chart: _chart, name: _chart._groupName, color: _chart.getColor()}]; - }; - - _chart.legendHighlight = function (d) { - resizeSymbolsWhere(function (symbol) { - return symbol.attr('fill') === d.color; - }, _highlightedSize); - _chart.selectAll('.chart-body path.symbol').filter(function () { - return d3.select(this).attr('fill') !== d.color; - }).classed('fadeout', true); - }; - - _chart.legendReset = function (d) { - resizeSymbolsWhere(function (symbol) { - return symbol.attr('fill') === d.color; - }, _symbolSize); - _chart.selectAll('.chart-body path.symbol').filter(function () { - return d3.select(this).attr('fill') !== d.color; - }).classed('fadeout', false); - }; - - function resizeSymbolsWhere (condition, size) { - var symbols = _chart.selectAll('.chart-body path.symbol').filter(function () { - return condition(d3.select(this)); - }); - var oldSize = _symbol.size(); - _symbol.size(Math.pow(size, 2)); - dc.transition(symbols, _chart.transitionDuration()).attr('d', _symbol); - _symbol.size(oldSize); - } - - _chart.setHandlePaths = function () { - // no handle paths for poly-brushes - }; - - _chart.extendBrush = function () { - var extent = _chart.brush().extent(); - if (_chart.round()) { - extent[0] = extent[0].map(_chart.round()); - extent[1] = extent[1].map(_chart.round()); - - _chart.g().select('.brush') - .call(_chart.brush().extent(extent)); - } - return extent; - }; - - _chart.brushIsEmpty = function (extent) { - return _chart.brush().empty() || !extent || extent[0][0] >= extent[1][0] || extent[0][1] >= extent[1][1]; - }; - - _chart._brushing = function () { - var extent = _chart.extendBrush(); - - _chart.redrawBrush(_chart.g()); - - if (_chart.brushIsEmpty(extent)) { - dc.events.trigger(function () { - _chart.filter(null); - _chart.redrawGroup(); - }); - - } else { - var ranged2DFilter = dc.filters.RangedTwoDimensionalFilter(extent); - dc.events.trigger(function () { - _chart.filter(null); - _chart.filter(ranged2DFilter); - _chart.redrawGroup(); - }, dc.constants.EVENT_DELAY); - - } - }; - - _chart.setBrushY = function (gBrush) { - gBrush.call(_chart.brush().y(_chart.y())); - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * A display of a single numeric value. - * Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and - * a valueAccessor that returns a single value. - * @class numberDisplay - * @memberof dc - * @mixes dc.baseMixin - * @example - * // create a number display under #chart-container1 element using the default global chart group - * var display1 = dc.numberDisplay('#chart-container1'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.numberDisplay} - */ -dc.numberDisplay = function (parent, chartGroup) { - var SPAN_CLASS = 'number-display'; - var _formatNumber = d3.format('.2s'); - var _chart = dc.baseMixin({}); - var _html = {one: '', some: '', none: ''}; - var _lastValue; - - // dimension not required - _chart._mandatoryAttributes(['group']); - - /** - * Gets or sets an optional object specifying HTML templates to use depending on the number - * displayed. The text `%number` will be replaced with the current value. - * - one: HTML template to use if the number is 1 - * - zero: HTML template to use if the number is 0 - * - some: HTML template to use otherwise - * @method html - * @memberof dc.numberDisplay - * @instance - * @example - * numberWidget.html({ - * one:'%number record', - * some:'%number records', - * none:'no records'}) - * @param {{one:String, some:String, none:String}} [html={one: '', some: '', none: ''}] - * @return {{one:String, some:String, none:String}} - * @return {dc.numberDisplay} - */ - _chart.html = function (html) { - if (!arguments.length) { - return _html; - } - if (html.none) { - _html.none = html.none;//if none available - } else if (html.one) { - _html.none = html.one;//if none not available use one - } else if (html.some) { - _html.none = html.some;//if none and one not available use some - } - if (html.one) { - _html.one = html.one;//if one available - } else if (html.some) { - _html.one = html.some;//if one not available use some - } - if (html.some) { - _html.some = html.some;//if some available - } else if (html.one) { - _html.some = html.one;//if some not available use one - } - return _chart; - }; - - /** - * Calculate and return the underlying value of the display - * @method value - * @memberof dc.numberDisplay - * @instance - * @return {Number} - */ - _chart.value = function () { - return _chart.data(); - }; - - _chart.data(function (group) { - var valObj = group.value ? group.value() : group.top(1)[0]; - return _chart.valueAccessor()(valObj); - }); - - _chart.transitionDuration(250); // good default - - _chart._doRender = function () { - var newValue = _chart.value(), - span = _chart.selectAll('.' + SPAN_CLASS); - - if (span.empty()) { - span = span.data([0]) - .enter() - .append('span') - .attr('class', SPAN_CLASS); - } - - span.transition() - .duration(_chart.transitionDuration()) - .ease('quad-out-in') - .tween('text', function () { - // [XA] don't try and interpolate from Infinity, else this breaks. - var interpStart = isFinite(_lastValue) ? _lastValue : 0; - var interp = d3.interpolateNumber(interpStart || 0, newValue); - _lastValue = newValue; - return function (t) { - var html = null, num = _chart.formatNumber()(interp(t)); - if (newValue === 0 && (_html.none !== '')) { - html = _html.none; - } else if (newValue === 1 && (_html.one !== '')) { - html = _html.one; - } else if (_html.some !== '') { - html = _html.some; - } - this.innerHTML = html ? html.replace('%number', num) : num; - }; - }); - }; - - _chart._doRedraw = function () { - return _chart._doRender(); - }; - - /** - * Get or set a function to format the value for the display. - * @method formatNumber - * @memberof dc.numberDisplay - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format} - * @param {Function} [formatter=d3.format('.2s')] - * @return {Function} - * @return {dc.numberDisplay} - */ - _chart.formatNumber = function (formatter) { - if (!arguments.length) { - return _formatNumber; - } - _formatNumber = formatter; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * A heat map is matrix that represents the values of two dimensions of data using colors. - * @class heatMap - * @memberof dc - * @mixes dc.colorMixin - * @mixes dc.marginMixin - * @mixes dc.baseMixin - * @example - * // create a heat map under #chart-container1 element using the default global chart group - * var heatMap1 = dc.heatMap('#chart-container1'); - * // create a heat map under #chart-container2 element using chart group A - * var heatMap2 = dc.heatMap('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.heatMap} - */ -dc.heatMap = function (parent, chartGroup) { - - var DEFAULT_BORDER_RADIUS = 6.75; - - var _chartBody; - - var _cols; - var _rows; - var _colOrdering = d3.ascending; - var _rowOrdering = d3.ascending; - var _colScale = d3.scale.ordinal(); - var _rowScale = d3.scale.ordinal(); - - var _xBorderRadius = DEFAULT_BORDER_RADIUS; - var _yBorderRadius = DEFAULT_BORDER_RADIUS; - - var _chart = dc.colorMixin(dc.marginMixin(dc.baseMixin({}))); - _chart._mandatoryAttributes(['group']); - _chart.title(_chart.colorAccessor()); - - var _colsLabel = function (d) { - return d; - }; - var _rowsLabel = function (d) { - return d; - }; - - /** - * Set or get the column label function. The chart class uses this function to render - * column labels on the X axis. It is passed the column name. - * @method colsLabel - * @memberof dc.heatMap - * @instance - * @example - * // the default label function just returns the name - * chart.colsLabel(function(d) { return d; }); - * @param {Function} [labelFunction=function(d) { return d; }] - * @return {Function} - * @return {dc.heatMap} - */ - _chart.colsLabel = function (labelFunction) { - if (!arguments.length) { - return _colsLabel; - } - _colsLabel = labelFunction; - return _chart; - }; - - /** - * Set or get the row label function. The chart class uses this function to render - * row labels on the Y axis. It is passed the row name. - * @method rowsLabel - * @memberof dc.heatMap - * @instance - * @example - * // the default label function just returns the name - * chart.rowsLabel(function(d) { return d; }); - * @param {Function} [labelFunction=function(d) { return d; }] - * @return {Function} - * @return {dc.heatMap} - */ - _chart.rowsLabel = function (labelFunction) { - if (!arguments.length) { - return _rowsLabel; - } - _rowsLabel = labelFunction; - return _chart; - }; - - var _xAxisOnClick = function (d) { filterAxis(0, d); }; - var _yAxisOnClick = function (d) { filterAxis(1, d); }; - var _boxOnClick = function (d) { - var filter = d.key; - dc.events.trigger(function () { - _chart.filter(filter); - _chart.redrawGroup(); - }); - }; - - function filterAxis (axis, value) { - var cellsOnAxis = _chart.selectAll('.box-group').filter(function (d) { - return d.key[axis] === value; - }); - var unfilteredCellsOnAxis = cellsOnAxis.filter(function (d) { - return !_chart.hasFilter(d.key); - }); - dc.events.trigger(function () { - if (unfilteredCellsOnAxis.empty()) { - cellsOnAxis.each(function (d) { - _chart.filter(d.key); - }); - } else { - unfilteredCellsOnAxis.each(function (d) { - _chart.filter(d.key); - }); - } - _chart.redrawGroup(); - }); - } - - dc.override(_chart, 'filter', function (filter) { - if (!arguments.length) { - return _chart._filter(); - } - - return _chart._filter(dc.filters.TwoDimensionalFilter(filter)); - }); - - /** - * Gets or sets the values used to create the rows of the heatmap, as an array. By default, all - * the values will be fetched from the data using the value accessor. - * @method rows - * @memberof dc.heatMap - * @instance - * @param {Array} [rows] - * @return {Array} - * @return {dc.heatMap} - */ - - _chart.rows = function (rows) { - if (!arguments.length) { - return _rows; - } - _rows = rows; - return _chart; - }; - - /** - #### .rowOrdering([orderFunction]) - Get or set an accessor to order the rows. Default is d3.ascending. - */ - _chart.rowOrdering = function (_) { - if (!arguments.length) { - return _rowOrdering; - } - _rowOrdering = _; - return _chart; - }; - - /** - * Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all - * the values will be fetched from the data using the key accessor. - * @method cols - * @memberof dc.heatMap - * @instance - * @param {Array} [cols] - * @return {Array} - * @return {dc.heatMap} - */ - _chart.cols = function (cols) { - if (!arguments.length) { - return _cols; - } - _cols = cols; - return _chart; - }; - - /** - #### .colOrdering([orderFunction]) - Get or set an accessor to order the cols. Default is ascending. - */ - _chart.colOrdering = function (_) { - if (!arguments.length) { - return _colOrdering; - } - _colOrdering = _; - return _chart; - }; - - _chart._doRender = function () { - _chart.resetSvg(); - - _chartBody = _chart.svg() - .append('g') - .attr('class', 'heatmap') - .attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')'); - - return _chart._doRedraw(); - }; - - _chart._doRedraw = function () { - var data = _chart.data(), - rows = _chart.rows() || data.map(_chart.valueAccessor()), - cols = _chart.cols() || data.map(_chart.keyAccessor()); - if (_rowOrdering) { - rows = rows.sort(_rowOrdering); - } - if (_colOrdering) { - cols = cols.sort(_colOrdering); - } - rows = _rowScale.domain(rows); - cols = _colScale.domain(cols); - - var rowCount = rows.domain().length, - colCount = cols.domain().length, - boxWidth = Math.floor(_chart.effectiveWidth() / colCount), - boxHeight = Math.floor(_chart.effectiveHeight() / rowCount); - - cols.rangeRoundBands([0, _chart.effectiveWidth()]); - rows.rangeRoundBands([_chart.effectiveHeight(), 0]); - - var boxes = _chartBody.selectAll('g.box-group').data(_chart.data(), function (d, i) { - return _chart.keyAccessor()(d, i) + '\0' + _chart.valueAccessor()(d, i); - }); - var gEnter = boxes.enter().append('g') - .attr('class', 'box-group'); - - gEnter.append('rect') - .attr('class', 'heat-box') - .attr('fill', 'white') - .on('click', _chart.boxOnClick()); - - if (_chart.renderTitle()) { - gEnter.append('title'); - boxes.selectAll('title').text(_chart.title()); - } - - dc.transition(boxes.selectAll('rect'), _chart.transitionDuration()) - .attr('x', function (d, i) { return cols(_chart.keyAccessor()(d, i)); }) - .attr('y', function (d, i) { return rows(_chart.valueAccessor()(d, i)); }) - .attr('rx', _xBorderRadius) - .attr('ry', _yBorderRadius) - .attr('fill', _chart.getColor) - .attr('width', boxWidth) - .attr('height', boxHeight); - - boxes.exit().remove(); - - var gCols = _chartBody.selectAll('g.cols'); - if (gCols.empty()) { - gCols = _chartBody.append('g').attr('class', 'cols axis'); - } - var gColsText = gCols.selectAll('text').data(cols.domain()); - gColsText.enter().append('text') - .attr('x', function (d) { return cols(d) + boxWidth / 2; }) - .style('text-anchor', 'middle') - .attr('y', _chart.effectiveHeight()) - .attr('dy', 12) - .on('click', _chart.xAxisOnClick()) - .text(_chart.colsLabel()); - dc.transition(gColsText, _chart.transitionDuration()) - .text(_chart.colsLabel()) - .attr('x', function (d) { return cols(d) + boxWidth / 2; }) - .attr('y', _chart.effectiveHeight()); - gColsText.exit().remove(); - var gRows = _chartBody.selectAll('g.rows'); - if (gRows.empty()) { - gRows = _chartBody.append('g').attr('class', 'rows axis'); - } - var gRowsText = gRows.selectAll('text').data(rows.domain()); - gRowsText.enter().append('text') - .attr('dy', 6) - .style('text-anchor', 'end') - .attr('x', 0) - .attr('dx', -2) - .on('click', _chart.yAxisOnClick()) - .text(_chart.rowsLabel()); - dc.transition(gRowsText, _chart.transitionDuration()) - .text(_chart.rowsLabel()) - .attr('y', function (d) { return rows(d) + boxHeight / 2; }); - gRowsText.exit().remove(); - - if (_chart.hasFilter()) { - _chart.selectAll('g.box-group').each(function (d) { - if (_chart.isSelectedNode(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.selectAll('g.box-group').each(function () { - _chart.resetHighlight(this); - }); - } - return _chart; - }; - - /** - * Gets or sets the handler that fires when an individual cell is clicked in the heatmap. - * By default, filtering of the cell will be toggled. - * @method boxOnClick - * @memberof dc.heatMap - * @instance - * @example - * // default box on click handler - * chart.boxOnClick(function (d) { - * var filter = d.key; - * dc.events.trigger(function () { - * _chart.filter(filter); - * _chart.redrawGroup(); - * }); - * }); - * @param {Function} [handler] - * @return {Function} - * @return {dc.heatMap} - */ - _chart.boxOnClick = function (handler) { - if (!arguments.length) { - return _boxOnClick; - } - _boxOnClick = handler; - return _chart; - }; - - /** - * Gets or sets the handler that fires when a column tick is clicked in the x axis. - * By default, if any cells in the column are unselected, the whole column will be selected, - * otherwise the whole column will be unselected. - * @method xAxisOnClick - * @memberof dc.heatMap - * @instance - * @param {Function} [handler] - * @return {Function} - * @return {dc.heatMap} - */ - _chart.xAxisOnClick = function (handler) { - if (!arguments.length) { - return _xAxisOnClick; - } - _xAxisOnClick = handler; - return _chart; - }; - - /** - * Gets or sets the handler that fires when a row tick is clicked in the y axis. - * By default, if any cells in the row are unselected, the whole row will be selected, - * otherwise the whole row will be unselected. - * @method yAxisOnClick - * @memberof dc.heatMap - * @instance - * @param {Function} [handler] - * @return {Function} - * @return {dc.heatMap} - */ - _chart.yAxisOnClick = function (handler) { - if (!arguments.length) { - return _yAxisOnClick; - } - _yAxisOnClick = handler; - return _chart; - }; - - /** - * Gets or sets the X border radius. Set to 0 to get full rectangles. - * @method xBorderRadius - * @memberof dc.heatMap - * @instance - * @param {Number} [xBorderRadius=6.75] - * @return {Number} - * @return {dc.heatMap} - */ - _chart.xBorderRadius = function (xBorderRadius) { - if (!arguments.length) { - return _xBorderRadius; - } - _xBorderRadius = xBorderRadius; - return _chart; - }; - - /** - * Gets or sets the Y border radius. Set to 0 to get full rectangles. - * @method yBorderRadius - * @memberof dc.heatMap - * @instance - * @param {Number} [yBorderRadius=6.75] - * @return {Number} - * @return {dc.heatMap} - */ - _chart.yBorderRadius = function (yBorderRadius) { - if (!arguments.length) { - return _yBorderRadius; - } - _yBorderRadius = yBorderRadius; - return _chart; - }; - - _chart.isSelectedNode = function (d) { - return _chart.hasFilter(d.key); - }; - - return _chart.anchor(parent, chartGroup); -}; - -// https://github.com/d3/d3-plugins/blob/master/box/box.js -(function () { - - // Inspired by http://informationandvisualization.de/blog/box-plot - d3.box = function () { - var width = 1, - height = 1, - duration = 0, - domain = null, - value = Number, - whiskers = boxWhiskers, - quartiles = boxQuartiles, - tickFormat = null; - - // For each small multiple… - function box (g) { - g.each(function (d, i) { - d = d.map(value).sort(d3.ascending); - var g = d3.select(this), - n = d.length, - min = d[0], - max = d[n - 1]; - - // Compute quartiles. Must return exactly 3 elements. - var quartileData = d.quartiles = quartiles(d); - - // Compute whiskers. Must return exactly 2 elements, or null. - var whiskerIndices = whiskers && whiskers.call(this, d, i), - whiskerData = whiskerIndices && whiskerIndices.map(function (i) { return d[i]; }); - - // Compute outliers. If no whiskers are specified, all data are 'outliers'. - // We compute the outliers as indices, so that we can join across transitions! - var outlierIndices = whiskerIndices ? - d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n)) : d3.range(n); - - // Compute the new x-scale. - var x1 = d3.scale.linear() - .domain(domain && domain.call(this, d, i) || [min, max]) - .range([height, 0]); - - // Retrieve the old x-scale, if this is an update. - var x0 = this.__chart__ || d3.scale.linear() - .domain([0, Infinity]) - .range(x1.range()); - - // Stash the new scale. - this.__chart__ = x1; - - // Note: the box, median, and box tick elements are fixed in number, - // so we only have to handle enter and update. In contrast, the outliers - // and other elements are variable, so we need to exit them! Variable - // elements also fade in and out. - - // Update center line: the vertical line spanning the whiskers. - var center = g.selectAll('line.center') - .data(whiskerData ? [whiskerData] : []); - - center.enter().insert('line', 'rect') - .attr('class', 'center') - .attr('x1', width / 2) - .attr('y1', function (d) { return x0(d[0]); }) - .attr('x2', width / 2) - .attr('y2', function (d) { return x0(d[1]); }) - .style('opacity', 1e-6) - .transition() - .duration(duration) - .style('opacity', 1) - .attr('y1', function (d) { return x1(d[0]); }) - .attr('y2', function (d) { return x1(d[1]); }); - - center.transition() - .duration(duration) - .style('opacity', 1) - .attr('y1', function (d) { return x1(d[0]); }) - .attr('y2', function (d) { return x1(d[1]); }); - - center.exit().transition() - .duration(duration) - .style('opacity', 1e-6) - .attr('y1', function (d) { return x1(d[0]); }) - .attr('y2', function (d) { return x1(d[1]); }) - .remove(); - - // Update innerquartile box. - var box = g.selectAll('rect.box') - .data([quartileData]); - - box.enter().append('rect') - .attr('class', 'box') - .attr('x', 0) - .attr('y', function (d) { return x0(d[2]); }) - .attr('width', width) - .attr('height', function (d) { return x0(d[0]) - x0(d[2]); }) - .transition() - .duration(duration) - .attr('y', function (d) { return x1(d[2]); }) - .attr('height', function (d) { return x1(d[0]) - x1(d[2]); }); - - box.transition() - .duration(duration) - .attr('y', function (d) { return x1(d[2]); }) - .attr('height', function (d) { return x1(d[0]) - x1(d[2]); }); - - // Update median line. - var medianLine = g.selectAll('line.median') - .data([quartileData[1]]); - - medianLine.enter().append('line') - .attr('class', 'median') - .attr('x1', 0) - .attr('y1', x0) - .attr('x2', width) - .attr('y2', x0) - .transition() - .duration(duration) - .attr('y1', x1) - .attr('y2', x1); - - medianLine.transition() - .duration(duration) - .attr('y1', x1) - .attr('y2', x1); - - // Update whiskers. - var whisker = g.selectAll('line.whisker') - .data(whiskerData || []); - - whisker.enter().insert('line', 'circle, text') - .attr('class', 'whisker') - .attr('x1', 0) - .attr('y1', x0) - .attr('x2', width) - .attr('y2', x0) - .style('opacity', 1e-6) - .transition() - .duration(duration) - .attr('y1', x1) - .attr('y2', x1) - .style('opacity', 1); - - whisker.transition() - .duration(duration) - .attr('y1', x1) - .attr('y2', x1) - .style('opacity', 1); - - whisker.exit().transition() - .duration(duration) - .attr('y1', x1) - .attr('y2', x1) - .style('opacity', 1e-6) - .remove(); - - // Update outliers. - var outlier = g.selectAll('circle.outlier') - .data(outlierIndices, Number); - - outlier.enter().insert('circle', 'text') - .attr('class', 'outlier') - .attr('r', 5) - .attr('cx', width / 2) - .attr('cy', function (i) { return x0(d[i]); }) - .style('opacity', 1e-6) - .transition() - .duration(duration) - .attr('cy', function (i) { return x1(d[i]); }) - .style('opacity', 1); - - outlier.transition() - .duration(duration) - .attr('cy', function (i) { return x1(d[i]); }) - .style('opacity', 1); - - outlier.exit().transition() - .duration(duration) - .attr('cy', function (i) { return x1(d[i]); }) - .style('opacity', 1e-6) - .remove(); - - // Compute the tick format. - var format = tickFormat || x1.tickFormat(8); - - // Update box ticks. - var boxTick = g.selectAll('text.box') - .data(quartileData); - - boxTick.enter().append('text') - .attr('class', 'box') - .attr('dy', '.3em') - .attr('dx', function (d, i) { return i & 1 ? 6 : -6; }) - .attr('x', function (d, i) { return i & 1 ? width : 0; }) - .attr('y', x0) - .attr('text-anchor', function (d, i) { return i & 1 ? 'start' : 'end'; }) - .text(format) - .transition() - .duration(duration) - .attr('y', x1); - - boxTick.transition() - .duration(duration) - .text(format) - .attr('y', x1); - - // Update whisker ticks. These are handled separately from the box - // ticks because they may or may not exist, and we want don't want - // to join box ticks pre-transition with whisker ticks post-. - var whiskerTick = g.selectAll('text.whisker') - .data(whiskerData || []); - - whiskerTick.enter().append('text') - .attr('class', 'whisker') - .attr('dy', '.3em') - .attr('dx', 6) - .attr('x', width) - .attr('y', x0) - .text(format) - .style('opacity', 1e-6) - .transition() - .duration(duration) - .attr('y', x1) - .style('opacity', 1); - - whiskerTick.transition() - .duration(duration) - .text(format) - .attr('y', x1) - .style('opacity', 1); - - whiskerTick.exit().transition() - .duration(duration) - .attr('y', x1) - .style('opacity', 1e-6) - .remove(); - }); - d3.timer.flush(); - } - - box.width = function (x) { - if (!arguments.length) { - return width; - } - width = x; - return box; - }; - - box.height = function (x) { - if (!arguments.length) { - return height; - } - height = x; - return box; - }; - - box.tickFormat = function (x) { - if (!arguments.length) { - return tickFormat; - } - tickFormat = x; - return box; - }; - - box.duration = function (x) { - if (!arguments.length) { - return duration; - } - duration = x; - return box; - }; - - box.domain = function (x) { - if (!arguments.length) { - return domain; - } - domain = x === null ? x : d3.functor(x); - return box; - }; - - box.value = function (x) { - if (!arguments.length) { - return value; - } - value = x; - return box; - }; - - box.whiskers = function (x) { - if (!arguments.length) { - return whiskers; - } - whiskers = x; - return box; - }; - - box.quartiles = function (x) { - if (!arguments.length) { - return quartiles; - } - quartiles = x; - return box; - }; - - return box; - }; - - function boxWhiskers (d) { - return [0, d.length - 1]; - } - - function boxQuartiles (d) { - return [ - d3.quantile(d, 0.25), - d3.quantile(d, 0.5), - d3.quantile(d, 0.75) - ]; - } - -})(); - -/** - * A box plot is a chart that depicts numerical data via their quartile ranges. - * - * Examples: - * - {@link http://dc-js.github.io/dc.js/examples/box-plot-time.html Box plot time example} - * - {@link http://dc-js.github.io/dc.js/examples/box-plot.html Box plot example} - * @class boxPlot - * @memberof dc - * @mixes dc.coordinateGridMixin - * @example - * // create a box plot under #chart-container1 element using the default global chart group - * var boxPlot1 = dc.boxPlot('#chart-container1'); - * // create a box plot under #chart-container2 element using chart group A - * var boxPlot2 = dc.boxPlot('#chart-container2', 'chartGroupA'); - * @param {String|node|d3.selection} parent - Any valid - * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying - * a dom block element such as a div; or a dom element or d3 selection. - * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in. - * Interaction with a chart will only trigger events and redraws within the chart's group. - * @return {dc.boxPlot} - */ -dc.boxPlot = function (parent, chartGroup) { - var _chart = dc.coordinateGridMixin({}); - - // Returns a function to compute the interquartile range. - function DEFAULT_WHISKERS_IQR (k) { - return function (d) { - var q1 = d.quartiles[0], - q3 = d.quartiles[2], - iqr = (q3 - q1) * k, - i = -1, - j = d.length; - do { ++i; } while (d[i] < q1 - iqr); - do { --j; } while (d[j] > q3 + iqr); - return [i, j]; - }; - } - - var _whiskerIqrFactor = 1.5; - var _whiskersIqr = DEFAULT_WHISKERS_IQR; - var _whiskers = _whiskersIqr(_whiskerIqrFactor); - - var _box = d3.box(); - var _tickFormat = null; - - var _boxWidth = function (innerChartWidth, xUnits) { - if (_chart.isOrdinal()) { - return _chart.x().rangeBand(); - } else { - return innerChartWidth / (1 + _chart.boxPadding()) / xUnits; - } - }; - - // default padding to handle min/max whisker text - _chart.yAxisPadding(12); - - // default to ordinal - _chart.x(d3.scale.ordinal()); - _chart.xUnits(dc.units.ordinal); - - // valueAccessor should return an array of values that can be coerced into numbers - // or if data is overloaded for a static array of arrays, it should be `Number`. - // Empty arrays are not included. - _chart.data(function (group) { - return group.all().map(function (d) { - d.map = function (accessor) { return accessor.call(d, d); }; - return d; - }).filter(function (d) { - var values = _chart.valueAccessor()(d); - return values.length !== 0; - }); - }); - - /** - * Get or set the spacing between boxes as a fraction of box size. Valid values are within 0-1. - * See the {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3 docs} - * for a visual description of how the padding is applied. - * @method boxPadding - * @memberof dc.boxPlot - * @instance - * @see {@link https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeBands d3.scale.ordinal.rangeBands} - * @param {Number} [padding=0.8] - * @return {Number} - * @return {dc.boxPlot} - */ - _chart.boxPadding = _chart._rangeBandPadding; - _chart.boxPadding(0.8); - - /** - * Get or set the outer padding on an ordinal box chart. This setting has no effect on non-ordinal charts - * or on charts with a custom {@link dc.boxPlot#boxWidth .boxWidth}. Will pad the width by - * `padding * barWidth` on each side of the chart. - * @method outerPadding - * @memberof dc.boxPlot - * @instance - * @param {Number} [padding=0.5] - * @return {Number} - * @return {dc.boxPlot} - */ - _chart.outerPadding = _chart._outerRangeBandPadding; - _chart.outerPadding(0.5); - - /** - * Get or set the numerical width of the boxplot box. The width may also be a function taking as - * parameters the chart width excluding the right and left margins, as well as the number of x - * units. - * @example - * // Using numerical parameter - * chart.boxWidth(10); - * // Using function - * chart.boxWidth((innerChartWidth, xUnits) { ... }); - * @method boxWidth - * @memberof dc.boxPlot - * @instance - * @param {Number|Function} [boxWidth=0.5] - * @return {Number|Function} - * @return {dc.boxPlot} - */ - _chart.boxWidth = function (boxWidth) { - if (!arguments.length) { - return _boxWidth; - } - _boxWidth = d3.functor(boxWidth); - return _chart; - }; - - var boxTransform = function (d, i) { - var xOffset = _chart.x()(_chart.keyAccessor()(d, i)); - return 'translate(' + xOffset + ', 0)'; - }; - - _chart._preprocessData = function () { - if (_chart.elasticX()) { - _chart.x().domain([]); - } - }; - - _chart.plotData = function () { - var _calculatedBoxWidth = _boxWidth(_chart.effectiveWidth(), _chart.xUnitCount()); - - _box.whiskers(_whiskers) - .width(_calculatedBoxWidth) - .height(_chart.effectiveHeight()) - .value(_chart.valueAccessor()) - .domain(_chart.y().domain()) - .duration(_chart.transitionDuration()) - .tickFormat(_tickFormat); - - var boxesG = _chart.chartBodyG().selectAll('g.box').data(_chart.data(), function (d) { return d.key; }); - - renderBoxes(boxesG); - updateBoxes(boxesG); - removeBoxes(boxesG); - - _chart.fadeDeselectedArea(); - }; - - function renderBoxes (boxesG) { - var boxesGEnter = boxesG.enter().append('g'); - - boxesGEnter - .attr('class', 'box') - .attr('transform', boxTransform) - .call(_box) - .on('click', function (d) { - _chart.filter(d.key); - _chart.redrawGroup(); - }); - } - - function updateBoxes (boxesG) { - dc.transition(boxesG, _chart.transitionDuration()) - .attr('transform', boxTransform) - .call(_box) - .each(function () { - d3.select(this).select('rect.box').attr('fill', _chart.getColor); - }); - } - - function removeBoxes (boxesG) { - boxesG.exit().remove().call(_box); - } - - _chart.fadeDeselectedArea = function () { - if (_chart.hasFilter()) { - _chart.g().selectAll('g.box').each(function (d) { - if (_chart.isSelectedNode(d)) { - _chart.highlightSelected(this); - } else { - _chart.fadeDeselected(this); - } - }); - } else { - _chart.g().selectAll('g.box').each(function () { - _chart.resetHighlight(this); - }); - } - }; - - _chart.isSelectedNode = function (d) { - return _chart.hasFilter(d.key); - }; - - _chart.yAxisMin = function () { - var min = d3.min(_chart.data(), function (e) { - return d3.min(_chart.valueAccessor()(e)); - }); - return dc.utils.subtract(min, _chart.yAxisPadding()); - }; - - _chart.yAxisMax = function () { - var max = d3.max(_chart.data(), function (e) { - return d3.max(_chart.valueAccessor()(e)); - }); - return dc.utils.add(max, _chart.yAxisPadding()); - }; - - /** - * Set the numerical format of the boxplot median, whiskers and quartile labels. Defaults to - * integer formatting. - * @example - * // format ticks to 2 decimal places - * chart.tickFormat(d3.format('.2f')); - * @method tickFormat - * @memberof dc.boxPlot - * @instance - * @param {Function} [tickFormat] - * @return {Number|Function} - * @return {dc.boxPlot} - */ - _chart.tickFormat = function (tickFormat) { - if (!arguments.length) { - return _tickFormat; - } - _tickFormat = tickFormat; - return _chart; - }; - - return _chart.anchor(parent, chartGroup); -}; - -/** - * The select menu is a simple widget designed to filter a dimension by selecting an option from - * an HTML `` menu. The menu can be optionally turned into a multiselect.\n * @class selectMenu\n * @memberof dc\n * @mixes dc.baseMixin\n * @example\n * // create a select menu under #select-container using the default global chart group\n * var select = dc.selectMenu('#select-container')\n * .dimension(states)\n * .group(stateGroup);\n * // the option text can be set via the title() function\n * // by default the option text is '`key`: `value`'\n * select.title(function (d){\n * return 'STATE: ' + d.key;\n * })\n * @param {String|node|d3.selection|dc.compositeChart} parent - Any valid\n * [d3 single selector](https://github.com/mbostock/d3/wiki/Selections#selecting-elements) specifying\n * a dom block element such as a div; or a dom element or d3 selection.\n * @param {String} [chartGroup] - The name of the chart group this widget should be placed in.\n * Interaction with the widget will only trigger events and redraws within its group.\n * @returns {selectMenu}\n **/\ndc.selectMenu = function (parent, chartGroup) {\n var SELECT_CSS_CLASS = 'dc-select-menu';\n var OPTION_CSS_CLASS = 'dc-select-option';\n\n var _chart = dc.baseMixin({});\n\n var _select;\n var _promptText = 'Select all';\n var _multiple = false;\n var _promptValue = null;\n var _numberVisible = null;\n var _order = function (a, b) {\n return _chart.keyAccessor()(a) > _chart.keyAccessor()(b) ?\n 1 : _chart.keyAccessor()(b) > _chart.keyAccessor()(a) ?\n -1 : 0;\n };\n\n var _filterDisplayed = function (d) {\n return _chart.valueAccessor()(d) > 0;\n };\n\n _chart.data(function (group) {\n return group.all().filter(_filterDisplayed);\n });\n\n _chart._doRender = function () {\n _chart.select('select').remove();\n _select = _chart.root().append('select')\n .classed(SELECT_CSS_CLASS, true);\n _select.append('option').text(_promptText).attr('value', '');\n\n _chart._doRedraw();\n return _chart;\n };\n\n _chart._doRedraw = function () {\n setAttributes();\n renderOptions();\n // select the option(s) corresponding to current filter(s)\n if (_chart.hasFilter() && _multiple) {\n _select.selectAll('option')\n .property('selected', function (d) {\n return d && _chart.filters().indexOf(String(_chart.keyAccessor()(d))) >= 0;\n });\n } else if (_chart.hasFilter()) {\n _select.property('value', _chart.filter());\n } else {\n _select.property('value', '');\n }\n return _chart;\n };\n\n function renderOptions () {\n var options = _select.selectAll('option.' + OPTION_CSS_CLASS)\n .data(_chart.data(), function (d) { return _chart.keyAccessor()(d); });\n\n options.enter()\n .append('option')\n .classed(OPTION_CSS_CLASS, true)\n .attr('value', function (d) { return _chart.keyAccessor()(d); });\n\n options.text(_chart.title());\n options.exit().remove();\n _select.selectAll('option.' + OPTION_CSS_CLASS).sort(_order);\n\n _select.on('change', onChange);\n return options;\n }\n\n function onChange (d, i) {\n var values;\n var target = d3.event.target;\n if (target.selectedOptions) {\n var selectedOptions = Array.prototype.slice.call(target.selectedOptions);\n values = selectedOptions.map(function (d) {\n return d.value;\n });\n } else { // IE and other browsers do not support selectedOptions\n // adapted from this polyfill: https://gist.github.com/brettz9/4212217\n var options = [].slice.call(d3.event.target.options);\n values = options.filter(function (option) {\n return option.selected;\n }).map(function (option) {\n return option.value;\n });\n }\n // console.log(values);\n // check if only prompt option is selected\n if (values.length === 1 && values[0] === '') {\n values = _promptValue || null;\n } else if (!_multiple && values.length === 1) {\n values = values[0];\n }\n _chart.onChange(values);\n }\n\n _chart.onChange = function (val) {\n if (val && _multiple) {\n _chart.replaceFilter([val]);\n } else if (val) {\n _chart.replaceFilter(val);\n } else {\n _chart.filterAll();\n }\n dc.events.trigger(function () {\n _chart.redrawGroup();\n });\n };\n\n function setAttributes () {\n if (_multiple) {\n _select.attr('multiple', true);\n } else {\n _select.attr('multiple', null);\n }\n if (_numberVisible !== null) {\n _select.attr('size', _numberVisible);\n } else {\n _select.attr('size', null);\n }\n }\n\n /**\n * Get or set the function that controls the ordering of option tags in the\n * select menu. By default options are ordered by the group key in ascending\n * order.\n * @name order\n * @memberof dc.selectMenu\n * @instance\n * @param {Function} [order]\n * @example\n * // order by the group's value\n * chart.order(function (a,b) {\n * return a.value > b.value ? 1 : b.value > a.value ? -1 : 0;\n * });\n **/\n _chart.order = function (order) {\n if (!arguments.length) {\n return _order;\n }\n _order = order;\n return _chart;\n };\n\n /**\n * Get or set the text displayed in the options used to prompt selection.\n * @name promptText\n * @memberof dc.selectMenu\n * @instance\n * @param {String} [promptText='Select all']\n * @example\n * chart.promptText('All states');\n **/\n _chart.promptText = function (_) {\n if (!arguments.length) {\n return _promptText;\n }\n _promptText = _;\n return _chart;\n };\n\n /**\n * Get or set the function that filters option tags prior to display. By default options\n * with a value of < 1 are not displayed.\n * @name filterDisplayed\n * @memberof dc.selectMenu\n * @instance\n * @param {function} [filterDisplayed]\n * @example\n * // display all options override the `filterDisplayed` function:\n * chart.filterDisplayed(function () {\n * return true;\n * });\n **/\n _chart.filterDisplayed = function (filterDisplayed) {\n if (!arguments.length) {\n return _filterDisplayed;\n }\n _filterDisplayed = filterDisplayed;\n return _chart;\n };\n\n /**\n * Controls the type of select menu. Setting it to true converts the underlying\n * HTML tag into a multiple select.\n * @name multiple\n * @memberof dc.selectMenu\n * @instance\n * @param {boolean} [multiple=false]\n * @example\n * chart.multiple(true);\n **/\n _chart.multiple = function (multiple) {\n if (!arguments.length) {\n return _multiple;\n }\n _multiple = multiple;\n\n return _chart;\n };\n\n /**\n * Controls the default value to be used for\n * [dimension.filter](https://github.com/crossfilter/crossfilter/wiki/API-Reference#dimension_filter)\n * when only the prompt value is selected. If `null` (the default), no filtering will occur when\n * just the prompt is selected.\n * @name promptValue\n * @memberof dc.selectMenu\n * @instance\n * @param {?*} [promptValue=null]\n **/\n _chart.promptValue = function (promptValue) {\n if (!arguments.length) {\n return _promptValue;\n }\n _promptValue = promptValue;\n\n return _chart;\n };\n\n /**\n * Controls the number of items to show in the select menu, when `.multiple()` is true. This\n * controls the [`size` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Attributes) of\n * the `select` element. If `null` (the default), uses the browser's default height.\n * @name numberItems\n * @memberof dc.selectMenu\n * @instance\n * @param {?number} [numberVisible=null]\n * @example\n * chart.numberVisible(10);\n **/\n _chart.numberVisible = function (numberVisible) {\n if (!arguments.length) {\n return _numberVisible;\n }\n _numberVisible = numberVisible;\n\n return _chart;\n };\n\n _chart.size = dc.logger.deprecate(_chart.numberVisible, 'selectMenu.size is ambiguous - use numberVisible instead');\n\n return _chart.anchor(parent, chartGroup);\n};\n","// Renamed functions\n\ndc.abstractBubbleChart = dc.bubbleMixin;\ndc.baseChart = dc.baseMixin;\ndc.capped = dc.capMixin;\ndc.colorChart = dc.colorMixin;\ndc.coordinateGridChart = dc.coordinateGridMixin;\ndc.marginable = dc.marginMixin;\ndc.stackableChart = dc.stackMixin;\n\n// Expose d3 and crossfilter, so that clients in browserify\n// case can obtain them if they need them.\ndc.d3 = d3;\ndc.crossfilter = crossfilter;\n\nreturn dc;}\n if(typeof define === \"function\" && define.amd) {\n define([\"d3\", \"crossfilter\"], _dc);\n } else if(typeof module === \"object\" && module.exports) {\n var _d3 = require('d3');\n var _crossfilter = require('crossfilter2');\n // When using npm + browserify, 'crossfilter' is a function,\n // since package.json specifies index.js as main function, and it\n // does special handling. When using bower + browserify,\n // there's no main in bower.json (in fact, there's no bower.json),\n // so we need to fix it.\n if (typeof _crossfilter !== \"function\") {\n _crossfilter = _crossfilter.crossfilter;\n }\n module.exports = _dc(_d3, _crossfilter);\n } else {\n this.dc = _dc(d3, crossfilter);\n }\n}\n)();\n"]} \ No newline at end of file diff --git a/web/js/dc.min.js b/web/js/dc.min.js deleted file mode 100644 index 94a81aa2c7..0000000000 --- a/web/js/dc.min.js +++ /dev/null @@ -1,23 +0,0 @@ -/*! - * dc 2.1.0-dev - * http://dc-js.github.io/dc.js/ - * Copyright 2012-2016 Nick Zhu & the dc.js Developers - * https://github.com/dc-js/dc.js/blob/master/AUTHORS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -!function(){function a(a,b){"use strict";var c={version:"2.1.0-dev",constants:{CHART_CLASS:"dc-chart",DEBUG_GROUP_CLASS:"debug",STACK_CLASS:"stack",DESELECTED_CLASS:"deselected",SELECTED_CLASS:"selected",NODE_INDEX_NAME:"__index__",GROUP_INDEX_NAME:"__group_index__",DEFAULT_CHART_GROUP:"__default_chart_group__",EVENT_DELAY:40,NEGLIGIBLE_NUMBER:1e-10},_renderlet:null};c.chartRegistry=function(){function a(a){return a||(a=c.constants.DEFAULT_CHART_GROUP),b[a]||(b[a]=[]),a}var b={};return{has:function(a){for(var c in b)if(b[c].indexOf(a)>=0)return!0;return!1},register:function(c,d){d=a(d),b[d].push(c)},deregister:function(c,d){d=a(d);for(var e=0;e=b||void 0===b||c.disableTransitions)return a;var f=a.transition(e).duration(b);return"function"==typeof d&&d(f),f},c.optionalTransition=function(a,b,d,e){return a?function(a){return c.transition(a,b,d,e)}:function(a){return a}},c.afterTransition=function(a,b){if(a.empty()||!a.duration)b.call(a);else{var c=0;a.each(function(){++c}).each("end",function(){--c||b.call(a)})}},c.units={},c.units.integers=function(a,b){return Math.abs(b-a)},c.units.ordinal=function(a,b,c){return c},c.units.fp={},c.units.fp.precision=function(a){var b=function(a,d){var e=Math.abs((d-a)/b.resolution);return c.utils.isNegligible(e-Math.floor(e))?Math.floor(e):Math.ceil(e)};return b.resolution=a,b},c.round={},c.round.floor=function(a){return Math.floor(a)},c.round.ceil=function(a){return Math.ceil(a)},c.round.round=function(a){return Math.round(a)},c.override=function(a,b,c){var d=a[b];a["_"+b]=d,a[b]=c},c.renderlet=function(a){return arguments.length?(c._renderlet=a,c):c._renderlet},c.instanceOfChart=function(a){return a instanceof Object&&a.__dcFlag__&&!0},c.errors={},c.errors.Exception=function(a){var b=a||"Unexpected internal error";this.message=b,this.toString=function(){return b},this.stack=(new Error).stack},c.errors.Exception.prototype=Object.create(Error.prototype),c.errors.Exception.prototype.constructor=c.errors.Exception,c.errors.InvalidStateException=function(){c.errors.Exception.apply(this,arguments)},c.errors.InvalidStateException.prototype=Object.create(c.errors.Exception.prototype),c.errors.InvalidStateException.prototype.constructor=c.errors.InvalidStateException,c.errors.BadArgumentException=function(){c.errors.Exception.apply(this,arguments)},c.errors.BadArgumentException.prototype=Object.create(c.errors.Exception.prototype),c.errors.BadArgumentException.prototype.constructor=c.errors.BadArgumentException,c.dateFormat=a.time.format("%m/%d/%Y"),c.printers={},c.printers.filters=function(a){for(var b="",d=0;d0&&(b+=", "),b+=c.printers.filter(a[d]);return b},c.printers.filter=function(a){var b="";return"undefined"!=typeof a&&null!==a&&(a instanceof Array?a.length>=2?b="["+c.utils.printSingleValue(a[0])+" -> "+c.utils.printSingleValue(a[1])+"]":a.length>=1&&(b=c.utils.printSingleValue(a[0])):b=c.utils.printSingleValue(a)),b},c.pluck=function(a,b){return b?function(c,d){return b.call(c,c[a],d)}:function(b){return b[a]}},c.utils={},c.utils.printSingleValue=function(a){var b=""+a;return a instanceof Date?b=c.dateFormat(a):"string"==typeof a?b=a:c.utils.isFloat(a)?b=c.utils.printSingleValue.fformat(a):c.utils.isInteger(a)&&(b=Math.round(a)),b},c.utils.printSingleValue.fformat=a.format(".2f"),c.utils.add=function(a,b){if("string"==typeof b&&(b=b.replace("%","")),a instanceof Date){"string"==typeof b&&(b=+b);var c=new Date;return c.setTime(a.getTime()),c.setDate(a.getDate()+b),c}if("string"==typeof b){var d=+b/100;return a>0?a*(1+d):a*(1-d)}return a+b},c.utils.subtract=function(a,b){if("string"==typeof b&&(b=b.replace("%","")),a instanceof Date){"string"==typeof b&&(b=+b);var c=new Date;return c.setTime(a.getTime()),c.setDate(a.getDate()-b),c}if("string"==typeof b){var d=+b/100;return 0>a?a*(1+d):a*(1-d)}return a-b},c.utils.isNumber=function(a){return a===+a},c.utils.isFloat=function(a){return a===+a&&a!==(0|a)},c.utils.isInteger=function(a){return a===+a&&a===(0|a)},c.utils.isNegligible=function(a){return!c.utils.isNumber(a)||a-c.constants.NEGLIGIBLE_NUMBER},c.utils.clamp=function(a,b,c){return b>a?b:a>c?c:a};var d=0;return c.utils.uniqueId=function(){return++d},c.utils.nameToId=function(a){return a.toLowerCase().replace(/[\s]/g,"_").replace(/[\.']/g,"")},c.utils.appendOrSelect=function(a,b,c){c=c||b;var d=a.select(b);return d.empty()&&(d=a.append(c)),d},c.utils.safeNumber=function(a){return c.utils.isNumber(+a)?+a:0},c.logger={},c.logger.enableDebugLog=!1,c.logger.warn=function(a){return console&&(console.warn?console.warn(a):console.log&&console.log(a)),c.logger},c.logger.debug=function(a){return c.logger.enableDebugLog&&console&&(console.debug?console.debug(a):console.log&&console.log(a)),c.logger},c.logger.deprecate=function(a,b){function d(){return e||(c.logger.warn(b),e=!0),a.apply(this,arguments)}var e=!1;return d},c.events={current:null},c.events.trigger=function(a,b){return b?(c.events.current=a,void setTimeout(function(){a===c.events.current&&a()},b)):void a()},c.filters={},c.filters.RangedFilter=function(a,b){var c=new Array(a,b);return c.isFiltered=function(a){return a>=this[0]&&a=b[0][0]&&c=b[0][1]&&dt?b:t},v=u,w=200,x=function(a){var b=a&&a.getBoundingClientRect&&a.getBoundingClientRect().height;return b&&b>w?b:w},y=x,z=c.pluck("key"),A=c.pluck("value"),B=c.pluck("key"),C=c.pluck("key"),D=!1,E=function(a){return d.keyAccessor()(a)+": "+d.valueAccessor()(a)},F=!0,G=!1,H=750,I=c.printers.filters,J=["dimension","group"],K=c.constants.DEFAULT_CHART_GROUP,L=a.dispatch("preRender","postRender","preRedraw","postRedraw","filtered","zoomed","renderlet","pretransition"),M=[],N=function(a,b){return 0===b.length?a.filter(null):1!==b.length||b[0].isFiltered?1===b.length&&"RangedFilter"===b[0].filterType?a.filterRange(b[0]):a.filterFunction(function(a){for(var c=0;c=d&&d>=a)return!0}return!1}):a.filterExact(b[0]),b},O=function(a){return a.all()};d.height=function(b){return arguments.length?(y=a.functor(b||x),p=void 0,d):(c.utils.isNumber(p)||(p=y(l.node())),p)},d.width=function(b){return arguments.length?(v=a.functor(b||u),o=void 0,d):(c.utils.isNumber(o)||(o=v(l.node())),o)},d.minWidth=function(a){return arguments.length?(t=a,d):t},d.minHeight=function(a){return arguments.length?(w=a,d):w},d.dimension=function(a){return arguments.length?(i=a,d.expireCache(),d):i},d.data=function(b){return arguments.length?(O=a.functor(b),d.expireCache(),d):O.call(d,j)},d.group=function(a,b){return arguments.length?(j=a,d._groupName=b,d.expireCache(),d):j},d.ordering=function(a){return arguments.length?(C=a,q=b.quicksort.by(C),d.expireCache(),d):C},d._computeOrderedGroups=function(a){var c=a.slice(0);return c.length<=1?c:(q||(q=b.quicksort.by(C)),q(c,0,c.length))},d.filterAll=function(){return d.filter(null)},d.select=function(a){return l.select(a)},d.selectAll=function(a){return l?l.selectAll(a):null},d.anchor=function(b,e){if(!arguments.length)return k;if(c.instanceOfChart(b))k=b.anchor(),l=b.root(),n=!0;else{if(!b)throw new c.errors.BadArgumentException("parent must be defined");k=b.select&&b.classed?b.node():b,l=a.select(k),l.classed(c.constants.CHART_CLASS,!0),c.registerChart(d,e),n=!1}return K=e,d},d.anchorName=function(){var a=d.anchor();return a&&a.id?a.id:a&&a.replace?a.replace("#",""):"dc-chart"+d.chartID()},d.root=function(a){return arguments.length?(l=a,d):l},d.svg=function(a){return arguments.length?(m=a,d):m},d.resetSvg=function(){return d.select("svg").remove(),f()},d.filterPrinter=function(a){return arguments.length?(I=a,d):I},d.controlsUseVisibility=function(a){return arguments.length?(G=a,d):G},d.turnOnControls=function(){if(l){var a=d.controlsUseVisibility()?"visibility":"display";d.selectAll(".reset").style(a,null),d.selectAll(".filter").text(I(d.filters())).style(a,null)}return d},d.turnOffControls=function(){if(l){var a=d.controlsUseVisibility()?"visibility":"display",b=d.controlsUseVisibility()?"hidden":"none";d.selectAll(".reset").style(a,b),d.selectAll(".filter").style(a,b).text(d.filter())}return d},d.transitionDuration=function(a){return arguments.length?(H=a,d):H},d._mandatoryAttributes=function(a){return arguments.length?(J=a,d):J},d.render=function(){p=o=void 0,L.preRender(d),J&&J.forEach(g);var a=d._doRender();return r&&r.render(),d._activateRenderlets("postRender"),a},d._activateRenderlets=function(a){L.pretransition(d),d.transitionDuration()>0&&m?m.transition().duration(d.transitionDuration()).each("end",function(){L.renderlet(d),a&&L[a](d)}):(L.renderlet(d),a&&L[a](d))},d.redraw=function(){e(),L.preRedraw(d);var a=d._doRedraw();return r&&r.render(),d._activateRenderlets("postRedraw"),a},d.commitHandler=function(a){return arguments.length?(s=a,d):s},d.redrawGroup=function(){return s?s(!1,function(a,b){a?console.log(a):c.redrawAll(d.chartGroup())}):c.redrawAll(d.chartGroup()),d},d.renderGroup=function(){return s?s(!1,function(a,b){a?console.log(a):c.renderAll(d.chartGroup())}):c.renderAll(d.chartGroup()),d},d._invokeFilteredListener=function(a){void 0!==a&&L.filtered(d,a)},d._invokeZoomedListener=function(){L.zoomed(d)};var P=function(a,b){return null===b||"undefined"==typeof b?a.length>0:a.some(function(a){return a>=b&&b>=a})};d.hasFilterHandler=function(a){return arguments.length?(P=a,d):P},d.hasFilter=function(a){return P(M,a)};var Q=function(a,b){for(var c=0;c=b){a.splice(c,1);break}return a};d.removeFilterHandler=function(a){return arguments.length?(Q=a,d):Q};var R=function(a,b){return a.push(b),a};d.addFilterHandler=function(a){return arguments.length?(R=a,d):R};var S=function(a){return[]};return d.resetFilterHandler=function(a){return arguments.length?(S=a,d):S},d.replaceFilter=function(a){M=S(M),d.filter(a)},d.filter=function(a){if(!arguments.length)return M.length>0?M[0]:null;var b=M;return a instanceof Array&&a[0]instanceof Array&&!a.isFiltered?a[0].forEach(function(a){b=P(b,a)?Q(b,a):R(b,a)}):b=null===a?S(b):P(b,a)?Q(b,a):R(b,a),M=h(b),d._invokeFilteredListener(a),null!==l&&d.hasFilter()?d.turnOnControls():d.turnOffControls(),d},d.filters=function(){return M},d.highlightSelected=function(b){a.select(b).classed(c.constants.SELECTED_CLASS,!0),a.select(b).classed(c.constants.DESELECTED_CLASS,!1)},d.fadeDeselected=function(b){a.select(b).classed(c.constants.SELECTED_CLASS,!1),a.select(b).classed(c.constants.DESELECTED_CLASS,!0)},d.resetHighlight=function(b){a.select(b).classed(c.constants.SELECTED_CLASS,!1),a.select(b).classed(c.constants.DESELECTED_CLASS,!1)},d.onClick=function(a){var b=d.keyAccessor()(a);c.events.trigger(function(){d.filter(b),d.redrawGroup()})},d.filterHandler=function(a){return arguments.length?(N=a,d):N},d._doRender=function(){return d},d._doRedraw=function(){return d},d.legendables=function(){return[]},d.legendHighlight=function(){},d.legendReset=function(){},d.legendToggle=function(){},d.isLegendableHidden=function(){return!1},d.keyAccessor=function(a){return arguments.length?(z=a,d):z},d.valueAccessor=function(a){return arguments.length?(A=a,d):A},d.label=function(a,b){return arguments.length?(B=a,(void 0===b||b)&&(D=!0),d):B},d.renderLabel=function(a){return arguments.length?(D=a,d):D},d.title=function(a){return arguments.length?(E=a,d):E},d.renderTitle=function(a){return arguments.length?(F=a,d):F},d.renderlet=c.logger.deprecate(function(a){return d.on("renderlet."+c.utils.uniqueId(),a),d},'chart.renderlet has been deprecated. Please use chart.on("renderlet.", renderletFunction)'),d.chartGroup=function(a){return arguments.length?(n||c.deregisterChart(d,K),K=a,n||c.registerChart(d,K),d):K},d.expireCache=function(){return d},d.legend=function(a){return arguments.length?(r=a,r.parent(d),d):r},d.chartID=function(){return d.__dcFlag__},d.options=function(a){var b=["anchor","group","xAxisLabel","yAxisLabel","stack","title","point","getColor","overlayGeoJson"];for(var e in a)"function"==typeof d[e]?a[e]instanceof Array&&-1!==b.indexOf(e)?d[e].apply(d,a[e]):d[e].call(d,a[e]):c.logger.debug("Not a valid option setter name: "+e);return d},d.on=function(a,b){return L.on(a,b),d},d},c.marginMixin=function(a){var b={top:10,right:50,bottom:30,left:30};return a.margins=function(c){return arguments.length?(b=c,a):b},a.effectiveWidth=function(){return a.width()-a.margins().left-a.margins().right},a.effectiveHeight=function(){return a.height()-a.margins().top-a.margins().bottom},a},c.colorMixin=function(b){var c=a.scale.category20c(),d=!0,e=function(a){return b.keyAccessor()(a)};return b.colors=function(d){return arguments.length?(c=d instanceof Array?a.scale.quantize().range(d):a.functor(d),b):c},b.ordinalColors=function(c){return b.colors(a.scale.ordinal().range(c))},b.linearColors=function(c){return b.colors(a.scale.linear().range(c).interpolate(a.interpolateHcl))},b.colorAccessor=function(a){return arguments.length?(e=a,d=!1,b):e},b.defaultColorAccessor=function(){return d},b.colorDomain=function(a){return arguments.length?(c.domain(a),b):c.domain()},b.calculateColorDomain=function(){var d=[a.min(b.data(),b.colorAccessor()),a.max(b.data(),b.colorAccessor())];return c.domain(d),b},b.getColor=function(a,b){return c(e.call(this,a,b))},b.colorCalculator=function(a){return arguments.length?(b.getColor=a,b):b.getColor},b},c.coordinateGridMixin=function(b){function d(){V=!0,Y&&(b.x().domain(m(b.x().domain(),z)),G&&b.x().domain(m(b.x().domain(),G.x().domain())));var a=b.x().domain(),d=c.filters.RangedFilter(a[0],a[1]);b.replaceFilter(d),b.rescale(),b.redraw(),G&&!n(b.filter(),G.filter())&&c.events.trigger(function(){G.replaceFilter(d),G.redraw()}),b._invokeZoomedListener(),c.events.trigger(function(){b.redrawGroup()},c.constants.EVENT_DELAY),V=!n(a,z)}function e(a,b){return!a||!b||a.length!==b.length||a.some(function(a,c){return a&&b[c]?a.toString()!==b[c].toString():a===b[c]})}function f(a,c){b.isOrdinal()?(b.elasticX()||0===y.domain().length)&&y.domain(b._ordinalXDomain()):b.elasticX()&&y.domain([b.xAxisMin(),b.xAxisMax()]);var d=y.domain();(c||e(B,d))&&b.rescale(),B=d,b.isOrdinal()?y.rangeBands([0,b.xAxisLength()],da,b._useOuterPadding()?ca:0):y.range([0,b.xAxisLength()]),I=I.scale(b.x()),g(a)}function g(a){var d=a.selectAll("g."+r);if(U){d.empty()&&(d=a.insert("g",":first-child").attr("class",p+" "+r).attr("transform","translate("+b.margins().left+","+b.margins().top+")"));var e=I.tickValues()?I.tickValues():"function"==typeof y.ticks?y.ticks(I.ticks()[0]):y.domain(),f=d.selectAll("line").data(e),g=f.enter().append("line").attr("x1",function(a){return y(a)}).attr("y1",b._xAxisY()-b.margins().top).attr("x2",function(a){return y(a)}).attr("y2",0).attr("opacity",0);c.transition(g,b.transitionDuration()).attr("opacity",1),c.transition(f,b.transitionDuration()).attr("x1",function(a){return y(a)}).attr("y1",b._xAxisY()-b.margins().top).attr("x2",function(a){return y(a)}).attr("y2",0),f.exit().remove()}else d.selectAll("line").remove()}function h(){return b._xAxisY()-b.margins().top}function i(){return b.anchorName().replace(/[ .#=\[\]]/g,"-")+"-clip"}function j(){var a=c.utils.appendOrSelect(v,"defs"),d=i(),e=c.utils.appendOrSelect(a,"#"+d,"clipPath").attr("id",d),f=2*ba;c.utils.appendOrSelect(e,"rect").attr("width",b.xAxisLength()+f).attr("height",b.yAxisHeight()+f).attr("transform","translate(-"+ba+", -"+ba+")")}function k(a){b.isOrdinal()&&(S=!1),f(b.g(),a),b._prepareYAxis(b.g()),b.plotData(),(b.elasticX()||W||a)&&b.renderXAxis(b.g()),(b.elasticY()||W||a)&&b.renderYAxis(b.g()),a?b.renderBrush(b.g(),!1):b.redrawBrush(b.g(),W),b.fadeDeselectedArea(),W=!1}function l(){aa?b._enableMouseZoom():_&&b._disableMouseZoom()}function m(b,c){var d=[];return d[0]=a.max([b[0],c[0]]),d[1]=a.min([b[1],c[1]]),d}function n(a,b){return a||b?a&&b?0===a.length&&0===b.length?!0:a[0].valueOf()===b[0].valueOf()&&a[1].valueOf()===b[1].valueOf():!1:!0}function o(a){return a instanceof Array&&a.length>1}var p="grid-line",q="horizontal",r="vertical",s="y-axis-label",t="x-axis-label",u=12;b=c.colorMixin(c.marginMixin(c.baseMixin(b))),b.colors(a.scale.category10()),b._mandatoryAttributes().push("x");var v,w,x,y,z,A,B,C,D,E,F,G,H,I=a.svg.axis().orient("bottom"),J=c.units.integers,K=0,L=!1,M=0,N=a.svg.axis().orient("left"),O=0,P=!1,Q=0,R=a.svg.brush(),S=!0,T=!1,U=!1,V=!1,W=!1,X=[1,1/0],Y=!0,Z=a.behavior.zoom().on("zoom",d),$=a.behavior.zoom().on("zoom",null),_=!1,aa=!1,ba=0,ca=.5,da=0,ea=!1;return b.rescale=function(){return F=void 0,W=!0,b},b.resizing=function(){return W},b.rangeChart=function(a){return arguments.length?(G=a,G.focusChart(b),b):G},b.zoomScale=function(a){return arguments.length?(X=a,b):X},b.zoomOutRestrict=function(a){return arguments.length?(X[0]=a?1:0,Y=a,b):Y},b._generateG=function(a){v=void 0===a?b.svg():a;var c=window.location.href.split("#")[0];return w=v.append("g"),x=w.append("g").attr("class","chart-body").attr("transform","translate("+b.margins().left+", "+b.margins().top+")").attr("clip-path","url("http://github.com/+c+%22#%22+i()+")"),w},b.g=function(a){return arguments.length?(w=a,b):w},b.mouseZoomable=function(a){return arguments.length?(aa=a,b):aa},b.chartBodyG=function(a){return arguments.length?(x=a,b):x},b.x=function(a){return arguments.length?(y=a,z=y.domain(),b.rescale(),b):y},b.xOriginalDomain=function(){return z},b.xUnits=function(a){return arguments.length?(J=a,b):J},b.xAxis=function(a){return arguments.length?(I=a,b):I},b.elasticX=function(a){return arguments.length?(L=a,b):L},b.xAxisPadding=function(a){return arguments.length?(K=a,b):K},b.xUnitCount=function(){if(void 0===F){var a=b.xUnits()(b.x().domain()[0],b.x().domain()[1],b.x().domain());F=a instanceof Array?a.length:a}return F},b.useRightYAxis=function(a){return arguments.length?(ea=a,b):ea},b.isOrdinal=function(){return b.xUnits()===c.units.ordinal},b._useOuterPadding=function(){return!0},b._ordinalXDomain=function(){var a=b._computeOrderedGroups(b.data());return a.map(b.keyAccessor())},b.renderXAxis=function(a){var d=a.selectAll("g.x");d.empty()&&(d=a.append("g").attr("class","axis x").attr("transform","translate("+b.margins().left+","+b._xAxisY()+")"));var e=a.selectAll("text."+t);e.empty()&&b.xAxisLabel()&&(e=a.append("text").attr("class",t).attr("transform","translate("+(b.margins().left+b.xAxisLength()/2)+","+(b.height()-M)+")").attr("text-anchor","middle")),b.xAxisLabel()&&e.text()!==b.xAxisLabel()&&e.text(b.xAxisLabel()),c.transition(d,b.transitionDuration()).attr("transform","translate("+b.margins().left+","+b._xAxisY()+")").call(I),c.transition(e,b.transitionDuration()).attr("transform","translate("+(b.margins().left+b.xAxisLength()/2)+","+(b.height()-M)+")")},b._xAxisY=function(){return b.height()-b.margins().bottom},b.xAxisLength=function(){return b.effectiveWidth()},b.xAxisLabel=function(a,c){return arguments.length?(A=a,b.margins().bottom-=M,M=void 0===c?u:c,b.margins().bottom+=M,b):A},b._prepareYAxis=function(c){if(void 0===C||b.elasticY()){void 0===C&&(C=a.scale.linear());var d=b.yAxisMin()||0,e=b.yAxisMax()||0;C.domain([d,e]).rangeRound([b.yAxisHeight(),0])}C.range([b.yAxisHeight(),0]),N=N.scale(C),ea&&N.orient("right"),b._renderHorizontalGridLinesForAxis(c,C,N)},b.renderYAxisLabel=function(a,d,e,f){f=f||Q;var g=b.g().selectAll("text."+s+"."+a+"-label"),h=b.margins().top+b.yAxisHeight()/2;g.empty()&&d&&(g=b.g().append("text").attr("transform","translate("+f+","+h+"),rotate("+e+")").attr("class",s+" "+a+"-label").attr("text-anchor","middle").text(d)),d&&g.text()!==d&&g.text(d),c.transition(g,b.transitionDuration()).attr("transform","translate("+f+","+h+"),rotate("+e+")")},b.renderYAxisAt=function(a,d,e){var f=b.g().selectAll("g."+a);f.empty()&&(f=b.g().append("g").attr("class","axis "+a).attr("transform","translate("+e+","+b.margins().top+")")),c.transition(f,b.transitionDuration()).attr("transform","translate("+e+","+b.margins().top+")").call(d)},b.renderYAxis=function(){var a=ea?b.width()-b.margins().right:b._yAxisX();b.renderYAxisAt("y",N,a);var c=ea?b.width()-Q:Q,d=ea?90:-90;b.renderYAxisLabel("y",b.yAxisLabel(),d,c)},b._renderHorizontalGridLinesForAxis=function(a,d,e){var f=a.selectAll("g."+q);if(T){var g=e.tickValues()?e.tickValues():d.ticks(e.ticks()[0]);f.empty()&&(f=a.insert("g",":first-child").attr("class",p+" "+q).attr("transform","translate("+b.margins().left+","+b.margins().top+")"));var h=f.selectAll("line").data(g),i=h.enter().append("line").attr("x1",1).attr("y1",function(a){return d(a)}).attr("x2",b.xAxisLength()).attr("y2",function(a){return d(a)}).attr("opacity",0);c.transition(i,b.transitionDuration()).attr("opacity",1),c.transition(h,b.transitionDuration()).attr("x1",1).attr("y1",function(a){return d(a)}).attr("x2",b.xAxisLength()).attr("y2",function(a){return d(a)}),h.exit().remove()}else f.selectAll("line").remove()},b._yAxisX=function(){return b.useRightYAxis()?b.width()-b.margins().right:b.margins().left},b.yAxisLabel=function(a,c){return arguments.length?(D=a,b.margins().left-=Q,Q=void 0===c?u:c,b.margins().left+=Q,b):D},b.y=function(a){return arguments.length?(C=a,b.rescale(),b):C},b.yAxis=function(a){return arguments.length?(N=a,b):N},b.elasticY=function(a){return arguments.length?(P=a,b):P},b.renderHorizontalGridLines=function(a){return arguments.length?(T=a,b):T},b.renderVerticalGridLines=function(a){return arguments.length?(U=a,b):U},b.xAxisMin=function(){var d=a.min(b.data(),function(a){return b.keyAccessor()(a)});return c.utils.subtract(d,K)},b.xAxisMax=function(){var d=a.max(b.data(),function(a){return b.keyAccessor()(a)});return c.utils.add(d,K)},b.yAxisMin=function(){var d=a.min(b.data(),function(a){return b.valueAccessor()(a)});return c.utils.subtract(d,O)},b.yAxisMax=function(){var d=a.max(b.data(),function(a){return b.valueAccessor()(a)});return c.utils.add(d,O)},b.yAxisPadding=function(a){return arguments.length?(O=a,b):O},b.yAxisHeight=function(){return b.effectiveHeight()},b.round=function(a){return arguments.length?(E=a,b):E},b._rangeBandPadding=function(a){return arguments.length?(da=a,b):da},b._outerRangeBandPadding=function(a){return arguments.length?(ca=a,b):ca},c.override(b,"filter",function(a){return arguments.length?(b._filter(a),a?b.brush().extent(a):b.brush().clear(),b):b._filter()}),b.brush=function(a){return arguments.length?(R=a,b):R},b.renderBrush=function(a){if(S){R.on("brush",b._brushing),R.on("brushstart",b._disableMouseZoom),R.on("brushend",l);var c=a.append("g").attr("class","brush").attr("transform","translate("+b.margins().left+","+b.margins().top+")").call(R.x(b.x()));b.setBrushY(c,!1),b.setHandlePaths(c),b.hasFilter()&&b.redrawBrush(a,!1)}},b.setHandlePaths=function(a){a.selectAll(".resize").append("path").attr("d",b.resizeHandlePath)},b.setBrushY=function(a){a.selectAll("rect").attr("height",h()),a.selectAll(".resize path").attr("d",b.resizeHandlePath)},b.extendBrush=function(){var a=R.extent();return b.round()&&(a[0]=a.map(b.round())[0],a[1]=a.map(b.round())[1],w.select(".brush").call(R.extent(a))),a},b.brushIsEmpty=function(a){return R.empty()||!a||a[1]<=a[0]},b._brushing=function(){var a=b.extendBrush();if(b.redrawBrush(w,!1),b.brushIsEmpty(a))c.events.trigger(function(){b.filter(null),b.redrawGroup()},c.constants.EVENT_DELAY);else{var d=c.filters.RangedFilter(a[0],a[1]);c.events.trigger(function(){b.replaceFilter(d),b.redrawGroup()},c.constants.EVENT_DELAY)}},b.redrawBrush=function(a,d){if(S){b.filter()&&b.brush().empty()&&b.brush().extent(b.filter());var e=c.optionalTransition(d,b.transitionDuration())(a.select("g.brush"));b.setBrushY(e),e.call(b.brush().x(b.x()).extent(b.brush().extent()))}b.fadeDeselectedArea()},b.fadeDeselectedArea=function(){},b.resizeHandlePath=function(a){var b=+("e"===a),c=b?1:-1,d=h()/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)},b.clipPadding=function(a){return arguments.length?(ba=a,b):ba},b._preprocessData=function(){},b._doRender=function(){return b.resetSvg(),b._preprocessData(),b._generateG(),j(),k(!0),l(),b},b._doRedraw=function(){return b._preprocessData(),k(!1),j(),b},b._enableMouseZoom=function(){_=!0,Z.x(b.x()).scaleExtent(X).size([b.width(),b.height()]).duration(b.transitionDuration()),b.root().call(Z)},b._disableMouseZoom=function(){b.root().call($)},b.focus=function(a){o(a)?b.x().domain(a):b.x().domain(z),Z.x(b.x()),d()},b.refocused=function(){return V},b.focusChart=function(a){return arguments.length?(H=a,b.on("filtered",function(a){a.filter()?n(a.filter(),H.filter())||c.events.trigger(function(){H.focus(a.filter())}):c.events.trigger(function(){H.x().domain(H.xOriginalDomain())})}),b):H},b.brushOn=function(a){return arguments.length?(S=a,b):S},b},c.stackMixin=function(b){function d(a,c){var d=a.accessor||b.valueAccessor();return a.name=String(a.name||c),a.values=a.group.all().map(function(c,e){return{x:b.keyAccessor()(c,e),y:a.hidden?null:d(c,e),data:c,layer:a.name,hidden:a.hidden}}),a.values=a.values.filter(e()),a.values}function e(){if(!b.x())return a.functor(!0);var c=b.x().domain();return b.isOrdinal()?function(){return!0}:b.elasticX()?function(){return!0}:function(a){return a.x>=c[0]&&a.x<=c[c.length-1]}}function f(a){var b=j.map(c.pluck("name")).indexOf(a);return j[b]}function g(){var a=b.data().map(function(a){return a.values});return Array.prototype.concat.apply([],a)}function h(a){return!a.hidden}var i=a.layout.stack().values(d),j=[],k={},l=!1;return b.stack=function(a,c,d){if(!arguments.length)return j;arguments.length<=2&&(d=c);var e={group:a};return"string"==typeof c&&(e.name=c),"function"==typeof d&&(e.accessor=d),j.push(e),b},c.override(b,"group",function(a,c,d){return arguments.length?(j=[],k={},b.stack(a,c),d&&b.valueAccessor(d),b._group(a,c)):b._group()}),b.hidableStacks=function(a){return arguments.length?(l=a,b):l},b.hideStack=function(a){var c=f(a);return c&&(c.hidden=!0),b},b.showStack=function(a){var c=f(a);return c&&(c.hidden=!1),b},b.getValueAccessorByIndex=function(a){return j[a].accessor||b.valueAccessor()},b.yAxisMin=function(){var d=a.min(g(),function(a){return a.y<0?a.y+a.y0:a.y0});return c.utils.subtract(d,b.yAxisPadding())},b.yAxisMax=function(){var d=a.max(g(),function(a){return a.y>0?a.y+a.y0:a.y0});return c.utils.add(d,b.yAxisPadding())},b.xAxisMin=function(){var d=a.min(g(),c.pluck("x"));return c.utils.subtract(d,b.xAxisPadding())},b.xAxisMax=function(){var d=a.max(g(),c.pluck("x"));return c.utils.add(d,b.xAxisPadding())},c.override(b,"title",function(a,c){return a?"function"==typeof a?b._title(a):a===b._groupName&&"function"==typeof c?b._title(c):"function"!=typeof c?k[a]||b._title():(k[a]=c,b):b._title()}),b.stackLayout=function(c){return arguments.length?(i=c,i.values()===a.layout.stack().values()&&i.values(d),b):i},b.data(function(){var a=j.filter(h);return a.length?b.stackLayout()(a):[]}),b._ordinalXDomain=function(){var a=g().map(c.pluck("data")),d=b._computeOrderedGroups(a);return d.map(b.keyAccessor())},b.colorAccessor(function(a){var b=this.layer||this.name||a.name||a.layer;return b}),b.legendables=function(){return j.map(function(a,c){return{chart:b,name:a.name,hidden:a.hidden||!1,color:b.getColor.call(a,a.values,c)}})},b.isLegendableHidden=function(a){var b=f(a.name);return b?b.hidden:!1},b.legendToggle=function(a){l&&(b.isLegendableHidden(a)?b.showStack(a.name):b.hideStack(a.name),b.renderGroup())},b},c.capMixin=function(b){var d=1/0,e="Others",f=function(c){var d=a.sum(c,b.valueAccessor()),f=b.group().all(),g=a.sum(f,b.valueAccessor()),h=c.map(b.keyAccessor()),i=f.map(b.keyAccessor()),j=a.set(h),k=i.filter(function(a){return!j.has(a)});return g>d?c.concat([{others:k,key:e,value:g-d}]):c};return b.cappedKeyAccessor=function(a,c){return a.others?a.key:b.keyAccessor()(a,c)},b.cappedValueAccessor=function(a,c){return a.others?a.value:b.valueAccessor()(a,c)},b.data(function(a){if(d===1/0)return b._computeOrderedGroups(a.all());var c=a.top(d);return c=b._computeOrderedGroups(c),f?f(c):c}),b.cap=function(a){return arguments.length?(d=a,b):d},b.othersLabel=function(a){return arguments.length?(e=a,b):e},b.othersGrouper=function(a){return arguments.length?(f=a,b):f},c.override(b,"onClick",function(a){a.others&&b.filter([a.others]),b._onClick(a)}),b},c.bubbleMixin=function(b){var d=.3,e=10;b.BUBBLE_NODE_CLASS="node",b.BUBBLE_CLASS="bubble",b.MIN_RADIUS=10,b=c.colorMixin(b),b.renderLabel(!0),b.data(function(a){return a.top(1/0)});var f=a.scale.linear().domain([0,100]),g=function(a){return a.r};b.r=function(a){return arguments.length?(f=a,b):f},b.radiusValueAccessor=function(a){return arguments.length?(g=a,b):g},b.rMin=function(){var c=a.min(b.data(),function(a){return b.radiusValueAccessor()(a)});return c},b.rMax=function(){var c=a.max(b.data(),function(a){return b.radiusValueAccessor()(a)});return c},b.bubbleR=function(a){var c=b.radiusValueAccessor()(a),d=b.r()(c);return(isNaN(d)||0>=c)&&(d=0),d};var h=function(a){return b.label()(a)},i=function(a){return b.bubbleR(a)>e},j=function(a){return i(a)?1:0},k=function(a){return i(a)?"all":"none"};b._doRenderLabel=function(a){if(b.renderLabel()){var d=a.select("text");d.empty()&&(d=a.append("text").attr("text-anchor","middle").attr("dy",".3em").on("click",b.onClick)),d.attr("opacity",0).attr("pointer-events",k).text(h),c.transition(d,b.transitionDuration()).attr("opacity",j)}},b.doUpdateLabels=function(a){if(b.renderLabel()){var d=a.selectAll("text").attr("pointer-events",k).text(h);c.transition(d,b.transitionDuration()).attr("opacity",j)}};var l=function(a){return b.title()(a)};return b._doRenderTitles=function(a){if(b.renderTitle()){var c=a.select("title");c.empty()&&a.append("title").text(l)}},b.doUpdateTitles=function(a){b.renderTitle()&&a.selectAll("title").text(l)},b.minRadius=function(a){return arguments.length?(b.MIN_RADIUS=a,b):b.MIN_RADIUS},b.minRadiusWithLabel=function(a){return arguments.length?(e=a,b):e},b.maxBubbleRelativeSize=function(a){return arguments.length?(d=a,b):d; -},b.fadeDeselectedArea=function(){b.hasFilter()?b.selectAll("g."+b.BUBBLE_NODE_CLASS).each(function(a){b.isSelectedNode(a)?b.highlightSelected(this):b.fadeDeselected(this)}):b.selectAll("g."+b.BUBBLE_NODE_CLASS).each(function(){b.resetHighlight(this)})},b.isSelectedNode=function(a){return b.hasFilter(a.key)},b.onClick=function(a){var d=a.key;c.events.trigger(function(){b.filter(d),b.redrawGroup()})},b},c.pieChart=function(b,d){function e(){F=G?G:a.min([W.width(),W.height()])/2;var b,d=t(),e=v();if(a.sum(W.data(),W.valueAccessor())?(b=e(W.data()),H.classed(Q,!1)):(b=e([{key:R,value:1,others:[R]}]),H.classed(Q,!0)),H){var g=H.select("g."+O).selectAll("g."+M).data(b),h=H.select("g."+P).selectAll("text."+N).data(b);f(g,h,d,b),n(b,d),r(g,h),s(),c.transition(H,W.transitionDuration()).attr("transform","translate("+W.cx()+","+W.cy()+")")}}function f(a,b,c,d){var e=g(a);h(e,c),i(e),l(b,d,c)}function g(a){var b=a.enter().append("g").attr("class",function(a,b){return M+" _"+b});return b}function h(a,b){var d=a.append("path").attr("fill",A).on("click",B).attr("d",function(a,c){return C(a,c,b)});c.transition(d,W.transitionDuration(),function(a){a.attrTween("d",y)})}function i(a){W.renderTitle()&&a.append("title").text(function(a){return W.title()(a.data)})}function j(a,b){W._applyLabelText(a),c.transition(a,W.transitionDuration()).attr("transform",function(a){return D(a,b)}).attr("text-anchor","middle")}function k(a,b){W.select("g.pie-slice._"+a).classed("highlight",b)}function l(a,b,c){if(W.renderLabel()){var d=a.enter().append("text").attr("class",function(a,b){var c=M+" "+N+" _"+b;return K&&(c+=" external"),c}).on("click",B).on("mouseover",function(a,b){k(b,!0)}).on("mouseout",function(a,b){k(b,!1)});j(d,c),K&&V&&m(b,c)}}function m(b,d){var e=H.selectAll("polyline."+M).data(b);e.enter().append("polyline").attr("class",function(a,b){return"pie-path _"+b+" "+M}).on("click",B).on("mouseover",function(a,b){k(b,!0)}).on("mouseout",function(a,b){k(b,!1)}),e.exit().remove();var f=a.svg.arc().outerRadius(F-T+K).innerRadius(F-T),g=c.transition(e,W.transitionDuration());g.attrTween?g.attrTween("points",function(b){this._current=this._current||b;var c=a.interpolate(this._current,b);return this._current=c(0),function(a){var b=c(a);return[d.centroid(b),f.centroid(b)]}}):g.attr("points",function(a){return[d.centroid(a),f.centroid(a)]}),g.style("visibility",function(a){return a.endAngle-a.startAngle<1e-4?"hidden":"visible"})}function n(a,b){o(a,b),p(a,b),q(a)}function o(a,b){var d=H.selectAll("g."+M).data(a).select("path").attr("d",function(a,c){return C(a,c,b)});c.transition(d,W.transitionDuration(),function(a){a.attrTween("d",y)}).attr("fill",A)}function p(a,b){if(W.renderLabel()){var c=H.selectAll("text."+N).data(a);j(c,b),K&&V&&m(a,b)}}function q(a){W.renderTitle()&&H.selectAll("g."+M).data(a).select("title").text(function(a){return W.title()(a.data)})}function r(a,b){a.exit().remove(),b.exit().remove()}function s(){W.hasFilter()?W.selectAll("g."+M).each(function(a){u(a)?W.highlightSelected(this):W.fadeDeselected(this)}):W.selectAll("g."+M).each(function(){W.resetHighlight(this)})}function t(){return a.svg.arc().outerRadius(F-T).innerRadius(S)}function u(a){return W.hasFilter(W.cappedKeyAccessor(a.data))}function v(){return a.layout.pie().sort(null).value(W.cappedValueAccessor)}function w(a){var b=a.endAngle-a.startAngle;return isNaN(b)||U>b}function x(a){return 0===W.cappedValueAccessor(a)}function y(b){b.innerRadius=S;var c=this._current;c=z(c)?{startAngle:0,endAngle:0}:{startAngle:c.startAngle,endAngle:c.endAngle};var d=a.interpolate(c,b);return this._current=d(0),function(a){return C(d(a),0,t())}}function z(a){return!a||isNaN(a.startAngle)||isNaN(a.endAngle)}function A(a,b){return W.getColor(a.data,b)}function B(a,b){H.attr("class")!==Q&&W.onClick(a.data,b)}function C(a,b,c){var d=c(a,b);return d.indexOf("NaN")>=0&&(d="M0,0"),d}function D(b,c){var d;return d=K?a.svg.arc().outerRadius(F-T+K).innerRadius(F-T+K).centroid(b):c.centroid(b),isNaN(d[0])||isNaN(d[1])?"translate(0,0)":"translate("+d+")"}function E(b,c){W.selectAll("g.pie-slice").each(function(d){b.name===d.data.key&&a.select(this).classed("highlight",c)})}var F,G,H,I,J,K,L=.5,M="pie-slice",N="pie-label",O="pie-slice-group",P="pie-label-group",Q="empty-chart",R="empty",S=0,T=0,U=L,V=!1,W=c.capMixin(c.colorMixin(c.baseMixin({})));return W.colorAccessor(W.cappedKeyAccessor),W.title(function(a){return W.cappedKeyAccessor(a)+": "+W.cappedValueAccessor(a)}),W.slicesCap=W.cap,W.label(W.cappedKeyAccessor),W.renderLabel(!0),W.transitionDuration(350),W._doRender=function(){return W.resetSvg(),H=W.svg().append("g").attr("transform","translate("+W.cx()+","+W.cy()+")"),H.append("g").attr("class",O),H.append("g").attr("class",P),e(),W},W._applyLabelText=function(a){a.text(function(a){var b=a.data;return!x(b)&&!w(a)||u(a)?W.label()(a.data):""})},W.externalRadiusPadding=function(a){return arguments.length?(T=a,W):T},W.innerRadius=function(a){return arguments.length?(S=a,W):S},W.radius=function(a){return arguments.length?(G=a,W):G},W.cx=function(a){return arguments.length?(I=a,W):I||W.width()/2},W.cy=function(a){return arguments.length?(J=a,W):J||W.height()/2},W._doRedraw=function(){return e(),W},W.minAngleForLabel=function(a){return arguments.length?(U=a,W):U},W.emptyTitle=function(a){return 0===arguments.length?R:(R=a,W)},W.externalLabels=function(a){return 0===arguments.length?K:(K=a?a:void 0,W)},W.drawPaths=function(a){return 0===arguments.length?V:(V=a,W)},W.legendables=function(){return W.data().map(function(a,b){var c={name:a.key,data:a.value,others:a.others,chart:W};return c.color=W.getColor(a,b),c})},W.legendHighlight=function(a){E(a,!0)},W.legendReset=function(a){E(a,!1)},W.legendToggle=function(a){W.onClick({key:a.name,others:a.others})},W.anchor(b,d)},c.barChart=function(b,d){function e(a){return c.utils.safeNumber(Math.abs(n.y()(a.y+a.y0)-n.y()(a.y0)))}function f(a,b,d){var f=a.selectAll("text.barLabel").data(d.values,c.pluck("x"));f.enter().append("text").attr("class","barLabel").attr("text-anchor","middle"),n.isOrdinal()&&(f.on("click",n.onClick),f.attr("cursor","pointer")),c.transition(f,n.transitionDuration()).attr("x",function(a){var b=n.x()(a.x);return p||(b+=j/2),c.utils.safeNumber(b)}).attr("y",function(a){var b=n.y()(a.y+a.y0);return a.y<0&&(b-=e(a)),c.utils.safeNumber(b-m)}).text(function(a){return n.label()(a)}),c.transition(f.exit(),n.transitionDuration()).attr("height",0).remove()}function g(a,b,d){var f=a.selectAll("rect.bar").data(d.values,c.pluck("x")),g=f.enter().append("rect").attr("class","bar").attr("fill",c.pluck("data",n.getColor)).attr("y",n.yAxisHeight()).attr("height",0);n.renderTitle()&&g.append("title").text(c.pluck("data",n.title(d.name))),n.isOrdinal()&&f.on("click",n.onClick),c.transition(f,n.transitionDuration()).attr("x",function(a){var b=n.x()(a.x);return p&&(b-=j/2),n.isOrdinal()&&void 0!==o&&(b+=o/2),c.utils.safeNumber(b)}).attr("y",function(a){var b=n.y()(a.y+a.y0);return a.y<0&&(b-=e(a)),c.utils.safeNumber(b)}).attr("width",j).attr("height",function(a){return e(a)}).attr("fill",c.pluck("data",n.getColor)).select("title").text(c.pluck("data",n.title(d.name))),c.transition(f.exit(),n.transitionDuration()).attr("x",function(a){return n.x()(a.x)}).attr("width",.9*j).remove()}function h(){if(void 0===j){var a=n.xUnitCount();j=n.isOrdinal()&&void 0===o?Math.floor(n.x().rangeBand()):o?Math.floor((n.xAxisLength()-(a-1)*o)/a):Math.floor(n.xAxisLength()/(1+n.barPadding())/a),(j===1/0||isNaN(j)||k>j)&&(j=k)}}function i(b,c){return function(){var d=a.select(this),e=d.attr("fill")===b;return c?!e:e}}var j,k=1,l=2,m=3,n=c.stackMixin(c.coordinateGridMixin({})),o=l,p=!1,q=!1;return c.override(n,"rescale",function(){return n._rescale(),j=void 0,n}),c.override(n,"render",function(){return n.round()&&p&&!q&&c.logger.warn("By default, brush rounding is disabled if bars are centered. See dc.js bar chart API documentation for details."),n._render()}),n.label(function(a){return c.utils.printSingleValue(a.y0+a.y)},!1),n.plotData=function(){var b=n.chartBodyG().selectAll("g.stack").data(n.data());h(),b.enter().append("g").attr("class",function(a,b){return"stack _"+b});var c=b.size()-1;b.each(function(b,d){var e=a.select(this);g(e,d,b),n.renderLabel()&&c===d&&f(e,d,b)})},n.fadeDeselectedArea=function(){var a=n.chartBodyG().selectAll("rect.bar"),b=n.brush().extent();if(n.isOrdinal())n.hasFilter()?(a.classed(c.constants.SELECTED_CLASS,function(a){return n.hasFilter(a.x)}),a.classed(c.constants.DESELECTED_CLASS,function(a){return!n.hasFilter(a.x)})):(a.classed(c.constants.SELECTED_CLASS,!1),a.classed(c.constants.DESELECTED_CLASS,!1));else if(n.brushIsEmpty(b))a.classed(c.constants.DESELECTED_CLASS,!1);else{var d=b[0],e=b[1];a.classed(c.constants.DESELECTED_CLASS,function(a){return a.x=e})}},n.centerBar=function(a){return arguments.length?(p=a,n):p},c.override(n,"onClick",function(a){n._onClick(a.data)}),n.barPadding=function(a){return arguments.length?(n._rangeBandPadding(a),o=void 0,n):n._rangeBandPadding()},n._useOuterPadding=function(){return void 0===o},n.outerPadding=n._outerRangeBandPadding,n.gap=function(a){return arguments.length?(o=a,n):o},n.extendBrush=function(){var a=n.brush().extent();return!n.round()||p&&!q||(a[0]=a.map(n.round())[0],a[1]=a.map(n.round())[1],n.chartBodyG().select(".brush").call(n.brush().extent(a))),a},n.alwaysUseRounding=function(a){return arguments.length?(q=a,n):q},n.legendHighlight=function(a){n.isLegendableHidden(a)||n.g().selectAll("rect.bar").classed("highlight",i(a.color)).classed("fadeout",i(a.color,!0))},n.legendReset=function(){n.g().selectAll("rect.bar").classed("highlight",!1).classed("fadeout",!1)},c.override(n,"xAxisMax",function(){var a=this._xAxisMax();if("resolution"in n.xUnits()){var b=n.xUnits().resolution;a+=b}return a}),n.anchor(b,d)},c.lineChart=function(b,d){function e(a,b){return B.getColor.call(a,a.values,b)}function f(b,d){var f=a.svg.line().x(function(a){return B.x()(a.x)}).y(function(a){return B.y()(a.y+a.y0)}).interpolate(H).tension(I);s&&f.defined(s);var g=b.append("path").attr("class","line").attr("stroke",e);t&&g.attr("stroke-dasharray",t),c.transition(d.select("path.line"),B.transitionDuration()).attr("stroke",e).attr("d",function(a){return h(f(a.values))})}function g(b,d){if(C){var f=a.svg.area().x(function(a){return B.x()(a.x)}).y(function(a){return B.y()(a.y+a.y0)}).y0(function(a){return B.y()(a.y0)}).interpolate(H).tension(I);s&&f.defined(s),b.append("path").attr("class","area").attr("fill",e).attr("d",function(a){return h(f(a.values))}),c.transition(d.select("path.area"),B.transitionDuration()).attr("fill",e).attr("d",function(a){return h(f(a.values))})}}function h(a){return!a||a.indexOf("NaN")>=0?"M0,0":a}function i(b,d){if(!B.brushOn()&&B.xyTipsOn()){var e=v+"-list",f=b.select("g."+e);f.empty()&&(f=b.append("g").attr("class",e)),d.each(function(b,d){var e=b.values;s&&(e=e.filter(s));var g=f.select("g."+v+"._"+d);g.empty()&&(g=f.append("g").attr("class",v+" _"+d)),k(g);var h=g.selectAll("circle."+w).data(e,c.pluck("x"));h.enter().append("circle").attr("class",w).attr("r",n()).style("fill-opacity",F).style("stroke-opacity",G).attr("fill",B.getColor).on("mousemove",function(){var b=a.select(this);l(b),m(b,g)}).on("mouseout",function(){var b=a.select(this);o(b),p(g)}),h.call(q,b),c.transition(h,B.transitionDuration()).attr("cx",function(a){return c.utils.safeNumber(B.x()(a.x))}).attr("cy",function(a){return c.utils.safeNumber(B.y()(a.y+a.y0))}).attr("fill",B.getColor),h.exit().remove()})}}function j(b){b.each(function(b,d){var e=a.select(this),f=e.selectAll("text.lineLabel").data(b.values,c.pluck("x"));f.enter().append("text").attr("class","lineLabel").attr("text-anchor","middle"),c.transition(f,B.transitionDuration()).attr("x",function(a){return c.utils.safeNumber(B.x()(a.x))}).attr("y",function(a){var b=B.y()(a.y+a.y0)-A;return c.utils.safeNumber(b)}).text(function(a){return B.label()(a)}),c.transition(f.exit(),B.transitionDuration()).attr("height",0).remove()})}function k(a){var b=a.select("path."+x).empty()?a.append("path").attr("class",x):a.select("path."+x);b.style("display","none").attr("stroke-dasharray","5,5");var c=a.select("path."+y).empty()?a.append("path").attr("class",y):a.select("path."+y);c.style("display","none").attr("stroke-dasharray","5,5")}function l(a){return a.style("fill-opacity",.8),a.style("stroke-opacity",.8),a.attr("r",D),a}function m(a,b){var c=a.attr("cx"),d=a.attr("cy"),e=B._yAxisX()-B.margins().left,f="M"+e+" "+d+"L"+c+" "+d,g="M"+c+" "+B.yAxisHeight()+"L"+c+" "+d;b.select("path."+x).style("display","").attr("d",f),b.select("path."+y).style("display","").attr("d",g)}function n(){return E||D}function o(a){a.style("fill-opacity",F).style("stroke-opacity",G).attr("r",n())}function p(a){a.select("path."+x).style("display","none"),a.select("path."+y).style("display","none")}function q(a,b){B.renderTitle()&&(a.selectAll("title").remove(),a.append("title").text(c.pluck("data",B.title(b.name))))}function r(b,c,d){return function(){var e=a.select(this),f=e.attr("stroke")===b&&e.attr("stroke-dasharray")===(c instanceof Array?c.join(","):null)||e.attr("fill")===b;return d?!f:f}}var s,t,u=5,v="dc-tooltip",w="dot",x="yRef",y="xRef",z=1e-6,A=3,B=c.stackMixin(c.coordinateGridMixin({})),C=!1,D=u,E=null,F=z,G=z,H="linear",I=.7,J=!0;return B.transitionDuration(500),B._rangeBandPadding(1),B.plotData=function(){var a=B.chartBodyG(),b=a.selectAll("g.stack-list");b.empty()&&(b=a.append("g").attr("class","stack-list"));var c=b.selectAll("g.stack").data(B.data()),d=c.enter().append("g").attr("class",function(a,b){return"stack _"+b});f(d,c),g(d,c),i(a,c),B.renderLabel()&&j(c)},B.interpolate=function(a){return arguments.length?(H=a,B):H},B.tension=function(a){return arguments.length?(I=a,B):I},B.defined=function(a){return arguments.length?(s=a,B):s},B.dashStyle=function(a){return arguments.length?(t=a,B):t},B.renderArea=function(a){return arguments.length?(C=a,B):C},B.label(function(a){return c.utils.printSingleValue(a.y0+a.y)},!1),B.xyTipsOn=function(a){return arguments.length?(J=a,B):J},B.dotRadius=function(a){return arguments.length?(D=a,B):D},B.renderDataPoints=function(a){return arguments.length?(a?(F=a.fillOpacity||.8,G=a.strokeOpacity||.8,E=a.radius||2):(F=z,G=z,E=null),B):{fillOpacity:F,strokeOpacity:G,radius:E}},B.legendHighlight=function(a){B.isLegendableHidden(a)||B.g().selectAll("path.line, path.area").classed("highlight",r(a.color,a.dashstyle)).classed("fadeout",r(a.color,a.dashstyle,!0))},B.legendReset=function(){B.g().selectAll("path.line, path.area").classed("highlight",!1).classed("fadeout",!1)},c.override(B,"legendables",function(){var a=B._legendables();return t?a.map(function(a){return a.dashstyle=t,a}):a}),B.anchor(b,d)},c.dataCount=function(b,d){var e=a.format(",d"),f=c.baseMixin({}),g={some:"",all:""};return f.html=function(a){return arguments.length?(a.all&&(g.all=a.all),a.some&&(g.some=a.some),f):g},f.formatNumber=function(a){return arguments.length?(e=a,f):e},f._doRender=function(){var a=f.dimension().size(),b=f.group().value(),c=e(a),d=e(b);return a===b&&""!==g.all?f.root().html(g.all.replace("%total-count",c).replace("%filter-count",d)):""!==g.some?f.root().html(g.some.replace("%total-count",c).replace("%filter-count",d)):(f.selectAll(".total-count").text(c),f.selectAll(".filter-count").text(d)),f},f._doRedraw=function(){return f._doRender()},f.anchor(b,d)},c.dataTable=function(b,d){function e(){var a=!0;if(p.forEach(function(b){a&="function"==typeof b}),!a){var b=n.selectAll("thead").data([0]);b.enter().append("thead"),b.exit().remove();var c=b.selectAll("tr").data([0]);c.enter().append("tr"),c.exit().remove();var d=c.selectAll("th").data(p);d.enter().append("th"),d.exit().remove(),d.attr("class",m).html(function(a){return n._doColumnHeaderFormat(a)})}var e=n.root().selectAll("tbody").data(f(),function(a){return n.keyAccessor()(a)}),g=e.enter().append("tbody");return t===!0&&g.append("tr").attr("class",l).append("td").attr("class",i).attr("colspan",p.length).html(function(a){return n.keyAccessor()(a)}),e.exit().remove(),g}function f(){var b;return b=r===a.ascending?n.dimension().bottom(o):n.dimension().top(o),a.nest().key(n.group()).sortKeys(r).entries(b.sort(function(a,b){return r(q(a),q(b))}).slice(s,h))}function g(a){var b=a.order().selectAll("tr."+j).data(function(a){return a.values}),c=b.enter().append("tr").attr("class",j);return p.forEach(function(a,b){c.append("td").attr("class",k+" _"+b).html(function(b){return n._doColumnValueFormat(a,b)})}),b.exit().remove(),b}var h,i="dc-table-label",j="dc-table-row",k="dc-table-column",l="dc-table-group",m="dc-table-head",n=c.baseMixin({}),o=25,p=[],q=function(a){return a},r=a.ascending,s=0,t=!0;return n._doRender=function(){return n.selectAll("tbody").remove(),g(e()),n},n._doColumnValueFormat=function(a,b){return"function"==typeof a?a(b):"string"==typeof a?b[a]:a.format(b)},n._doColumnHeaderFormat=function(a){return"function"==typeof a?n._doColumnHeaderFnToString(a):"string"==typeof a?n._doColumnHeaderCapitalize(a):String(a.label)},n._doColumnHeaderCapitalize=function(a){return a.charAt(0).toUpperCase()+a.slice(1)},n._doColumnHeaderFnToString=function(a){var b=String(a),c=b.indexOf("return ");if(c>=0){var d=b.lastIndexOf(";");if(d>=0){b=b.substring(c+7,d);var e=b.indexOf("numberFormat");e>=0&&(b=b.replace("numberFormat",""))}}return b},n._doRedraw=function(){return n._doRender()},n.size=function(a){return arguments.length?(o=a,n):o},n.beginSlice=function(a){return arguments.length?(s=a,n):s},n.endSlice=function(a){return arguments.length?(h=a,n):h},n.columns=function(a){return arguments.length?(p=a,n):p},n.sortBy=function(a){return arguments.length?(q=a,n):q},n.order=function(a){return arguments.length?(r=a,n):r},n.showGroups=function(a){return arguments.length?(t=a,n):t},n.anchor(b,d)},c.dataGrid=function(b,d){function e(){var a=m.root().selectAll("div."+l).data(f(),function(a){return m.keyAccessor()(a)}),b=a.enter().append("div").attr("class",l);return s&&b.html(function(a){return s(a)}),a.exit().remove(),b}function f(){var b=m.dimension().top(n);return a.nest().key(m.group()).sortKeys(q).entries(b.sort(function(a,b){return q(p(a),p(b))}).slice(r,h))}function g(a){var b=a.order().selectAll("div."+j).data(function(a){return a.values});return b.enter().append("div").attr("class",j).html(function(a){return o(a)}),b.exit().remove(),b}var h,i="dc-grid-label",j="dc-grid-item",k="dc-grid-group",l="dc-grid-top",m=c.baseMixin({}),n=999,o=function(a){return"you need to provide an html() handling param: "+JSON.stringify(a)},p=function(a){return a},q=a.ascending,r=0,s=function(a){return"

    "+m.keyAccessor()(a)+"

    "};return m._doRender=function(){return m.selectAll("div."+l).remove(),g(e()),m},m._doRedraw=function(){return m._doRender()},m.beginSlice=function(a){return arguments.length?(r=a,m):r},m.endSlice=function(a){return arguments.length?(h=a,m):h},m.size=function(a){return arguments.length?(n=a,m):n},m.html=function(a){return arguments.length?(o=a,m):o},m.htmlGroup=function(a){return arguments.length?(s=a,m):s},m.sortBy=function(a){return arguments.length?(p=a,m):p},m.order=function(a){return arguments.length?(q=a,m):q},m.anchor(b,d)},c.bubbleChart=function(b,d){function e(a){var b=a.enter().append("g");b.attr("class",j.BUBBLE_NODE_CLASS).attr("transform",m).append("circle").attr("class",function(a,b){return j.BUBBLE_CLASS+" _"+b}).on("click",j.onClick).attr("fill",j.getColor).attr("r",0),c.transition(a,j.transitionDuration()).selectAll("circle."+j.BUBBLE_CLASS).attr("r",function(a){return j.bubbleR(a)}).attr("opacity",function(a){return j.bubbleR(a)>0?1:0}),j._doRenderLabel(b),j._doRenderTitles(b)}function f(a){c.transition(a,j.transitionDuration()).attr("transform",m).selectAll("circle."+j.BUBBLE_CLASS).attr("fill",j.getColor).attr("r",function(a){return j.bubbleR(a)}).attr("opacity",function(a){return j.bubbleR(a)>0?1:0}),j.doUpdateLabels(a),j.doUpdateTitles(a)}function g(a){a.exit().remove()}function h(a){var b=j.x()(j.keyAccessor()(a));return isNaN(b)&&(b=0),b}function i(a){var b=j.y()(j.valueAccessor()(a));return isNaN(b)&&(b=0),b}var j=c.bubbleMixin(c.coordinateGridMixin({})),k=!1,l=!1;j.transitionDuration(750);var m=function(a){return"translate("+h(a)+","+i(a)+")"};return j.elasticRadius=function(a){return arguments.length?(k=a,j):k},j.sortBubbleSize=function(a){return arguments.length?(l=a,j):l},j.plotData=function(){k&&j.r().domain([j.rMin(),j.rMax()]),j.r().range([j.MIN_RADIUS,j.xAxisLength()*j.maxBubbleRelativeSize()]);var b=j.data();if(l){var c=j.radiusValueAccessor();b.sort(function(b,d){return a.descending(c(b),c(d))})}var d=j.chartBodyG().selectAll("g."+j.BUBBLE_NODE_CLASS).data(b,function(a){return a.key});l&&d.order(),e(d),f(d),g(d),j.fadeDeselectedArea()},j.renderBrush=function(){},j.redrawBrush=function(){j.fadeDeselectedArea()},j.anchor(b,d)},c.compositeChart=function(b,d){function e(a,b){var c,d,e,g,h;return a&&(c=m(),d=p()),b&&(e=n(),g=q()),w.alignYAxes()&&a&&b&&(h=f(c,d,e,g)),h||{lyAxisMin:c,lyAxisMax:d,ryAxisMin:e,ryAxisMax:g}}function f(a,b,c,d){var e=(d-c)/(b-a);return{lyAxisMin:Math.min(a,c/e),lyAxisMax:Math.max(b,d/e),ryAxisMin:Math.min(c,a*e),ryAxisMax:Math.max(d,b*e)}}function g(b){var c=void 0===w.rightY()||w.elasticY(),d=c||w.resizing();void 0===w.rightY()&&w.rightY(a.scale.linear()),c&&w.rightY().domain([b.ryAxisMin,b.ryAxisMax]),d&&w.rightY().rangeRound([w.yAxisHeight(),0]),w.rightY().range([w.yAxisHeight(),0]),w.rightYAxis(w.rightYAxis().scale(w.rightY())),w.rightYAxis().orient("right")}function h(b){var c=void 0===w.y()||w.elasticY(),d=c||w.resizing();void 0===w.y()&&w.y(a.scale.linear()),c&&w.y().domain([b.lyAxisMin,b.lyAxisMax]),d&&w.y().rangeRound([w.yAxisHeight(),0]),w.y().range([w.yAxisHeight(),0]),w.yAxis(w.yAxis().scale(w.y())),w.yAxis().orient("left")}function i(a,b){a._generateG(w.g()),a.g().attr("class",u+" _"+b)}function j(){return x.filter(function(a){return!a.useRightYAxis()})}function k(){return x.filter(function(a){return a.useRightYAxis()})}function l(a){return a.map(function(a){return a.yAxisMin()})}function m(){return a.min(l(j()))}function n(){return a.min(l(k()))}function o(a){return a.map(function(a){return a.yAxisMax()})}function p(){return c.utils.add(a.max(o(j())),w.yAxisPadding())}function q(){return c.utils.add(a.max(o(k())),w.yAxisPadding())}function r(){return x.map(function(a){return a.xAxisMin()})}function s(){return x.map(function(a){return a.xAxisMax()})}var t,u="sub",v=12,w=c.coordinateGridMixin({}),x=[],y={},z=!1,A=!0,B=!1,C=a.svg.axis(),D=0,E=v,F=!1;return w._mandatoryAttributes([]),w.transitionDuration(500),c.override(w,"_generateG",function(){for(var a=this.__generateG(),b=0;b0&&!F?w._renderHorizontalGridLinesForAxis(w.g(),w.y(),w.yAxis()):k().length>0&&w._renderHorizontalGridLinesForAxis(w.g(),t,C)},w.renderYAxis=function(){0!==j().length&&(w.renderYAxisAt("y",w.yAxis(),w.margins().left),w.renderYAxisLabel("y",w.yAxisLabel(),-90)),0!==k().length&&(w.renderYAxisAt("yr",w.rightYAxis(),w.width()-w.margins().right),w.renderYAxisLabel("yr",w.rightYAxisLabel(),90,w.width()-E))},w.plotData=function(){for(var a=0;a0&&(b[0]=0),b[1]<0&&(b[1]=0),t=a.scale.linear().domain(b).range([0,G.effectiveWidth()])}H.scale(t)}function f(){var a=s.select("g.axis");e(),a.empty()&&(a=s.append("g").attr("class","axis")),a.attr("transform","translate(0, "+G.effectiveHeight()+")"),c.transition(a,G.transitionDuration()).call(H)}function g(){s.selectAll("g.tick").select("line.grid-line").remove(),s.selectAll("g.tick").append("line").attr("class","grid-line").attr("x1",0).attr("y1",0).attr("x2",0).attr("y2",function(){return-G.effectiveHeight()})}function h(){v=G.data(),f(),g();var a=s.selectAll("g."+D).data(v);i(a),j(a),l(a)}function i(a){var b=a.enter().append("g").attr("class",function(a,b){return D+" _"+b});b.append("rect").attr("width",0),n(b)}function j(a){a.exit().remove()}function k(){var a=t(0);return a===-(1/0)||a!==a?t(1):a}function l(a){var b,d=v.length;b=C?C:(G.effectiveHeight()-(d+1)*B)/d,y||(x=b/2);var e=a.attr("transform",function(a,c){return"translate(0,"+((c+1)*B+c*b)+")"}).select("rect").attr("height",b).attr("fill",G.getColor).on("click",p).classed("deselected",function(a){return G.hasFilter()?!r(a):!1}).classed("selected",function(a){return G.hasFilter()?r(a):!1});c.transition(e,G.transitionDuration()).attr("width",function(a){return Math.abs(k()-t(G.valueAccessor()(a))); -}).attr("transform",q),m(a),o(a)}function m(a){G.renderTitle()&&(a.selectAll("title").remove(),a.append("title").text(G.title()))}function n(a){G.renderLabel()&&a.append("text").on("click",p),G.renderTitleLabel()&&a.append("text").attr("class",E).on("click",p)}function o(a){if(G.renderLabel()){var b=a.select("text").attr("x",w).attr("y",x).attr("dy",z).on("click",p).attr("class",function(a,b){return D+" _"+b}).text(function(a){return G.label()(a)});c.transition(b,G.transitionDuration()).attr("transform",q)}if(G.renderTitleLabel()){var d=a.select("."+E).attr("x",G.effectiveWidth()-A).attr("y",x).attr("dy",z).attr("text-anchor","end").on("click",p).attr("class",function(a,b){return E+" _"+b}).text(function(a){return G.title()(a)});c.transition(d,G.transitionDuration()).attr("transform",q)}}function p(a){G.onClick(a)}function q(a){var b=t(G.cappedValueAccessor(a)),c=k(),d=b>c?c:b;return"translate("+d+",0)"}function r(a){return G.hasFilter(G.cappedKeyAccessor(a))}var s,t,u,v,w=10,x=15,y=!1,z="0.35em",A=2,B=5,C=!1,D="row",E="titlerow",F=!1,G=c.capMixin(c.marginMixin(c.colorMixin(c.baseMixin({})))),H=a.svg.axis().orient("bottom");return G.rowsCap=G.cap,G._doRender=function(){return G.resetSvg(),s=G.svg().append("g").attr("transform","translate("+G.margins().left+","+G.margins().top+")"),h(),G},G.title(function(a){return G.cappedKeyAccessor(a)+": "+G.cappedValueAccessor(a)}),G.label(G.cappedKeyAccessor),G.x=function(a){return arguments.length?(t=a,G):t},G.renderTitleLabel=function(a){return arguments.length?(F=a,G):F},G._doRedraw=function(){return h(),G},G.xAxis=function(){return H},G.fixedBarHeight=function(a){return arguments.length?(C=a,G):C},G.gap=function(a){return arguments.length?(B=a,G):B},G.elasticX=function(a){return arguments.length?(u=a,G):u},G.labelOffsetX=function(a){return arguments.length?(w=a,G):w},G.labelOffsetY=function(a){return arguments.length?(x=a,y=!0,G):x},G.titleLabelOffsetX=function(a){return arguments.length?(A=a,G):A},G.anchor(b,d)},c.legend=function(){function a(){return j+i}var b,d,e=2,f={},g=0,h=0,i=12,j=5,k=!1,l=560,m=70,n=!1,o=c.pluck("name");return f.parent=function(a){return arguments.length?(b=a,f):b},f.render=function(){b.svg().select("g.dc-legend").remove(),d=b.svg().append("g").attr("class","dc-legend").attr("transform","translate("+g+","+h+")");var f=b.legendables(),p=d.selectAll("g.dc-legend-item").data(f).enter().append("g").attr("class","dc-legend-item").on("mouseover",function(a){b.legendHighlight(a)}).on("mouseout",function(a){b.legendReset(a)}).on("click",function(a){a.chart.legendToggle(a)});d.selectAll("g.dc-legend-item").classed("fadeout",function(a){return a.chart.isLegendableHidden(a)}),f.some(c.pluck("dashstyle"))?p.append("line").attr("x1",0).attr("y1",i/2).attr("x2",i).attr("y2",i/2).attr("stroke-width",2).attr("stroke-dasharray",c.pluck("dashstyle")).attr("stroke",c.pluck("color")):p.append("rect").attr("width",i).attr("height",i).attr("fill",function(a){return a?a.color:"blue"}),p.append("text").text(o).attr("x",i+e).attr("y",function(){return i/2+(this.clientHeight?this.clientHeight:13)/2-2});var q=0,r=0;p.attr("transform",function(b,c){if(k){var d="translate("+q+","+r*a()+")",e=n===!0?this.getBBox().width+j:m;return q+e>=l?(++r,q=0):q+=e,d}return"translate(0,"+c*a()+")"})},f.x=function(a){return arguments.length?(g=a,f):g},f.y=function(a){return arguments.length?(h=a,f):h},f.gap=function(a){return arguments.length?(j=a,f):j},f.itemHeight=function(a){return arguments.length?(i=a,f):i},f.horizontal=function(a){return arguments.length?(k=a,f):k},f.legendWidth=function(a){return arguments.length?(l=a,f):l},f.itemWidth=function(a){return arguments.length?(m=a,f):m},f.autoItemWidth=function(a){return arguments.length?(n=a,f):n},f.legendText=function(a){return arguments.length?(o=a,f):o},f},c.scatterPlot=function(b,d){function e(b,d){var e=f.selectAll(".chart-body path.symbol").filter(function(){return b(a.select(this))}),h=g.size();g.size(Math.pow(d,2)),c.transition(e,f.transitionDuration()).attr("d",g),g.size(h)}var f=c.coordinateGridMixin({}),g=a.svg.symbol(),h=function(a){return a.value},i=f.keyAccessor();f.keyAccessor(function(a){return i(a)[0]}),f.valueAccessor(function(a){return i(a)[1]}),f.colorAccessor(function(){return f._groupName});var j=function(a){return"translate("+f.x()(f.keyAccessor()(a))+","+f.y()(f.valueAccessor()(a))+")"},k=7,l=5,m=3,n=null,o=1,p=0,q=[];return g.size(function(a,b){return h(a)?q[b]?Math.pow(l,2):Math.pow(m,2):p}),c.override(f,"_filter",function(a){return arguments.length?f.__filter(c.filters.RangedTwoDimensionalFilter(a)):f.__filter()}),f.plotData=function(){var a=f.chartBodyG().selectAll("path.symbol").data(f.data());a.enter().append("path").attr("class","symbol").attr("opacity",0).attr("fill",f.getColor).attr("transform",j),a.each(function(a,b){q[b]=!f.filter()||f.filter().isFiltered([a.key[0],a.key[1]])}),c.transition(a,f.transitionDuration()).attr("opacity",function(a,b){return h(a)?q[b]?1:f.excludedOpacity():0}).attr("fill",function(a,b){return f.excludedColor()&&!q[b]?f.excludedColor():f.getColor(a)}).attr("transform",j).attr("d",g),c.transition(a.exit(),f.transitionDuration()).attr("opacity",0).remove()},f.existenceAccessor=function(a){return arguments.length?(h=a,this):h},f.symbol=function(a){return arguments.length?(g.type(a),f):g.type()},f.symbolSize=function(a){return arguments.length?(l=a,f):l},f.highlightedSize=function(a){return arguments.length?(k=a,f):k},f.excludedSize=function(a){return arguments.length?(m=a,f):m},f.excludedColor=function(a){return arguments.length?(n=a,f):n},f.excludedOpacity=function(a){return arguments.length?(o=a,f):o},f.hiddenSize=f.emptySize=function(a){return arguments.length?(p=a,f):p},f.legendables=function(){return[{chart:f,name:f._groupName,color:f.getColor()}]},f.legendHighlight=function(b){e(function(a){return a.attr("fill")===b.color},k),f.selectAll(".chart-body path.symbol").filter(function(){return a.select(this).attr("fill")!==b.color}).classed("fadeout",!0)},f.legendReset=function(b){e(function(a){return a.attr("fill")===b.color},l),f.selectAll(".chart-body path.symbol").filter(function(){return a.select(this).attr("fill")!==b.color}).classed("fadeout",!1)},f.setHandlePaths=function(){},f.extendBrush=function(){var a=f.brush().extent();return f.round()&&(a[0]=a[0].map(f.round()),a[1]=a[1].map(f.round()),f.g().select(".brush").call(f.brush().extent(a))),a},f.brushIsEmpty=function(a){return f.brush().empty()||!a||a[0][0]>=a[1][0]||a[0][1]>=a[1][1]},f._brushing=function(){var a=f.extendBrush();if(f.redrawBrush(f.g()),f.brushIsEmpty(a))c.events.trigger(function(){f.filter(null),f.redrawGroup()});else{var b=c.filters.RangedTwoDimensionalFilter(a);c.events.trigger(function(){f.filter(null),f.filter(b),f.redrawGroup()},c.constants.EVENT_DELAY)}},f.setBrushY=function(a){a.call(f.brush().y(f.y()))},f.anchor(b,d)},c.numberDisplay=function(b,d){var e,f="number-display",g=a.format(".2s"),h=c.baseMixin({}),i={one:"",some:"",none:""};return h._mandatoryAttributes(["group"]),h.html=function(a){return arguments.length?(a.none?i.none=a.none:a.one?i.none=a.one:a.some&&(i.none=a.some),a.one?i.one=a.one:a.some&&(i.one=a.some),a.some?i.some=a.some:a.one&&(i.some=a.one),h):i},h.value=function(){return h.data()},h.data(function(a){var b=a.value?a.value():a.top(1)[0];return h.valueAccessor()(b)}),h.transitionDuration(250),h._doRender=function(){var b=h.value(),c=h.selectAll("."+f);c.empty()&&(c=c.data([0]).enter().append("span").attr("class",f)),c.transition().duration(h.transitionDuration()).ease("quad-out-in").tween("text",function(){var c=isFinite(e)?e:0,d=a.interpolateNumber(c||0,b);return e=b,function(a){var c=null,e=h.formatNumber()(d(a));0===b&&""!==i.none?c=i.none:1===b&&""!==i.one?c=i.one:""!==i.some&&(c=i.some),this.innerHTML=c?c.replace("%number",e):e}})},h._doRedraw=function(){return h._doRender()},h.formatNumber=function(a){return arguments.length?(g=a,h):g},h.anchor(b,d)},c.heatMap=function(b,d){function e(a,b){var d=p.selectAll(".box-group").filter(function(c){return c.key[a]===b}),e=d.filter(function(a){return!p.hasFilter(a.key)});c.events.trigger(function(){e.empty()?d.each(function(a){p.filter(a.key)}):e.each(function(a){p.filter(a.key)}),p.redrawGroup()})}var f,g,h,i=6.75,j=a.ascending,k=a.ascending,l=a.scale.ordinal(),m=a.scale.ordinal(),n=i,o=i,p=c.colorMixin(c.marginMixin(c.baseMixin({})));p._mandatoryAttributes(["group"]),p.title(p.colorAccessor());var q=function(a){return a},r=function(a){return a};p.colsLabel=function(a){return arguments.length?(q=a,p):q},p.rowsLabel=function(a){return arguments.length?(r=a,p):r};var s=function(a){e(0,a)},t=function(a){e(1,a)},u=function(a){var b=a.key;c.events.trigger(function(){p.filter(b),p.redrawGroup()})};return c.override(p,"filter",function(a){return arguments.length?p._filter(c.filters.TwoDimensionalFilter(a)):p._filter()}),p.rows=function(a){return arguments.length?(h=a,p):h},p.rowOrdering=function(a){return arguments.length?(k=a,p):k},p.cols=function(a){return arguments.length?(g=a,p):g},p.colOrdering=function(a){return arguments.length?(j=a,p):j},p._doRender=function(){return p.resetSvg(),f=p.svg().append("g").attr("class","heatmap").attr("transform","translate("+p.margins().left+","+p.margins().top+")"),p._doRedraw()},p._doRedraw=function(){var a=p.data(),b=p.rows()||a.map(p.valueAccessor()),d=p.cols()||a.map(p.keyAccessor());k&&(b=b.sort(k)),j&&(d=d.sort(j)),b=m.domain(b),d=l.domain(d);var e=b.domain().length,g=d.domain().length,h=Math.floor(p.effectiveWidth()/g),i=Math.floor(p.effectiveHeight()/e);d.rangeRoundBands([0,p.effectiveWidth()]),b.rangeRoundBands([p.effectiveHeight(),0]);var q=f.selectAll("g.box-group").data(p.data(),function(a,b){return p.keyAccessor()(a,b)+"\x00"+p.valueAccessor()(a,b)}),r=q.enter().append("g").attr("class","box-group");r.append("rect").attr("class","heat-box").attr("fill","white").on("click",p.boxOnClick()),p.renderTitle()&&(r.append("title"),q.selectAll("title").text(p.title())),c.transition(q.selectAll("rect"),p.transitionDuration()).attr("x",function(a,b){return d(p.keyAccessor()(a,b))}).attr("y",function(a,c){return b(p.valueAccessor()(a,c))}).attr("rx",n).attr("ry",o).attr("fill",p.getColor).attr("width",h).attr("height",i),q.exit().remove();var s=f.selectAll("g.cols");s.empty()&&(s=f.append("g").attr("class","cols axis"));var t=s.selectAll("text").data(d.domain());t.enter().append("text").attr("x",function(a){return d(a)+h/2}).style("text-anchor","middle").attr("y",p.effectiveHeight()).attr("dy",12).on("click",p.xAxisOnClick()).text(p.colsLabel()),c.transition(t,p.transitionDuration()).text(p.colsLabel()).attr("x",function(a){return d(a)+h/2}).attr("y",p.effectiveHeight()),t.exit().remove();var u=f.selectAll("g.rows");u.empty()&&(u=f.append("g").attr("class","rows axis"));var v=u.selectAll("text").data(b.domain());return v.enter().append("text").attr("dy",6).style("text-anchor","end").attr("x",0).attr("dx",-2).on("click",p.yAxisOnClick()).text(p.rowsLabel()),c.transition(v,p.transitionDuration()).text(p.rowsLabel()).attr("y",function(a){return b(a)+i/2}),v.exit().remove(),p.hasFilter()?p.selectAll("g.box-group").each(function(a){p.isSelectedNode(a)?p.highlightSelected(this):p.fadeDeselected(this)}):p.selectAll("g.box-group").each(function(){p.resetHighlight(this)}),p},p.boxOnClick=function(a){return arguments.length?(u=a,p):u},p.xAxisOnClick=function(a){return arguments.length?(s=a,p):s},p.yAxisOnClick=function(a){return arguments.length?(t=a,p):t},p.xBorderRadius=function(a){return arguments.length?(n=a,p):n},p.yBorderRadius=function(a){return arguments.length?(o=a,p):o},p.isSelectedNode=function(a){return p.hasFilter(a.key)},p.anchor(b,d)},function(){function b(a){return[0,a.length-1]}function c(b){return[a.quantile(b,.25),a.quantile(b,.5),a.quantile(b,.75)]}a.box=function(){function d(b){b.each(function(b,c){b=b.map(i).sort(a.ascending);var d=a.select(this),m=b.length,n=b[0],o=b[m-1],p=b.quartiles=k(b),q=j&&j.call(this,b,c),r=q&&q.map(function(a){return b[a]}),s=q?a.range(0,q[0]).concat(a.range(q[1]+1,m)):a.range(m),t=a.scale.linear().domain(h&&h.call(this,b,c)||[n,o]).range([f,0]),u=this.__chart__||a.scale.linear().domain([0,1/0]).range(t.range());this.__chart__=t;var v=d.selectAll("line.center").data(r?[r]:[]);v.enter().insert("line","rect").attr("class","center").attr("x1",e/2).attr("y1",function(a){return u(a[0])}).attr("x2",e/2).attr("y2",function(a){return u(a[1])}).style("opacity",1e-6).transition().duration(g).style("opacity",1).attr("y1",function(a){return t(a[0])}).attr("y2",function(a){return t(a[1])}),v.transition().duration(g).style("opacity",1).attr("y1",function(a){return t(a[0])}).attr("y2",function(a){return t(a[1])}),v.exit().transition().duration(g).style("opacity",1e-6).attr("y1",function(a){return t(a[0])}).attr("y2",function(a){return t(a[1])}).remove();var w=d.selectAll("rect.box").data([p]);w.enter().append("rect").attr("class","box").attr("x",0).attr("y",function(a){return u(a[2])}).attr("width",e).attr("height",function(a){return u(a[0])-u(a[2])}).transition().duration(g).attr("y",function(a){return t(a[2])}).attr("height",function(a){return t(a[0])-t(a[2])}),w.transition().duration(g).attr("y",function(a){return t(a[2])}).attr("height",function(a){return t(a[0])-t(a[2])});var x=d.selectAll("line.median").data([p[1]]);x.enter().append("line").attr("class","median").attr("x1",0).attr("y1",u).attr("x2",e).attr("y2",u).transition().duration(g).attr("y1",t).attr("y2",t),x.transition().duration(g).attr("y1",t).attr("y2",t);var y=d.selectAll("line.whisker").data(r||[]);y.enter().insert("line","circle, text").attr("class","whisker").attr("x1",0).attr("y1",u).attr("x2",e).attr("y2",u).style("opacity",1e-6).transition().duration(g).attr("y1",t).attr("y2",t).style("opacity",1),y.transition().duration(g).attr("y1",t).attr("y2",t).style("opacity",1),y.exit().transition().duration(g).attr("y1",t).attr("y2",t).style("opacity",1e-6).remove();var z=d.selectAll("circle.outlier").data(s,Number);z.enter().insert("circle","text").attr("class","outlier").attr("r",5).attr("cx",e/2).attr("cy",function(a){return u(b[a])}).style("opacity",1e-6).transition().duration(g).attr("cy",function(a){return t(b[a])}).style("opacity",1),z.transition().duration(g).attr("cy",function(a){return t(b[a])}).style("opacity",1),z.exit().transition().duration(g).attr("cy",function(a){return t(b[a])}).style("opacity",1e-6).remove();var A=l||t.tickFormat(8),B=d.selectAll("text.box").data(p);B.enter().append("text").attr("class","box").attr("dy",".3em").attr("dx",function(a,b){return 1&b?6:-6}).attr("x",function(a,b){return 1&b?e:0}).attr("y",u).attr("text-anchor",function(a,b){return 1&b?"start":"end"}).text(A).transition().duration(g).attr("y",t),B.transition().duration(g).text(A).attr("y",t);var C=d.selectAll("text.whisker").data(r||[]);C.enter().append("text").attr("class","whisker").attr("dy",".3em").attr("dx",6).attr("x",e).attr("y",u).text(A).style("opacity",1e-6).transition().duration(g).attr("y",t).style("opacity",1),C.transition().duration(g).text(A).attr("y",t).style("opacity",1),C.exit().transition().duration(g).attr("y",t).style("opacity",1e-6).remove()}),a.timer.flush()}var e=1,f=1,g=0,h=null,i=Number,j=b,k=c,l=null;return d.width=function(a){return arguments.length?(e=a,d):e},d.height=function(a){return arguments.length?(f=a,d):f},d.tickFormat=function(a){return arguments.length?(l=a,d):l},d.duration=function(a){return arguments.length?(g=a,d):g},d.domain=function(b){return arguments.length?(h=null===b?b:a.functor(b),d):h},d.value=function(a){return arguments.length?(i=a,d):i},d.whiskers=function(a){return arguments.length?(j=a,d):j},d.quartiles=function(a){return arguments.length?(k=a,d):k},d}}(),c.boxPlot=function(b,d){function e(a){return function(b){var c=b.quartiles[0],d=b.quartiles[2],e=(d-c)*a,f=-1,g=b.length;do++f;while(b[f]d+e);return[f,g]}}function f(a){var b=a.enter().append("g");b.attr("class","box").attr("transform",p).call(m).on("click",function(a){i.filter(a.key),i.redrawGroup()})}function g(b){c.transition(b,i.transitionDuration()).attr("transform",p).call(m).each(function(){a.select(this).select("rect.box").attr("fill",i.getColor)})}function h(a){a.exit().remove().call(m)}var i=c.coordinateGridMixin({}),j=1.5,k=e,l=k(j),m=a.box(),n=null,o=function(a,b){return i.isOrdinal()?i.x().rangeBand():a/(1+i.boxPadding())/b};i.yAxisPadding(12),i.x(a.scale.ordinal()),i.xUnits(c.units.ordinal),i.data(function(a){return a.all().map(function(a){return a.map=function(b){return b.call(a,a)},a}).filter(function(a){var b=i.valueAccessor()(a);return 0!==b.length})}),i.boxPadding=i._rangeBandPadding,i.boxPadding(.8),i.outerPadding=i._outerRangeBandPadding,i.outerPadding(.5),i.boxWidth=function(b){return arguments.length?(o=a.functor(b),i):o};var p=function(a,b){var c=i.x()(i.keyAccessor()(a,b));return"translate("+c+", 0)"};return i._preprocessData=function(){i.elasticX()&&i.x().domain([])},i.plotData=function(){var a=o(i.effectiveWidth(),i.xUnitCount());m.whiskers(l).width(a).height(i.effectiveHeight()).value(i.valueAccessor()).domain(i.y().domain()).duration(i.transitionDuration()).tickFormat(n);var b=i.chartBodyG().selectAll("g.box").data(i.data(),function(a){return a.key});f(b),g(b),h(b),i.fadeDeselectedArea()},i.fadeDeselectedArea=function(){i.hasFilter()?i.g().selectAll("g.box").each(function(a){i.isSelectedNode(a)?i.highlightSelected(this):i.fadeDeselected(this)}):i.g().selectAll("g.box").each(function(){i.resetHighlight(this)})},i.isSelectedNode=function(a){return i.hasFilter(a.key)},i.yAxisMin=function(){var b=a.min(i.data(),function(b){return a.min(i.valueAccessor()(b))});return c.utils.subtract(b,i.yAxisPadding())},i.yAxisMax=function(){var b=a.max(i.data(),function(b){return a.max(i.valueAccessor()(b))});return c.utils.add(b,i.yAxisPadding())},i.tickFormat=function(a){return arguments.length?(n=a,i):n},i.anchor(b,d)},c.selectMenu=function(b,d){function e(){var a=h.selectAll("option."+j).data(k.data(),function(a){return k.keyAccessor()(a)});return a.enter().append("option").classed(j,!0).attr("value",function(a){return k.keyAccessor()(a)}),a.text(k.title()),a.exit().remove(),h.selectAll("option."+j).sort(p),h.on("change",f),a}function f(b,c){var d,e=a.event.target;if(e.selectedOptions){var f=Array.prototype.slice.call(e.selectedOptions);d=f.map(function(a){return a.value})}else{var g=[].slice.call(a.event.target.options);d=g.filter(function(a){return a.selected}).map(function(a){return a.value})}1===d.length&&""===d[0]?d=n||null:m||1!==d.length||(d=d[0]),k.onChange(d)}function g(){m?h.attr("multiple",!0):h.attr("multiple",null),null!==o?h.attr("size",o):h.attr("size",null)}var h,i="dc-select-menu",j="dc-select-option",k=c.baseMixin({}),l="Select all",m=!1,n=null,o=null,p=function(a,b){return k.keyAccessor()(a)>k.keyAccessor()(b)?1:k.keyAccessor()(b)>k.keyAccessor()(a)?-1:0},q=function(a){return k.valueAccessor()(a)>0};return k.data(function(a){return a.all().filter(q)}),k._doRender=function(){return k.select("select").remove(),h=k.root().append("select").classed(i,!0),h.append("option").text(l).attr("value",""),k._doRedraw(),k},k._doRedraw=function(){return g(),e(),k.hasFilter()&&m?h.selectAll("option").property("selected",function(a){return a&&k.filters().indexOf(String(k.keyAccessor()(a)))>=0}):k.hasFilter()?h.property("value",k.filter()):h.property("value",""),k},k.onChange=function(a){a&&m?k.replaceFilter([a]):a?k.replaceFilter(a):k.filterAll(),c.events.trigger(function(){k.redrawGroup()})},k.order=function(a){return arguments.length?(p=a,k):p},k.promptText=function(a){return arguments.length?(l=a,k):l},k.filterDisplayed=function(a){return arguments.length?(q=a,k):q},k.multiple=function(a){return arguments.length?(m=a,k):m},k.promptValue=function(a){return arguments.length?(n=a,k):n},k.numberVisible=function(a){return arguments.length?(o=a,k):o},k.size=c.logger.deprecate(k.numberVisible,"selectMenu.size is ambiguous - use numberVisible instead"),k.anchor(b,d)},c.abstractBubbleChart=c.bubbleMixin,c.baseChart=c.baseMixin,c.capped=c.capMixin,c.colorChart=c.colorMixin,c.coordinateGridChart=c.coordinateGridMixin,c.marginable=c.marginMixin,c.stackableChart=c.stackMixin,c.d3=a,c.crossfilter=b,c}if("function"==typeof define&&define.amd)define(["d3","crossfilter"],a);else if("object"==typeof module&&module.exports){var b=require("d3"),c=require("crossfilter2");"function"!=typeof c&&(c=c.crossfilter),module.exports=a(b,c)}else this.dc=a(d3,crossfilter)}(); -//# sourceMappingURL=dc.min.js.map \ No newline at end of file diff --git a/web/js/dc.min.js.map b/web/js/dc.min.js.map deleted file mode 100644 index 666ff535ab..0000000000 --- a/web/js/dc.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["dc.js"],"names":["_dc","d3","crossfilter","dc","version","constants","CHART_CLASS","DEBUG_GROUP_CLASS","STACK_CLASS","DESELECTED_CLASS","SELECTED_CLASS","NODE_INDEX_NAME","GROUP_INDEX_NAME","DEFAULT_CHART_GROUP","EVENT_DELAY","NEGLIGIBLE_NUMBER","_renderlet","chartRegistry","initializeChartGroup","group","_chartMap","has","chart","e","indexOf","register","push","deregister","i","length","anchorName","splice","clear","list","registerChart","deregisterChart","hasChart","deregisterAllCharts","filterAll","charts","refocusAll","focus","renderAll","render","redrawAll","redraw","disableTransitions","transition","selections","duration","callback","name","undefined","s","optionalTransition","enable","selection","afterTransition","empty","call","n","each","units","integers","start","end","Math","abs","ordinal","domain","fp","precision","_f","d","resolution","utils","isNegligible","floor","ceil","round","override","obj","functionName","newFunction","existingFunction","renderlet","_","arguments","instanceOfChart","o","Object","__dcFlag__","errors","Exception","msg","_msg","this","message","toString","stack","Error","prototype","create","constructor","InvalidStateException","apply","BadArgumentException","dateFormat","time","format","printers","filters","filter","Array","printSingleValue","pluck","f","Date","isFloat","fformat","isInteger","add","l","r","replace","setTime","getTime","setDate","getDate","percentage","subtract","isNumber","clamp","val","min","max","_idCounter","uniqueId","nameToId","toLowerCase","appendOrSelect","parent","selector","tag","element","select","append","safeNumber","logger","enableDebugLog","warn","console","log","debug","deprecate","fn","deprecated","warned","events","current","trigger","closure","delay","setTimeout","RangedFilter","low","high","range","isFiltered","value","filterType","TwoDimensionalFilter","RangedTwoDimensionalFilter","fromBottomLeft","Infinity","x","y","baseMixin","_chart","sizeSvg","_svg","attr","width","height","generateSvg","root","checkForMandatoryAttributes","a","applyFilters","dimension","fs","_filterHandler","_dimension","_group","_anchor","_root","_isChild","_width","_height","_orderSort","_legend","_commitHandler","_minWidth","_defaultWidthCalc","getBoundingClientRect","_widthCalc","_minHeight","_defaultHeightCalc","_heightCalc","_keyAccessor","_valueAccessor","_label","_ordering","_renderLabel","_title","keyAccessor","valueAccessor","_renderTitle","_controlsUseVisibility","_transitionDuration","_filterPrinter","_mandatoryAttributes","_chartGroup","_listeners","dispatch","_filters","filterRange","filterFunction","filterExact","_data","all","functor","node","minWidth","minHeight","expireCache","data","_groupName","ordering","orderFunction","quicksort","by","_computeOrderedGroups","dataCopy","slice","selectAll","anchor","chartGroup","classed","id","chartID","rootElement","svg","svgElement","resetSvg","remove","filterPrinter","filterPrinterFunction","controlsUseVisibility","useVisibility","turnOnControls","attribute","style","text","turnOffControls","transitionDuration","preRender","forEach","result","_doRender","_activateRenderlets","event","pretransition","preRedraw","_doRedraw","commitHandler","redrawGroup","error","renderGroup","_invokeFilteredListener","filtered","_invokeZoomedListener","zoomed","_hasFilterHandler","some","hasFilterHandler","hasFilter","_removeFilterHandler","removeFilterHandler","_addFilterHandler","addFilterHandler","_resetFilterHandler","resetFilterHandler","replaceFilter","highlightSelected","fadeDeselected","resetHighlight","onClick","datum","filterHandler","legendables","legendHighlight","legendReset","legendToggle","isLegendableHidden","label","labelFunction","enableLabels","renderLabel","title","titleFunction","renderTitle","renderletFunction","on","legend","options","opts","applyOptions","listener","marginMixin","_margin","top","right","bottom","left","margins","effectiveWidth","effectiveHeight","colorMixin","_colors","scale","category20c","_defaultAccessor","_colorAccessor","colors","colorScale","quantize","ordinalColors","linearColors","linear","interpolate","interpolateHcl","colorAccessor","defaultColorAccessor","colorDomain","calculateColorDomain","newDomain","getColor","colorCalculator","coordinateGridMixin","zoomHandler","_refocused","_zoomOutRestrict","constrainRange","_xOriginalDomain","_rangeChart","domFilter","rescale","rangesEqual","compareDomains","d1","d2","elem","prepareXAxis","g","isOrdinal","elasticX","_x","_ordinalXDomain","xAxisMin","xAxisMax","xdom","_lastXDomain","rangeBands","xAxisLength","_rangeBandPadding","_useOuterPadding","_outerRangeBandPadding","_xAxis","renderVerticalGridLines","gridLineG","VERTICAL_CLASS","_renderVerticalGridLine","insert","GRID_LINE_CLASS","ticks","tickValues","lines","linesGEnter","enter","_xAxisY","exit","brushHeight","getClipPathId","generateClipPath","defs","_parent","chartBodyClip","padding","_clipPadding","yAxisHeight","drawChart","_brushOn","_prepareYAxis","plotData","_resizing","renderXAxis","elasticY","renderYAxis","renderBrush","redrawBrush","fadeDeselectedArea","configureMouseZoom","_mouseZoomable","_enableMouseZoom","_hasBeenMouseZoomable","_disableMouseZoom","constraint","constrainedRange","range1","range2","valueOf","hasRangeSelected","HORIZONTAL_CLASS","Y_AXIS_LABEL_CLASS","X_AXIS_LABEL_CLASS","DEFAULT_AXIS_LABEL_PADDING","category10","_g","_chartBodyG","_xAxisLabel","_y","_yAxisLabel","_round","_unitCount","_focusChart","axis","orient","_xUnits","_xAxisPadding","_xElasticity","_xAxisLabelPadding","_yAxis","_yAxisPadding","_yElasticity","_yAxisLabelPadding","_brush","brush","_renderHorizontalGridLine","_zoomScale","_zoom","behavior","zoom","_nullZoom","_useRightYAxis","resizing","rangeChart","focusChart","zoomScale","extent","zoomOutRestrict","_generateG","href","window","location","split","gElement","mouseZoomable","chartBodyG","xScale","xOriginalDomain","xUnits","xAxis","xAxisPadding","xUnitCount","useRightYAxis","groups","map","axisXG","axisXLab","xAxisLabel","labelText","yAxisMin","yAxisMax","rangeRound","_renderHorizontalGridLinesForAxis","renderYAxisLabel","axisClass","rotation","labelXPosition","axisYLab","labelYPosition","renderYAxisAt","position","axisYG","axisPosition","_yAxisX","labelPosition","yAxisLabel","yScale","yAxis","renderHorizontalGridLines","yAxisPadding","_filter","_brushing","gBrush","setBrushY","setHandlePaths","resizeHandlePath","extendBrush","brushIsEmpty","rangedFilter","doTransition","clipPadding","_preprocessData","scaleExtent","size","refocused","c","brushOn","stackMixin","prepareValues","layer","layerIdx","valAccessor","accessor","String","values","hidden","domainFilter","xDomain","p","findLayerByName","_stack","flattenStack","valueses","concat","visability","_stackLayout","layout","_titles","_hidableStacks","hidableStacks","hideStack","stackName","showStack","getValueAccessorByIndex","index","y0","titleAccessor","stackLayout","layers","flat","ordered","color","capMixin","_cap","_othersLabel","_othersGrouper","topRows","topRowsSum","sum","allRows","allRowsSum","topKeys","allKeys","topSet","set","others","key","cappedKeyAccessor","cappedValueAccessor","cap","count","othersLabel","othersGrouper","grouperFunction","_onClick","bubbleMixin","_maxBubbleRelativeSize","_minRadiusWithLabel","BUBBLE_NODE_CLASS","BUBBLE_CLASS","MIN_RADIUS","_r","_rValueAccessor","bubbleRadiusScale","radiusValueAccessor","rMin","rMax","bubbleR","isNaN","shouldLabel","labelOpacity","labelPointerEvent","_doRenderLabel","bubbleGEnter","doUpdateLabels","labels","_doRenderTitles","doUpdateTitles","minRadius","radius","minRadiusWithLabel","maxBubbleRelativeSize","relativeSize","isSelectedNode","pieChart","_radius","_givenRadius","pieData","arc","buildArcs","pie","pieLayout","_emptyCssClass","_emptyTitle","slices","_sliceGroupCssClass","_sliceCssClass","_labelGroupCssClass","_labelCssClass","createElements","updateElements","removeElements","highlightFilter","cx","cy","slicesEnter","createSliceNodes","createSlicePath","createTitles","createLabels","slicePath","fill","safeArc","attrTween","tweenPie","positionLabels","_applyLabelText","highlightSlice","whether","labelsEnter","classes","_externalLabelRadius","_drawPaths","updateLabelPaths","polyline","arc2","outerRadius","_externalRadiusPadding","innerRadius","_current","t","centroid","endAngle","startAngle","updateSlicePaths","updateLabels","updateTitles","slicePaths","isSelectedSlice","_innerRadius","sort","sliceTooSmall","angle","_minAngleForLabel","sliceHasNoData","b","isOffCanvas","path","highlightSliceFromLegendable","legendable","highlighted","_cx","_cy","DEFAULT_MIN_ANGLE_FOR_LABEL","slicesCap","externalRadiusPadding","minAngleForLabel","emptyTitle","externalLabels","externalLabelRadius","drawPaths","barChart","barHeight","renderLabels","layerIndex","_centerBar","_barWidth","LABEL_PADDING","renderBars","bars","_gap","calculateBarWidth","numberOfBars","rangeBand","barPadding","MIN_BAR_WIDTH","colorFilter","inv","item","match","DEFAULT_GAP_BETWEEN_BARS","_alwaysUseRounding","_rescale","_render","last","centerBar","outerPadding","gap","alwaysUseRounding","_xAxisMax","res","lineChart","drawLine","layersEnter","line","_interpolate","tension","_tension","_defined","defined","_dashStyle","safeD","drawArea","_renderArea","area","drawDots","chartBody","xyTipsOn","tooltipListClass","TOOLTIP_G_CLASS","tooltips","points","createRefLines","dots","DOT_CIRCLE_CLASS","getDotRadius","_dataPointFillOpacity","_dataPointStrokeOpacity","dot","showDot","showRefLines","hideDot","hideRefLines","drawLabels","yRefLine","Y_AXIS_REF_LINE_CLASS","xRefLine","X_AXIS_REF_LINE_CLASS","_dotRadius","yAxisX","yAxisRefPathD","xAxisRefPathD","_dataPointRadius","dashstyle","join","DEFAULT_DOT_RADIUS","DEFAULT_DOT_OPACITY","_xyTipsOn","layersList","dashStyle","renderArea","dotRadius","renderDataPoints","fillOpacity","strokeOpacity","_legendables","dataCount","_formatNumber","_html","html","formatNumber","formatter","tot","selected","dataTable","renderGroups","bAllFunctions","_columns","thead","headrow","headcols","HEAD_CSS_CLASS","_doColumnHeaderFormat","nestEntries","rowGroup","_showGroups","GROUP_CSS_CLASS","LABEL_CSS_CLASS","entries","_order","ascending","_size","nest","sortKeys","_sortBy","_beginSlice","_endSlice","renderRows","rows","order","ROW_CSS_CLASS","rowEnter","v","COLUMN_CSS_CLASS","_doColumnValueFormat","_doColumnHeaderFnToString","_doColumnHeaderCapitalize","charAt","toUpperCase","i1","i2","lastIndexOf","substring","i3","beginSlice","endSlice","columns","sortBy","showGroups","dataGrid","GRID_CSS_CLASS","itemGroup","_htmlGroup","renderItems","items","ITEM_CSS_CLASS","JSON","stringify","htmlGroup","sortByFunction","bubbleChart","renderNodes","bubbleG","bubbleLocator","updateNodes","removeNodes","bubbleX","bubbleY","_elasticRadius","_sortBubbleSize","elasticRadius","sortBubbleSize","radiusAccessor","descending","compositeChart","calculateYAxisRanges","lyAxisMin","lyAxisMax","ryAxisMin","ryAxisMax","ranges","rightYAxisMin","rightYAxisMax","alignYAxes","alignYAxisRanges","extentRatio","prepareRightYAxis","needDomain","rightY","needRange","rightYAxis","prepareLeftYAxis","generateChildG","child","SUB_CHART_CLASS","leftYAxisChildren","_children","rightYAxisChildren","getYAxisMin","getYAxisMax","getAllXAxisMinFromChildCharts","getAllXAxisMaxFromChildCharts","_rightY","DEFAULT_RIGHT_Y_AXIS_LABEL_PADDING","_childOptions","_shareColors","_shareTitle","_alignYAxes","_rightYAxis","_rightYAxisLabel","_rightYAxisLabelPadding","_rightAxisGridLines","__generateG","rightYAxisLabel","useRightAxisGridLines","childOptions","compose","subChartArray","children","shareColors","shareTitle","reduce","j","seriesChart","keySort","clearChart","_charts","resetChildren","keys","_seriesAccessor","_chartFunction","_seriesSort","_valueSort","childrenChanged","keep","nester","sortValues","nesting","sub","subChart","_compose","chartFunction","seriesAccessor","seriesSort","sortFunction","valueSort","geoChoroplethChart","generateLayeredData","isDataLayer","regionG","renderRegionG","renderPaths","groupAll","geoJson","layerSelector","isSelected","isDeselected","layerNameClass","regionClass","baseClasses","getKey","_geoJsons","paths","currentFill","_projectionFlag","_geoPath","geo","states","selectedRegion","overlayGeoJson","json","projection","geoJsons","geoPath","removeGeoJson","bubbleOverlay","initOverlayG","BUBBLE_OVERLAY_CLASS","initializeBubbles","mapData","_points","point","nodeG","getNodeG","circle","bubbleNodeClass","updateBubbles","flag","debugG","debugText","mouse","rowChart","calculateAxisScale","_elasticX","_rowData","drawAxis","axisG","drawGridLines","_rowCssClass","rootValue","_fixedBarHeight","_hasLabelOffsetY","_labelOffsetY","rect","isSelectedRow","translateX","renderTitleLabel","_titleRowCssClass","lab","_labelOffsetX","_dyOffset","titlelab","_titleLabelOffsetX","x0","_renderTitleLabel","rowsCap","fixedBarHeight","labelOffsetX","labelOffsetY","labelOffsety","titleLabelOffsetX","legendItemHeight","_itemHeight","LABEL_GAP","_horizontal","_legendWidth","_itemWidth","_autoItemWidth","_legendText","itemEnter","clientHeight","_cumulativeLegendTextWidth","row","translateBy","itemWidth","getBBox","itemHeight","horizontal","legendWidth","autoItemWidth","legendText","scatterPlot","resizeSymbolsWhere","condition","symbols","oldSize","_symbol","pow","symbol","_existenceAccessor","originalKeyAccessor","_locator","_highlightedSize","_symbolSize","_excludedSize","_excludedColor","_excludedOpacity","_emptySize","_filtered","__filter","excludedOpacity","excludedColor","existenceAccessor","type","symbolSize","highlightedSize","excludedSize","hiddenSize","emptySize","ranged2DFilter","numberDisplay","_lastValue","SPAN_CLASS","one","none","valObj","newValue","span","ease","tween","interpStart","isFinite","interp","interpolateNumber","num","innerHTML","heatMap","filterAxis","cellsOnAxis","unfilteredCellsOnAxis","_chartBody","_cols","_rows","DEFAULT_BORDER_RADIUS","_colOrdering","_rowOrdering","_colScale","_rowScale","_xBorderRadius","_yBorderRadius","_colsLabel","_rowsLabel","colsLabel","rowsLabel","_xAxisOnClick","_yAxisOnClick","_boxOnClick","rowOrdering","cols","colOrdering","rowCount","colCount","boxWidth","boxHeight","rangeRoundBands","boxes","gEnter","boxOnClick","gCols","gColsText","xAxisOnClick","gRows","gRowsText","yAxisOnClick","handler","xBorderRadius","yBorderRadius","boxWhiskers","boxQuartiles","quantile","box","quartileData","quartiles","whiskerIndices","whiskers","whiskerData","outlierIndices","x1","__chart__","center","medianLine","whisker","outlier","Number","tickFormat","boxTick","whiskerTick","timer","flush","boxPlot","DEFAULT_WHISKERS_IQR","k","q1","q3","iqr","renderBoxes","boxesG","boxesGEnter","boxTransform","_box","updateBoxes","removeBoxes","_whiskerIqrFactor","_whiskersIqr","_whiskers","_tickFormat","_boxWidth","innerChartWidth","boxPadding","xOffset","_calculatedBoxWidth","selectMenu","renderOptions","_select","OPTION_CSS_CLASS","onChange","target","selectedOptions","option","_promptValue","_multiple","setAttributes","_numberVisible","SELECT_CSS_CLASS","_promptText","_filterDisplayed","property","promptText","filterDisplayed","multiple","promptValue","numberVisible","abstractBubbleChart","baseChart","capped","colorChart","coordinateGridChart","marginable","stackableChart","define","amd","module","exports","_d3","require","_crossfilter"],"mappings":"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","file":"dc.min.js"} \ No newline at end of file diff --git a/web/resizing/index.html b/web/resizing/index.html deleted file mode 100644 index e742319875..0000000000 --- a/web/resizing/index.html +++ /dev/null @@ -1,21 +0,0 @@ -Index of dc.js resizing tests - -
    -

    Eyeball tests for resizing dc.js charts

    -

    It's a lot easier to test resizing behavior by eye. These pages fit the charts to the browser dynamically so it's easier to test.

    -

    Contributions welcome. -Source -here.

    - - - - - - - - - - - -
    resizing barresizing heatmapresizing pieresizing right axisresizing row
    resizing series
    -
    \ No newline at end of file diff --git a/web/transitions/index.html b/web/transitions/index.html deleted file mode 100644 index 8f9cdda685..0000000000 --- a/web/transitions/index.html +++ /dev/null @@ -1,24 +0,0 @@ -Index of dc.js transition tests - -
    -

    Eyeball tests for dc.js transitions

    -

    Transitions can only be tested by eye. These pages automate the transitions so they can be visually verified.

    -

    Contributions welcome. -Source -here.

    - - - - - - - - - - - - - - -
    area transitionsbar transitionsnumber transitionsordinal bar transitionsordinal line transitions
    ordinal row transitionspie external label transitionspie transitionsstacked bar transitions
    -
    \ No newline at end of file diff --git a/web/transitions/transition-test.js b/web/transitions/transition-test.js deleted file mode 100644 index c15f2a543a..0000000000 --- a/web/transitions/transition-test.js +++ /dev/null @@ -1,46 +0,0 @@ -var transitionTest = (function() { - - // http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript - var querystring = (function(a) { - if (a == "") return {}; - var b = {}; - for (var i = 0; i < a.length; ++i) - { - var p=a[i].split('=', 2); - if (p.length == 1) - b[p[0]] = ""; - else - b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); - } - return b; - })(window.location.search.substr(1).split('&')); - - var inter, duration = +querystring.duration, pause = +querystring.pause; - if(isNaN(duration)) duration = 3000; - if(isNaN(pause)) pause = 500; - function stop() { - window.clearInterval(inter); - } - function oscillate(f1, f2) { - return function() { - stop(); - var which = false; - f1(); - dc.redrawAll(); - inter = window.setInterval(function() { - if((which = !which)) - f2(); - else - f1(); - dc.redrawAll(); - }, duration+pause); - }; - } - return { - querystring : querystring, - duration: duration, - pause: pause, - stop: stop, - oscillate: oscillate - }; -})(); diff --git a/welcome.md b/welcome.md deleted file mode 100644 index 6b15ac0e8b..0000000000 --- a/welcome.md +++ /dev/null @@ -1,11 +0,0 @@ -# dc.js - -Welcome to the dc.js documentation. - -The entire library is scoped under {@link dc the dc namespace}. - -The other Namespaces contain utilities. - -The charts are listed under Classes. - -And shared chart functionality is under Mixins.