├── .eslintrc.json ├── .gitignore ├── .jshintrc ├── .travis.yml ├── GruntFile.js ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── bower.json ├── build ├── nv.d3.css ├── nv.d3.js ├── nv.d3.js.map ├── nv.d3.min.css ├── nv.d3.min.css.map ├── nv.d3.min.js └── nv.d3.min.js.map ├── composer.json ├── examples ├── TimeSeries.html ├── actual.json ├── boxPlot.html ├── boxPlotCustomModel.html ├── bullet.html ├── bulletChart.html ├── candlestick.html ├── candlestickChart.html ├── cumulativeLineChart.html ├── differenceChart.html ├── discreteBarChart.html ├── distroPlotChart.html ├── documentation.html ├── donutChart.html ├── forceDirected.html ├── furiousLegend.html ├── heatMap.html ├── historicalBar.html ├── historicalBarChart.html ├── images │ ├── background.png │ ├── body-background.png │ ├── bullet.png │ ├── hr.png │ └── octocat-logo.png ├── index.html ├── legend.html ├── lib │ ├── colorbrewer.js │ └── stream_layers.js ├── line.html ├── lineChart.html ├── lineChartLogScale.html ├── lineChartSVGResize.html ├── linePlusBarChart.html ├── lineWithFocusChart.html ├── lineWithFocusChart_x2AxisLabel.html ├── monitoringChart.html ├── multiBarChart.html ├── multiBarChart2.html ├── multiBarHorizontalChart.html ├── multiChart.html ├── ohlc.html ├── ohlcChart.html ├── parallelCoordinates.html ├── parallelCoordinatesChart.html ├── pie.html ├── pieChart.html ├── predicted.json ├── sankeyChart.html ├── scatter.html ├── scatterChart.html ├── scatterPlusLineChart.html ├── site.html ├── sparkline.html ├── sparklinePlus.html ├── stackedArea.html ├── stackedAreaChart.html ├── stackedAreaWithFocusChart.html ├── stylesheets │ ├── pygment_trac.css │ └── styles.css ├── sunburst.html └── tooltip.html ├── index.html ├── meteor └── export.js ├── package.js ├── package.json ├── src ├── core.js ├── css │ ├── axis.css │ ├── bars.css │ ├── boxplot.css │ ├── bullet.css │ ├── candlestick.css │ ├── forceDirectedGraph.css │ ├── furiousLegend.css │ ├── lineplusbar.css │ ├── lines.css │ ├── main.css │ ├── ohlc.css │ ├── parallelcoordinates.css │ ├── pie.css │ ├── scatter.css │ ├── sparkline.css │ ├── stackedarea.css │ └── tooltip.css ├── dom.js ├── interactiveLayer.js ├── models │ ├── axis.js │ ├── boxPlot.js │ ├── boxPlotChart.js │ ├── bullet.js │ ├── bulletChart.js │ ├── candlestickBar.js │ ├── cumulativeLineChart.js │ ├── differenceChart.js │ ├── discreteBar.js │ ├── discreteBarChart.js │ ├── distribution.js │ ├── distroPlot.js │ ├── distroPlotChart.js │ ├── focus.js │ ├── forceDirectedGraph.js │ ├── furiousLegend.js │ ├── heatMap.js │ ├── heatMapChart.js │ ├── historicalBar.js │ ├── historicalBarChart.js │ ├── legend.js │ ├── line.js │ ├── lineChart.js │ ├── linePlusBarChart.js │ ├── multiBar.js │ ├── multiBarChart.js │ ├── multiBarHorizontal.js │ ├── multiBarHorizontalChart.js │ ├── multiChart.js │ ├── ohlcBar.js │ ├── parallelCoordinates.js │ ├── parallelCoordinatesChart.js │ ├── pie.js │ ├── pieChart.js │ ├── sankey.js │ ├── sankeyChart.js │ ├── scatter.js │ ├── scatterChart.js │ ├── sparkline.js │ ├── sparklinePlus.js │ ├── stackedArea.js │ ├── stackedAreaChart.js │ ├── sunburst.js │ └── sunburstChart.js ├── tooltip.js └── utils.js └── test ├── ScatterChartTest.html ├── bootstrapModalTest.html ├── boxPlotTest.html ├── cumulativeLineChart.html ├── lineChartTest.html ├── linePlusBarChart.html ├── linePlusBarWithFocusChart.html ├── lineWithFisheyeChart.html ├── lineWithFocusChart.html ├── lineWithFocusChartMissingData.html ├── mocha ├── axis.coffee ├── boxplot.coffee ├── bullet.coffee ├── core.coffee ├── cumulative-line.coffee ├── differenceChart.js ├── discretebar.coffee ├── distrochart.coffee ├── heatmap.coffee ├── historical-bar.coffee ├── legend.coffee ├── line.coffee ├── multibar-horizontal.coffee ├── multibar.coffee ├── pie.coffee ├── sankey.coffee ├── scatter.coffee ├── sparkline.coffee ├── stacked.coffee ├── sunburst.coffee ├── test-utils.coffee └── utils.coffee ├── multiBarChartTest.html ├── multiBarHorizontalChart.html ├── node ├── GruntFile.js ├── README.md ├── nodeTest.html ├── nodeTest.js └── package.json ├── pieChartTest.html ├── polylinearTest.html ├── realTimeChartTest.html ├── scatterPlusLineChart.html ├── scrollTest.html ├── scrollTest2.html ├── stackedAreaChartMissingData.html ├── stackedAreaChartTest.html ├── stream_layers.js ├── testScript.js ├── teststyle.css ├── tinytest └── nv-is-defined-test.js └── translateTest.html /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "es6": true, 6 | "mocha": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "parserOptions": { 10 | "sourceType": "module" 11 | }, 12 | "globals": { 13 | "nv": true, 14 | "d3": true 15 | }, 16 | "rules": { 17 | "indent": [ 18 | "error", 19 | 2 20 | ], 21 | "linebreak-style": [ 22 | "error", 23 | "unix" 24 | ], 25 | "quotes": [ 26 | "error", 27 | "single" 28 | ], 29 | "object-curly-spacing": [ 30 | "error", 31 | "always" 32 | ], 33 | "prefer-arrow-callback": [ 34 | "never", 35 | { 36 | "allowNamedFunctions": true 37 | } 38 | ], 39 | "arrow-parens": [ 40 | "error", 41 | "always" 42 | ], 43 | "space-before-function-paren": ["error", { 44 | "anonymous": "never", 45 | "named": "never", 46 | "asyncArrow": "never" 47 | }], 48 | "semi": [ 49 | "error", 50 | "always" 51 | ], 52 | "comma-dangle": ["error", { 53 | "arrays": "never", 54 | "objects": "never", 55 | "imports": "never", 56 | "exports": "never", 57 | "functions": "ignore" 58 | }] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea 3 | *.swp 4 | *~ 5 | *.log 6 | .DS_Store* 7 | ehthumbs.db 8 | Icon? 9 | Thumbs.db 10 | node_modules 11 | bower_components 12 | coverage 13 | test-results.xml 14 | *.orig 15 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "asi": true 3 | } 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | before_install: 5 | - "npm install -g bower" 6 | - "npm install -g grunt-cli" 7 | - "export DISPLAY=:99.0" 8 | - "sh -e /etc/init.d/xvfb start" 9 | # Meteor Tinytest support 10 | - "curl https://install.meteor.com | /bin/sh" 11 | - export PATH="$HOME/.meteor:$PATH" 12 | - "npm install -g spacejam" 13 | install: 14 | - "npm install" 15 | - "bower install" 16 | 17 | script: 18 | - "npm test" 19 | - "spacejam test-packages ./" 20 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | PLEASE READ THIS BEFORE SUBMITTING A NEW ISSUE. 2 | 3 | ARE YOU ASKING FOR HELP? Please use Stack Overflow tag nvd3.js and include a link to a live, minimal example on jsfiddle / plunker. 4 | 5 | The live example should use the latest code for nvd3. Links are below: 6 | https://raw.githubusercontent.com/novus/nvd3/master/build/nv.d3.js 7 | https://raw.githubusercontent.com/novus/nvd3/master/build/nv.d3.css 8 | 9 | Supported D3 js version. v3.5.17 10 | 11 | https://github.com/cdnjs/cdnjs/blob/master/ajax/libs/d3/3.5.17/d3.min.js 12 | 13 | ARE YOU REPORTING AN ISSUE? Please provide below information with the issue: 14 | 15 | NVD3 version used: 16 | 17 | Browser and OS used: 18 | 19 | Live Example: Jsfiddle / Plunker 20 | 21 | Expected Behaviour: 22 | 23 | Present Behaviour: 24 | 25 | Any more information regarding the issue: 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ##nvd3.js License 2 | 3 | Copyright (c) 2011-2014 [Novus Partners, Inc.][novus] 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | [novus]: https://www.novus.com/ 18 | 19 | 20 | 21 | ##d3.js License 22 | 23 | Copyright (c) 2012, Michael Bostock 24 | All rights reserved. 25 | 26 | Redistribution and use in source and binary forms, with or without 27 | modification, are permitted provided that the following conditions are met: 28 | 29 | * Redistributions of source code must retain the above copyright notice, this 30 | list of conditions and the following disclaimer. 31 | 32 | * Redistributions in binary form must reproduce the above copyright notice, 33 | this list of conditions and the following disclaimer in the documentation 34 | and/or other materials provided with the distribution. 35 | 36 | * The name Michael Bostock may not be used to endorse or promote products 37 | derived from this software without specific prior written permission. 38 | 39 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 40 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, 43 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 44 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 45 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 46 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 47 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 48 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 49 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nvd3", 3 | "homepage": "http://www.nvd3.org", 4 | "authors": [ 5 | "Bob Monteverde", 6 | "Tyler Wolf", 7 | "Robin Hu", 8 | "Frank Shao", 9 | "liquidpele" 10 | ], 11 | "description": "Re-usable charts and chart components for d3.", 12 | "main": [ 13 | "build/nv.d3.js", 14 | "build/nv.d3.css" 15 | ], 16 | "keywords": [ 17 | "d3", 18 | "visualization", 19 | "svg", 20 | "charts" 21 | ], 22 | "license": "Apache-2.0", 23 | "dependencies": { 24 | "d3": "^3.4.4" 25 | }, 26 | "ignore": [ 27 | "**/.*", 28 | "node_modules", 29 | "bower_components", 30 | "test", 31 | "src", 32 | "examples", 33 | "GruntFile.js", 34 | "*.html", 35 | "*.log", 36 | "*.xml", 37 | "*.json", 38 | "*.md" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /build/nv.d3.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"AAqBA,oBAfA,oBAgBI,KAAM,KAiWN,gBAAiB,WA/ErB,kBA+DA,uBAlVA,oBAfA,oBAiXI,gBAAiB,WAqErB,UAAW,UAJX,mBAvbA,eAoaA,uBAgCA,uCACI,eAAgB,KArcpB,eAEI,QAAS,EAuCb,2BAsJA,0DACI,QAAS,EA3Lb,oBAEI,OAAQ,KACR,eAAgB,IAIpB,2BACI,eAAgB,IAGpB,gCACI,eAAgB,EAGpB,oBAEI,OAAQ,QAIZ,0BACI,0BACA,eAAgB,IAGpB,mCACI,YAAa,IAGjB,sCACA,uCACA,uCACI,YAAa,OAOjB,oBACI,aAAc,IAEd,WAAY,aAAa,MAAM,OAGnC,0BACI,aAAc,EAGlB,2BACI,KAAM,QAGV,oBACI,KAAM,YAGV,2BACI,KAAM,cAKV,sCAFA,mCACA,6CAEI,eAAgB,EAEhB,WAAY,aAAa,MAAM,OA8EnC,wDAwEA,6CACI,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAlJhE,8CACA,4CAHA,yCACA,mDAGI,aAAc,EAGlB,sCACA,6CACI,YAAa,IACb,KAAM,cACN,OAAQ,YAIZ,yBACE,aAAc,GAGhB,+BAIA,6BAHE,aAAc,EAOhB,6BACE,OAAQ,KAGV,uBACE,aAAc,MAGhB,gBAAkB,KAAM,KAAK,WAC7B,4BAA8B,aAAc,GAC5C,kCAAoC,aAAc,EAClD,2BAA6B,OAAQ,KAAM,aAAc,IACzD,mCAAqC,OAAQ,KAAM,KAAM,KAAM,aAAc,MAC7E,+BAAiC,OAAQ,KAAM,aAAc,MAC7D,8BAAgC,OAAQ,KAAM,aAAc,KAC5D,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,0BAA4B,UAAW,KAAM,YAAa,IAC1D,6BAA+B,KAAM,KAErC,0BACI,KAAM,QACN,aAAc,GAGlB,gCACI,aAAc,GAGlB,2CACI,aAAc,IAGlB,iDACI,aAAc,IAGlB,yDACI,OAAQ,QACR,KAAM,QAGV,yDACI,OAAQ,QACR,KAAM,QAOV,uCACI,OAAQ,KAGZ,eACI,OAAQ,KACR,aAAc,MAGlB,eACI,OAAQ,KACR,eAAgB,GAGpB,oBACI,aAAc,EAOlB,4BACI,aAAa,EACb,aAAa,EAGjB,8BACI,aAAa,EACb,aAAa,EAGjB,qDACI,aAAa,EACb,eAAe,EAQnB,kCACI,aAAc,IAGlB,wCACI,aAAc,EAElB,8BACI,KAAM,KAGV,8BACI,OAAQ,KAGZ,oDACI,aAAc,EACd,eAAgB,EAGpB,sDACI,aAAc,aACd,eAAgB,aASpB,iCADA,4CAEI,aAAc,IACd,aAAc,cACd,eAAgB,cAIpB,2BACI,OAAQ,KACR,eAAgB,EAChB,KAAM,KACN,aAAc,EAIlB,oBACI,OAAQ,UAUZ,aACI,oBAAqB,KAClB,iBAAkB,KACjB,gBAAiB,KACb,YAAa,KACrB,QAAS,MACT,MAAM,KACN,OAAO,KAMX,0BAA2B,2BACvB,WAAY,EAAE,IAAI,KAAK,eACvB,cAAe,IAInB,WACI,KAAM,IAAO,KAAK,MAAO,WAG7B,aACI,KAAM,IAAK,KAAK,MAAO,WAG3B,qBACI,KAAM,KACN,aAAc,EAGlB,gBACI,UAAW,KACX,YAAa,IAQjB,kBACI,aAAc,KAIlB,uBACI,KAAM,KACN,OAAQ,KAQZ,4BACI,OAAQ,QAGZ,qCACI,aAAc,EAIlB,wBACI,aAAc,YAGlB,+BACI,OAAQ,KACR,aAAc,GACd,KAAM,KACN,aAAc,GAOlB,aACI,WACI,aAAc,EACd,aAAc,GAItB,oCACI,aAAc,IAGlB,0CACI,aAAc,IAGlB,6CACI,OAAQ,QAGZ,6CACI,OAAQ,QAIZ,uBACI,KAAM,KACN,OAAQ,KACR,eAAgB,GAIpB,uBACI,KAAM,KACN,eAAgB,GAGpB,4CACI,KAAM,KACN,aAAc,GACd,OAAQ,KACR,gBAAiB,WAGrB,qCACI,aAAc,EACjB,aAAc,IAIf,8BACE,KAAM,KACN,OAAQ,KACR,aAAc,EACd,eAAgB,EAChB,iBAAkB,EAAG,EAQvB,2BACI,UAAW,KACX,KAAM,qBAGV,4BACI,OAAQ,KACR,aAAc,EAGlB,kBAbI,WAAY,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OAcvF,OAAQ,KACR,aAAc,IACd,eAAgB,EAIhB,aAAc,GAGlB,yBACI,aAAc,EAOlB,4BACI,aAAc,EACd,eAAgB,EAIpB,iCACI,aAAc,KACd,eAAgB,GAGpB,kCACI,aAAc,EAYlB,wBACI,KAAM,KAOV,2CACI,OAAQ,KACR,aAAc,MAGlB,uBACA,yBACI,eAAgB,IAsLpB,+BApIA,WAqII,eAAe,KApLnB,oBACI,aAAc,EACd,eAAgB,EAGpB,kCACA,kCACI,aAAc,EACd,UAAW,KACX,YAAa,IAGjB,kCACI,OAAQ,KAGZ,oCACI,OAAQ,QACR,KAAM,QAGV,oCACI,OAAQ,QACR,KAAM,QAGV,wCACI,YAAa,IACb,UAAW,MAgEf,cAoCA,wBACI,YAAa,IAlGjB,kCACI,aAAc,GACd,eAAgB,EAChB,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAGhE,wCACI,aAAc,GAIlB,0CACI,eAAgB,EAChB,aAAc,EAGlB,WACI,SAAU,SAEV,MAAO,cACP,QAAS,IAET,QAAS,MACT,QAAS,MAET,YAAa,MAAO,WACpB,UAAW,KACX,WAAY,KAGZ,YAAa,OAEb,oBAAqB,KAElB,iBAAkB,KAEjB,gBAAiB,KAEb,YAAa,KAIrB,WAAY,qBACZ,OAAQ,IAAI,MAAM,eAClB,cAAe,IAiBnB,cAcA,aACI,OAAQ,EAER,WAAY,OA5BhB,4BAA6B,6BACzB,WAAY,QAAQ,KAAK,OAEzB,iBAAkB,MAGtB,uBACA,uBACI,QAAS,IAGb,cAEI,QAAS,IAAI,KACb,YAAa,KAEb,iBAAkB,sBAClB,MAAO,cAGP,cAAe,IAAI,MAAM,QAEzB,cAAe,IAAI,IAAI,EAAE,EAG7B,aAEI,QAAS,IAAI,KAIjB,gBACI,QAAS,aACT,OAAQ,IAAI,EAGhB,iBACI,OAAQ,IACR,eAAe,EAInB,oBACI,QAAS,IAAI,IAAI,IAAI,EACrB,eAAgB,OAOpB,8BACI,YAAa,IAGjB,0BACI,WAAY,MACZ,YAAa,IAGjB,4BACI,MAAO,QAGX,iCACI,QAAS,IAAI,IAAI,IAAI,EACrB,oBAAqB,MACrB,oBAAqB,IACrB,iBAAkB,MAClB,iBAAkB,IAGtB,2CAGI,eAAgB,OAIhB,MAAO,KACP,OAAQ,KACR,OAAQ,IAAI,MAAM,KAGtB,mBACI,QAAS,IACT,WAAY,OAGhB,2BACI,eAAgB,KAChB,QAAS,KAWb,wBACI,OAAQ"} -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "novus/nvd3", 3 | "description": "A reusable charting library written in d3.js", 4 | "keywords": [ 5 | "nvd3", 6 | "d3", 7 | "chart", 8 | "graph" 9 | ], 10 | "homepage": "https://github.com/novus/nvd3", 11 | "license": "Apache-2.0", 12 | "authors": [ 13 | { 14 | "name": "Bob Monteverde" 15 | }, 16 | { 17 | "name": "Tyler Wolf" 18 | }, 19 | { 20 | "name": "Robin Hu" 21 | }, 22 | { 23 | "name": "Frank Shao" 24 | }, 25 | { 26 | "name": "liquidpele" 27 | } 28 | ], 29 | "require": { 30 | "mbostock/d3": "@stable" 31 | } 32 | } -------------------------------------------------------------------------------- /examples/boxPlot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/boxPlotCustomModel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/bullet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 59 | 60 | -------------------------------------------------------------------------------- /examples/bulletChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | Normal Bullet Chart 27 | 28 | 29 | Bullet Chart with Custom Labels 30 | 31 | 32 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /examples/discreteBarChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 92 | 93 | -------------------------------------------------------------------------------- /examples/donutChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /examples/furiousLegend.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 |

Legend 1

26 | 27 | 28 | 29 |

Legend 2

30 |

Setting align(false)

31 | 32 | 33 |

Legend 3

34 |

Setting legend padding distance

35 | 36 | 37 | 109 | 110 | -------------------------------------------------------------------------------- /examples/historicalBar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 89 | 90 | -------------------------------------------------------------------------------- /examples/historicalBarChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 91 | 92 | -------------------------------------------------------------------------------- /examples/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novus/nvd3/447cce8c180a92fcabd571cca410760deb3a2c1d/examples/images/background.png -------------------------------------------------------------------------------- /examples/images/body-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novus/nvd3/447cce8c180a92fcabd571cca410760deb3a2c1d/examples/images/body-background.png -------------------------------------------------------------------------------- /examples/images/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novus/nvd3/447cce8c180a92fcabd571cca410760deb3a2c1d/examples/images/bullet.png -------------------------------------------------------------------------------- /examples/images/octocat-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novus/nvd3/447cce8c180a92fcabd571cca410760deb3a2c1d/examples/images/octocat-logo.png -------------------------------------------------------------------------------- /examples/legend.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 |

Legend 1

26 | 27 | 28 | 29 |

Legend 2

30 |

Setting align(false)

31 | 32 | 33 |

Legend 3

34 |

Setting legend padding distance

35 | 36 | 37 | 105 | 106 | -------------------------------------------------------------------------------- /examples/lib/stream_layers.js: -------------------------------------------------------------------------------- 1 | 2 | /* Inspired by Lee Byron's test data generator. */ 3 | function stream_layers(n, m, o) { 4 | if (arguments.length < 3) o = 0; 5 | function bump(a) { 6 | var x = 1 / (.1 + Math.random()), 7 | y = 2 * Math.random() - .5, 8 | z = 10 / (.1 + Math.random()); 9 | for (var i = 0; i < m; i++) { 10 | var w = (i / m - y) * z; 11 | a[i] += x * Math.exp(-w * w); 12 | } 13 | } 14 | return d3.range(n).map(function() { 15 | var a = [], i; 16 | for (i = 0; i < m; i++) a[i] = o + o * Math.random(); 17 | for (i = 0; i < 5; i++) bump(a); 18 | return a.map(stream_index); 19 | }); 20 | } 21 | 22 | /* Another layer generator using gamma distributions. */ 23 | function stream_waves(n, m) { 24 | return d3.range(n).map(function(i) { 25 | return d3.range(m).map(function(j) { 26 | var x = 20 * j / m - i / 3; 27 | return 2 * x * Math.exp(-.5 * x); 28 | }).map(stream_index); 29 | }); 30 | } 31 | 32 | function stream_index(d, i) { 33 | return {x: i, y: Math.max(0, d)}; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /examples/line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 99 | 100 | -------------------------------------------------------------------------------- /examples/lineChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 41 |
42 |
43 | 44 | 157 | 158 | -------------------------------------------------------------------------------- /examples/lineChartLogScale.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 27 | 28 | 29 |
30 | 31 | 94 | 95 | -------------------------------------------------------------------------------- /examples/lineChartSVGResize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 |
31 | Zoom In Zoom Out 32 |
33 | 34 |
35 | 36 |
37 | 38 | 146 | 147 | -------------------------------------------------------------------------------- /examples/lineWithFocusChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /examples/lineWithFocusChart_x2AxisLabel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /examples/monitoringChart.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /examples/multiBarChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 100 | 101 | -------------------------------------------------------------------------------- /examples/multiBarChart2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 79 | 80 | -------------------------------------------------------------------------------- /examples/multiChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /examples/pie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 | 30 |
31 |
32 | 33 | 102 | 103 | -------------------------------------------------------------------------------- /examples/pieChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /examples/sankeyChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 57 | 58 | 59 |

Sankey Chart

60 | 61 |
Basic CSS for Sankey chart:
62 |
 63 | .node rect {
 64 |     cursor: move;
 65 |     fill-opacity: .9;
 66 |     shape-rendering: crispEdges;
 67 | }
 68 | 
 69 | .node text {
 70 |     pointer-events: none;
 71 |     text-shadow: 0 1px 0 #fff;
 72 | }
 73 | 
 74 | .link {
 75 |     fill: none;
 76 |     stroke: #000;
 77 |     stroke-opacity: .2;
 78 | }
 79 | 
 80 | .link:hover {
 81 |     stroke-opacity: .5;
 82 | }
 83 | 
84 | 85 |
86 |
87 | 88 | 167 | 168 | -------------------------------------------------------------------------------- /examples/scatter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 | 27 | 28 | 64 | 65 | -------------------------------------------------------------------------------- /examples/scatterChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 96 | 97 | -------------------------------------------------------------------------------- /examples/scatterPlusLineChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 83 | 84 | -------------------------------------------------------------------------------- /examples/sparkline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 24 | 25 | 26 | 27 |

Sparkline:

28 | 29 | 56 | 57 | -------------------------------------------------------------------------------- /examples/sparklinePlus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 27 | 28 | 29 | 30 |

31 |

32 |

33 | 34 | 88 | 89 | -------------------------------------------------------------------------------- /examples/stackedArea.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 123 | 124 | -------------------------------------------------------------------------------- /examples/stylesheets/pygment_trac.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #404040 } 2 | .highlight { color: #d0d0d0 } 3 | .highlight .c { color: #999999; font-style: italic } /* Comment */ 4 | .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 5 | .highlight .g { color: #d0d0d0 } /* Generic */ 6 | .highlight .k { color: #6ab825; font-weight: normal } /* Keyword */ 7 | .highlight .l { color: #d0d0d0 } /* Literal */ 8 | .highlight .n { color: #d0d0d0 } /* Name */ 9 | .highlight .o { color: #d0d0d0 } /* Operator */ 10 | .highlight .x { color: #d0d0d0 } /* Other */ 11 | .highlight .p { color: #d0d0d0 } /* Punctuation */ 12 | .highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */ 13 | .highlight .cp { color: #cd2828; font-weight: normal } /* Comment.Preproc */ 14 | .highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */ 15 | .highlight .cs { color: #e50808; font-weight: normal; background-color: #520000 } /* Comment.Special */ 16 | .highlight .gd { color: #d22323 } /* Generic.Deleted */ 17 | .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ 18 | .highlight .gr { color: #d22323 } /* Generic.Error */ 19 | .highlight .gh { color: #ffffff; font-weight: normal } /* Generic.Heading */ 20 | .highlight .gi { color: #589819 } /* Generic.Inserted */ 21 | .highlight .go { color: #cccccc } /* Generic.Output */ 22 | .highlight .gp { color: #aaaaaa } /* Generic.Prompt */ 23 | .highlight .gs { color: #d0d0d0; font-weight: normal } /* Generic.Strong */ 24 | .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ 25 | .highlight .gt { color: #d22323 } /* Generic.Traceback */ 26 | .highlight .kc { color: #6ab825; font-weight: normal } /* Keyword.Constant */ 27 | .highlight .kd { color: #6ab825; font-weight: normal } /* Keyword.Declaration */ 28 | .highlight .kn { color: #6ab825; font-weight: normal } /* Keyword.Namespace */ 29 | .highlight .kp { color: #6ab825 } /* Keyword.Pseudo */ 30 | .highlight .kr { color: #6ab825; font-weight: normal } /* Keyword.Reserved */ 31 | .highlight .kt { color: #6ab825; font-weight: normal } /* Keyword.Type */ 32 | .highlight .ld { color: #d0d0d0 } /* Literal.Date */ 33 | .highlight .m { color: #3677a9 } /* Literal.Number */ 34 | .highlight .s { color: #ff8 } /* Literal.String */ 35 | .highlight .na { color: #bbbbbb } /* Name.Attribute */ 36 | .highlight .nb { color: #24909d } /* Name.Builtin */ 37 | .highlight .nc { color: #447fcf; text-decoration: underline } /* Name.Class */ 38 | .highlight .no { color: #40ffff } /* Name.Constant */ 39 | .highlight .nd { color: #ffa500 } /* Name.Decorator */ 40 | .highlight .ni { color: #d0d0d0 } /* Name.Entity */ 41 | .highlight .ne { color: #bbbbbb } /* Name.Exception */ 42 | .highlight .nf { color: #447fcf } /* Name.Function */ 43 | .highlight .nl { color: #d0d0d0 } /* Name.Label */ 44 | .highlight .nn { color: #447fcf; text-decoration: underline } /* Name.Namespace */ 45 | .highlight .nx { color: #d0d0d0 } /* Name.Other */ 46 | .highlight .py { color: #d0d0d0 } /* Name.Property */ 47 | .highlight .nt { color: #6ab825;} /* Name.Tag */ 48 | .highlight .nv { color: #40ffff } /* Name.Variable */ 49 | .highlight .ow { color: #6ab825; font-weight: normal } /* Operator.Word */ 50 | .highlight .w { color: #666666 } /* Text.Whitespace */ 51 | .highlight .mf { color: #3677a9 } /* Literal.Number.Float */ 52 | .highlight .mh { color: #3677a9 } /* Literal.Number.Hex */ 53 | .highlight .mi { color: #3677a9 } /* Literal.Number.Integer */ 54 | .highlight .mo { color: #3677a9 } /* Literal.Number.Oct */ 55 | .highlight .sb { color: #ff8 } /* Literal.String.Backtick */ 56 | .highlight .sc { color: #ff8 } /* Literal.String.Char */ 57 | .highlight .sd { color: #ff8 } /* Literal.String.Doc */ 58 | .highlight .s2 { color: #ff8 } /* Literal.String.Double */ 59 | .highlight .se { color: #ff8 } /* Literal.String.Escape */ 60 | .highlight .sh { color: #ff8 } /* Literal.String.Heredoc */ 61 | .highlight .si { color: #ff8 } /* Literal.String.Interpol */ 62 | .highlight .sx { color: #ffa500 } /* Literal.String.Other */ 63 | .highlight .sr { color: #ff8 } /* Literal.String.Regex */ 64 | .highlight .s1 { color: #ff8 } /* Literal.String.Single */ 65 | .highlight .ss { color: #ff8 } /* Literal.String.Symbol */ 66 | .highlight .bp { color: #24909d } /* Name.Builtin.Pseudo */ 67 | .highlight .vc { color: #40ffff } /* Name.Variable.Class */ 68 | .highlight .vg { color: #40ffff } /* Name.Variable.Global */ 69 | .highlight .vi { color: #40ffff } /* Name.Variable.Instance */ 70 | .highlight .il { color: #3677a9 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /examples/tooltip.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 32 | 33 | 34 | 35 |
36 |
37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 |
54 |
55 |
56 | 111 | 112 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 11 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /meteor/export.js: -------------------------------------------------------------------------------- 1 | /*global nv:true*/ // Meteor creates a file-scope global for exporting. This comment prevents a potential JSHint warning. 2 | nv = window.nv; 3 | delete window.nv; 4 | 5 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | // Package metadata for Meteor.js full stack web framework 2 | // This file is defined in Meteor documentation at http://docs.meteor.com/#/full/packagejs 3 | // and used by Meteor https://www.meteor.com/ and its package repository Atmosphere https://atmospherejs.com 4 | 5 | Package.describe({ 6 | "name": 'nvd3:nvd3', 7 | summary: 'Nvd3.org charts.', 8 | version: '1.8.6-dev', 9 | git: "https://github.com/novus/nvd3.git" 10 | }); 11 | Package.on_use(function (api) { 12 | api.versionsFrom("METEOR@1.0"); 13 | api.use('d3js:d3@3.5.5', 'client'); 14 | api.add_files('build/nv.d3.js', 'client'); 15 | api.add_files('build/nv.d3.css', 'client'); 16 | api.add_files('meteor/export.js', 'client'); 17 | api.export("nv"); 18 | }); 19 | Package.onTest(function(api) { 20 | api.use(['tinytest', 'test-helpers']); 21 | api.use('d3js:d3', 'client'); 22 | api.addFiles(['build/nv.d3.js', 'meteor/export.js'], "client"); 23 | api.addFiles('test/tinytest/nv-is-defined-test.js', "client"); 24 | }); 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nvd3", 3 | "version": "1.8.6-dev", 4 | "description": "A reusable charting library written in d3.js", 5 | "url": "https://github.com/novus/nvd3", 6 | "main": "build/nv.d3.js", 7 | "scripts": { 8 | "test": "grunt", 9 | "build": "grunt" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/novus/nvd3" 14 | }, 15 | "keywords": [ 16 | "nvd3", 17 | "d3", 18 | "chart", 19 | "graph" 20 | ], 21 | "readmeFilename": "README.md", 22 | "license": "Apache-2.0", 23 | "peerDependencies": { 24 | "d3": "^3.4.4" 25 | }, 26 | "devDependencies": { 27 | "autoprefixer": "^6.5.0", 28 | "es6-promise": "^4.0.3", 29 | "grunt": "^0.4.5", 30 | "grunt-cli": "^1.2.0", 31 | "grunt-contrib-concat": "~1.0.1", 32 | "grunt-contrib-copy": "~0.4.1", 33 | "grunt-contrib-cssmin": "~0.13.0", 34 | "grunt-contrib-jshint": "^0.11.0", 35 | "grunt-contrib-uglify": "~0.9.1", 36 | "grunt-contrib-watch": "~0.3.1", 37 | "grunt-karma": "^0.9.0", 38 | "grunt-postcss": "^0.8.0", 39 | "grunt-text-replace": "^0.4.0", 40 | "karma": "^0.12.23", 41 | "karma-chrome-launcher": "^0.1.4", 42 | "karma-coffee-preprocessor": "^0.2.1", 43 | "karma-coverage": "^0.2.6", 44 | "karma-firefox-launcher": "^0.1.4", 45 | "karma-junit-reporter": "^0.2.2", 46 | "karma-mocha": "^0.1.9", 47 | "karma-sinon-chai": "^0.2.0", 48 | "karma-spec-reporter": "0.0.13", 49 | "mocha": "^1.21.4", 50 | "moment": "^2.18.1" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/css/axis.css: -------------------------------------------------------------------------------- 1 | .nvd3 .nv-axis { 2 | pointer-events:none; 3 | opacity: 1; 4 | } 5 | 6 | .nvd3 .nv-axis path { 7 | fill: none; 8 | stroke: #000; 9 | stroke-opacity: .75; 10 | shape-rendering: crispEdges; 11 | } 12 | 13 | .nvd3 .nv-axis path.domain { 14 | stroke-opacity: .75; 15 | } 16 | 17 | .nvd3 .nv-axis.nv-x path.domain { 18 | stroke-opacity: 0; 19 | } 20 | 21 | .nvd3 .nv-axis line { 22 | fill: none; 23 | stroke: #e5e5e5; 24 | shape-rendering: crispEdges; 25 | } 26 | 27 | .nvd3 .nv-axis .zero line, 28 | /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { 29 | stroke-opacity: .75; 30 | } 31 | 32 | .nvd3 .nv-axis .nv-axisMaxMin text { 33 | font-weight: bold; 34 | } 35 | 36 | .nvd3 .x .nv-axis .nv-axisMaxMin text, 37 | .nvd3 .x2 .nv-axis .nv-axisMaxMin text, 38 | .nvd3 .x3 .nv-axis .nv-axisMaxMin text { 39 | text-anchor: middle; 40 | } 41 | 42 | .nvd3 .nv-axis.nv-disabled { 43 | opacity: 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/css/bars.css: -------------------------------------------------------------------------------- 1 | .nvd3 .nv-bars rect { 2 | fill-opacity: .75; 3 | 4 | transition: fill-opacity 250ms linear; 5 | } 6 | 7 | .nvd3 .nv-bars rect.hover { 8 | fill-opacity: 1; 9 | } 10 | 11 | .nvd3 .nv-bars .hover rect { 12 | fill: lightblue; 13 | } 14 | 15 | .nvd3 .nv-bars text { 16 | fill: rgba(0,0,0,0); 17 | } 18 | 19 | .nvd3 .nv-bars .hover text { 20 | fill: rgba(0,0,0,1); 21 | } 22 | 23 | .nvd3 .nv-multibar .nv-groups rect, 24 | .nvd3 .nv-multibarHorizontal .nv-groups rect, 25 | .nvd3 .nv-discretebar .nv-groups rect { 26 | stroke-opacity: 0; 27 | 28 | transition: fill-opacity 250ms linear; 29 | } 30 | 31 | .nvd3 .nv-multibar .nv-groups rect:hover, 32 | .nvd3 .nv-multibarHorizontal .nv-groups rect:hover, 33 | .nvd3 .nv-candlestickBar .nv-ticks rect:hover, 34 | .nvd3 .nv-discretebar .nv-groups rect:hover { 35 | fill-opacity: 1; 36 | } 37 | 38 | .nvd3 .nv-discretebar .nv-groups text, 39 | .nvd3 .nv-multibarHorizontal .nv-groups text { 40 | font-weight: bold; 41 | fill: rgba(0,0,0,1); 42 | stroke: rgba(0,0,0,0); 43 | } 44 | -------------------------------------------------------------------------------- /src/css/boxplot.css: -------------------------------------------------------------------------------- 1 | /* boxplot CSS */ 2 | .nvd3 .nv-boxplot circle { 3 | fill-opacity: 0.5; 4 | } 5 | 6 | .nvd3 .nv-boxplot circle:hover { 7 | fill-opacity: 1; 8 | } 9 | 10 | .nvd3 .nv-boxplot rect:hover { 11 | fill-opacity: 1; 12 | } 13 | 14 | .nvd3 line.nv-boxplot-median { 15 | stroke: black; 16 | } 17 | 18 | .nv-boxplot-tick:hover { 19 | stroke-width: 2.5px; 20 | } -------------------------------------------------------------------------------- /src/css/bullet.css: -------------------------------------------------------------------------------- 1 | /* bullet */ 2 | .nvd3.nv-bullet { font: 10px sans-serif; } 3 | .nvd3.nv-bullet .nv-measure { fill-opacity: .8; } 4 | .nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } 5 | .nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } 6 | .nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } 7 | .nvd3.nv-bullet .nv-markerLine { stroke: #000; stroke-width: 1.5px; } 8 | .nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } 9 | .nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } 10 | .nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } 11 | .nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } 12 | .nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } 13 | .nvd3.nv-bullet .nv-subtitle { fill: #999; } 14 | 15 | .nvd3.nv-bullet .nv-range { 16 | fill: #bababa; 17 | fill-opacity: .4; 18 | } 19 | 20 | .nvd3.nv-bullet .nv-range:hover { 21 | fill-opacity: .7; 22 | } 23 | -------------------------------------------------------------------------------- /src/css/candlestick.css: -------------------------------------------------------------------------------- 1 | .nvd3.nv-candlestickBar .nv-ticks .nv-tick { 2 | stroke-width: 1px; 3 | } 4 | 5 | .nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { 6 | stroke-width: 2px; 7 | } 8 | 9 | .nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { 10 | stroke: #2ca02c; 11 | fill: #2ca02c; 12 | } 13 | 14 | .nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { 15 | stroke: #d62728; 16 | fill: #d62728; 17 | } 18 | 19 | .with-transitions .nv-candlestickBar .nv-ticks .nv-tick { 20 | transition: stroke-width 250ms linear, stroke-opacity 250ms linear; 21 | } 22 | 23 | .nvd3.nv-candlestickBar .nv-ticks line { 24 | stroke: #333; 25 | } 26 | -------------------------------------------------------------------------------- /src/css/forceDirectedGraph.css: -------------------------------------------------------------------------------- 1 | .nv-force-node { 2 | stroke: #fff; 3 | stroke-width: 1.5px; 4 | } 5 | 6 | .nv-force-link { 7 | stroke: #999; 8 | stroke-opacity: .6; 9 | } 10 | 11 | .nv-force-node text { 12 | stroke-width: 0px; 13 | } 14 | -------------------------------------------------------------------------------- /src/css/furiousLegend.css: -------------------------------------------------------------------------------- 1 | .nvd3 .nv-legend .nv-disabled rect { 2 | /*fill-opacity: 0;*/ 3 | } 4 | 5 | .nvd3 .nv-check-box .nv-box { 6 | fill-opacity:0; 7 | stroke-width:2; 8 | } 9 | 10 | .nvd3 .nv-check-box .nv-check { 11 | fill-opacity:0; 12 | stroke-width:4; 13 | } 14 | 15 | .nvd3 .nv-series.nv-disabled .nv-check-box .nv-check { 16 | fill-opacity:0; 17 | stroke-opacity:0; 18 | } 19 | 20 | .nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check { 21 | opacity: 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/css/lineplusbar.css: -------------------------------------------------------------------------------- 1 | /* line plus bar */ 2 | .nvd3.nv-linePlusBar .nv-bar rect { 3 | fill-opacity: .75; 4 | } 5 | 6 | .nvd3.nv-linePlusBar .nv-bar rect:hover { 7 | fill-opacity: 1; 8 | } -------------------------------------------------------------------------------- /src/css/lines.css: -------------------------------------------------------------------------------- 1 | .nvd3 .nv-groups path.nv-line { 2 | fill: none; 3 | } 4 | 5 | .nvd3 .nv-groups path.nv-area { 6 | stroke: none; 7 | } 8 | 9 | .nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { 10 | fill-opacity: 0; 11 | stroke-opacity: 0; 12 | } 13 | 14 | .nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { 15 | fill-opacity: .5 !important; 16 | stroke-opacity: .5 !important; 17 | } 18 | 19 | 20 | .with-transitions .nvd3 .nv-groups .nv-point { 21 | transition: stroke-width 250ms linear, stroke-opacity 250ms linear; 22 | } 23 | 24 | .nvd3.nv-scatter .nv-groups .nv-point.hover, 25 | .nvd3 .nv-groups .nv-point.hover { 26 | stroke-width: 7px; 27 | fill-opacity: .95 !important; 28 | stroke-opacity: .95 !important; 29 | } 30 | 31 | 32 | .nvd3 .nv-point-paths path { 33 | stroke: #aaa; 34 | stroke-opacity: 0; 35 | fill: #eee; 36 | fill-opacity: 0; 37 | } 38 | 39 | 40 | .nvd3 .nv-indexLine { 41 | cursor: ew-resize; 42 | } 43 | -------------------------------------------------------------------------------- /src/css/main.css: -------------------------------------------------------------------------------- 1 | /******************** 2 | * SVG CSS 3 | */ 4 | 5 | /******************** 6 | Default CSS for an svg element nvd3 used 7 | */ 8 | svg.nvd3-svg { 9 | user-select: none; 10 | display: block; 11 | width:100%; 12 | height:100%; 13 | } 14 | 15 | /******************** 16 | Box shadow and border radius styling 17 | */ 18 | .nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { 19 | box-shadow: 0 5px 10px rgba(0,0,0,.2); 20 | border-radius: 5px; 21 | } 22 | 23 | 24 | .nvd3 text { 25 | font: normal 12px Arial, sans-serif; 26 | } 27 | 28 | .nvd3 .title { 29 | font: bold 14px Arial, sans-serif; 30 | } 31 | 32 | .nvd3 .nv-background { 33 | fill: white; 34 | fill-opacity: 0; 35 | } 36 | 37 | .nvd3.nv-noData { 38 | font-size: 18px; 39 | font-weight: bold; 40 | } 41 | 42 | 43 | /********** 44 | * Brush 45 | */ 46 | 47 | .nv-brush .extent { 48 | fill-opacity: .125; 49 | shape-rendering: crispEdges; 50 | } 51 | 52 | .nv-brush .resize path { 53 | fill: #eee; 54 | stroke: #666; 55 | } 56 | 57 | 58 | /********** 59 | * Legend 60 | */ 61 | 62 | .nvd3 .nv-legend .nv-series { 63 | cursor: pointer; 64 | } 65 | 66 | .nvd3 .nv-legend .nv-disabled circle { 67 | fill-opacity: 0; 68 | } 69 | 70 | /* focus */ 71 | .nvd3 .nv-brush .extent { 72 | fill-opacity: 0 !important; 73 | } 74 | 75 | .nvd3 .nv-brushBackground rect { 76 | stroke: #000; 77 | stroke-width: .4; 78 | fill: #fff; 79 | fill-opacity: .7; 80 | } 81 | 82 | /********** 83 | * Print 84 | */ 85 | 86 | @media print { 87 | .nvd3 text { 88 | stroke-width: 0; 89 | fill-opacity: 1; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/css/ohlc.css: -------------------------------------------------------------------------------- 1 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick { 2 | stroke-width: 1px; 3 | } 4 | 5 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { 6 | stroke-width: 2px; 7 | } 8 | 9 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { 10 | stroke: #2ca02c; 11 | } 12 | 13 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { 14 | stroke: #d62728; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/css/parallelcoordinates.css: -------------------------------------------------------------------------------- 1 | .nvd3 .background path { 2 | fill: none; 3 | stroke: #EEE; 4 | stroke-opacity: .4; 5 | shape-rendering: crispEdges; 6 | } 7 | 8 | .nvd3 .foreground path { 9 | fill: none; 10 | stroke-opacity: .7; 11 | } 12 | 13 | .nvd3 .nv-parallelCoordinates-brush .extent { 14 | fill: #fff; 15 | fill-opacity: .6; 16 | stroke: gray; 17 | shape-rendering: crispEdges; 18 | } 19 | 20 | .nvd3 .nv-parallelCoordinates .hover { 21 | fill-opacity: 1; 22 | stroke-width: 3px; 23 | } 24 | 25 | 26 | .nvd3 .missingValuesline line { 27 | fill: none; 28 | stroke: black; 29 | stroke-width: 1; 30 | stroke-opacity: 1; 31 | stroke-dasharray: 5, 5; 32 | } 33 | -------------------------------------------------------------------------------- /src/css/pie.css: -------------------------------------------------------------------------------- 1 | .nvd3.nv-pie path { 2 | stroke-opacity: 0; 3 | transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; 4 | } 5 | 6 | .nvd3.nv-pie .nv-pie-title { 7 | font-size: 24px; 8 | fill: rgba(19, 196, 249, 0.59); 9 | } 10 | 11 | .nvd3.nv-pie .nv-slice text { 12 | stroke: #000; 13 | stroke-width: 0; 14 | } 15 | 16 | .nvd3.nv-pie path { 17 | stroke: #fff; 18 | stroke-width: 1px; 19 | stroke-opacity: 1; 20 | } 21 | 22 | .nvd3.nv-pie path { 23 | fill-opacity: .7; 24 | } 25 | 26 | .nvd3.nv-pie .hover path { 27 | fill-opacity: 1; 28 | } 29 | 30 | .nvd3.nv-pie .nv-label { 31 | pointer-events: none; 32 | } 33 | 34 | .nvd3.nv-pie .nv-label rect { 35 | fill-opacity: 0; 36 | stroke-opacity: 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/css/scatter.css: -------------------------------------------------------------------------------- 1 | /* scatter */ 2 | .nvd3 .nv-groups .nv-point.hover { 3 | stroke-width: 20px; 4 | stroke-opacity: .5; 5 | } 6 | 7 | .nvd3 .nv-scatter .nv-point.hover { 8 | fill-opacity: 1; 9 | } 10 | 11 | .nv-noninteractive { 12 | pointer-events: none; 13 | } 14 | 15 | .nv-distx, .nv-disty { 16 | pointer-events: none; 17 | } 18 | -------------------------------------------------------------------------------- /src/css/sparkline.css: -------------------------------------------------------------------------------- 1 | /* sparkline */ 2 | .nvd3.nv-sparkline path { 3 | fill: none; 4 | } 5 | 6 | .nvd3.nv-sparklineplus g.nv-hoverValue { 7 | pointer-events: none; 8 | } 9 | 10 | .nvd3.nv-sparklineplus .nv-hoverValue line { 11 | stroke: #333; 12 | stroke-width: 1.5px; 13 | } 14 | 15 | .nvd3.nv-sparklineplus, 16 | .nvd3.nv-sparklineplus g { 17 | pointer-events: all; 18 | } 19 | 20 | .nvd3 .nv-hoverArea { 21 | fill-opacity: 0; 22 | stroke-opacity: 0; 23 | } 24 | 25 | .nvd3.nv-sparklineplus .nv-xValue, 26 | .nvd3.nv-sparklineplus .nv-yValue { 27 | stroke-width: 0; 28 | font-size: .9em; 29 | font-weight: normal; 30 | } 31 | 32 | .nvd3.nv-sparklineplus .nv-yValue { 33 | stroke: #f66; 34 | } 35 | 36 | .nvd3.nv-sparklineplus .nv-maxValue { 37 | stroke: #2ca02c; 38 | fill: #2ca02c; 39 | } 40 | 41 | .nvd3.nv-sparklineplus .nv-minValue { 42 | stroke: #d62728; 43 | fill: #d62728; 44 | } 45 | 46 | .nvd3.nv-sparklineplus .nv-currentValue { 47 | font-weight: bold; 48 | font-size: 1.1em; 49 | } -------------------------------------------------------------------------------- /src/css/stackedarea.css: -------------------------------------------------------------------------------- 1 | /* stacked area */ 2 | .nvd3.nv-stackedarea path.nv-area { 3 | fill-opacity: .7; 4 | stroke-opacity: 0; 5 | transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; 6 | } 7 | 8 | .nvd3.nv-stackedarea path.nv-area.hover { 9 | fill-opacity: .9; 10 | } 11 | 12 | 13 | .nvd3.nv-stackedarea .nv-groups .nv-point { 14 | stroke-opacity: 0; 15 | fill-opacity: 0; 16 | } 17 | -------------------------------------------------------------------------------- /src/css/tooltip.css: -------------------------------------------------------------------------------- 1 | .nvtooltip { 2 | position: absolute; 3 | background-color: rgba(255,255,255,1.0); 4 | color: rgba(0,0,0,1.0); 5 | padding: 1px; 6 | border: 1px solid rgba(0,0,0,.2); 7 | z-index: 10000; 8 | display: block; 9 | 10 | font-family: Arial, sans-serif; 11 | font-size: 13px; 12 | text-align: left; 13 | pointer-events: none; 14 | 15 | white-space: nowrap; 16 | 17 | user-select: none; 18 | } 19 | 20 | .nvtooltip { 21 | background: rgba(255,255,255, 0.8); 22 | border: 1px solid rgba(0,0,0,0.5); 23 | border-radius: 4px; 24 | } 25 | 26 | /*Give tooltips that old fade in transition by 27 | putting a "with-transitions" class on the container div. 28 | */ 29 | .nvtooltip.with-transitions, .with-transitions .nvtooltip { 30 | transition: opacity 50ms linear; 31 | 32 | transition-delay: 200ms; 33 | } 34 | 35 | .nvtooltip.x-nvtooltip, 36 | .nvtooltip.y-nvtooltip { 37 | padding: 8px; 38 | } 39 | 40 | .nvtooltip h3 { 41 | margin: 0; 42 | padding: 4px 14px; 43 | line-height: 18px; 44 | font-weight: normal; 45 | background-color: rgba(247,247,247,0.75); 46 | color: rgba(0,0,0,1.0); 47 | text-align: center; 48 | 49 | border-bottom: 1px solid #ebebeb; 50 | 51 | border-radius: 5px 5px 0 0; 52 | } 53 | 54 | .nvtooltip p { 55 | margin: 0; 56 | padding: 5px 14px; 57 | text-align: center; 58 | } 59 | 60 | .nvtooltip span { 61 | display: inline-block; 62 | margin: 2px 0; 63 | } 64 | 65 | .nvtooltip table { 66 | margin: 6px; 67 | border-spacing:0; 68 | } 69 | 70 | 71 | .nvtooltip table td { 72 | padding: 2px 9px 2px 0; 73 | vertical-align: middle; 74 | } 75 | 76 | .nvtooltip table td.key { 77 | font-weight: normal; 78 | } 79 | 80 | .nvtooltip table td.key.total { 81 | font-weight: bold; 82 | } 83 | 84 | .nvtooltip table td.value { 85 | text-align: right; 86 | font-weight: bold; 87 | } 88 | 89 | .nvtooltip table td.percent { 90 | color: darkgray; 91 | } 92 | 93 | .nvtooltip table tr.highlight td { 94 | padding: 1px 9px 1px 0; 95 | border-bottom-style: solid; 96 | border-bottom-width: 1px; 97 | border-top-style: solid; 98 | border-top-width: 1px; 99 | } 100 | 101 | .nvtooltip table td.legend-color-guide div { 102 | width: 8px; 103 | height: 8px; 104 | vertical-align: middle; 105 | } 106 | 107 | .nvtooltip table td.legend-color-guide div { 108 | width: 12px; 109 | height: 12px; 110 | border: 1px solid #999; 111 | } 112 | 113 | .nvtooltip .footer { 114 | padding: 3px; 115 | text-align: center; 116 | } 117 | 118 | .nvtooltip-pending-removal { 119 | pointer-events: none; 120 | display: none; 121 | } 122 | 123 | 124 | /**** 125 | Interactive Layer 126 | */ 127 | .nvd3 .nv-interactiveGuideLine { 128 | pointer-events:none; 129 | } 130 | 131 | .nvd3 line.nv-guideline { 132 | stroke: #ccc; 133 | } 134 | -------------------------------------------------------------------------------- /src/dom.js: -------------------------------------------------------------------------------- 1 | /* Facade for queueing DOM write operations 2 | * with Fastdom (https://github.com/wilsonpage/fastdom) 3 | * if available. 4 | * This could easily be extended to support alternate 5 | * implementations in the future. 6 | */ 7 | nv.dom.write = function(callback) { 8 | if (window.fastdom !== undefined) { 9 | return fastdom.mutate(callback); 10 | } 11 | return callback(); 12 | }; 13 | 14 | /* Facade for queueing DOM read operations 15 | * with Fastdom (https://github.com/wilsonpage/fastdom) 16 | * if available. 17 | * This could easily be extended to support alternate 18 | * implementations in the future. 19 | */ 20 | nv.dom.read = function(callback) { 21 | if (window.fastdom !== undefined) { 22 | return fastdom.measure(callback); 23 | } 24 | return callback(); 25 | }; 26 | -------------------------------------------------------------------------------- /src/models/sunburstChart.js: -------------------------------------------------------------------------------- 1 | nv.models.sunburstChart = function() { 2 | "use strict"; 3 | 4 | //============================================================ 5 | // Public Variables with Default Settings 6 | //------------------------------------------------------------ 7 | 8 | var sunburst = nv.models.sunburst(); 9 | var tooltip = nv.models.tooltip(); 10 | 11 | var margin = {top: 30, right: 20, bottom: 20, left: 20} 12 | , width = null 13 | , height = null 14 | , color = nv.utils.defaultColor() 15 | , showTooltipPercent = false 16 | , id = Math.round(Math.random() * 100000) 17 | , defaultState = null 18 | , noData = null 19 | , duration = 250 20 | , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd'); 21 | 22 | 23 | //============================================================ 24 | // Private Variables 25 | //------------------------------------------------------------ 26 | 27 | var renderWatch = nv.utils.renderWatch(dispatch); 28 | 29 | tooltip 30 | .duration(0) 31 | .headerEnabled(false) 32 | .valueFormatter(function(d){return d;}); 33 | 34 | //============================================================ 35 | // Chart function 36 | //------------------------------------------------------------ 37 | 38 | function chart(selection) { 39 | renderWatch.reset(); 40 | renderWatch.models(sunburst); 41 | 42 | selection.each(function(data) { 43 | var container = d3.select(this); 44 | 45 | nv.utils.initSVG(container); 46 | 47 | var availableWidth = nv.utils.availableWidth(width, container, margin); 48 | var availableHeight = nv.utils.availableHeight(height, container, margin); 49 | 50 | chart.update = function() { 51 | if (duration === 0) { 52 | container.call(chart); 53 | } else { 54 | container.transition().duration(duration).call(chart); 55 | } 56 | }; 57 | chart.container = container; 58 | 59 | // Display No Data message if there's nothing to show. 60 | if (!data || !data.length) { 61 | nv.utils.noData(chart, container); 62 | return chart; 63 | } else { 64 | container.selectAll('.nv-noData').remove(); 65 | } 66 | 67 | sunburst.width(availableWidth).height(availableHeight).margin(margin); 68 | container.call(sunburst); 69 | }); 70 | 71 | renderWatch.renderEnd('sunburstChart immediate'); 72 | return chart; 73 | } 74 | 75 | //============================================================ 76 | // Event Handling/Dispatching (out of chart's scope) 77 | //------------------------------------------------------------ 78 | 79 | sunburst.dispatch.on('elementMouseover.tooltip', function(evt) { 80 | evt.series = { 81 | key: evt.data.name, 82 | value: (evt.data.value || evt.data.size), 83 | color: evt.color, 84 | percent: evt.percent 85 | }; 86 | if (!showTooltipPercent) { 87 | delete evt.percent; 88 | delete evt.series.percent; 89 | } 90 | tooltip.data(evt).hidden(false); 91 | }); 92 | 93 | sunburst.dispatch.on('elementMouseout.tooltip', function(evt) { 94 | tooltip.hidden(true); 95 | }); 96 | 97 | sunburst.dispatch.on('elementMousemove.tooltip', function(evt) { 98 | tooltip(); 99 | }); 100 | 101 | //============================================================ 102 | // Expose Public Variables 103 | //------------------------------------------------------------ 104 | 105 | // expose chart's sub-components 106 | chart.dispatch = dispatch; 107 | chart.sunburst = sunburst; 108 | chart.tooltip = tooltip; 109 | chart.options = nv.utils.optionsFunc.bind(chart); 110 | 111 | // use Object get/set functionality to map between vars and chart functions 112 | chart._options = Object.create({}, { 113 | // simple options, just get/set the necessary values 114 | noData: {get: function(){return noData;}, set: function(_){noData=_;}}, 115 | defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, 116 | showTooltipPercent: {get: function(){return showTooltipPercent;}, set: function(_){showTooltipPercent=_;}}, 117 | 118 | // options that require extra logic in the setter 119 | color: {get: function(){return color;}, set: function(_){ 120 | color = _; 121 | sunburst.color(color); 122 | }}, 123 | duration: {get: function(){return duration;}, set: function(_){ 124 | duration = _; 125 | renderWatch.reset(duration); 126 | sunburst.duration(duration); 127 | }}, 128 | margin: {get: function(){return margin;}, set: function(_){ 129 | margin.top = _.top !== undefined ? _.top : margin.top; 130 | margin.right = _.right !== undefined ? _.right : margin.right; 131 | margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; 132 | margin.left = _.left !== undefined ? _.left : margin.left; 133 | sunburst.margin(margin); 134 | }} 135 | }); 136 | nv.utils.inheritOptions(chart, sunburst); 137 | nv.utils.initOptions(chart); 138 | return chart; 139 | 140 | }; 141 | -------------------------------------------------------------------------------- /test/bootstrapModalTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

Noraml Example

15 |
16 | 17 |

Modal Example

18 |
19 | Launch Modal 20 |
21 | 22 | 34 |
35 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /test/lineWithFisheyeChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 33 | 34 | 35 |
36 | 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 104 | -------------------------------------------------------------------------------- /test/lineWithFocusChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 33 | 34 | 35 |
36 | 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 90 | -------------------------------------------------------------------------------- /test/lineWithFocusChartMissingData.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 78 | 79 | -------------------------------------------------------------------------------- /test/mocha/axis.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Axis', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | [-1,-1] 7 | [0,0] 8 | [1,1] 9 | [2,2] 10 | ] 11 | ] 12 | 13 | options = 14 | x: (d)-> d[0] 15 | y: (d)-> d[1] 16 | 17 | axisOptions = 18 | margin: 19 | top: 0 20 | right: 0 21 | bottom: 0 22 | left: 0 23 | width: 75 24 | height: 60 25 | axisLabel: 'Date' 26 | showMaxMin: true 27 | scale: d3.scale.linear() 28 | rotateYLabel: true 29 | rotateLabels: 0 30 | staggerLabels: false 31 | axisLabelDistance: 12 32 | duration: 0 33 | 34 | builder = null 35 | beforeEach -> 36 | builder = new ChartBuilder nv.models.lineChart() 37 | builder.build options, sampleData1 38 | 39 | axis = builder.model.xAxis 40 | for opt, val of axisOptions 41 | axis[opt](val) 42 | 43 | builder.model.update() 44 | 45 | afterEach -> 46 | builder.teardown() 47 | 48 | it 'api check', -> 49 | axis = builder.model.xAxis 50 | 51 | for opt, val of axisOptions 52 | should.exist axis[opt](), "#{opt} can be called" 53 | 54 | it 'x axis structure', -> 55 | axis = builder.$ '.nv-x.nv-axis' 56 | 57 | should.exist axis[0], '.nv-axis exists' 58 | 59 | maxMin = builder.$ '.nv-x.nv-axis .nv-axisMaxMin' 60 | 61 | maxMin.should.have.length 2 62 | 63 | maxMin[0].textContent.should.equal '-1' 64 | maxMin[1].textContent.should.equal '2' 65 | 66 | ticks = builder.$ '.nv-x.nv-axis .tick' 67 | 68 | ticks.should.have.length 2 69 | 70 | expected = [ 71 | '0' 72 | '1' 73 | ] 74 | 75 | for tick,i in ticks 76 | tick.textContent.should.equal expected[i] 77 | 78 | axisLabel = builder.$ '.nv-x.nv-axis .nv-axislabel' 79 | should.exist axisLabel[0], 'axis label exists' 80 | axisLabel[0].textContent.should.equal 'Date' 81 | 82 | it 'y axis structure', -> 83 | axis = builder.$ '.nv-y.nv-axis' 84 | 85 | should.exist axis[0], '.nv-axis exists' 86 | 87 | maxMin = builder.$ '.nv-y.nv-axis .nv-axisMaxMin' 88 | 89 | maxMin.should.have.length 2 90 | 91 | maxMin[0].textContent.should.equal '-1' 92 | maxMin[1].textContent.should.equal '2' 93 | 94 | ticks = builder.$ '.nv-y.nv-axis .tick' 95 | 96 | ticks.should.have.length 4 97 | 98 | expected = [ 99 | '-1' 100 | '0' 101 | '1' 102 | '2' 103 | ] 104 | 105 | for tick,i in ticks 106 | tick.textContent.should.equal expected[i] 107 | 108 | it 'axis rotate labels', -> 109 | axis = builder.model.xAxis 110 | axis.rotateLabels 30 111 | builder.model.update() 112 | 113 | ticks = builder.$ '.nv-x.nv-axis .tick text' 114 | 115 | for tick in ticks 116 | transform = tick.getAttribute 'transform' 117 | transform.should.match /rotate\(30 0,\d+?.*?\)/ 118 | 119 | maxMin = builder.$ '.nv-x.nv-axis .nv-axisMaxMin text' 120 | 121 | for tick in maxMin 122 | transform = tick.getAttribute 'transform' 123 | transform.should.match /rotate\(30 0,\d+?.*?\)/ 124 | 125 | it 'axis stagger labels', -> 126 | axis = builder.model.xAxis 127 | axis.staggerLabels true 128 | builder.model.update() 129 | 130 | ticks = builder.$ '.nv-x.nv-axis .tick text' 131 | 132 | prevTransform = '' 133 | for tick, i in ticks 134 | transform = tick.getAttribute 'transform' 135 | 136 | transform.should.not.equal prevTransform 137 | transform.should.match /translate\(0,(12|0)\)/ 138 | prevTransform = transform 139 | 140 | it 'axis orientation', (done)-> 141 | axis = builder.model.xAxis 142 | axis.orient 'top' 143 | builder.model.update() 144 | 145 | axis.orient 'right' 146 | builder.model.update() 147 | 148 | done() 149 | 150 | it 'has CSS class "zero" to mark zero tick', -> 151 | tick = builder.$ '.nv-x.nv-axis .tick.zero' 152 | tick.length.should.equal 1, 'x axis zero' 153 | 154 | tick = builder.$ '.nv-y.nv-axis .tick.zero' 155 | tick.length.should.equal 1, 'y axis zero' 156 | 157 | it 'default tick format for max/min should be integer based', -> 158 | axis = builder.model.xAxis 159 | builder.model.update() 160 | minAxisText = builder.$('.nv-axisMaxMin.nv-axisMaxMin-x.nv-axisMin-x text')[0].textContent 161 | 162 | minAxisText.should.equal('-1') 163 | 164 | it 'tickFormatMaxMin should change tick format of max/min', -> 165 | axis = builder.model.xAxis 166 | axis.tickFormatMaxMin(d3.format(',.2f')) 167 | builder.model.update() 168 | minAxisText = builder.$('.nv-axisMaxMin.nv-axisMaxMin-x.nv-axisMin-x text')[0].textContent 169 | 170 | minAxisText.should.equal('-1.00') 171 | -------------------------------------------------------------------------------- /test/mocha/boxplot.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Box Plot', -> 3 | sampleData1 = [ 4 | label: 'Sample A', 5 | values: 6 | Q1: 120, 7 | Q2: 150, 8 | Q3: 200, 9 | whisker_low: 115, 10 | whisker_high: 210, 11 | outliers: [50, 100, 225] 12 | ] 13 | 14 | sampleData2 = [ 15 | label: 'Sample A', 16 | values: 17 | Q1: 120, 18 | Q2: 150, 19 | Q3: 200, 20 | whisker_low: 115, 21 | whisker_high: 210, 22 | outliers: [] 23 | ] 24 | 25 | sampleData3 = [ 26 | { 27 | label: 'Sample A', 28 | values: { Q1: 120, Q2: 150, Q3: 200, whisker_low: 115, whisker_high: 210, outliers: [50, 100, 225] } 29 | }, 30 | { 31 | label: 'Sample B', 32 | values: { Q1: 300, Q2: 350, Q3: 400, whisker_low: 2255, whisker_high: 400, outliers: [175] } 33 | } 34 | ] 35 | 36 | sampleData4 = [ 37 | label: 'Sample A', 38 | values: 39 | Q1: -3, 40 | Q2: -2, 41 | Q3: -1, 42 | whisker_low: -5, 43 | whisker_high: 0, 44 | outliers: [-10, 10] 45 | ] 46 | 47 | options = 48 | x: (d)-> d.label 49 | y: (d)-> d.values.Q3 50 | margin: 51 | top: 30 52 | right: 20 53 | bottom: 50 54 | left: 75 55 | color: nv.utils.defaultColor() 56 | height: 400 57 | width: 800 58 | showXAxis: true 59 | showYAxis: true 60 | noData: 'No Data Available' 61 | duration: 0 62 | maxBoxWidth: 75 63 | 64 | builder = null 65 | beforeEach -> 66 | builder = new ChartBuilder nv.models.boxPlotChart() 67 | builder.build options, sampleData1 68 | 69 | afterEach -> 70 | builder.teardown() 71 | 72 | it 'api check', -> 73 | should.exist builder.model.options, 'options exposed' 74 | for opt of options 75 | should.exist builder.model[opt](), "#{opt} can be called" 76 | 77 | builder.model.update() 78 | 79 | it 'renders', -> 80 | wrap = builder.$ 'g.nvd3.nv-boxPlotWithAxes' 81 | should.exist wrap[0] 82 | 83 | it 'no data text', -> 84 | builder = new ChartBuilder nv.models.boxPlotChart() 85 | builder.build options, [] 86 | 87 | noData = builder.$ '.nv-noData' 88 | noData[0].textContent.should.equal 'No Data Available' 89 | 90 | it 'has correct structure', -> 91 | cssClasses = [ 92 | '.nv-x.nv-axis' 93 | '.nv-y.nv-axis' 94 | '.nv-barsWrap' 95 | '.nv-wrap' 96 | '.nv-boxplot' 97 | '.nv-boxplot-median' 98 | '.nv-boxplot-tick.nv-boxplot-low' 99 | '.nv-boxplot-whisker.nv-boxplot-low' 100 | '.nv-boxplot-tick.nv-boxplot-high' 101 | '.nv-boxplot-whisker.nv-boxplot-high' 102 | ] 103 | for cssClass in cssClasses 104 | do (cssClass) -> 105 | should.exist builder.$("g.nvd3.nv-boxPlotWithAxes #{cssClass}")[0] 106 | 107 | it 'Has boxplots', -> 108 | builder = new ChartBuilder nv.models.boxPlotChart() 109 | builder.buildover options, sampleData3, [] 110 | 111 | boxes = builder.$ '.nv-boxplot-box' 112 | boxes.length.should.equal 2, 'boxplots exist' 113 | 114 | it 'Has outliers', -> 115 | builder = new ChartBuilder nv.models.boxPlotChart() 116 | builder.buildover options, sampleData1, [] 117 | 118 | outliers = builder.$ '.nv-boxplot .nv-boxplot-outlier' 119 | outliers.length.should.equal 3, 'outliers exist' 120 | 121 | it 'Has no outliers', -> 122 | builder = new ChartBuilder nv.models.boxPlotChart() 123 | builder.buildover options, sampleData2, [] 124 | 125 | outliers = builder.$ '.nv-boxplot-outlier' 126 | outliers.length.should.equal 0, 'empty outliers' 127 | 128 | it 'Displays whiskers whose value are <= 0', -> 129 | builder = new ChartBuilder nv.models.boxPlotChart() 130 | builder.buildover options, sampleData4, [] 131 | 132 | whiskers = builder.$ '.nv-boxplot-whisker' 133 | whiskers.length.should.equal 2, 'zero whiskers' 134 | -------------------------------------------------------------------------------- /test/mocha/core.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | 3 | describe 'Core', -> 4 | 5 | objects = [ 6 | 'window.nv' 7 | 'd3_time_range' 8 | 'nv.utils' 9 | 'nv.models' 10 | 'nv.charts' 11 | 'nv.graphs' 12 | 'nv.logs' 13 | 'nv.dispatch' 14 | 'nv.log' 15 | 'nv.deprecated' 16 | 'nv.render' 17 | 'nv.addGraph' 18 | ] 19 | 20 | describe 'has', -> 21 | for obj in objects 22 | it " #{obj} object", -> 23 | should.exist eval obj 24 | 25 | describe 'has nv.dispatch with default', -> 26 | dispatchDefaults = ['render_start', 'render_end'] 27 | for event in dispatchDefaults 28 | do (event) -> 29 | it "#{event} event", -> assert.isFunction nv.dispatch[event] 30 | -------------------------------------------------------------------------------- /test/mocha/discretebar.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Discrete Bar Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | {label: 'America', value: 100} 7 | {label: 'Europe', value: 200} 8 | {label: 'Asia', value: 50} 9 | {label: 'Africa', value: 70} 10 | ] 11 | ] 12 | 13 | options = 14 | x: (d)-> d.label 15 | y: (d)-> d.value 16 | margin: 17 | top: 30 18 | right: 20 19 | bottom: 50 20 | left: 75 21 | color: nv.utils.defaultColor() 22 | showXAxis: true 23 | showYAxis: true 24 | rightAlignYAxis: false 25 | staggerLabels: true 26 | showValues: true 27 | valueFormat: (d)-> d.toFixed 2 28 | noData: 'No Data Available' 29 | duration: 0 30 | 31 | builder = null 32 | beforeEach -> 33 | builder = new ChartBuilder nv.models.discreteBarChart() 34 | builder.build options, sampleData1 35 | 36 | afterEach -> 37 | builder.teardown() 38 | 39 | it 'api check', -> 40 | should.exist builder.model.options, 'options exposed' 41 | for opt of options 42 | should.exist builder.model[opt](), "#{opt} can be called" 43 | 44 | it 'renders', -> 45 | wrap = builder.$ 'g.nvd3.nv-discreteBarWithAxes' 46 | should.exist wrap[0] 47 | 48 | it 'clears chart objects for no data', -> 49 | builder = new ChartBuilder nv.models.discreteBarChart() 50 | builder.buildover options, sampleData1, [] 51 | 52 | groups = builder.$ 'g' 53 | groups.length.should.equal 0, 'removes chart components' 54 | 55 | it 'has correct structure', -> 56 | cssClasses = [ 57 | '.nv-x.nv-axis' 58 | '.nv-y.nv-axis' 59 | '.nv-barsWrap' 60 | '.nv-discretebar' 61 | ] 62 | for cssClass in cssClasses 63 | do (cssClass) -> 64 | should.exist builder.$("g.nvd3.nv-discreteBarWithAxes #{cssClass}")[0] 65 | 66 | it 'can override axis ticks', -> 67 | builder.model.xAxis.ticks(34) 68 | builder.model.yAxis.ticks(56) 69 | builder.model.update() 70 | builder.model.xAxis.ticks().should.equal 34 71 | builder.model.yAxis.ticks().should.equal 56 72 | 73 | -------------------------------------------------------------------------------- /test/mocha/historical-bar.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Historical Bar Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | [-1,-1] 7 | [0,0] 8 | [1,1] 9 | [2,2] 10 | ] 11 | ] 12 | 13 | options = 14 | x: (d,i)-> i 15 | y: (d)-> d[1] 16 | margin: 17 | top: 30 18 | right: 20 19 | bottom: 50 20 | left: 75 21 | width: 200 22 | height: 200 23 | color: nv.utils.defaultColor() 24 | showLegend: true 25 | showXAxis: true 26 | showYAxis: true 27 | rightAlignYAxis: false 28 | noData: 'No Data Available' 29 | 30 | builder = null 31 | beforeEach -> 32 | builder = new ChartBuilder nv.models.historicalBarChart() 33 | builder.build options, sampleData1 34 | 35 | afterEach -> 36 | builder.teardown() 37 | 38 | it 'api check', -> 39 | should.exist builder.model.options, 'options exposed' 40 | for opt of options 41 | should.exist builder.model[opt](), "#{opt} can be called" 42 | 43 | it 'renders', -> 44 | wrap = builder.$ 'g.nvd3.nv-historicalBarChart' 45 | should.exist wrap[0] 46 | 47 | it 'clears chart objects for no data', -> 48 | builder = new ChartBuilder nv.models.historicalBarChart() 49 | builder.buildover options, sampleData1, [] 50 | 51 | groups = builder.$ 'g' 52 | groups.length.should.equal 0, 'removes chart components' 53 | 54 | it 'has correct structure', -> 55 | cssClasses = [ 56 | '.nv-x.nv-axis' 57 | '.nv-y.nv-axis' 58 | '.nv-barsWrap' 59 | '.nv-bars' 60 | '.nv-legendWrap' 61 | ] 62 | for cssClass in cssClasses 63 | do (cssClass) -> 64 | should.exist builder.$("g.nvd3.nv-historicalBarChart #{cssClass}")[0] 65 | 66 | it 'can override axis ticks', -> 67 | builder.model.xAxis.ticks(34) 68 | builder.model.yAxis.ticks(56) 69 | builder.model.update() 70 | builder.model.xAxis.ticks().should.equal 34 71 | builder.model.yAxis.ticks().should.equal 56 72 | -------------------------------------------------------------------------------- /test/mocha/legend.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Legend', -> 3 | sampleData1 = [ 4 | {"values":[{"x":1,"y":2},{"x":3,"y":4},{"x":5,"y":6}],"key":"key 1"} 5 | {"values":[{"x":7,"y":8},{"x":9,"y":10},{"x":11,"y":12}],"key":"key 2"} 6 | {"values":[{"x":13,"y":14},{"x":15,"y":16},{"x":17,"y":18}],"key":"key 3"} 7 | ] 8 | 9 | sampleData2 = [ 10 | key: 'series 1' 11 | , 12 | key: 'series 2' 13 | , 14 | key: 'series 3' 15 | , 16 | key: 'series 4' 17 | ] 18 | 19 | legendOptions = 20 | margin: 21 | top: 0 22 | right: 0 23 | bottom: 0 24 | left: 0 25 | width: 100 26 | height: 100 27 | key: (d) -> d.key 28 | color: nv.utils.defaultColor() 29 | align: true 30 | rightAlign: false 31 | updateState: true 32 | radioButtonMode: false 33 | 34 | builder = null 35 | beforeEach -> 36 | builder = new ChartBuilder nv.models.legend() 37 | builder.build legendOptions, sampleData1 38 | 39 | legend = builder.model 40 | for opt, val of legendOptions 41 | legend[opt](val) 42 | 43 | afterEach -> 44 | builder.teardown() 45 | 46 | it 'api check', -> 47 | legend = builder.model 48 | for opt, val of legendOptions 49 | should.exist legend[opt](), "#{opt} can be called" 50 | 51 | it 'exists', -> 52 | legend = builder.$('.nvd3.nv-legend') 53 | should.exist legend[0], '.nvd3.nv-legend' 54 | 55 | describe 'appends items correctly', -> 56 | for item, i in sampleData1 57 | do (item, i) -> 58 | key = item.key 59 | it "'#{key}' text, position and structure", -> 60 | 61 | nvSeries = builder.$(".nvd3.nv-legend .nv-series")[i] 62 | transformCalculated = "translate(0,#{i*20+5})" 63 | transform = nvSeries.getAttribute 'transform' 64 | transform.should.be.equal transformCalculated 65 | 66 | nvLegendSymbol = nvSeries.querySelector('.nv-legend-symbol') 67 | nvLegendText = nvSeries.querySelector('.nv-legend-text') 68 | 69 | should.exist nvLegendSymbol 70 | should.exist nvLegendText 71 | nvLegendText.textContent.should.be.equal key 72 | 73 | describe 'clicking and double clicking', -> 74 | it 'clicking one legend turns it off', -> 75 | legendItems = builder.$ '.nv-legend .nv-series' 76 | legendItems.length.should.equal 3 77 | 78 | clickFn = d3.select(legendItems[0]).on 'click' 79 | clickFn(sampleData1[0]) 80 | sampleData1[0].disabled.should.equal true 81 | clickFn(sampleData1[1]) 82 | sampleData1[1].disabled.should.equal true 83 | 84 | clickFn(sampleData1[2]) 85 | sampleData1[0].disabled.should.equal false 86 | sampleData1[1].disabled.should.equal false 87 | sampleData1[2].disabled.should.equal false 88 | 89 | it 'double clicking legend keeps only one on', -> 90 | legendItems = builder.$ '.nv-legend .nv-series' 91 | 92 | clickFn = d3.select(legendItems[0]).on 'dblclick' 93 | clickFn(sampleData1[0]) 94 | sampleData1[0].disabled.should.equal false 95 | 96 | sampleData1[1].disabled.should.equal true 97 | sampleData1[2].disabled.should.equal true 98 | 99 | it 'updating legend data does not break double click (issue 784)', -> 100 | builder.updateData sampleData2 101 | 102 | legendItems = builder.$ '.nv-legend .nv-series' 103 | 104 | clickFn = d3.select(legendItems[0]).on 'dblclick' 105 | clickFn(sampleData2[0]) 106 | sampleData2[0].disabled.should.equal false 107 | 108 | sampleData2[1].disabled.should.equal true 109 | sampleData2[2].disabled.should.equal true 110 | sampleData2[3].disabled.should.equal true 111 | 112 | it 'legend padding', -> 113 | builder = new ChartBuilder nv.models.legend() 114 | builder.build {padding: 40}, sampleData1 115 | 116 | legendItems = builder.$ '.nv-legend .nv-series' 117 | xSpacing = [0, 80, 160] 118 | for legend,i in legendItems 119 | transform = legend.getAttribute 'transform' 120 | transform.should.equal "translate(#{xSpacing[i]},5)" 121 | -------------------------------------------------------------------------------- /test/mocha/line.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Line Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | [-1,-1] 7 | [0,0] 8 | [1,1] 9 | [2,2] 10 | ] 11 | ] 12 | 13 | sampleData2 = [ 14 | key: 'Series 1' 15 | classed: 'dashed' 16 | values: [ 17 | [-1,-3] 18 | [0,6] 19 | [1,12] 20 | [2,18] 21 | ] 22 | , 23 | key: 'Series 2' 24 | values: [ 25 | [-1,-4] 26 | [0,7] 27 | [1,13] 28 | [2,14] 29 | ] 30 | , 31 | key: 'Series 3' 32 | values: [ 33 | [-1,-5] 34 | [0,7.2] 35 | [1,11] 36 | [2,18.5] 37 | ] 38 | ] 39 | 40 | options = 41 | x: (d)-> d[0] 42 | y: (d)-> d[1] 43 | margin: 44 | top: 30 45 | right: 20 46 | bottom: 50 47 | left: 75 48 | color: nv.utils.defaultColor() 49 | height: 400 50 | width: 800 51 | showLegend: true 52 | showXAxis: true 53 | showYAxis: true 54 | rightAlignYAxis: true 55 | useInteractiveGuideline: true 56 | noData: 'No Data Available' 57 | duration: 0 58 | clipEdge: false 59 | isArea: (d)-> d.area 60 | defined: (d)-> true 61 | interpolate: 'linear' 62 | 63 | builder = null 64 | beforeEach -> 65 | builder = new ChartBuilder nv.models.lineChart() 66 | builder.build options, sampleData1 67 | 68 | afterEach -> 69 | builder.teardown() 70 | 71 | it 'api check', -> 72 | should.exist builder.model.options, 'options exposed' 73 | for opt of options 74 | should.exist builder.model[opt](), "#{opt} can be called" 75 | 76 | builder.model.update() 77 | 78 | it 'renders', -> 79 | wrap = builder.$ 'g.nvd3.nv-lineChart' 80 | should.exist wrap[0] 81 | 82 | it 'no data text', -> 83 | builder = new ChartBuilder nv.models.lineChart() 84 | builder.build options, [] 85 | 86 | noData = builder.$ '.nv-noData' 87 | noData[0].textContent.should.equal 'No Data Available' 88 | 89 | it 'clears chart objects for no data', -> 90 | builder = new ChartBuilder nv.models.lineChart() 91 | builder.buildover options, sampleData1, [] 92 | 93 | groups = builder.$ 'g' 94 | groups.length.should.equal 0, 'removes chart components' 95 | 96 | 97 | it 'has correct structure', -> 98 | cssClasses = [ 99 | '.nv-x.nv-axis' 100 | '.nv-y.nv-axis' 101 | '.nv-linesWrap' 102 | '.nv-legendWrap' 103 | '.nv-line' 104 | '.nv-scatter' 105 | '.nv-legend' 106 | ] 107 | for cssClass in cssClasses 108 | do (cssClass) -> 109 | should.exist builder.$("g.nvd3.nv-lineChart #{cssClass}")[0] 110 | 111 | it 'can override axis ticks', -> 112 | builder.model.xAxis.ticks(34) 113 | builder.model.yAxis.ticks(56) 114 | builder.model.update() 115 | builder.model.xAxis.ticks().should.equal 34 116 | builder.model.yAxis.ticks().should.equal 56 117 | 118 | it 'can add custom CSS class to series', -> 119 | builder.updateData sampleData2 120 | 121 | classed = builder.$ '.nv-linesWrap .nv-groups .nv-group.dashed' 122 | 123 | # Since classing has been implemented at the data-level for 124 | # scatter points, there will actually be 2 elements matching 125 | # the above selector, one for the scatter g element, 126 | # and one for the line. 127 | 128 | classed.length.should.equal 2, 'dashed class exists' 129 | 130 | scatter = builder.$ '.nv-scatterWrap .nv-groups .nv-group.dashed' 131 | scatter.length.should.equal 1, 'one classed element is from scatter' 132 | 133 | it 'shows focus chart when focusEnable is set to true', -> 134 | builder.model.focusEnable(true).update(); 135 | focus = builder.$ '.nv-focusWrap .nv-focus' 136 | should.exist focus[0] 137 | 138 | it 'hides focus chart when focusEnable is set to false', -> 139 | builder.model.focusEnable(true).update(); 140 | builder.model.focusEnable(false).update(); 141 | focusWrap = builder.$ '.nv-focusWrap' 142 | focusWrap[0].style.display.should.equal 'none' 143 | 144 | it 'does not reset selected focus range when focusEnable is set to false', -> 145 | builder.model.focusEnable(true).update(); 146 | builder.model.brushExtent([0, 1]).update(); 147 | builder.model.focusEnable(false).update(); 148 | builder.model.brushExtent()[0].should.equal 0 149 | builder.model.brushExtent()[1].should.equal 1 150 | 151 | -------------------------------------------------------------------------------- /test/mocha/multibar-horizontal.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'MultiBar Horizontal Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | {label: 'America', value: 100} 7 | {label: 'Europe', value: 200} 8 | {label: 'Asia', value: 50} 9 | {label: 'Africa', value: 70} 10 | ] 11 | , 12 | key: 'Series 2' 13 | values: [ 14 | {label: 'America', value: 110} 15 | {label: 'Europe', value: 230} 16 | {label: 'Asia', value: 51} 17 | {label: 'Africa', value: 78} 18 | ] 19 | , 20 | key: 'Series 3' 21 | values: [ 22 | {label: 'America', value: 230} 23 | {label: 'Europe', value: 280} 24 | {label: 'Asia', value: 31} 25 | {label: 'Africa', value: 13} 26 | ] 27 | ] 28 | 29 | options = 30 | x: (d)-> d.label 31 | y: (d)-> d.value 32 | margin: 33 | top: 30 34 | right: 20 35 | bottom: 50 36 | left: 75 37 | width: 200 38 | height: 200 39 | color: nv.utils.defaultColor() 40 | stacked: false 41 | showControls: true 42 | showLegend: true 43 | showXAxis: true 44 | showYAxis: true 45 | noData: 'No Data Available' 46 | duration: 0 47 | 48 | builder = null 49 | beforeEach -> 50 | builder = new ChartBuilder nv.models.multiBarHorizontalChart() 51 | builder.build options, sampleData1 52 | 53 | afterEach -> 54 | builder.teardown() 55 | 56 | it 'api check', -> 57 | should.exist builder.model.options, 'options exposed' 58 | for opt of options 59 | should.exist builder.model[opt](), "#{opt} can be called" 60 | 61 | it 'renders', -> 62 | wrap = builder.$ 'g.nvd3.nv-multiBarHorizontalChart' 63 | should.exist wrap[0] 64 | 65 | it 'clears chart objects for no data', -> 66 | builder = new ChartBuilder nv.models.multiBarHorizontalChart() 67 | builder.buildover options, sampleData1, [] 68 | 69 | groups = builder.$ 'g' 70 | groups.length.should.equal 0, 'removes chart components' 71 | 72 | it 'has correct structure', -> 73 | cssClasses = [ 74 | '.nv-x.nv-axis' 75 | '.nv-y.nv-axis' 76 | '.nv-barsWrap' 77 | '.nv-multibarHorizontal' 78 | '.nv-legendWrap' 79 | '.nv-controlsWrap' 80 | ] 81 | for cssClass in cssClasses 82 | do (cssClass) -> 83 | should.exist builder.$("g.nvd3.nv-multiBarHorizontalChart #{cssClass}")[0] 84 | 85 | it 'renders bars', -> 86 | bars = builder.$('g.nvd3.nv-multiBarHorizontalChart .nv-multibarHorizontal .nv-bar') 87 | bars.should.have.length 12 88 | 89 | it 'can override axis ticks', -> 90 | builder.model.xAxis.ticks(34) 91 | builder.model.yAxis.ticks(56) 92 | builder.model.update() 93 | builder.model.xAxis.ticks().should.equal 34 94 | builder.model.yAxis.ticks().should.equal 56 95 | -------------------------------------------------------------------------------- /test/mocha/multibar.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'MultiBar Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | {label: 'America', value: 100} 7 | {label: 'Europe', value: 200} 8 | {label: 'Asia', value: 50} 9 | {label: 'Africa', value: 70} 10 | ] 11 | , 12 | key: 'Series 2' 13 | values: [ 14 | {label: 'America', value: 110} 15 | {label: 'Europe', value: 230} 16 | {label: 'Asia', value: 51} 17 | {label: 'Africa', value: 78} 18 | ] 19 | , 20 | key: 'Series 3' 21 | values: [ 22 | {label: 'America', value: 230} 23 | {label: 'Europe', value: 280} 24 | {label: 'Asia', value: 31} 25 | {label: 'Africa', value: 13} 26 | ] 27 | ] 28 | 29 | options = 30 | x: (d)-> d.label 31 | y: (d)-> d.value 32 | margin: 33 | top: 30 34 | right: 20 35 | bottom: 50 36 | left: 75 37 | width: 200 38 | height: 200 39 | color: nv.utils.defaultColor() 40 | showControls: true 41 | showLegend: true 42 | showXAxis: true 43 | showYAxis: true 44 | rightAlignYAxis: false 45 | reduceXTicks: true 46 | staggerLabels: true 47 | rotateLabels: 0 48 | noData: 'No Data Available' 49 | duration: 0 50 | 51 | builder = null 52 | beforeEach -> 53 | builder = new ChartBuilder nv.models.multiBarChart() 54 | builder.build options, sampleData1 55 | 56 | afterEach -> 57 | builder.teardown() 58 | 59 | it 'api check', -> 60 | should.exist builder.model.options, 'options exposed' 61 | for opt of options 62 | should.exist builder.model[opt](), "#{opt} can be called" 63 | 64 | it 'renders', -> 65 | wrap = builder.$ 'g.nvd3.nv-multiBarWithLegend' 66 | should.exist wrap[0] 67 | 68 | it 'clears chart objects for no data', -> 69 | builder = new ChartBuilder nv.models.multiBarChart() 70 | builder.buildover options, sampleData1, [] 71 | 72 | groups = builder.$ 'g' 73 | groups.length.should.equal 0, 'removes chart components' 74 | 75 | it 'has correct structure', -> 76 | cssClasses = [ 77 | '.nv-x.nv-axis' 78 | '.nv-y.nv-axis' 79 | '.nv-barsWrap' 80 | '.nv-multibar' 81 | '.nv-legendWrap' 82 | '.nv-controlsWrap' 83 | ] 84 | 85 | for cssClass in cssClasses 86 | do (cssClass) -> 87 | should.exist builder.$("g.nvd3.nv-multiBarWithLegend #{cssClass}")[0] 88 | 89 | it 'renders bars', -> 90 | bars = builder.$("g.nvd3.nv-multiBarWithLegend .nv-multibar .nv-bar") 91 | bars.should.have.length 12 92 | 93 | it 'can override axis ticks', -> 94 | builder.model.xAxis.ticks(34) 95 | builder.model.yAxis.ticks(56) 96 | builder.model.update() 97 | builder.model.xAxis.ticks().should.equal 34 98 | builder.model.yAxis.ticks().should.equal 56 99 | 100 | describe "useInteractiveGuideline", -> 101 | it "true", -> 102 | options.useInteractiveGuideline = true 103 | builder.build options, sampleData1 104 | builder.$(".nv-multiBarWithLegend .nv-interactiveLineLayer").should.have.length 1 105 | it "false", -> 106 | options.useInteractiveGuideline = false 107 | builder.build options, sampleData1 108 | builder.$(".nv-multiBarWithLegend .nv-interactiveLineLayer").should.have.length 0 109 | 110 | -------------------------------------------------------------------------------- /test/mocha/pie.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Pie Chart', -> 3 | sampleData1 = [ 4 | {label: 'America', value: 100} 5 | {label: 'Europe', value: 200} 6 | {label: 'Asia', value: 50} 7 | {label: 'Africa', value: 70} 8 | ] 9 | 10 | options = 11 | x: (d)-> d.label 12 | y: (d)-> d.value 13 | margin: 14 | top: 30 15 | right: 20 16 | bottom: 50 17 | left: 75 18 | width: 200 19 | height: 200 20 | color: nv.utils.defaultColor() 21 | showLegend: true 22 | valueFormat: (d)-> d.toFixed 2 23 | showLabels: true 24 | labelsOutside: true 25 | donut: false 26 | donutRatio: 0.5 27 | labelThreshold: 0.02 28 | labelType: 'key' 29 | noData: 'No Data Available' 30 | duration: 0 31 | startAngle: false 32 | endAngle: false 33 | padAngle: false 34 | cornerRadius: 0 35 | labelSunbeamLayout: false 36 | 37 | builder = null 38 | beforeEach -> 39 | builder = new ChartBuilder nv.models.pieChart() 40 | builder.build options, sampleData1 41 | 42 | afterEach -> 43 | builder.teardown() 44 | 45 | it 'api check', -> 46 | should.exist builder.model.options, 'options exposed' 47 | for opt of options 48 | should.exist builder.model[opt](), "#{opt} can be called" 49 | 50 | describe 'renders', -> 51 | 52 | wrap = null 53 | labels = null 54 | 55 | beforeEach -> 56 | wrap = builder.$ 'g.nvd3.nv-pieChart' 57 | labels = wrap[0].querySelectorAll('.nv-label text') 58 | 59 | it '.nv-pieChart', -> 60 | should.exist wrap[0] 61 | 62 | it 'can access margin', -> 63 | builder.model.margin 64 | top: 31 65 | right: 21 66 | bottom: 51 67 | left: 76 68 | 69 | m = builder.model.margin() 70 | m.should.deep.equal 71 | top: 31 72 | right: 21 73 | bottom: 51 74 | left: 76 75 | 76 | describe 'labels correctly', -> 77 | it "[#{sampleData1.length}] labels", -> 78 | wrap[0].querySelectorAll('.nv-label').should.have.length sampleData1.length 79 | 80 | for item, i in sampleData1 81 | do (item, i) -> 82 | it "label '#{item.label}'", -> 83 | item.label.should.be.equal labels[i].textContent 84 | 85 | it 'clears chart objects for no data', -> 86 | builder = new ChartBuilder nv.models.pieChart() 87 | builder.buildover options, sampleData1, [] 88 | 89 | groups = builder.$ 'g' 90 | groups.length.should.equal 0, 'removes chart components' 91 | 92 | it 'has correct structure', -> 93 | cssClasses = [ 94 | '.nv-pieWrap' 95 | '.nv-pie' 96 | '.nv-pieLabels' 97 | '.nv-legendWrap' 98 | ] 99 | for cssClass in cssClasses 100 | do (cssClass) -> 101 | should.exist builder.$("g.nvd3.nv-pieChart #{cssClass}")[0] 102 | 103 | it 'can handle donut mode and options', (done)-> 104 | builder.teardown() 105 | options.donut = true 106 | options.labelSunbeamLayout = true 107 | options.startAngle = (d)-> d.startAngle/2 - Math.PI/2 108 | options.endAngle = (d)-> d.endAngle/2 - Math.PI/2 109 | 110 | builder.build options, sampleData1 111 | 112 | done() 113 | 114 | it 'can handle cornerRadius and padAngle options', (done)-> 115 | builder.teardown() 116 | options.padAngle = 5 117 | options.cornerRadius = 5 118 | 119 | builder.build options, sampleData1 120 | done() 121 | 122 | it 'can render pie labels in other formats', -> 123 | opts = 124 | x: (d)-> d.label 125 | y: (d)-> d.value 126 | labelType: 'value' 127 | valueFormat: d3.format('.2f') 128 | builder2 = new ChartBuilder nv.models.pie() 129 | builder2.build opts, [sampleData1] 130 | 131 | labels = builder2.$ '.nv-pieLabels .nv-label text' 132 | labels.length.should.equal 4 133 | 134 | expected = ['100.00','200.00','50.00','70.00'] 135 | for label,i in labels 136 | label.textContent.should.equal expected[i] 137 | 138 | # Test labelType = 'percent' 139 | builder2.teardown() 140 | 141 | opts.labelType = 'percent' 142 | opts.valueFormat = d3.format('%') 143 | builder2.build opts, [sampleData1] 144 | 145 | labels = builder2.$ '.nv-pieLabels .nv-label text' 146 | labels.length.should.equal 4 147 | 148 | expected = ['24%','48%','12%','17%'] 149 | for label,i in labels 150 | label.textContent.should.equal expected[i] 151 | -------------------------------------------------------------------------------- /test/mocha/sankey.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Sankey Chart', -> 3 | sampleData1 = 4 | nodes: 5 | [ 6 | {'node': 1, 'name': 'Test 1'} 7 | {'node': 2, 'name': 'Test 2'} 8 | {'node': 3, 'name': 'Test 3'} 9 | {'node': 4, 'name': 'Test 4'} 10 | {'node': 5, 'name': 'Test 5'} 11 | {'node': 6, 'name': 'Test 6'} 12 | ] 13 | links: 14 | [ 15 | {'source': 0, 'target': 1, 'value': 2295} 16 | {'source': 0, 'target': 5, 'value': 1199} 17 | {'source': 1, 'target': 2, 'value': 1119} 18 | {'source': 1, 'target': 5, 'value': 1176} 19 | {'source': 2, 'target': 3, 'value': 487} 20 | {'source': 2, 'target': 5, 'value': 632} 21 | {'source': 3, 'target': 4, 'value': 301} 22 | {'source': 3, 'target': 5, 'value': 186} 23 | ] 24 | 25 | 26 | options = 27 | margin: 28 | top: 30 29 | right: 20 30 | bottom: 50 31 | left: 75 32 | width: 200 33 | height: 200 34 | units: 'test' 35 | format: -> 36 | linkTitle: -> 'link title test' 37 | nodeWidth: 77 38 | nodePadding: 10 39 | nodeStyle: 40 | nodeFillColor: -> '#f00' 41 | nodeStrokeColor: -> '#00f' 42 | nodeTitle: -> 'testing the title' 43 | 44 | builder = null 45 | beforeEach -> 46 | builder = new ChartBuilder nv.models.sankeyChart() 47 | builder.build options, sampleData1 48 | 49 | afterEach -> 50 | builder.teardown() 51 | 52 | it 'api check', -> 53 | should.exist builder.model.options, 'options exposed' 54 | for opt of options 55 | should.exist builder.model[opt](), "#{opt} can be called" 56 | 57 | it 'renders', -> 58 | wrap = builder.$ 'g.nvd3.nv-sankeyChart' 59 | should.exist wrap[0] 60 | 61 | it 'has correct structure', -> 62 | cssClasses = [ 63 | '.node' 64 | '.link' 65 | ] 66 | 67 | for cssClass in cssClasses 68 | do (cssClass) -> 69 | should.exist builder.$("g.nvd3.nv-sankeyChart #{cssClass}")[0] 70 | 71 | it 'renders nodes', -> 72 | nodes = builder.$("g.nvd3.nv-sankeyChart .node") 73 | nodes.should.have.length 6 74 | 75 | it 'nodes has the right width', -> 76 | should.exist builder.$("g.nvd3.nv-sankeyChart .node rect[width]")[0] 77 | builder.$("g.nvd3.nv-sankeyChart .node rect[width]")[0].width.animVal.value.should.equal 77 78 | 79 | it 'renders links', -> 80 | links = builder.$("g.nvd3.nv-sankeyChart .link") 81 | links.should.have.length 8 82 | 83 | it 'link titles has the test text', -> 84 | link = builder.$("g.nvd3.nv-sankeyChart .link title") 85 | link[0].textContent.should.equal 'link title test' 86 | -------------------------------------------------------------------------------- /test/mocha/sparkline.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Sparkline Chart', -> 3 | sampleData1 = [ 4 | {x: 1, y: 100} 5 | {x: 2, y: 101} 6 | {x: 3, y: 99} 7 | {x: 4, y: 56} 8 | {x: 5, y: 87} 9 | ] 10 | 11 | options = 12 | x: (d)-> d.x 13 | y: (d)-> d.y 14 | margin: 15 | top: 30 16 | right: 20 17 | bottom: 50 18 | left: 75 19 | width: 200 20 | height: 50 21 | xTickFormat: (d)-> d 22 | yTickFormat: (d)-> d.toFixed 2 23 | showLastValue: true 24 | alignValue: true 25 | rightAlignValue: false 26 | noData: 'No Data Available' 27 | 28 | builder = null 29 | beforeEach -> 30 | builder = new ChartBuilder nv.models.sparklinePlus() 31 | builder.build options, sampleData1 32 | 33 | afterEach -> 34 | builder.teardown() 35 | 36 | it 'api check', -> 37 | should.exist builder.model.options, 'options exposed' 38 | for opt of options 39 | should.exist builder.model[opt](), "#{opt} can be called" 40 | 41 | it 'clears chart objects for no data', -> 42 | builder = new ChartBuilder nv.models.sparklinePlus() 43 | builder.buildover options, sampleData1, [] 44 | 45 | groups = builder.$ 'g' 46 | groups.length.should.equal 0, 'removes chart components' 47 | 48 | it 'renders', -> 49 | wrap = builder.$ 'g.nvd3.nv-sparklineplus' 50 | should.exist wrap[0] 51 | 52 | 53 | 54 | it 'has correct structure', -> 55 | cssClasses = [ 56 | '.nv-sparklineWrap' 57 | '.nv-sparkline' 58 | '.nv-minValue' 59 | '.nv-maxValue' 60 | '.nv-currentValue' 61 | '.nv-valueWrap' 62 | ] 63 | for cssClass in cssClasses 64 | do(cssClass) -> 65 | should.exist builder.$("g.nvd3.nv-sparklineplus #{cssClass}")[0] -------------------------------------------------------------------------------- /test/mocha/stacked.coffee: -------------------------------------------------------------------------------- 1 | describe 'NVD3', -> 2 | describe 'Stacked Area Chart', -> 3 | sampleData1 = [ 4 | key: 'Series 1' 5 | values: [ 6 | [-1,-1] 7 | [0,0] 8 | [1,1] 9 | [2,2] 10 | ] 11 | ] 12 | 13 | sampleData2 = [ 14 | key: 'Series 1' 15 | values: [ 16 | [-1,-3] 17 | [0,6] 18 | [1,12] 19 | [2,18] 20 | ] 21 | , 22 | key: 'Series 2' 23 | values: [ 24 | [-1,-4] 25 | [0,7] 26 | [1,13] 27 | [2,14] 28 | ] 29 | ] 30 | 31 | options = 32 | x: (d)-> d[0] 33 | y: (d)-> d[1] 34 | margin: 35 | top: 30 36 | right: 20 37 | bottom: 50 38 | left: 75 39 | color: nv.utils.defaultColor() 40 | showLegend: true 41 | showControls: true 42 | showXAxis: true 43 | showYAxis: true 44 | rightAlignYAxis: false 45 | useInteractiveGuideline: true 46 | noData: 'No Data Available' 47 | duration: 0 48 | controlLabels: 49 | stacked: 'Stacked' 50 | stream: 'Stream' 51 | expanded: 'Expanded' 52 | 53 | builder = null 54 | beforeEach -> 55 | builder = new ChartBuilder nv.models.stackedAreaChart() 56 | builder.build options, sampleData1 57 | 58 | afterEach -> 59 | builder.teardown() 60 | 61 | it 'api check', -> 62 | should.exist builder.model.options, 'options exposed' 63 | for opt of options 64 | should.exist builder.model[opt](), "#{opt} can be called" 65 | 66 | it 'renders', -> 67 | wrap = builder.$ 'g.nvd3.nv-stackedAreaChart' 68 | should.exist wrap[0] 69 | 70 | it 'clears chart objects for no data', -> 71 | builder = new ChartBuilder nv.models.stackedAreaChart() 72 | builder.buildover options, sampleData1, [] 73 | 74 | groups = builder.$ 'g' 75 | groups.length.should.equal 0, 'removes chart components' 76 | 77 | it 'has correct structure', -> 78 | cssClasses = [ 79 | '.nv-x.nv-axis' 80 | '.nv-y.nv-axis' 81 | '.nv-stackedWrap' 82 | '.nv-legendWrap' 83 | '.nv-controlsWrap' 84 | '.nv-interactive' 85 | ] 86 | 87 | for cssClass in cssClasses 88 | do (cssClass) -> 89 | should.exist builder.$("g.nvd3.nv-stackedAreaChart #{cssClass}")[0] 90 | 91 | it 'formats y-Axis correctly depending on stacked style', -> 92 | chart = nv.models.stackedAreaChart() 93 | chart.yAxis.tickFormat (d)-> "<#{d}>" 94 | 95 | builder = new ChartBuilder chart 96 | builder.build options, sampleData1 97 | 98 | yTicks = builder.$ '.nv-y.nv-axis .tick text' 99 | yTicks.should.have.length.greaterThan 2 100 | 101 | for tick in yTicks 102 | tick.textContent.should.match /<.*?>/ 103 | 104 | # Update chart to 'Expand' mode 105 | chart.dispatch.changeState 106 | style: 'expand' 107 | 108 | chart.stacked.style().should.equal 'expand' 109 | newTickFormat = chart.yAxis.tickFormat() 110 | newTickFormat(1).should.equal '100%' 111 | 112 | chart.dispatch.changeState 113 | style: 'stacked' 114 | 115 | chart.stacked.style().should.equal 'stacked' 116 | newTickFormat = chart.yAxis.tickFormat() 117 | newTickFormat(1).should.equal '<1>' 118 | 119 | it 'can override axis ticks', -> 120 | builder.model.xAxis.ticks(34) 121 | builder.model.yAxis.ticks(56) 122 | builder.model.update() 123 | builder.model.xAxis.ticks().should.equal 34 124 | builder.model.yAxis.ticks().should.equal 56 125 | 126 | it 'if stacked.offset is "wiggle", y ticks is zero', -> 127 | builder.model.stacked.offset 'wiggle' 128 | builder.model.update() 129 | builder.model.yAxis.ticks().should.equal 0 130 | 131 | it 'should allow stream-center to be used', -> 132 | builder.model.controlOptions(['Stream_Center']) 133 | builder.model.update() 134 | builder.model.controls.dispatch.legendClick({ 135 | style: 'stream-center', 136 | disabled: true 137 | }) 138 | builder.model.style().should.equal 'stream-center' 139 | 140 | it 'should set color property if not specified', -> 141 | sampleData3 = [ 142 | key: 'Series 1' 143 | values: [ 144 | [-1,-1] 145 | [0,0] 146 | [1,1] 147 | [2,2] 148 | ] 149 | ] 150 | builder.build options, sampleData3 151 | should.exist sampleData3[0].color 152 | -------------------------------------------------------------------------------- /test/mocha/test-utils.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Utility to build an NVD3 chart. 3 | ### 4 | class ChartBuilder 5 | # @model should be something like nv.models.scatterChart() 6 | constructor: (@model)-> 7 | 8 | ### 9 | options: an object hash of chart options. 10 | data: sample data to pass in to chart. 11 | 12 | This method builds a chart and puts it on the element. 13 | ### 14 | build: (options, data)-> 15 | @svg = document.createElement 'svg' 16 | document.querySelector('body').appendChild @svg 17 | 18 | for opt, val of options 19 | unless @model[opt]? 20 | console.warn "#{opt} not property of model." 21 | else 22 | @model[opt](val) 23 | 24 | @updateData data 25 | 26 | ### 27 | Update the data while preserving the chart model. 28 | ### 29 | updateData: (data)-> 30 | d3.select(@svg).datum(data).call(@model) 31 | 32 | ### 33 | options: an object hash of chart options. 34 | data: sample data to pass in to initial chart render chart 35 | data2: sample data to pass to second chart render 36 | 37 | This method builds a chart, puts it on the element, and then rebuilds using the second set of data 38 | Useful for testing the results of transitioning and the 'noData' state after a chart has had data 39 | ### 40 | buildover: (options, data, data2)-> 41 | @svg = document.createElement 'svg' 42 | document.querySelector('body').appendChild @svg 43 | 44 | for opt, val of options 45 | unless @model[opt]? 46 | console.warn "#{opt} not property of model." 47 | else 48 | @model[opt](val) 49 | 50 | #Set initial data 51 | chart = d3.select(@svg) 52 | chart.datum(data) 53 | .call(@model) 54 | 55 | #Reset the data 56 | chart.datum(data2) 57 | .call(@model) 58 | 59 | 60 | 61 | # Removes chart from element. 62 | teardown: -> 63 | if @svg? 64 | document.querySelector('body').removeChild @svg 65 | 66 | # Runs a simple CSS selector to retrieve elements 67 | $: (cssSelector)-> 68 | @svg.querySelectorAll cssSelector 69 | -------------------------------------------------------------------------------- /test/node/GruntFile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | browserify: { 4 | js: { 5 | src: './nodeTest.js', dest: './build/nodeTest.js', 6 | }, 7 | }, 8 | copy: { 9 | all: { 10 | src: ['../../build/nv.d3.css'], dest: './build/nv.d3.css', 11 | }, 12 | }, 13 | }); 14 | grunt.loadNpmTasks('grunt-browserify'); 15 | grunt.loadNpmTasks('grunt-contrib-copy'); 16 | grunt.registerTask('default', ['browserify', 'copy']); 17 | }; 18 | -------------------------------------------------------------------------------- /test/node/README.md: -------------------------------------------------------------------------------- 1 | Build steps: 2 | 3 | - Build `nvd3`. 4 | - Build the example. 5 | - Start an HTTP server. 6 | 7 | nvd3 $ grunt production 8 | nvd3 $ cd test/node 9 | nvd3/test/node $ npm install . 10 | nvd3/test/node $ grunt 11 | nvd3/test/node $ python -m SimpleHTTPServer 8000 12 | 13 | Browse to `http://localhost:8000/nodeTest.html` 14 | -------------------------------------------------------------------------------- /test/node/nodeTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Node Test 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/node/nodeTest.js: -------------------------------------------------------------------------------- 1 | window.d3 = require('d3'); 2 | var nv = require('../../build/nv.d3'); 3 | var invariant = require('invariant'); 4 | 5 | window.addEventListener("load", function load(event) { 6 | window.removeEventListener("load", load, false); 7 | invariant(typeof(nv) !== 'undefined', "Cannot resolve NVD3 via CommonJS"); 8 | nv.addGraph(function() { 9 | var chart = nv.models.bulletChart(); 10 | d3.select('#chart svg') 11 | .datum(exampleData()) 12 | .transition().duration(1000) 13 | .call(chart); 14 | return chart; 15 | }); 16 | }, false); 17 | 18 | function exampleData() { 19 | return { 20 | "title":"Revenue", 21 | "subtitle":"US$, in thousands", 22 | "ranges":[150,225,300], 23 | "measures":[220], 24 | "markers":[250] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-test", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "d3": "<=3.4.4", 7 | "invariant": "1.0.2" 8 | }, 9 | "devDependencies": { 10 | "grunt-browserify": "3.3.0", 11 | "grunt-contrib-copy": "~0.4.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/pieChartTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 28 |
29 |

Standard Pie Chart

30 | 31 |
32 | 33 |
34 |

Donut pie chart

35 | 36 |
37 | 38 |
39 |

Pie chart with 30 series'

40 | 41 |
42 | 43 |
44 |

Pie chart with percent label type

45 | 46 |
47 | 48 |
49 |

Empty array passed in

50 | 51 |
52 | 53 |
54 |

Series' have only zero values

55 | 56 |
57 | 58 |
59 |

NaN, null, undefined values passed in

60 | 61 |
62 | 63 |
64 |

Half donut pie chart with outside label

65 | 66 |
67 | 68 | 196 | -------------------------------------------------------------------------------- /test/realTimeChartTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 |

Example showing real time chart updating

18 | The chart below is a historical bar chart, which is ideal for visualizing time series data.
19 | First, you need to update the data model for the chart. In the example, we append a random number 20 | every half a second. Then, you call chart.update(). 21 | 22 |
23 | 24 | 25 |
26 | 27 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /test/scatterPlusLineChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 40 | 41 | 42 | 43 |
44 |
45 | 46 |
47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 120 | -------------------------------------------------------------------------------- /test/scrollTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 31 | 32 | 33 |

Charts:

34 |
35 |
36 |

Chart 1

37 | 38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /test/scrollTest2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 27 | 28 | 29 | 30 | 125 |

.

126 |

.

127 |

.

128 |

.

129 |

.

130 |

.

131 |

.

132 |

.

133 |

.

134 |

.

135 |

.

136 |

.

137 |

.

138 |

.

139 |

.

140 |

.

141 |

.

142 |

.

143 | 144 | 145 | -------------------------------------------------------------------------------- /test/stream_layers.js: -------------------------------------------------------------------------------- 1 | 2 | /* Inspired by Lee Byron's test data generator. */ 3 | function stream_layers(n, m, o) { 4 | if (arguments.length < 3) o = 0; 5 | function bump(a) { 6 | var x = 1 / (.1 + Math.random()), 7 | y = 2 * Math.random() - .5, 8 | z = 10 / (.1 + Math.random()); 9 | for (var i = 0; i < m; i++) { 10 | var w = (i / m - y) * z; 11 | a[i] += x * Math.exp(-w * w); 12 | } 13 | } 14 | return d3.range(n).map(function() { 15 | var a = [], i; 16 | for (i = 0; i < m; i++) a[i] = o + o * Math.random(); 17 | for (i = 0; i < 5; i++) bump(a); 18 | return a.map(stream_index); 19 | }); 20 | } 21 | 22 | /* Another layer generator using gamma distributions. */ 23 | function stream_waves(n, m) { 24 | return d3.range(n).map(function(i) { 25 | return d3.range(m).map(function(j) { 26 | var x = 20 * j / m - i / 3; 27 | return 2 * x * Math.exp(-.5 * x); 28 | }).map(stream_index); 29 | }); 30 | } 31 | 32 | function stream_index(d, i) { 33 | return {x: i, y: Math.max(0, d)}; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test/testScript.js: -------------------------------------------------------------------------------- 1 | //A little snippet of D3 code that creates a button that lets you toggle whether a chart is the only one visible on a page or not. 2 | d3.selectAll(".chart button").on("click",function() { 3 | var thisId = this.parentElement.id; 4 | 5 | var chartContainer = d3.select("#" + thisId); 6 | if (chartContainer.attr("class").match("selected")) 7 | chartContainer.classed("selected",false); 8 | else 9 | chartContainer.classed("selected",true); 10 | 11 | d3.selectAll(".chart").style("display",function() { 12 | if (thisId === this.id) return "block"; 13 | 14 | if (d3.select(this).style("display") === "none") 15 | return "block"; 16 | else 17 | return "none"; 18 | }); 19 | window.onresize(); 20 | }); -------------------------------------------------------------------------------- /test/teststyle.css: -------------------------------------------------------------------------------- 1 | body { 2 | overflow-y:scroll; 3 | font-family: arial; 4 | } 5 | 6 | text { 7 | font: 12px sans-serif; 8 | } 9 | 10 | .chart { 11 | float:left; 12 | height: 500px; 13 | text-align: center; 14 | font-weight: bold; 15 | margin-bottom: 2em; 16 | } 17 | .chart.full { 18 | width: 100%; 19 | } 20 | 21 | .chart.half { 22 | width: 50%; 23 | } 24 | 25 | .chart.third { 26 | width: 33%; 27 | } 28 | 29 | .chart.selected { 30 | width: 100% !important; 31 | } 32 | 33 | .navigation a{ 34 | margin-right: 1em; 35 | } 36 | 37 | .navigation { 38 | margin-bottom: 1em; 39 | } 40 | -------------------------------------------------------------------------------- /test/tinytest/nv-is-defined-test.js: -------------------------------------------------------------------------------- 1 | // nv-is-defined-test.js 2 | 3 | Tinytest.add('nv object is defined', function(test) { 4 | test.isNotUndefined(nv, 'nv is undefined at global scope for Meteor'); 5 | }); 6 | 7 | -------------------------------------------------------------------------------- /test/translateTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 18 | 19 | 20 | 21 | 37 | 38 | 39 | --------------------------------------------------------------------------------