├── .babelrc ├── .editorconfig ├── .gitignore ├── .npmignore ├── README.md ├── build ├── build-docs.js ├── build.js ├── check-versions.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js ├── webpack.docs.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── docs ├── css │ ├── app.bcd4a6d6c0c5c538263a59ace08a095b.css │ └── app.bcd4a6d6c0c5c538263a59ace08a095b.css.map ├── fonts │ ├── fontawesome-webfont.1dc35d2.ttf │ ├── fontawesome-webfont.c8ddf1e.woff │ └── fontawesome-webfont.e6cf7c6.woff2 ├── index.html └── js │ ├── app.8b801674da618ae1fb4d.js │ ├── app.8b801674da618ae1fb4d.js.map │ ├── manifest.6cc5ad0920809a83e254.js │ ├── manifest.6cc5ad0920809a83e254.js.map │ ├── vendor.5b51df77783bb28b5f63.js │ └── vendor.5b51df77783bb28b5f63.js.map ├── index.html ├── package.json ├── src ├── App.vue ├── components │ ├── BarChart.js │ ├── BaseChartMixin.js │ ├── BubbleChart.js │ ├── HBarChart.js │ ├── LineBarChart.js │ ├── LineChart.js │ ├── PieChart.js │ ├── README.md │ ├── StackedAreaChart.js │ └── index.js ├── examples │ ├── BarChart.vue │ ├── BubbleChart.vue │ ├── HBarChart.vue │ ├── LineBarChart.vue │ ├── LineChart.vue │ ├── PieChart.vue │ └── StackedAreaChart.vue └── main.js ├── static └── .gitkeep └── test ├── e2e ├── custom-assertions │ └── elementCount.js ├── nightwatch.conf.js ├── runner.js └── specs │ └── test.js └── unit ├── .eslintrc ├── index.js ├── karma.conf.js └── specs └── Hello.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-vue-jsx"], 4 | "comments": false, 5 | "env": { 6 | "test": { 7 | "plugins": [ "istanbul" ] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | test/unit/coverage 6 | test/e2e/reports 7 | selenium-debug.log 8 | .idea 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | test/unit/coverage 5 | test/e2e/reports 6 | selenium-debug.log 7 | .idea 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-nvd3 2 | 3 | The NVD3 chart library for Vue. 4 | 5 | > This library is just in beta version. It's only using in my project i will add the tests and examples in the future versions. 6 | 7 | 8 | ## Install 9 | 10 | ``` 11 | $ npm install vue-nvd3 12 | ``` 13 | 14 | [Live Demo](https://dotnetage.github.io/vue-nvd3) 15 | 16 | ## Components in this library 17 | 18 | Tag | Component 19 | ----|---------- 20 | ``| `BarChart` 21 | ``| `BubbleChart` 22 | ``| `HBarChart` 23 | ``| `LineBarChart` 24 | ``| `LineChart` 25 | ``| `PieChart` 26 | ``| `StackedAreaChart` 27 | 28 | ## Dependencies 29 | 30 | - vue: "^2.1.0" 31 | - nvd3: "^1.8.5", 32 | - d3: "^3.5.17" 33 | 34 | ## How to use 35 | 36 | ```js 37 | import Vue from 'Vue' 38 | import VueNVD3 from 'vue-nvd3' 39 | Vue.use(VueNVD3) 40 | ``` 41 | 42 | ## References 43 | 44 | ### `` - `BarChart` 45 | 46 | attribute | type | default | description 47 | ----------|------|---------|------------ 48 | `model`| `Array` | `[]` | The data to show on the chart 49 | `height` | `String` | `'300px'` | The chart height 50 | `textField`| `String`| `'label'` | Specify which field should be show as axis label text of the data model 51 | `valueField`| `String` | `'value'` | Specify which field should be use as axis values of the data model 52 | `staggerLabels`| `Boolean`| `true` | - 53 | `tooltips`| `Boolean`| `false`| Whether show the tooltips when mouse on the bars 54 | `showValues`| `Boolean`| `true` | Identity whether show the values on the chart 55 | `colors`| `Array`| `['#82DFD6', '#ddd']` | The bar colors 56 | 57 | 58 | 59 | ### `` - `BubbleChart` 60 | 61 | attribute | type | default | description 62 | ----------|------|---------|------------ 63 | `model`| `Array` | `[]` | The data to show on the chart 64 | `height` | `String` | `300px` | The chart height 65 | `xFormat` | `Function`, `String` | `undefined` | 66 | `yFormat` | `Function` `String` | `undefined` | 67 | `showDistX` | `Boolean` | `true` | 68 | `showDistY` | `Boolean` | `true` | 69 | `colors` | `Array` | `['#82DFD6', '#ddd']` | 70 | 71 | ### `` - `HBarChart` 72 | 73 | attribute | type | default | description 74 | ----------|------|---------|------------ 75 | `model`| `Array` | `[]` | The data to show on the chart 76 | `height` | `String` | `300px` | The chart height 77 | `textField`| `String`| `'label'` | Specify which field should be show as axis label text of the data model 78 | `valueField`| `String` | `'value'` | Specify which field should be use as axis values of the data model 79 | `height` | `Number`| `null` | 80 | `yFormat` | `Function`,`String` | `undefined` | 81 | `showControls` | `Boolean` | `true` | 82 | `colors` | `Array` | `['#82DFD6', '#ddd']` | 83 | 84 | 85 | ### `` - `LineBarChart` 86 | 87 | attribute | type | default | description 88 | ----------|------|---------|------------ 89 | `model`| `Array` | `[]` | The data to show on the chart 90 | `height` | `String` | `300px` | The chart height 91 | `xFormat` | `Function`, `String` | `undefined` | 92 | `y1Format` | `Function`, `String` | `undefined` | 93 | `y2Format` | `Function`, `String` | `undefined` | 94 | `colors`| `Array` | `['#82DFD6', '#ddd']` | 95 | 96 | ### `` - `LineChart` 97 | 98 | attribute | type | default | description 99 | ----------|------|---------|------------ 100 | `model`| `Array` | `[]` | The data to show on the chart 101 | `height` | `String` | `300px` | The chart height 102 | `xFormat` | `Function`, `String` | `undefined` | 103 | `yFormat`| `Function`, `String`| `undefined` | 104 | `colors` | `Array` | `['#82DFD6', '#ddd']`| 105 | 106 | ### `` - `PieChart` 107 | 108 | attribute | type | default | description 109 | ----------|------|---------|------------ 110 | `model`| `Array` | `[]` | The data to show on the chart 111 | `height` | `String` | `300px` | The chart height 112 | `showLabels` | `Boolean` | `true` | 113 | `margin` | `Object` | `{top: 30, right: 20, bottom: 20, left: 20}`, 114 | `width` | `Number` | `null` | 115 | `height` | `Number` |`null`| 116 | `showTooltipPercent` | `Boolean` | `false` | 117 | `showLegend`| `Boolean` | `true` | 118 | `legendPosition` | `String` | `'top'` | 119 | `labelThreshold` | `Number`| `0.05` | 120 | `labelType` | `String` | `'percent'` | 121 | `donut` | `Boolean` | `false` | 122 | `donutRatio`| `Number` | `0.35` | 123 | `textField`| `String`| `'label'` | Specify which field should be show as axis label text of the data model 124 | `valueField`| `String` | `'value'` | Specify which field should be use as axis values of the data model 125 | `colors` | `Array` | `['#82DFD6', '#ddd']` | 126 | 127 | ### `` - `StackedAreaChart` 128 | 129 | attribute | type | default | description 130 | ----------|------|---------|------------ 131 | `model`| `Array` | `[]` | The data to show on the chart 132 | `height` | `String` | `300px` | The chart height 133 | `xFormat` | `Function`, `String` |`undefined` | 134 | `yFormat` | `Function`, `String` |`undefined` | 135 | `rightAlignYAxis` | `Boolean` | `true` | 136 | `showControls` | `Boolean` | `true` | 137 | `clipEdge` | `Boolean` | `true` | 138 | `colors` | `Array` | `['#82DFD6', '#ddd']`| 139 | -------------------------------------------------------------------------------- /build/build-docs.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('./check-versions')() 3 | require('shelljs/global') 4 | env.NODE_ENV = 'production' 5 | 6 | var path = require('path') 7 | var config = require('../config') 8 | var ora = require('ora') 9 | var webpack = require('webpack') 10 | var webpackConfig = require('./webpack.docs.conf.js') 11 | 12 | console.log( 13 | ' Tip:\n' + 14 | ' Built files are meant to be served over an HTTP server.\n' + 15 | ' Opening index.html over file:// won\'t work.\n' 16 | ) 17 | 18 | var spinner = ora('building for docs...') 19 | spinner.start() 20 | 21 | var assetsPath = path.join(config.build.docsRoot, config.build.assetsSubDirectory) 22 | rm('-rf', assetsPath) 23 | mkdir('-p', assetsPath) 24 | cp('-R', 'static/*', assetsPath) 25 | 26 | webpack(webpackConfig, function (err, stats) { 27 | spinner.stop() 28 | if (err) throw err 29 | process.stdout.write(stats.toString({ 30 | colors: true, 31 | modules: false, 32 | children: false, 33 | chunks: false, 34 | chunkModules: false 35 | }) + '\n') 36 | }) 37 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('./check-versions')() 3 | require('shelljs/global') 4 | env.NODE_ENV = 'production' 5 | 6 | var path = require('path') 7 | var config = require('../config') 8 | var ora = require('ora') 9 | var webpack = require('webpack') 10 | var webpackConfig = require('./webpack.prod.conf') 11 | 12 | console.log( 13 | ' Tip:\n' + 14 | ' Built files are meant to be served over an HTTP server.\n' + 15 | ' Opening index.html over file:// won\'t work.\n' 16 | ) 17 | 18 | var spinner = ora('building for production...') 19 | spinner.start() 20 | 21 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 22 | rm('-rf', assetsPath) 23 | mkdir('-p', assetsPath) 24 | cp('-R', 'static/*', assetsPath) 25 | 26 | webpack(webpackConfig, function (err, stats) { 27 | spinner.stop() 28 | if (err) throw err 29 | process.stdout.write(stats.toString({ 30 | colors: true, 31 | modules: false, 32 | children: false, 33 | chunks: false, 34 | chunkModules: false 35 | }) + '\n') 36 | }) 37 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver') 2 | var chalk = require('chalk') 3 | var packageConfig = require('../package.json') 4 | var exec = function (cmd) { 5 | return require('child_process') 6 | .execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | var config = require('../config') 3 | if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 4 | var path = require('path') 5 | var express = require('express') 6 | var webpack = require('webpack') 7 | var opn = require('opn') 8 | var proxyMiddleware = require('http-proxy-middleware') 9 | var webpackConfig = process.env.NODE_ENV === 'testing' 10 | ? require('./webpack.prod.conf') 11 | : require('./webpack.dev.conf') 12 | 13 | // default port where dev server listens for incoming traffic 14 | var port = process.env.PORT || config.dev.port 15 | // Define HTTP proxies to your custom API backend 16 | // https://github.com/chimurai/http-proxy-middleware 17 | var proxyTable = config.dev.proxyTable 18 | 19 | var app = express() 20 | var compiler = webpack(webpackConfig) 21 | 22 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 23 | publicPath: webpackConfig.output.publicPath, 24 | quiet: true 25 | }) 26 | 27 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 28 | log: () => {} 29 | }) 30 | // force page reload when html-webpack-plugin template changes 31 | compiler.plugin('compilation', function (compilation) { 32 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 33 | hotMiddleware.publish({ action: 'reload' }) 34 | cb() 35 | }) 36 | }) 37 | 38 | // proxy api requests 39 | Object.keys(proxyTable).forEach(function (context) { 40 | var options = proxyTable[context] 41 | if (typeof options === 'string') { 42 | options = { target: options } 43 | } 44 | app.use(proxyMiddleware(context, options)) 45 | }) 46 | 47 | // handle fallback for HTML5 history API 48 | app.use(require('connect-history-api-fallback')()) 49 | 50 | // serve webpack bundle output 51 | app.use(devMiddleware) 52 | 53 | // enable hot-reload and state-preserving 54 | // compilation error display 55 | app.use(hotMiddleware) 56 | 57 | // serve pure static assets 58 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 59 | app.use(staticPath, express.static('./static')) 60 | 61 | var uri = 'http://localhost:' + port 62 | 63 | devMiddleware.waitUntilValid(function () { 64 | console.log('> Listening at ' + uri + '\n') 65 | }) 66 | 67 | module.exports = app.listen(port, function (err) { 68 | if (err) { 69 | console.log(err) 70 | return 71 | } 72 | 73 | // when env is testing, don't need open it 74 | if (process.env.NODE_ENV !== 'testing') { 75 | opn(uri) 76 | } 77 | }) 78 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | // Extract CSS when that option is specified 29 | // (which is the case during production build) 30 | if (options.extract) { 31 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 32 | } else { 33 | return ['vue-style-loader', sourceLoader].join('!') 34 | } 35 | } 36 | 37 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 38 | return { 39 | css: generateLoaders(['css']), 40 | postcss: generateLoaders(['css']), 41 | less: generateLoaders(['css', 'less']), 42 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 43 | scss: generateLoaders(['css', 'sass']), 44 | stylus: generateLoaders(['css', 'stylus']), 45 | styl: generateLoaders(['css', 'stylus']) 46 | } 47 | } 48 | 49 | // Generate loaders for standalone style files (outside of .vue) 50 | exports.styleLoaders = function (options) { 51 | var output = [] 52 | var loaders = exports.cssLoaders(options) 53 | for (var extension in loaders) { 54 | var loader = loaders[extension] 55 | output.push({ 56 | test: new RegExp('\\.' + extension + '$'), 57 | loader: loader 58 | }) 59 | } 60 | return output 61 | } 62 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var projectRoot = path.resolve(__dirname, '../') 5 | 6 | var env = process.env.NODE_ENV 7 | // check env & config/index.js to decide whether to enable CSS source maps for the 8 | // various preprocessor loaders added to vue-loader at the end of this file 9 | var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap) 10 | var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap) 11 | var useCssSourceMap = cssSourceMapDev || cssSourceMapProd 12 | 13 | module.exports = { 14 | 15 | output: { 16 | path: config.build.assetsRoot, 17 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 18 | filename: '[name].js' 19 | }, 20 | resolve: { 21 | extensions: ['', '.js', '.vue', '.json'], 22 | fallback: [path.join(__dirname, '../node_modules')], 23 | alias: { 24 | 'vue$': 'vue/dist/vue.common.js', 25 | 'src': path.resolve(__dirname, '../src'), 26 | 'assets': path.resolve(__dirname, '../src/assets'), 27 | 'components': path.resolve(__dirname, '../src/components') 28 | } 29 | }, 30 | resolveLoader: { 31 | fallback: [path.join(__dirname, '../node_modules')] 32 | }, 33 | module: { 34 | loaders: [ 35 | { 36 | test: /\.vue$/, 37 | loader: 'vue' 38 | }, 39 | { 40 | test: /\.js$/, 41 | loader: 'babel', 42 | include: [ 43 | path.join(projectRoot, 'src') 44 | ], 45 | exclude: /node_modules/ 46 | }, 47 | { 48 | test: /\.json$/, 49 | loader: 'json' 50 | }, 51 | { 52 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 53 | loader: 'url', 54 | query: { 55 | limit: 10000, 56 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 57 | } 58 | }, 59 | { 60 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 61 | loader: 'url', 62 | query: { 63 | limit: 10000, 64 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 65 | } 66 | } 67 | ] 68 | }, 69 | vue: { 70 | loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), 71 | postcss: [ 72 | require('autoprefixer')({ 73 | browsers: ['last 2 versions'] 74 | }) 75 | ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrors = require('friendly-errors-webpack-plugin') 8 | 9 | // // add hot-reload related code to entry chunks 10 | // Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | // baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | // }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | module: { 19 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 20 | }, 21 | // eval-source-map is faster for development 22 | devtool: '#eval-source-map', 23 | plugins: [ 24 | new webpack.DefinePlugin({ 25 | 'process.env': config.dev.env 26 | }), 27 | new webpack.ProvidePlugin({ 28 | $: "jquery", 29 | jQuery: "jquery", 30 | "window.jQuery": "jquery", 31 | "window.$": "jquery" 32 | }), 33 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 34 | new webpack.optimize.OccurrenceOrderPlugin(), 35 | new webpack.HotModuleReplacementPlugin(), 36 | new webpack.NoErrorsPlugin(), 37 | // https://github.com/ampedandwired/html-webpack-plugin 38 | new HtmlWebpackPlugin({ 39 | filename: 'index.html', 40 | template: 'index.html', 41 | inject: true 42 | }), 43 | new FriendlyErrors() 44 | ] 45 | }) 46 | -------------------------------------------------------------------------------- /build/webpack.docs.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config/index') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf.js') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env.js') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | entry: { 15 | app: './src/main.js' 16 | }, 17 | module: { 18 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 19 | }, 20 | devtool: config.build.productionSourceMap ? '#source-map' : false, 21 | output: { 22 | path: config.build.docsRoot, 23 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 24 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 25 | }, 26 | vue: { 27 | loaders: utils.cssLoaders({ 28 | sourceMap: config.build.productionSourceMap, 29 | extract: true 30 | }) 31 | }, 32 | plugins: [ 33 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 34 | new webpack.DefinePlugin({ 35 | 'process.env': env 36 | }), 37 | new webpack.ProvidePlugin({ 38 | $: "jquery", 39 | jQuery: "jquery", 40 | "window.jQuery": "jquery", 41 | "window.$": "jquery" 42 | }), 43 | new webpack.optimize.UglifyJsPlugin({ 44 | compress: { 45 | warnings: false 46 | } 47 | }), 48 | new webpack.optimize.OccurrenceOrderPlugin(), 49 | // extract css into its own file 50 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 51 | // generate dist index.html with correct asset hash for caching. 52 | // you can customize output by editing /index.html 53 | // see https://github.com/ampedandwired/html-webpack-plugin 54 | new HtmlWebpackPlugin({ 55 | filename: process.env.NODE_ENV === 'testing' 56 | ? 'index.html' 57 | : config.build.index, 58 | template: 'index.html', 59 | inject: true, 60 | minify: { 61 | removeComments: true, 62 | collapseWhitespace: true, 63 | removeAttributeQuotes: true 64 | // more options: 65 | // https://github.com/kangax/html-minifier#options-quick-reference 66 | }, 67 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 68 | chunksSortMode: 'dependency' 69 | }), 70 | // split vendor js into its own file 71 | new webpack.optimize.CommonsChunkPlugin({ 72 | name: 'vendor', 73 | minChunks: function (module, count) { 74 | // any required modules inside node_modules are extracted to vendor 75 | return ( 76 | module.resource && 77 | /\.js$/.test(module.resource) && 78 | module.resource.indexOf( 79 | path.join(__dirname, '../node_modules') 80 | ) === 0 81 | ) 82 | } 83 | }), 84 | // extract webpack runtime and module manifest to its own file in order to 85 | // prevent vendor hash from being updated whenever app bundle is updated 86 | new webpack.optimize.CommonsChunkPlugin({ 87 | name: 'manifest', 88 | chunks: ['vendor'] 89 | }) 90 | ] 91 | }) 92 | 93 | if (config.build.productionGzip) { 94 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 95 | 96 | webpackConfig.plugins.push( 97 | new CompressionWebpackPlugin({ 98 | asset: '[path].gz[query]', 99 | algorithm: 'gzip', 100 | test: new RegExp( 101 | '\\.(' + 102 | config.build.productionGzipExtensions.join('|') + 103 | ')$' 104 | ), 105 | threshold: 10240, 106 | minRatio: 0.8 107 | }) 108 | ) 109 | } 110 | 111 | module.exports = webpackConfig 112 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | // var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var baseWebpackConfig = merge(require('./webpack.base.conf'), { 14 | entry: { 15 | 'vue-nvd3': './src/components/index.js' 16 | }, 17 | externals: { 18 | vue: 'vue', 19 | d3: 'd3', 20 | nv: 'nvd3' 21 | }, 22 | module: { 23 | loaders: utils.styleLoaders({sourceMap: config.build.productionSourceMap, extract: true}) 24 | }, 25 | vue: { 26 | loaders: utils.cssLoaders({ 27 | sourceMap: config.build.productionSourceMap, 28 | extract: true 29 | }) 30 | }, 31 | plugins: [ 32 | new webpack.optimize.OccurrenceOrderPlugin(), 33 | // extract css into its own file 34 | new ExtractTextPlugin(utils.assetsPath('[name].css')), 35 | // generate dist index.html with correct asset hash for caching. 36 | // you can customize output by editing /index.html 37 | // see https://github.com/ampedandwired/html-webpack-plugin 38 | new webpack.BannerPlugin(config.build.banner, { 39 | raw: true, 40 | entryOnly: true 41 | }) 42 | ] 43 | }) 44 | 45 | module.exports = [ 46 | // dist 47 | merge({}, baseWebpackConfig, { 48 | output: { 49 | path: 'dist', 50 | filename: '[name].js', 51 | chunkFilename: '[id].js' 52 | }, 53 | devtool: config.build.productionSourceMap ? '#source-map' : false, 54 | plugins: [ 55 | // http://vuejs.github.io/vue-loader/workflow/production.html 56 | new webpack.DefinePlugin({ 57 | 'process.env': env 58 | }), 59 | new webpack.optimize.UglifyJsPlugin({ 60 | compress: { 61 | warnings: false 62 | } 63 | }) 64 | ] 65 | }), 66 | // dist common 67 | merge({}, baseWebpackConfig, { 68 | output: { 69 | path: 'dist', 70 | filename: '[name].common.js', 71 | chunkFilename: '[id].common.js', 72 | library: 'VueNVD3', 73 | libraryTarget: 'commonjs2' 74 | }, 75 | devtool: false, 76 | }) 77 | ] 78 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | var version = require('../package.json').version 4 | 5 | module.exports = { 6 | build: { 7 | env: require('./prod.env'), 8 | index: path.resolve(__dirname, '../docs/index.html'), 9 | assetsRoot: path.resolve(__dirname, '../dist'), 10 | docsRoot: path.resolve(__dirname, '../docs'), 11 | assetsSubDirectory: '', 12 | assetsPublicPath: '/', 13 | productionSourceMap: true, 14 | // Gzip off by default as many popular static hosts such as 15 | // Surge or Netlify already gzip all static assets for you. 16 | // Before setting to `true`, make sure to: 17 | // npm install --save-dev compression-webpack-plugin 18 | productionGzip: false, 19 | productionGzipExtensions: ['js', 'css'], 20 | banner: 21 | '/*!\n' + 22 | ' * VueNVD3 v' + version + ' (https://github.com/DotNetAge/vue-nvd3)\n' + 23 | ' * (c) ' + new Date().getFullYear() + ' Ray Liang\n' + 24 | ' * Released under the MIT License.\n' + 25 | ' */' 26 | }, 27 | dev: { 28 | env: require('./dev.env'), 29 | port: 8080, 30 | assetsSubDirectory: 'static', 31 | assetsPublicPath: '/', 32 | proxyTable: {}, 33 | // CSS Sourcemaps off by default because relative paths are "buggy" 34 | // with this option, according to the CSS-Loader README 35 | // (https://github.com/webpack/css-loader#sourcemaps) 36 | // In our experience, they generally work as expected, 37 | // just be aware of this issue when enabling this option. 38 | cssSourceMap: false 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.1dc35d2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetAge/vue-nvd3/86108893b76934631ac83e8a70443a24059cc960/docs/fonts/fontawesome-webfont.1dc35d2.ttf -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.c8ddf1e.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetAge/vue-nvd3/86108893b76934631ac83e8a70443a24059cc960/docs/fonts/fontawesome-webfont.c8ddf1e.woff -------------------------------------------------------------------------------- /docs/fonts/fontawesome-webfont.e6cf7c6.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetAge/vue-nvd3/86108893b76934631ac83e8a70443a24059cc960/docs/fonts/fontawesome-webfont.e6cf7c6.woff2 -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-nvd3 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/js/app.8b801674da618ae1fb4d.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1,0],[function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}var n=a(56),i=r(n),u=a(39),o=r(u),s=a(34),l=r(s),d=a(55),f=r(d),c=a(40),m=r(c),v=a(41),p=r(v),h=a(42),_=r(h),b=a(43),y=r(b),x=a(44),k=r(x),g=a(45),F=r(g),w=a(46),C=r(w);i.default.use(l.default),i.default.use(f.default);var D=new f.default({routes:[{name:"BarChart",path:"/examples/bar-chart",component:m.default},{name:"BubbleChart",path:"/examples/bubble-chart",component:p.default},{name:"HBarChart",path:"/examples/hbar-chart",component:_.default},{name:"LineBarChart",path:"/examples/line-bar-chart",component:y.default},{name:"LineChart",path:"/examples/line-chart",component:k.default},{name:"PieChart",path:"/examples/pie-chart",component:F.default},{name:"StackedAreaChart",path:"/examples/stacked-area-chart",component:C.default}]});new i.default({el:"#app",router:D,template:"",components:{App:o.default}})},,,function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={props:{model:{type:Array},height:{type:String,default:"300px"}},data:function(){return{chartRef:void 0}},watch:{model:function(t){this.chartRef&&this.redraw(this.chartRef)}},methods:{redraw:function(t){d3.select(this.$refs.chart).style("height",this.height).datum(this.model).transition().duration(500).call(t)}},render:function(t){return t("svg",{ref:"chart"},[])}}},,,,,,,,,,,,,,,,function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),a(37),a(36),a(38),e.default={name:"app",mounted:function(){this.$router.push({name:"BarChart"})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=r(n),u=a(5),o=r(u),s=a(2),l=r(s);e.default={data:function(){var t=function(){return{domain:i.default.Internet.domainName(),visits:i.default.random.number(1e4)}},e=o.default.range(i.default.random.number(20));return{trafficData:o.default.map(e,t)}},computed:{traffics:function(){return[{key:"visits",area:!0,values:o.default.map(this.trafficData,function(t){return{label:t.domain,value:t.visits}})}]}},methods:{formatDate:function(t){return l.default.time.format("%x")(new Date(t))}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=(r(n),a(5)),u=r(i),o=a(2),s=r(o);e.default={data:function(){return{series:this.randomData(4,40)}},methods:{randomData:function(t,e){var a=["circle","cross","triangle-up","triangle-down","diamond","square"],r=s.default.random.normal();return u.default.map(u.default.range(t),function(t){return{key:"Group "+t,values:u.default.map(u.default.range(e),function(t){return{x:r(),y:r(),size:Math.random(),shape:Math.random()>.95?a[t%6]:"circle"}})}})}}}},function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={data:function(){return{dataModel:[{key:"Series 1",color:"#d67777",values:[{label:"Group A",value:-1.8746444827653},{label:"Group B",value:-8.0961543492239},{label:"Group C",value:-.57072943117674},{label:"Group D",value:-2.4174010336624},{label:"Group E",value:-.72009071426284},{label:"Group F",value:-.77154485523777},{label:"Group G",value:-.90152097798131},{label:"Group H",value:-.91445417330854},{label:"Group I",value:-.055746319141851}]},{key:"Series 2",color:"#4f99b4",values:[{label:"Group A",value:25.307646510375},{label:"Group B",value:16.756779544553},{label:"Group C",value:18.451534877007},{label:"Group D",value:8.6142352811805},{label:"Group E",value:7.8082472075876},{label:"Group F",value:5.259101026956},{label:"Group G",value:.30947953487127},{label:"Group H",value:0},{label:"Group I",value:0}]}]}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=r(n),u=a(5),o=r(u),s=a(2),l=r(s);e.default={data:function(){var t=function(t,e){return{date:new Date("2016-"+t+"-"+e).getTime(),visits:i.default.random.number(1e4),views:i.default.random.number(2e4),losses:i.default.random.number(3e3),stay:i.default.random.number(50)}},e=o.default.range(31),a=i.default.random.number(12);return{trafficData:o.default.map(e,function(e){return t(a,e+1)})}},computed:{traffics:function(){return[{key:"visits",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.visits}})},{key:"views",values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.views}})},{key:"losses",bar:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.losses}})}]}},methods:{formatDate:function(t){return l.default.time.format("%x")(new Date(t))}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=r(n),u=a(5),o=r(u),s=a(2),l=r(s);e.default={data:function(){var t=function(t,e){return{date:new Date("2016-"+t+"-"+e).getTime(),visits:i.default.random.number(1e4),views:i.default.random.number(2e4),losses:i.default.random.number(3e3),stay:i.default.random.number(50)}},e=o.default.range(31),a=i.default.random.number(12);return{trafficData:o.default.map(e,function(e){return t(a,e+1)})}},computed:{traffics:function(){return[{key:"visits",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.visits}})},{key:"views",bar:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.views}})},{key:"losses",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.losses}})}]}},methods:{formatDate:function(t){return l.default.time.format("%x")(new Date(t))}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=r(n),u=a(5),o=(r(u),a(2));r(o);e.default={data:function(){return{pages:[{name:"首页",views:i.default.random.number(1e6),stay:i.default.random.number(100),ratio:i.default.random.number(100)/100},{name:"产品详情",views:i.default.random.number(1e6),stay:i.default.random.number(100),ratio:i.default.random.number(100)/100},{name:"搜索结果",views:i.default.random.number(1e6),stay:i.default.random.number(100),ratio:i.default.random.number(100)/100},{name:"产品列表",views:i.default.random.number(1e6),stay:i.default.random.number(100),ratio:i.default.random.number(100)/100},{name:"购物车",views:i.default.random.number(1e6),stay:i.default.random.number(100),ratio:i.default.random.number(100)/100}],refers:[]}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(1),i=r(n),u=a(5),o=r(u),s=a(2),l=r(s);e.default={data:function(){var t=function(t,e){return{date:new Date("2016-"+t+"-"+e).getTime(),visits:i.default.random.number(1e4),views:i.default.random.number(2e4),losses:i.default.random.number(3e3),stay:i.default.random.number(50)}},e=o.default.range(31),a=i.default.random.number(12);return{trafficData:o.default.map(e,function(e){return t(a,e+1)})}},computed:{traffics:function(){return[{key:"visits",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.visits}})},{key:"views",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.views}})},{key:"losses",area:!0,values:o.default.map(this.trafficData,function(t){return{x:t.date,y:t.losses}})}]}},methods:{formatDate:function(t){return l.default.time.format("%x")(new Date(t))}}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(4),i=r(n),u=a(3),o=r(u);e.default={name:"BarChart",mixins:[o.default],props:{textField:{type:String,default:"label"},valueField:{type:String,default:"value"},staggerLabels:{type:Boolean,default:!0},tooltips:{type:Boolean,default:!1},showValues:{type:Boolean,default:!0},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this,e=this.textField,a=this.valueField;i.default.addGraph(function(){var r=i.default.models.discreteBarChart().x(function(t){return t[e]}).y(function(t){return t[a]}).staggerLabels(t.staggerLabels).showValues(t.showValues);return t.redraw(r),t.chartRef=r,i.default.utils.windowResize(r.update),r})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=r(n),u=a(4),o=r(u),s=a(3),l=r(s);e.default={name:"BubbleChart",mixins:[l.default],props:{xFormat:{type:[Function,String]},yFormat:{type:[Function,String]},showDistX:{type:Boolean,default:!0},showDistY:{type:Boolean,default:!0},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this;o.default.addGraph(function(){var e=o.default.models.scatterChart().showDistX(!0).showDistY(!0).height(t.height).color(i.default.scale.category10().range());return t.xFormat&&("string"==typeof t.xFormat?e.xAxis.tickFormat(i.default.format(t.xFormat)):e.xAxis.tickFormat(t.xFormat)),t.yFormat&&("string"==typeof t.yFormat?e.yAxis.tickFormat(i.default.format(t.yFormat)):e.yAxis.tickFormat(t.yFormat)),t.redraw(e),t.chartRef=e,o.default.utils.windowResize(e.update),e})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=r(n),u=a(4),o=r(u),s=a(3),l=r(s);e.default={name:"HBarChart",mixins:[l.default],props:{textField:{type:String,default:"label"},valueField:{type:String,default:"value"},yFormat:{type:[Function,String]},height:{type:Number,default:350},showControls:{type:Boolean,default:!0},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this;o.default.addGraph(function(){var e=t.textField,a=t.valueField,r=o.default.models.multiBarHorizontalChart().x(function(t){return t[e]}).y(function(t){return t[a]}).controlLabels({grouped:"分组",stacked:"堆叠"}).color(t.colors).showValues(!0);return t.height&&r.height(t.height),t.yFormat&&("string"==typeof t.yFormat?r.yAxis.tickFormat(i.default.format(t.yFormat)):r.yAxis.tickFormat(t.yFormat)),t.redraw(r),t.chartRef=r,o.default.utils.windowResize(r.update),r})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=r(n),u=a(4),o=r(u),s=a(3),l=r(s);e.default={name:"LineBarChart",mixins:[l.default],props:{xFormat:{type:[Function,String]},x2Format:{type:[Function,String]},y1Format:{type:[Function,String]},y2Format:{type:[Function,String]},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this;o.default.addGraph(function(){var e=o.default.models.linePlusBarChart().margin({left:80,bottom:50,right:80,top:30}).color(t.colors);return t.xFormat&&("string"==typeof t.xFormat?e.xAxis.tickFormat(i.default.format(t.xFormat)):e.xAxis.tickFormat(t.xFormat)),t.x2Format&&("string"==typeof t.x2Format?e.x2Axis.tickFormat(i.default.format(t.x2Format)):e.x2Axis.tickFormat(t.x2Format)),t.y1Format&&("string"==typeof t.y1Format?e.y1Axis.tickFormat(i.default.format(t.y1Format)):e.y1Axis.tickFormat(t.y1Format)),t.y2Format&&("string"==typeof t.y2Format?e.y2Axis.tickFormat(i.default.format(t.y2Format)):e.y2Axis.tickFormat(t.y2Format)),e.bars.forceY([0]),i.default.select(t.$refs.chart).style("height",t.height).datum(t.model).transition().duration(500).call(e),o.default.utils.windowResize(e.update),e})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=r(n),u=a(4),o=r(u),s=a(3),l=r(s);e.default={name:"LineChart",mixins:[l.default],props:{xFormat:{type:[Function,String]},yFormat:{type:[Function,String]},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this;o.default.addGraph(function(){var e=o.default.models.lineChart().useInteractiveGuideline(!0).margin({left:50,bottom:30,right:0}).color(t.colors),a=e.xAxis.showMaxMin(!1);t.xFormat&&("string"==typeof t.xFormat?a.tickFormat(i.default.format(t.xFormat)):a.tickFormat(t.xFormat));var r=e.yAxis.showMaxMin(!1);return t.yFormat&&("string"==typeof t.yFormat?r.tickFormat(i.default.format(t.yFormat)):r.tickFormat(t.yFormat)),t.redraw(e),t.chartRef=e,o.default.utils.windowResize(e.update),e})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=(r(n),a(4)),u=r(i),o=a(3),s=r(o);e.default={name:"PieChart",mixins:[s.default],props:{showLabels:{type:Boolean,default:!0},margin:{top:30,right:20,bottom:20,left:20},width:{type:Number,default:null},height:{type:Number,default:null},showTooltipPercent:{type:Boolean,default:!1},showLegend:{type:Boolean,default:!0},legendPosition:{type:String,default:"top"},labelThreshold:{type:Number,default:.05},labelType:{type:String,default:"percent"},donut:{type:Boolean,default:!1},donutRatio:{type:Number,default:.35},textField:{type:String,default:"label"},valueField:{type:String,default:"value"},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this,e=this.textField,a=this.valueField;u.default.addGraph(function(){var r=u.default.models.pieChart().x(function(t){return t[e]}).y(function(t){return t[a]}).showLabels(t.showLabels).legendPosition(t.legendPosition).labelThreshold(t.labelThreshold).donut(t.donut).donutRatio(t.donutRatio).showTooltipPercent(t.showTooltipPercent).showLegend(t.showLegend);return t.width&&r.width(t.width),t.height&&r.height(t.height),t.redraw(r),t.chartRef=r,u.default.utils.windowResize(r.update),r})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(2),i=r(n),u=a(4),o=r(u),s=a(3),l=r(s);e.default={name:"StackedAreaChart",mixins:[l.default],props:{xFormat:{type:[Function,String]},yFormat:{type:[Function,String]},rightAlignYAxis:{type:Boolean,default:!0},showControls:{type:Boolean,default:!0},clipEdge:{type:Boolean,default:!0},colors:{type:Array,default:function(){return["#82DFD6","#ddd"]}}},mounted:function(){var t=this;o.default.addGraph(function(){var e=o.default.models.stackedAreaChart().margin({right:100}).useInteractiveGuideline(!0).rightAlignYAxis(t.rightAlignYAxis).showControls(t.showControls).clipEdge(t.clipEdge).controlLabels({stacked:"堆叠",stream:"流",expanded:"扩展"});return t.xFormat&&("string"==typeof t.xFormat?e.xAxis.tickFormat(i.default.format(t.xFormat)):e.xAxis.tickFormat(t.xFormat)),t.yFormat&&("string"==typeof t.yFormat?e.yAxis.tickFormat(i.default.format(t.yFormat)):e.yAxis.tickFormat(t.yFormat)),t.redraw(e),t.chartRef=e,o.default.utils.windowResize(e.update),e})}}},function(t,e,a){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(31),i=r(n),u=a(30),o=r(u),s=a(32),l=r(s),d=a(29),f=r(d),c=a(27),m=r(c),v=a(28),p=r(v),h=a(33),_=r(h);a(35),e.default=function(t,e){t.component("vn-line",i.default),t.component("vn-line-bar",o.default),t.component("vn-pie",l.default),t.component("vn-hbar",f.default),t.component("vn-bar",m.default),t.component("vn-bubble",p.default),t.component("vn-stacked-area",_.default)}},function(t,e){},function(t,e){},function(t,e){},,function(t,e,a){var r,n;r=a(19);var i=a(47);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(20);var i=a(54);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(21);var i=a(53);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(22);var i=a(50);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(23);var i=a(48);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(24);var i=a(51);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(25);var i=a(49);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e,a){var r,n;r=a(26);var i=a(52);n=r=r||{},"object"!=typeof r.default&&"function"!=typeof r.default||(n=r=r.default),"function"==typeof n&&(n=n.options),n.render=i.render,n.staticRenderFns=i.staticRenderFns,t.exports=r},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{attrs:{id:"app"}},[t._m(0),t._v(" "),a("div",{staticClass:"uk-margin-large-top uk-container uk-container-center"},[a("div",{staticClass:"uk-grid",attrs:{"data-uk-grid-margin":""}},[a("div",{staticClass:"uk-width-medium-1-1"},[a("div",{staticClass:"uk-grid"},[a("div",{staticClass:"uk-width-medium-1-4"},[a("ul",{staticClass:"uk-tab uk-tab-left uk-width-medium-1-1",attrs:{"data-uk-tab":""}},[a("li",{staticClass:"uk-active"},[a("router-link",{attrs:{to:{name:"BarChart"}}},[t._v("Bar chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"BubbleChart"}}},[t._v("Bubble chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"HBarChart"}}},[t._v("Multi-bar horizontal chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"LineChart"}}},[t._v("Line chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"LineBarChart"}}},[t._v("Line-Bar combo chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"PieChart"}}},[t._v("Pie chart")])],1),t._v(" "),a("li",[a("router-link",{attrs:{to:{name:"StackedAreaChart"}}},[t._v("Stacked area chart")])],1)])]),t._v(" "),a("div",{staticClass:"uk-width-medium-3-4"},[a("router-view")],1)])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("nav",{staticClass:"uk-navbar"},[a("div",{staticClass:"uk-container uk-container-center"},[a("a",{staticClass:"uk-navbar-brand",attrs:{href:""}},[t._v("Vue Nvd3 Example")]),t._v(" "),a("ul",{staticClass:"uk-navbar-nav"},[a("li",[a("a",{attrs:{href:"https://github.com/DotNetAge/vue-nvd3",target:"_blank"}},[t._v("Github")])]),t._v(" "),a("li",[a("a",{attrs:{href:"https://www.npmjs.com/package/vue-nvd3"}},[t._v("NPM")])])]),t._v(" "),a("div",{staticClass:"uk-navbar-flip"},[a("ul",{staticClass:"uk-navbar-nav"},[a("li",[a("a",{attrs:{href:"https://github.com/DotNetAge/vue-nvd3/issues",target:"_blank"}},[t._v("Issues")])]),t._v(" "),a("li",[a("a",{attrs:{href:"http://www.cnblogs.com/ray-liang",target:"_blank"}},[t._v("My Blog")])])])])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Line Bar combo chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-line-bar",{attrs:{model:t.traffics,"x-format":t.formatDate,"x2-format":t.formatDate,"y-format":",f"}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.trafficData))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Pie chart")]),t._v(" "),a("div",{staticClass:"uk-grid uk-margin-bottom"},[a("div",{staticClass:"uk-width-1-2"},[a("vn-pie",{attrs:{model:t.pages,height:400,"text-field":"name","value-field":"views","show-tooltip-percent":!0,"show-legend":!0}})],1),t._v(" "),a("div",{staticClass:"uk-width-1-2"},[a("vn-pie",{attrs:{model:t.pages,height:400,donut:!0,"text-field":"name","value-field":"views","show-tooltip-percent":!0,"show-legend":!1}})],1)]),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.pages))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('
\n\n
\n
\n\n
')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Multi-bar horizontal chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-hbar",{attrs:{model:t.dataModel,"y-format":".2f",height:400}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.dataModel))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Line chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-line",{attrs:{model:t.traffics,"x-format":t.formatDate,"y-format":",f"}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.trafficData))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Stacked area chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-stacked-area",{attrs:{model:t.traffics,"x-format":t.formatDate,"y-format":",f"}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.trafficData))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Bubble chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-bubble",{attrs:{model:t.series,"x-format":".02f","y-format":".02f"}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.series))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n ')])])])}]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h2",[t._v("Bar chart")]),t._v(" "),a("div",{staticClass:"uk-margin-bottom"},[a("vn-bar",{attrs:{model:t.traffics,"x-format":t.formatDate,"y-format":",f"}})],1),t._v(" "),a("div",{staticClass:"uk-width-medium-1-1"},[t._m(0),t._v(" "),a("ul",{staticClass:"uk-switcher uk-margin",attrs:{id:"tab-content"}},[t._m(1),t._v(" "),a("li",[a("pre",[a("code",[t._v(t._s(t.traffics))])])])])])])},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ul",{staticClass:"uk-tab",attrs:{"data-uk-tab":"{connect:'#tab-content'}"}},[a("li",{staticClass:"uk-active",attrs:{"aria-expanded":"true"}},[a("a",{attrs:{href:"#"}},[t._v("HTML")])]),t._v(" "),a("li",{attrs:{"aria-expanded":"false"}},[a("a",{attrs:{href:"#"}},[t._v("Data")])])])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"uk-active"},[a("pre",[a("code",[t._v('\n')])])])}]}}]); 2 | //# sourceMappingURL=app.8b801674da618ae1fb4d.js.map -------------------------------------------------------------------------------- /docs/js/manifest.6cc5ad0920809a83e254.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(n){if(r[n])return r[n].exports;var a=r[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n=window.webpackJsonp;window.webpackJsonp=function(o,p){for(var l,s,c=0,i=[];c 2 | 3 | 4 | 5 | vue-nvd3 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-nvd3", 3 | "version": "1.0.0", 4 | "description": "The NVD3 chart library for Vue", 5 | "author": "Ray ", 6 | "scripts": { 7 | "dev": "node build/dev-server.js", 8 | "build": "node build/build.js", 9 | "docs": "node build/build-docs.js", 10 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e" 13 | }, 14 | "main": "dist/vue-nvd3.common.js", 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/DotNetAge/vue-nvd3.git" 18 | }, 19 | "bugs": { 20 | "url": "https://github.com/DotNetAge/vue-nvd3.git/issues" 21 | }, 22 | "keywords": [ 23 | "d3", 24 | "nvd3", 25 | "vue", 26 | "vue2", 27 | "chart" 28 | ], 29 | "dependencies": { 30 | "vue": "^2.1.0", 31 | "nvd3": "^1.8.5", 32 | "d3": "^3.5.17" 33 | }, 34 | "devDependencies": { 35 | "Faker": "^0.7.2", 36 | "autoprefixer": "^6.4.0", 37 | "babel-core": "^6.0.0", 38 | "babel-helper-vue-jsx-merge-props": "^2.0.2", 39 | "babel-loader": "^6.0.0", 40 | "babel-plugin-istanbul": "^3.0.0", 41 | "babel-plugin-syntax-jsx": "^6.18.0", 42 | "babel-plugin-transform-runtime": "^6.0.0", 43 | "babel-plugin-transform-vue-jsx": "^3.3.0", 44 | "babel-preset-es2015": "^6.0.0", 45 | "babel-preset-stage-2": "^6.0.0", 46 | "babel-register": "^6.0.0", 47 | "chai": "^3.5.0", 48 | "chalk": "^1.1.3", 49 | "chromedriver": "^2.21.2", 50 | "connect-history-api-fallback": "^1.1.0", 51 | "cross-env": "^3.1.3", 52 | "cross-spawn": "^4.0.2", 53 | "css-loader": "^0.25.0", 54 | "eventsource-polyfill": "^0.9.6", 55 | "express": "^4.13.3", 56 | "extract-text-webpack-plugin": "^1.0.1", 57 | "file-loader": "^0.9.0", 58 | "friendly-errors-webpack-plugin": "^1.1.2", 59 | "function-bind": "^1.0.2", 60 | "html-webpack-plugin": "^2.8.1", 61 | "http-proxy-middleware": "^0.17.2", 62 | "inject-loader": "^2.0.1", 63 | "jquery": "^3.1.1", 64 | "json-loader": "^0.5.4", 65 | "karma": "^1.3.0", 66 | "karma-coverage": "^1.1.1", 67 | "karma-mocha": "^1.2.0", 68 | "karma-phantomjs-launcher": "^1.0.0", 69 | "karma-sinon-chai": "^1.2.0", 70 | "karma-sourcemap-loader": "^0.3.7", 71 | "karma-spec-reporter": "0.0.26", 72 | "karma-webpack": "^1.7.0", 73 | "lodash": "^4.17.4", 74 | "lolex": "^1.4.0", 75 | "mocha": "^3.1.0", 76 | "nightwatch": "^0.9.8", 77 | "opn": "^4.0.2", 78 | "ora": "^0.3.0", 79 | "phantomjs-prebuilt": "^2.1.3", 80 | "selenium-server": "2.53.1", 81 | "semver": "^5.3.0", 82 | "shelljs": "^0.7.4", 83 | "sinon": "^1.17.3", 84 | "sinon-chai": "^2.8.0", 85 | "uikit": "^2.27.2", 86 | "url-loader": "^0.5.7", 87 | "vue-loader": "^10.0.0", 88 | "vue-router": "^2.1.1", 89 | "vue-style-loader": "^1.0.0", 90 | "vue-template-compiler": "^2.1.0", 91 | "webpack": "^1.13.2", 92 | "webpack-dev-middleware": "^1.8.3", 93 | "webpack-hot-middleware": "^2.12.2", 94 | "webpack-merge": "^0.14.1" 95 | }, 96 | "engines": { 97 | "node": ">= 4.0.0", 98 | "npm": ">= 3.0.0" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 69 | -------------------------------------------------------------------------------- /src/components/BarChart.js: -------------------------------------------------------------------------------- 1 | import nv from 'nvd3' 2 | import BaseChartMixin from './BaseChartMixin' 3 | 4 | export default { 5 | name: 'BarChart', 6 | mixins: [BaseChartMixin], 7 | props: { 8 | textField: {type: String, default: 'label'}, 9 | valueField: {type: String, default: 'value'}, 10 | staggerLabels: {type: Boolean, default: true}, 11 | tooltips: {type: Boolean, default: false}, 12 | showValues: {type: Boolean, default: true}, 13 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 14 | }, 15 | mounted () { 16 | const textField = this.textField 17 | const valField = this.valueField 18 | 19 | nv.addGraph(() => { 20 | 21 | const chart = nv.models.discreteBarChart() 22 | .x(d => d[textField]) 23 | .y(d => d[valField]) 24 | //.colors(this.colors) 25 | .staggerLabels(this.staggerLabels) //Too many bars and not enough room? Try staggering labels. 26 | //.tooltips(this.tooltips) //Don't show tooltips 27 | .showValues(this.showValues) //...instead, show the bar value right on top of each bar. 28 | //.transitionDuration(350) 29 | 30 | this.redraw(chart) 31 | this.chartRef = chart 32 | 33 | nv.utils.windowResize(chart.update); 34 | return chart 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/components/BaseChartMixin.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | model: {type: Array}, 4 | height: {type: String, default: '300px'} 5 | }, 6 | data () { 7 | return { 8 | chartRef: undefined 9 | } 10 | }, 11 | watch: { 12 | model (value) { 13 | if (this.chartRef) { 14 | this.redraw(this.chartRef) 15 | } 16 | } 17 | }, 18 | methods: { 19 | redraw (chart) { 20 | d3.select(this.$refs.chart) 21 | .style('height', this.height) 22 | .datum(this.model) 23 | .transition() 24 | .duration(500) 25 | .call(chart) 26 | } 27 | }, 28 | render (h) { 29 | return 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/components/BubbleChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | import BaseChartMixin from './BaseChartMixin' 4 | 5 | export default { 6 | name: 'BubbleChart', 7 | mixins: [BaseChartMixin], 8 | props: { 9 | xFormat: {type: [Function, String]}, 10 | yFormat: {type: [Function, String]}, 11 | showDistX: {type: Boolean, default: true}, 12 | showDistY: {type: Boolean, default: true}, 13 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 14 | }, 15 | mounted () { 16 | nv.addGraph(() => { 17 | const chart = nv.models.scatterChart() 18 | .showDistX(true) //showDist, when true, will display those little distribution lines on the axis. 19 | .showDistY(true) 20 | .height(this.height) 21 | //.transitionDuration(350) 22 | .color(d3.scale.category10().range()) 23 | 24 | //Configure how the tooltip looks. 25 | //chart.tooltipContent(key => '

' + key + '

') 26 | 27 | //Axis settings 28 | if (this.xFormat) { 29 | if (typeof(this.xFormat) === 'string') { 30 | chart.xAxis.tickFormat(d3.format(this.xFormat)) 31 | } else { 32 | chart.xAxis.tickFormat(this.xFormat) 33 | } 34 | } 35 | 36 | if (this.yFormat) { 37 | if (typeof(this.yFormat) === 'string') { 38 | chart.yAxis.tickFormat(d3.format(this.yFormat)) 39 | } else { 40 | chart.yAxis.tickFormat(this.yFormat) 41 | } 42 | } 43 | 44 | //We want to show shapes other than circles. 45 | //chart.scatter.onlyCircles(false) 46 | 47 | this.redraw(chart) 48 | this.chartRef = chart 49 | 50 | nv.utils.windowResize(chart.update); 51 | return chart 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/components/HBarChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | import BaseChartMixin from './BaseChartMixin' 4 | 5 | /** 6 | * 垂直多列分组柱状图 7 | */ 8 | export default { 9 | name: 'HBarChart', 10 | mixins: [BaseChartMixin], 11 | props: { 12 | textField: {type: String, default: 'label'}, 13 | valueField: {type: String, default: 'value'}, 14 | yFormat: {type: [Function, String]}, 15 | height: {type: Number, default: 350}, 16 | showControls: {type: Boolean, default: true}, 17 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 18 | }, 19 | mounted () { 20 | nv.addGraph(() => { 21 | const textField = this.textField 22 | const valField = this.valueField 23 | const chart = nv.models.multiBarHorizontalChart() 24 | .x(function (d) { 25 | return d[textField] 26 | }) 27 | .y(function (d) { 28 | return d[valField] 29 | }) 30 | .controlLabels({ 31 | 'grouped': '分组', 32 | 'stacked': '堆叠' 33 | }) 34 | .color(this.colors) 35 | .showValues(true) //Show bar value next to each bar. 36 | //.tooltips(true) //Show tooltips on hover. 37 | //.transitionDuration(350) 38 | //.showControls(true) //Allow user to switch between "Grouped" and "Stacked" mode. 39 | 40 | if (this.height) { 41 | chart.height(this.height) 42 | } 43 | 44 | if (this.yFormat) { 45 | if (typeof(this.yFormat) === 'string') { 46 | chart.yAxis.tickFormat(d3.format(this.yFormat)) 47 | } else { 48 | chart.yAxis.tickFormat(this.yFormat) 49 | } 50 | } 51 | 52 | this.redraw(chart) 53 | this.chartRef = chart 54 | nv.utils.windowResize(chart.update); 55 | return chart 56 | }) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/components/LineBarChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | import BaseChartMixin from './BaseChartMixin' 4 | 5 | export default { 6 | name: 'LineBarChart', 7 | mixins: [BaseChartMixin], 8 | props: { 9 | xFormat: {type: [Function, String]}, 10 | x2Format: {type: [Function, String]}, 11 | y1Format: {type: [Function, String]}, 12 | y2Format: {type: [Function, String]}, 13 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 14 | }, 15 | mounted () { 16 | nv.addGraph(() => { 17 | const chart = nv.models.linePlusBarChart() 18 | .margin({left: 80, bottom: 50, right: 80, top: 30}) 19 | .color(this.colors) 20 | 21 | if (this.xFormat) { 22 | if (typeof(this.xFormat) === 'string') { 23 | chart.xAxis.tickFormat(d3.format(this.xFormat)) 24 | } else { 25 | chart.xAxis.tickFormat(this.xFormat) 26 | } 27 | } 28 | 29 | if (this.x2Format) { 30 | if (typeof(this.x2Format) === 'string') { 31 | chart.x2Axis.tickFormat(d3.format(this.x2Format)) 32 | } else { 33 | chart.x2Axis.tickFormat(this.x2Format) 34 | } 35 | } 36 | 37 | if (this.y1Format) { 38 | if (typeof(this.y1Format) === 'string') { 39 | chart.y1Axis.tickFormat(d3.format(this.y1Format)) 40 | } else { 41 | chart.y1Axis.tickFormat(this.y1Format) 42 | } 43 | } 44 | 45 | if (this.y2Format) { 46 | if (typeof(this.y2Format) === 'string') { 47 | chart.y2Axis.tickFormat(d3.format(this.y2Format)) 48 | } else { 49 | chart.y2Axis.tickFormat(this.y2Format) 50 | } 51 | } 52 | 53 | chart.bars.forceY([0]) 54 | 55 | d3.select(this.$refs.chart) 56 | .style('height', this.height) 57 | .datum(this.model) 58 | .transition() 59 | .duration(500) 60 | .call(chart) 61 | 62 | nv.utils.windowResize(chart.update); 63 | return chart 64 | }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/components/LineChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | import BaseChartMixin from './BaseChartMixin' 4 | 5 | export default { 6 | name: 'LineChart', 7 | mixins: [BaseChartMixin], 8 | props: { 9 | xFormat: {type: [Function, String]}, 10 | yFormat: {type: [Function, String]}, 11 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 12 | }, 13 | mounted () { 14 | nv.addGraph(() => { 15 | const chart = nv.models.lineChart() 16 | .useInteractiveGuideline(true) 17 | .margin({left: 50, bottom: 30, right: 0}) 18 | .color(this.colors) 19 | 20 | const xaxis = chart.xAxis.showMaxMin(false) 21 | 22 | if (this.xFormat) { 23 | if (typeof(this.xFormat) === 'string') { 24 | xaxis.tickFormat(d3.format(this.xFormat)) 25 | } else { 26 | xaxis.tickFormat(this.xFormat) 27 | } 28 | } 29 | 30 | const yaxis = chart.yAxis.showMaxMin(false) 31 | if (this.yFormat) { 32 | if (typeof(this.yFormat) === 'string') { 33 | yaxis.tickFormat(d3.format(this.yFormat)) 34 | } else { 35 | yaxis.tickFormat(this.yFormat) 36 | } 37 | } 38 | 39 | this.redraw(chart) 40 | this.chartRef = chart 41 | nv.utils.windowResize(chart.update); 42 | return chart 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/components/PieChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | import BaseChartMixin from './BaseChartMixin' 4 | 5 | export default { 6 | name: 'PieChart', 7 | mixins: [BaseChartMixin], 8 | props: { 9 | showLabels: {type: Boolean, default: true}, 10 | margin: {top: 30, right: 20, bottom: 20, left: 20}, 11 | width: {type: Number, default: null}, 12 | height: {type: Number, default: null}, 13 | showTooltipPercent: {type: Boolean, default: false}, 14 | showLegend: {type: Boolean, default: true}, 15 | legendPosition: {type: String, default: 'top'}, 16 | labelThreshold: {type: Number, default: 0.05}, 17 | labelType: {type: String, default: 'percent'}, 18 | donut: {type: Boolean, default: false}, 19 | donutRatio: {type: Number, default: 0.35}, 20 | textField: {type: String, default: 'label'}, 21 | valueField: {type: String, default: 'value'}, 22 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 23 | }, 24 | mounted () { 25 | const textField = this.textField 26 | const valField = this.valueField 27 | 28 | nv.addGraph(() => { 29 | const chart = nv.models.pieChart() 30 | .x(d => d[textField]) 31 | .y(d => d[valField]) 32 | .showLabels(this.showLabels) 33 | .legendPosition(this.legendPosition) 34 | .labelThreshold(this.labelThreshold) 35 | .donut(this.donut) 36 | .donutRatio(this.donutRatio) 37 | .showTooltipPercent(this.showTooltipPercent) 38 | .showLegend(this.showLegend) 39 | 40 | if (this.width) { 41 | chart.width(this.width) 42 | } 43 | 44 | if (this.height) { 45 | chart.height(this.height) 46 | } 47 | 48 | this.redraw(chart) 49 | this.chartRef = chart 50 | 51 | nv.utils.windowResize(chart.update); 52 | return chart 53 | }) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/components/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetAge/vue-nvd3/86108893b76934631ac83e8a70443a24059cc960/src/components/README.md -------------------------------------------------------------------------------- /src/components/StackedAreaChart.js: -------------------------------------------------------------------------------- 1 | import d3 from 'd3' 2 | import nv from 'nvd3' 3 | 4 | import BaseChartMixin from './BaseChartMixin' 5 | 6 | export default { 7 | name: 'StackedAreaChart', 8 | mixins: [BaseChartMixin], 9 | props: { 10 | xFormat: {type: [Function, String]}, 11 | yFormat: {type: [Function, String]}, 12 | rightAlignYAxis: {type: Boolean, default: true}, 13 | showControls: {type: Boolean, default: true}, 14 | clipEdge: {type: Boolean, default: true}, 15 | colors: {type: Array, default: () => ['#82DFD6', '#ddd']} 16 | }, 17 | mounted () { 18 | nv.addGraph(() => { 19 | const chart = nv.models.stackedAreaChart() 20 | .margin({right: 100}) 21 | .useInteractiveGuideline(true) //Tooltips which show all data points. Very nice! 22 | .rightAlignYAxis(this.rightAlignYAxis) //Let's move the y-axis to the right side. 23 | // .transitionDuration(500) 24 | .showControls(this.showControls) //Allow user to choose 'Stacked', 'Stream', 'Expanded' mode. 25 | .clipEdge(this.clipEdge) 26 | .controlLabels({ 27 | 'stacked':'堆叠', 28 | 'stream':'流', 29 | 'expanded':'扩展' 30 | }) 31 | 32 | //Axis settings 33 | if (this.xFormat) { 34 | if (typeof(this.xFormat) === 'string') { 35 | chart.xAxis.tickFormat(d3.format(this.xFormat)) 36 | } else { 37 | chart.xAxis.tickFormat(this.xFormat) 38 | } 39 | } 40 | if (this.yFormat) { 41 | if (typeof(this.yFormat) === 'string') { 42 | chart.yAxis.tickFormat(d3.format(this.yFormat)) 43 | } else { 44 | chart.yAxis.tickFormat(this.yFormat) 45 | } 46 | } 47 | 48 | //We want to show shapes other than circles. 49 | // chart.scatter.onlyCircles(false) 50 | 51 | this.redraw(chart) 52 | this.chartRef = chart 53 | 54 | nv.utils.windowResize(chart.update); 55 | return chart 56 | }) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import LineChart from './LineChart' 2 | import LineBarChart from './LineBarChart' 3 | import PieChart from './PieChart' 4 | import HGBarChart from './HBarChart' 5 | import BarChart from './BarChart' 6 | import BubbleChart from './BubbleChart' 7 | import StackedAreaChart from './StackedAreaChart' 8 | import 'nvd3/build/nv.d3.css' 9 | 10 | export default (Vue, options) => { 11 | Vue.component('vn-line', LineChart) 12 | Vue.component('vn-line-bar', LineBarChart) 13 | Vue.component('vn-pie', PieChart) 14 | Vue.component('vn-hbar', HGBarChart) 15 | Vue.component('vn-bar', BarChart) 16 | Vue.component('vn-bubble', BubbleChart) 17 | Vue.component('vn-stacked-area',StackedAreaChart) 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/BarChart.vue: -------------------------------------------------------------------------------- 1 | 30 | 73 | -------------------------------------------------------------------------------- /src/examples/BubbleChart.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 65 | -------------------------------------------------------------------------------- /src/examples/HBarChart.vue: -------------------------------------------------------------------------------- 1 | 29 | 123 | -------------------------------------------------------------------------------- /src/examples/LineBarChart.vue: -------------------------------------------------------------------------------- 1 | 32 | 98 | -------------------------------------------------------------------------------- /src/examples/LineChart.vue: -------------------------------------------------------------------------------- 1 | 31 | 98 | -------------------------------------------------------------------------------- /src/examples/PieChart.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 99 | -------------------------------------------------------------------------------- /src/examples/StackedAreaChart.vue: -------------------------------------------------------------------------------- 1 | 32 | 99 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | // import VueNVD3 from '../dist/vue-nvd3.common' 6 | // import '../dist/vue-nvd3.css' 7 | import VueNVD3 from 'components' 8 | import VueRouter from 'vue-router' 9 | import BarChartExample from './examples/BarChart.vue' 10 | import BubbleChartExample from './examples/BubbleChart.vue' 11 | import HBarChartExample from './examples/HBarChart.vue' 12 | import LineBarChartExample from './examples/LineBarChart.vue' 13 | import LineChartExample from './examples/LineChart.vue' 14 | import PieChartExample from './examples/PieChart.vue' 15 | import StackedAreaChartExample from './examples/StackedAreaChart.vue' 16 | 17 | Vue.use(VueNVD3) 18 | Vue.use(VueRouter) 19 | 20 | const router = new VueRouter({ 21 | routes: [ 22 | {name: 'BarChart', path: '/examples/bar-chart', component: BarChartExample}, 23 | {name: 'BubbleChart', path: '/examples/bubble-chart', component: BubbleChartExample}, 24 | {name: 'HBarChart', path: '/examples/hbar-chart', component: HBarChartExample}, 25 | {name: 'LineBarChart', path: '/examples/line-bar-chart', component: LineBarChartExample}, 26 | {name: 'LineChart', path: '/examples/line-chart', component: LineChartExample}, 27 | {name: 'PieChart', path: '/examples/pie-chart', component: PieChartExample}, 28 | {name: 'StackedAreaChart', path: '/examples/stacked-area-chart', component: StackedAreaChartExample} 29 | ] 30 | }) 31 | 32 | /* eslint-disable no-new */ 33 | new Vue({ 34 | el: '#app', 35 | router, 36 | template: '', 37 | components: {App} 38 | }) 39 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DotNetAge/vue-nvd3/86108893b76934631ac83e8a70443a24059cc960/static/.gitkeep -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/guide#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar', 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind') 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var path = require('path') 7 | var merge = require('webpack-merge') 8 | var baseConfig = require('../../build/webpack.base.conf') 9 | var utils = require('../../build/utils') 10 | var webpack = require('webpack') 11 | var projectRoot = path.resolve(__dirname, '../../') 12 | 13 | var webpackConfig = merge(baseConfig, { 14 | // use inline sourcemap for karma-sourcemap-loader 15 | module: { 16 | loaders: utils.styleLoaders() 17 | }, 18 | devtool: '#inline-source-map', 19 | vue: { 20 | loaders: { 21 | js: 'babel-loader' 22 | } 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': require('../../config/test.env') 27 | }) 28 | ] 29 | }) 30 | 31 | // no need for app entry during tests 32 | delete webpackConfig.entry 33 | 34 | // Use babel for test files too 35 | webpackConfig.module.loaders.some(function (loader, i) { 36 | if (/^babel(-loader)?$/.test(loader.loader)) { 37 | loader.include.push(path.resolve(projectRoot, 'test/unit')) 38 | return true 39 | } 40 | }) 41 | 42 | module.exports = function (config) { 43 | config.set({ 44 | // to run in additional browsers: 45 | // 1. install corresponding karma launcher 46 | // http://karma-runner.github.io/0.13/config/browsers.html 47 | // 2. add it to the `browsers` array below. 48 | browsers: ['PhantomJS'], 49 | frameworks: ['mocha', 'sinon-chai'], 50 | reporters: ['spec', 'coverage'], 51 | files: ['./index.js'], 52 | preprocessors: { 53 | './index.js': ['webpack', 'sourcemap'] 54 | }, 55 | webpack: webpackConfig, 56 | webpackMiddleware: { 57 | noInfo: true 58 | }, 59 | coverageReporter: { 60 | dir: './coverage', 61 | reporters: [ 62 | { type: 'lcov', subdir: '.' }, 63 | { type: 'text-summary' } 64 | ] 65 | } 66 | }) 67 | } 68 | -------------------------------------------------------------------------------- /test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from 'src/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | el: document.createElement('div'), 8 | render: (h) => h(Hello) 9 | }) 10 | expect(vm.$el.querySelector('.hello h1').textContent) 11 | .to.equal('Welcome to Your Vue.js App') 12 | }) 13 | }) 14 | --------------------------------------------------------------------------------