├── .codeclimate.yml ├── .eslintignore ├── .eslintrc.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE.md ├── README.md ├── docs ├── .eslintrc.yml ├── index.html └── samples │ ├── csv-datapoint.html │ ├── csv-dataset.html │ ├── csv-index.html │ ├── index.html │ ├── json-datapoint.html │ ├── json-dataset.html │ ├── json-index.html │ ├── jsonl-datapoint.html │ ├── jsonl-dataset.html │ ├── jsonl-index.html │ ├── sample-datapoint.csv │ ├── sample-datapoint.json │ ├── sample-datapoint.jsonl │ ├── sample-datapoint.xlsx │ ├── sample-dataset.csv │ ├── sample-dataset.json │ ├── sample-dataset.jsonl │ ├── sample-dataset.xlsx │ ├── sample-index.csv │ ├── sample-index.json │ ├── sample-index.jsonl │ ├── sample-index.xlsx │ ├── sheet-datapoint.html │ ├── sheet-dataset.html │ └── sheet-index.html ├── gulpfile.js ├── karma.config.js ├── package.json ├── rollup.config.js ├── samples ├── .eslintrc.yml ├── csv-datapoint.html ├── csv-dataset.html ├── csv-index.html ├── index.html ├── json-datapoint.html ├── json-dataset.html ├── json-index.html ├── jsonl-datapoint.html ├── jsonl-dataset.html ├── jsonl-index.html ├── sample-datapoint.csv ├── sample-datapoint.json ├── sample-datapoint.jsonl ├── sample-datapoint.xlsx ├── sample-dataset.csv ├── sample-dataset.json ├── sample-dataset.jsonl ├── sample-dataset.xlsx ├── sample-index.csv ├── sample-index.json ├── sample-index.jsonl ├── sample-index.xlsx ├── sheet-datapoint.html ├── sheet-dataset.html ├── sheet-index.html └── style.css ├── scripts └── release.sh ├── src ├── core │ └── core.datasource.js ├── datasources │ ├── datasource.csv.js │ ├── datasource.json.js │ ├── datasource.jsonLines.js │ ├── datasource.sheet.js │ └── index.js ├── helpers │ └── helpers.datasource.js ├── index.js └── plugins │ └── plugin.datasource.js └── test ├── .eslintrc.yml ├── index.js ├── specs └── helpers.datasource.spec.js └── utils.js /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | duplication: 3 | enabled: true 4 | config: 5 | languages: 6 | - javascript 7 | eslint: 8 | enabled: true 9 | channel: "eslint-3" 10 | fixme: 11 | enabled: true 12 | ratings: 13 | paths: 14 | - "samples/**/*.js" 15 | - "src/**/*.js" 16 | exclude_paths: 17 | - dist/**/* 18 | - docs/**/* 19 | - node_modules/**/* 20 | - test/**/* 21 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | docs/index.html 3 | docs/samples/index.html 4 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: chartjs 2 | 3 | parserOptions: 4 | sourceType: module 5 | 6 | env: 7 | browser: true 8 | node: true 9 | es6: true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | bower.json 4 | cc-test-reporter 5 | coverage/ 6 | dist/ 7 | node_modules/ 8 | package-lock.json 9 | *.swp 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /.git 2 | /dist/*.zip 3 | /node_modules 4 | /scripts 5 | 6 | .codeclimate.yml 7 | .DS_Store 8 | .gitignore 9 | .idea 10 | .travis.yml 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - lts/* 4 | 5 | before_script: 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter 9 | - chmod +x ./cc-test-reporter 10 | - ./cc-test-reporter before-build 11 | 12 | script: 13 | - gulp test --coverage 14 | - gulp lint 15 | - gulp package 16 | - gulp bower 17 | 18 | after_script: 19 | - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT 20 | 21 | # IMPORTANT: scripts require GITHUB_AUTH_TOKEN and GITHUB_AUTH_EMAIL environment variables 22 | # IMPORTANT: scripts has to be set executables in the Git repository (error 127) 23 | # https://github.com/travis-ci/travis-ci/issues/5538#issuecomment-225025939 24 | # http://stackoverflow.com/a/15572639 25 | 26 | deploy: 27 | - provider: script 28 | script: ./scripts/release.sh 29 | skip_cleanup: true 30 | on: 31 | branch: release 32 | - provider: releases 33 | api_key: $GITHUB_AUTH_TOKEN 34 | file: 35 | - "./dist/chartjs-plugin-datasource.js" 36 | - "./dist/chartjs-plugin-datasource.min.js" 37 | - "./dist/chartjs-plugin-datasource.zip" 38 | skip_cleanup: true 39 | on: 40 | tags: true 41 | - provider: npm 42 | email: $NPM_AUTH_EMAIL 43 | api_key: $NPM_AUTH_TOKEN 44 | skip_cleanup: true 45 | on: 46 | tags: true 47 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Akihiko Kusanagi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chartjs-plugin-datasource 2 | 3 | [![npm](https://img.shields.io/npm/v/chartjs-plugin-datasource.svg?style=flat-square)](https://npmjs.com/package/chartjs-plugin-datasource) [![Bower](https://img.shields.io/bower/v/chartjs-plugin-datasource.svg?style=flat-square)](https://libraries.io/bower/chartjs-plugin-datasource) [![Build](https://img.shields.io/travis/com/nagix/chartjs-plugin-datasource/master.svg?style=flat-square)](https://travis-ci.com/nagix/chartjs-plugin-datasource) [![Coverage](https://img.shields.io/codeclimate/coverage/nagix/chartjs-plugin-datasource.svg?style=flat-square)](https://codeclimate.com/github/nagix/chartjs-plugin-datasource) [![Maintainability](https://img.shields.io/codeclimate/maintainability/nagix/chartjs-plugin-datasource.svg?style=flat-square)](https://codeclimate.com/github/nagix/chartjs-plugin-datasource) 4 | 5 | *[Chart.js](https://www.chartjs.org) plugin for automatic data loading* 6 | 7 | Version 0.1 requires Chart.js 2.6.0 or later. If you use the sheet data source type, [SheetJS](https://github.com/SheetJS/js-xlsx) 0.8.0 or later is also required. 8 | 9 | ## Installation 10 | 11 | You can download the latest version of chartjs-plugin-datasource from the [GitHub releases](https://github.com/nagix/chartjs-plugin-datasource/releases/latest). 12 | 13 | To install via npm: 14 | 15 | ```bash 16 | npm install chartjs-plugin-datasource --save 17 | ``` 18 | 19 | To install via bower: 20 | 21 | ```bash 22 | bower install chartjs-plugin-datasource --save 23 | ``` 24 | 25 | To use CDN: 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | ## Usage 32 | 33 | chartjs-plugin-datasource can be used with ES6 modules, plain JavaScript and module loaders. 34 | 35 | chartjs-plugin-datasource requires [Chart.js](https://www.chartjs.org). If you use the sheet data source type, [SheetJS (xlsx)](https://github.com/SheetJS/js-xlsx) is also required. 36 | 37 | First, include Chart.js, xlsx.full.js (optional) and chartjs-plugin-datasource.js to your page. Note that chartjs-plugin-datasource must be loaded after the Chart.js and SheetJS libraries. Once imported, the plugin is available under the global property `ChartDataSource`. 38 | 39 | Then, you need to register the plugin to enable it for all charts in the page. 40 | 41 | ```js 42 | Chart.plugins.register(ChartDataSource); 43 | ``` 44 | 45 | Or, you can enable the plugin only for specific charts. 46 | 47 | ```js 48 | var chart = new Chart(ctx, { 49 | plugins: [ChartDataSource], 50 | options: { 51 | // ... 52 | } 53 | }); 54 | ``` 55 | 56 | Now, a data source URL can be specified as shown in the example below. By default, each row in a CSV file will be mapped to one dataset, and the first column and the first row will be treated as dataset labels and index labels respectively. 57 | 58 | ```js 59 | options: { 60 | plugins: { 61 | datasource: { 62 | url: 'sample-dataset.csv' 63 | } 64 | } 65 | } 66 | ``` 67 | 68 | sample-dataset.csv 69 | 70 | ```csv 71 | ,January,February,March,April,May,June,July 72 | Temperature,7,7,10,15,20,23,26 73 | Precipitation,8.1,14.9,41.0,31.4,42.6,57.5,36.0 74 | ``` 75 | 76 | Version 0.1 supports CSV, TSV (Tab-Separated Values), PSV (Pipe-Separated Values), JSON, Excel, OpenDocument and more. More data source types are to be added in the upcoming releases. 77 | 78 | ### Usage in ES6 as module 79 | 80 | Import the module as `ChartDataSource`, and register it in the same way as described above. 81 | 82 | ```js 83 | import ChartDataSource from 'chartjs-plugin-datasource'; 84 | ``` 85 | 86 | ## Tutorial and Samples 87 | 88 | You can find a tutorial and samples at [nagix.github.io/chartjs-plugin-datasource](https://nagix.github.io/chartjs-plugin-datasource). 89 | 90 | ## Configuration 91 | 92 | The plugin options can be changed at 2 different levels and with the following priority: 93 | 94 | - per chart: `options.plugins.datasource.*` 95 | - globally: `Chart.defaults.global.plugins.datasource.*` 96 | 97 | Common options between data source types are listed below. 98 | 99 | | Name | Type | Default | Description 100 | | ---- | ---- | ------- | ----------- 101 | | `type` | `string` | | Data source type. [`'csv'`](#csv-data-source), [`'json'`](#json-data-source), [`'jsonl'`](#json-lines-data-source) and [`'sheet'`](#sheet-data-source) are supported by default. If not set, the type will be determined based on the [file extension](#supported-data-format) in the specified URL. If the URL doesn't have an extension, `'json'` will be set. 102 | | `url` | `string` | | Data source URL. It must have the same origin as your page, or a response must have a proper [CORS](#cross-origin-resource-sharing-cors) header set. 103 | 104 | ### CSV Data Source 105 | 106 | The CSV data source supports delimiter-separated values such as CSV, TSV and PSV. The following options are available in `'csv'` data type. 107 | 108 | | Name | Type | Default | Description 109 | | ---- | ---- | ------- | ----------- 110 | | `delimiter` | `string` | | Delimiter for values. If not set, the delimiter will be determined based on the file extension in the specified URL. If the URL doesn't have an extension, `','` will be set. 111 | | `rowMapping` | `string` | `'dataset'` | Element type to which each row is mapped. [more...](#row-mapping) 112 | | `datasetLabels` | `boolean` | `true` | If `true`, the first column (when `rowMapping` is `'dataset'`) or the first row (when `rowMapping` is `'index'`) will be treated as dataset labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. 113 | | `indexLabels` | `boolean` | `true` | If `true`, the first row (when `rowMapping` is `'dataset'`) or the first column (when `rowMapping` is `'index'`) will be treated as index labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. 114 | | `datapointLabels` | `boolean` | `true` | If `true`, the first row will be treated as property labels for Point objects. If `false`, `['_dataset', 'x', 'y', 'r']` will be used. This option is valid only when `rowMapping` is `'datapoint'`. 115 | | `datapointLabelMapping` | `object` | `{_dataset: '_dataset', _index: 'x'}` | Key-value pairs for datapoint label mapping. This option is valid only when `rowMapping` is `'datapoint'`. [more...](#datapoint-label-mapping) 116 | 117 | ### JSON Data Source 118 | 119 | The JSON data source supports JSON data. The following options are available in `'json'` data type. 120 | 121 | | Name | Type | Default | Description 122 | | ---- | ---- | ------- | ----------- 123 | | `rowMapping` | `string` | `'dataset'` | Element type to which each row is mapped. [more...](#row-mapping) 124 | | `datasetLabels` | `string` | | [Simplified JSONPath](#simplified-jsonpath) expression for an array of the dataset labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. If not specified but each pair of a dataset label and data is represented as a key-value pair in the objects selected by `data`, those keys will be used. [more...](#simplified-jsonpath) 125 | | `indexLabels` | `string` | | Simplified JSONPath expression for an array of the index labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. If not specified but each pair of an index label and data is represented as a key-value pair in the objects selected by `data`, those keys will be used. [more...](#simplified-jsonpath) 126 | | `datapointLabelMapping` | `object` | `{_dataset: '_dataset', _index: 'x'}` | Key-value pairs for datapoint label mapping. This option is valid only when `rowMapping` is `'datapoint'`. [more...](#datapoint-label-mapping) 127 | | `data` | `string` | | Simplified JSONPath expression for a two-dimensional array of the data. [more...](#simplified-jsonpath) 128 | 129 | ### JSON Lines Data Source 130 | 131 | The JSON Lines data source supports [JSON Lines](http://jsonlines.org) data. The same options are supported in `'jsonl'` data type as the JSON data source, but they have different default values. 132 | 133 | | Name | Type | Default | Description 134 | | ---- | ---- | ------- | ----------- 135 | | `rowMapping` | `string` | `'index'` | Element type to which each row is mapped. [more...](#row-mapping) 136 | | `datasetLabels` | `string` | | [Simplified JSONPath](#simplified-jsonpath) expression for an array of the dataset labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. If not specified but each pair of a dataset label and data is represented as a key-value pair in the objects selected by `data`, those keys will be used. [more...](#simplified-jsonpath) 137 | | `indexLabels` | `string` | | Simplified JSONPath expression for an array of the index labels. This option is valid when `rowMapping` is `'dataset'` or `'index'`. If not specified but each pair of an index label and data is represented as a key-value pair in the objects selected by `data`, those keys will be used. [more...](#simplified-jsonpath) 138 | | `datapointLabelMapping` | `object` | `{_dataset: '_dataset', _index: 'x'}` | Key-value pairs for datapoint label mapping. This option is valid only when `rowMapping` is `'datapoint'`. [more...](#datapoint-label-mapping) 139 | | `data` | `string` | | Simplified JSONPath expression for a two-dimensional array of the data. [more...](#simplified-jsonpath) 140 | 141 | #### Simplified JSONPath 142 | 143 | This plugin uses a simplified version of [JSONPath](https://goessner.net/articles/JsonPath/) expression to select an array or two-dimensional array from a JSON document. The top level element in JSON data is an object while that in JSON Lines data is an array. The following elements can be used in an expression. 144 | 145 | | Element | Description 146 | | ------- | ----------- 147 | | `.` or `[]` | Child/array operator. 148 | | `*` | Wildcard. All objects/elements regardless their names. 149 | | `[,]` | Union operator results in a combination of children/array indices sets. 150 | 151 | Below are a sample JSON document, Simplified JSONPath expressions and their results. 152 | 153 | ```json 154 | { 155 | "labels": ["January", "February", "March", "April", "May"], 156 | "datasets": [{ 157 | "label": "Temperature", 158 | "data": [7, 7, 10, 15, 20] 159 | }, { 160 | "label": "Precipitation", 161 | "data": [8.1, 14.9, 41.0, 31.4, 42.6] 162 | }] 163 | } 164 | ``` 165 | 166 | | Simplified JSONPath Expression | Result 167 | | ------------------------------ | ------ 168 | | `'labels'` | `['January', 'February', 'March', 'April', 'May']` 169 | | `'datasets[*].label'` | `['Temperature', 'Precipitation']` 170 | | `'datasets[*].data'` | `[[7, 7, 10, 15, 20], [8.1, 14.9, 41.0, 31.4, 42.6]]` 171 | | `'[label[0], datasets[*].data[0]]'` | `['January', [5, 6]]` 172 | 173 | So, the JSONPath expressions in the plugin options will look like below. 174 | 175 | ```js 176 | options: { 177 | plugins: { 178 | datasource: { 179 | url: 'sample-dataset.json', 180 | datasetLabels: 'datasets[*].label', 181 | indexLabels: 'labels', 182 | data: 'datasets[*].data' 183 | } 184 | } 185 | } 186 | ``` 187 | 188 | A JSON document may consist of nested objects where key-value pairs represent labels and corresponding data. In that case, dataset labels and/or index labels will be retrieved automatically, and there is no need to specify `datasetLabels` and `indexLabels` options. The following example will generate the same chart as the previous one. 189 | 190 | ```json 191 | { 192 | "Temperature": { 193 | "January": 7, 194 | "February": 7, 195 | "March": 10, 196 | "April": 15, 197 | "May": 20 198 | }, 199 | "Precipitation": { 200 | "January": 8.1, 201 | "February": 14.9, 202 | "March": 41.0, 203 | "April": 31.4, 204 | "May": 42.0 205 | } 206 | } 207 | ``` 208 | 209 | ```js 210 | options: { 211 | plugins: { 212 | datasource: { 213 | url: 'sample-dataset.json', 214 | data: '*.*' 215 | } 216 | } 217 | } 218 | ``` 219 | 220 | If you want to specify the order of labels explicitly, you can use union operators as shown below. 221 | 222 | ```js 223 | options: { 224 | plugins: { 225 | datasource: { 226 | url: 'sample-dataset.json', 227 | data: '[Temperature, Precipitation][January, February, March, April, May]' 228 | } 229 | } 230 | } 231 | ``` 232 | 233 | ### Sheet Data Source 234 | 235 | The sheet data source supports various spreadsheet formats such as Excel and OpenDocument. The following options are available in `'sheet'` data type. 236 | 237 | | Name | Type | Default | Description 238 | | ---- | ---- | ------- | ----------- 239 | | `rowMapping` | `string` | `'dataset'` | Element type to which each row is mapped. [more...](#row-mapping) 240 | | `datasetLabels` | `string` | | Range for dataset labels ([A1 Notation](#a1-notation)). This option is valid when `rowMapping` is `'dataset'` or `'index'`. If neither `datasetLabels` nor `data` are specified, the first column or row from the auto-detected range will be selected. 241 | | `indexLabels` | `string` | | Range for index labels (A1 Notation). This option is valid when `rowMapping` is `'dataset'` or `'index'`. If neither `indexLabels` nor `data` are specified, the first row or column from the auto-detected range will be selected. 242 | | `datapointLabels` | `string` | | Range for property labels for Point objects (A1 Notation). This option is valid only when `rowMapping` is `'datapoint'`. If neither `datapointLabels` nor `data` are specified, the first row from the auto-detected range will be selected. If no data is found, `['_dataset', 'x', 'y', 'r']` will be used. 243 | | `datapointLabelMapping` | `object` | `{_dataset: '_dataset', _index: 'x'}` | Key-value pairs for datapoint label mapping. This option is valid only when `rowMapping` is `'datapoint'`. [more...](#datapoint-label-mapping) 244 | | `data` | `string` | | Range for the data (A1 Notation). If not specified, the range will be detected automatically. 245 | 246 | #### A1 Notation 247 | 248 | Some options require a range in A1 notation. This is a string like `Sheet1!A1:B2` that refers to a group of cells in the spreadsheet. For example, valid ranges are: 249 | 250 | - `Sheet1!A1:B2` refers to the first two cells in the top two rows of Sheet1. 251 | - `Sheet1!A:A` refers to all the cells in the first column of Sheet1. 252 | - `Sheet1!1:2` refers to the all the cells in the first two rows of Sheet1. 253 | - `Sheet1!A5:A` refers to all the cells of the first column of Sheet 1, from row 5 onward. 254 | - `A1:B2` refers to the first two cells in the top two rows of the first visible sheet. 255 | - `Sheet1` refers to all the cells in Sheet1. 256 | 257 | If the sheet name has spaces or starts with a bracket, surround the sheet name with single quotes (`'`), e.g `'Sheet One'!A1:B2`. For simplicity, it is safe to always surround the sheet name with single quotes. 258 | 259 | ### Row Mapping 260 | 261 | `rowMapping` indicates an element type to which each row is mapped. Available values are listed below. 262 | 263 | - `'dataset'` 264 | - `'index'` 265 | - `'datapoint'` 266 | 267 | When each row contains values for one dataset, `'dataset'` is used. In many cases, the first column contains dataset labels and the first row contains index labels. Below is an example of dataset-mapped rows. 268 | 269 | | | January | February | March | April | May 270 | | - | ------: | -------: | ----: | ----: | --: 271 | | Temperature | 7 | 7 | 10 | 15 | 20 272 | | Precipitation | 8.1 | 14.9 | 41.0 | 31.4 | 42.6 273 | 274 | When each row contains values for one index, `'index'` is used. In many cases, the first column contains index labels and the first row contains dataset labels. Below is an example of index-mapped rows. 275 | 276 | | | Temperature | Precipitation 277 | | - | --------: | --------: 278 | | January | 7 | 8.1 279 | | February | 7 | 14.9 280 | | March | 10 | 41.0 281 | | April | 15 | 31.4 282 | | May | 20 | 42.6 283 | 284 | When each row contains values for one data point, `'datapoint'` is used. This type of data formatting is often called [Tidy Data](http://vita.had.co.nz/papers/tidy-data.pdf). The first row can have datapoint labels. Below is an example of datapoint-mapped rows. 285 | 286 | | dataset | month | value 287 | | ------- | ----- | ----: 288 | | Temperature | January | 7 289 | | Temperature | February | 7 290 | | Temperature | March | 10 291 | | Temperature | April | 15 292 | | Temperature | May | 20 293 | | Precipitation | January | 8.1 294 | | Precipitation | February | 14.9 295 | | Precipitation | March | 41.0 296 | | Precipitation | April | 31.4 297 | | Precipitation | May | 42.6 298 | 299 | ### Datapoint Label Mapping 300 | 301 | If `rowMapping` is `'datapoint'`, `datapointLabelMapping` can be used to correspond each column to specific datapoint property. It consists of key-value pairs where the key is a property name in Point data used in the [line chart](https://www.chartjs.org/docs/latest/charts/line.html#point), [bubble chart](https://www.chartjs.org/docs/latest/charts/bubble.html#data-structure) and [scatter chart](https://www.chartjs.org/docs/latest/charts/scatter.html#data-structure), and the value is a datapoint label specified by the `datapointLabels` option or a property name in case of `'json'` and `'jsonl'` data sources. 302 | 303 | The following keys are used to indicate a special usage of the column. 304 | 305 | - `_dataset`: This column is treated as dataset labels 306 | - `_index`: This column is treated as index labels 307 | 308 | In the following example, the values in the column labeled as `'month'` will be mapped to the property `x`, and the ones in the column labeled as `'value'` will be mapped to the property `y`. 309 | 310 | ```js 311 | datapointLabelMapping: { 312 | _dataset: 'dataset', 313 | _index: 'month', 314 | x: 'month', 315 | y: 'value' 316 | } 317 | ``` 318 | 319 | If the data source type is `'csv'`, a value can be a number instead of a label text. In that case, it indicates the column index starting with 0. If the data source type is `'sheet'`, a value can be a column-only A1 notation (for example, `'B'` indicates the second column). Below is an example of a CSV data source specifying the column index for each property in Point data. 320 | 321 | ```js 322 | datapointLabelMapping: { 323 | _dataset: 0, 324 | _index: 1, 325 | x: 1, 326 | y: 2 327 | } 328 | ``` 329 | 330 | ## Supported Data Format 331 | 332 | All supported data formats are listed below. 333 | 334 | | Data
Source
Type | Format | Extension | Description 335 | | ---------------- | ------ | --------- | ----------- 336 | | CSV | CSV | `csv` | [RFC 4180](https://www.ietf.org/rfc/rfc4180.txt)-compliant Comma-Separated Values. The default delimiter is `','`. 337 | | CSV | TSV | `tsv` | Tab-Separated Values. The default delimiter is `'\t'`. 338 | | CSV | PSV | `psv` | Pipe-Separated Values. The default delimiter is `'|'`. 339 | | JSON | JSON | `json` | JSON 340 | | JSON Lines | JSON Lines | `jsonl` | [JSON Lines](http://jsonlines.org) 341 | | Sheet | XLSX/XLSM | `xlsx` `xlsm` | [Excel 2007+ XML Formats](https://github.com/SheetJS/js-xlsx#excel-2007-xml-xlsxxlsm) 342 | | Sheet | XLSB BIFF12 | `xlsb` | [Excel 2007+ Binary](https://github.com/SheetJS/js-xlsx#excel-2007-binary-xlsb-biff12) 343 | | Sheet | XML SpreadsheetML | `xml` | [Excel 2003-2004 XML Format](https://github.com/SheetJS/js-xlsx#excel-2003-2004-spreadsheetml) 344 | | Sheet | XLS BIFF8 | `xls` | [Excel 97-2004](https://github.com/SheetJS/js-xlsx#excel-97-2004-binary-biff8) 345 | | Sheet | XLS BIFF5 | `xls` | [Excel 5.0/95](https://github.com/SheetJS/js-xlsx#excel-20-95-biff2biff3biff4biff5) 346 | | Sheet | XLS/XLW BIFF4 | `xls` `xlw` | [Excel 4.0](https://github.com/SheetJS/js-xlsx#excel-20-95-biff2biff3biff4biff5) 347 | | Sheet | XLS BIFF3 | `xls` | [Excel 3.0](https://github.com/SheetJS/js-xlsx#excel-20-95-biff2biff3biff4biff5) 348 | | Sheet | XLS BIFF2 | `xls` | [Excel 2.0/2.1](https://github.com/SheetJS/js-xlsx#excel-20-95-biff2biff3biff4biff5) 349 | | Sheet | CSV/TXT | `csv` `txt` | [Delimiter-Separated Values](https://github.com/SheetJS/js-xlsx#delimiter-separated-values-csvtxt) 350 | | Sheet | DIF | `dif` | [Data Interchange Format](https://github.com/SheetJS/js-xlsx#data-interchange-format-dif) 351 | | Sheet | SYLK/SLK | `sylk` `slk` | [Symbolic Link](https://github.com/SheetJS/js-xlsx#symbolic-link-sylk) 352 | | Sheet | PRN | `prn` | [Lotus Formatted Text](https://github.com/SheetJS/js-xlsx#lotus-formatted-text-prn) 353 | | Sheet | TXT | `txt` | UTF-16 Unicode Text 354 | | Sheet | ODS | `ods` | [OpenDocument Spreadsheet](https://github.com/SheetJS/js-xlsx#opendocument-spreadsheet-odsfods) 355 | | Sheet | DODS | `fods` | [Flat XML ODF Spreadsheet](https://github.com/SheetJS/js-xlsx#opendocument-spreadsheet-odsfods) 356 | | Sheet | 标文通 UOS1/UOS2 | `uos` | [Uniform Office Format Spreadsheet](https://github.com/SheetJS/js-xlsx#uniform-office-spreadsheet-uos12) 357 | | Sheet | DBF | `dbf` | [dBASE II/III/IV / Visual FoxPro](https://github.com/SheetJS/js-xlsx#dbase-and-visual-foxpro-dbf) 358 | | Sheet | WKS/WK1/WK2/WK3/WK4/123 | `wks` `wk1` `wk2` `wk3` `wk4` `123` | [Lotus 1-2-3](https://github.com/SheetJS/js-xlsx#lotus-1-2-3-wkswk1wk2wk3wk4123) 359 | | Sheet | WQ1/WQ2/WB1/WB2/WB3/QPW | `wq1` `wq2` `wb1` `wb2` `wb3` `qpw` | [Quattro Pro Spreadsheet](https://github.com/SheetJS/js-xlsx#quattro-pro-wq1wq2wb1wb2wb3qpw) 360 | | Sheet | HTML | `html` `htm`| [HTML Tables](https://github.com/SheetJS/js-xlsx#html) 361 | | Sheet | ETH | `eth` | [EtherCalc Record Format](https://github.com/SheetJS/js-xlsx#ethercalc-record-format-eth) 362 | 363 | ## Cross-Origin Resource Sharing (CORS) 364 | 365 | If your data source doesn't share the origin (domain, protocol and port) with your page, the HTTP response from the data source must include the right CORS headers to allow cross-site requests. Modern browsers handle the client-side components of cross-origin sharing, including headers and policy enforcement, and no extra code or configuration is required in your page. But, the server at the data source needs to have the proper configuration to handle requests and response headers. 366 | 367 | Response HTTP headers must include at least the following header, which indicates that requests from this origin will be allowed. 368 | 369 | ``` 370 | Access-Control-Allow-Origin: [:][:] 371 | ``` 372 | 373 | The value can also be `*` which means that the resource can be accessed by any domain in a cross-site manner. 374 | 375 | ``` 376 | Access-Control-Allow-Origin: * 377 | ``` 378 | 379 | See [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for more details. 380 | 381 | ## Building 382 | 383 | You first need to install node dependencies (requires [Node.js](https://nodejs.org/)): 384 | 385 | ```bash 386 | npm install 387 | ``` 388 | 389 | The following commands will then be available from the repository root: 390 | 391 | ```bash 392 | gulp build # build dist files 393 | gulp build --watch # build and watch for changes 394 | gulp test # run all tests 395 | gulp test --watch # run all tests and watch for changes 396 | gulp test --coverage # run all tests and generate code coverage 397 | gulp lint # perform code linting 398 | gulp package # create an archive with dist files and samples 399 | ``` 400 | 401 | ## License 402 | 403 | chartjs-plugin-datasource is available under the [MIT license](https://opensource.org/licenses/MIT). 404 | -------------------------------------------------------------------------------- /docs/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | plugins: [es, html] 2 | 3 | extends: [ 4 | plugin:es/no-2018, 5 | plugin:es/no-2017, 6 | plugin:es/no-2016, 7 | plugin:es/no-2015 8 | ] 9 | 10 | globals: 11 | Chart: true 12 | XLSX: true 13 | ChartDataSource: true 14 | 15 | parserOptions: 16 | sourceType: script 17 | 18 | rules: 19 | no-unused-vars: 0 20 | -------------------------------------------------------------------------------- /docs/samples/csv-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'CSV data source (datapoint) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'csv',
105 | 				url: 'sample-datapoint.csv',
106 | 				delimiter: ',',
107 | 				rowMapping: 'datapoint',
108 | 				datapointLabels: true,
109 | 				datapointLabelMapping: {
110 | 					_dataset: 'dataset',
111 | 					_index: 'month',
112 | 					x: 'month',
113 | 					y: 'value'
114 | 				}
115 | 			}
116 | 		}
117 | 	}
118 | };
119 | 
120 | window.onload = function() {
121 | 	var ctx = document.getElementById('myChart').getContext('2d');
122 | 	window.myChart = new Chart(ctx, config);
123 | };
124 |
125 |
126 |
dataset,month,value
127 | Temperature,January,7
128 | Temperature,February,7
129 | Temperature,March,10
130 | Temperature,April,15
131 | Temperature,May,20
132 | Temperature,June,23
133 | Temperature,July,26
134 | Precipitation,January,8.1
135 | Precipitation,February,14.9
136 | Precipitation,March,41.0
137 | Precipitation,April,31.4
138 | Precipitation,May,42.6
139 | Precipitation,June,57.5
140 | Precipitation,July,36.0
141 |
142 |
143 |
<head>
144 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
145 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
146 | </head>
147 | <body>
148 | 	<div>
149 | 		<canvas id="myChart"></canvas>
150 | 	</div>
151 | </body>
152 |
153 |
154 |
155 | 156 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /docs/samples/csv-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'CSV data source (dataset) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'csv',
105 | 				url: 'sample-dataset.csv',
106 | 				delimiter: ',',
107 | 				rowMapping: 'dataset',
108 | 				datasetLabels: true,
109 | 				indexLabels: true
110 | 			}
111 | 		}
112 | 	}
113 | };
114 | 
115 | window.onload = function() {
116 | 	var ctx = document.getElementById('myChart').getContext('2d');
117 | 	window.myChart = new Chart(ctx, config);
118 | };
119 |
120 |
121 |
,January,February,March,April,May,June,July
122 | Temperature,7,7,10,15,20,23,26
123 | Precipitation,8.1,14.9,41.0,31.4,42.6,57.5,36.0
124 |
125 |
126 |
<head>
127 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
128 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
129 | </head>
130 | <body>
131 | 	<div>
132 | 		<canvas id="myChart"></canvas>
133 | 	</div>
134 | </body>
135 |
136 |
137 |
138 | 139 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /docs/samples/csv-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'CSV data source (index) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'csv',
105 | 				url: 'sample-index.csv',
106 | 				delimiter: ',',
107 | 				rowMapping: 'index',
108 | 				datasetLabels: true,
109 | 				indexLabels: true
110 | 			}
111 | 		}
112 | 	}
113 | };
114 | 
115 | window.onload = function() {
116 | 	var ctx = document.getElementById('myChart').getContext('2d');
117 | 	window.myChart = new Chart(ctx, config);
118 | };
119 |
120 |
121 |
,Temperature,Precipitation
122 | January,7,8.1
123 | February,7,14.9
124 | March,10,41.0
125 | April,15,31.4
126 | May,20,42.6
127 | June,23,57.5
128 | July,26,36.0
129 |
130 |
131 |
<head>
132 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
133 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
134 | </head>
135 | <body>
136 | 	<div>
137 | 		<canvas id="myChart"></canvas>
138 | 	</div>
139 | </body>
140 |
141 |
142 |
143 | 144 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /docs/samples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | chartjs-plugin-datasource Samples 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

chartjs-plugin-datasource
Samples

20 |

Tutorial | GitHub

21 |
22 |
23 | 45 |
46 | 47 |
48 | 53 | 54 | 55 | 56 | 59 |
60 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/samples/json-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON data source (datapoint) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'json',
105 | 				url: 'sample-datapoint.json',
106 | 				rowMapping: 'datapoint',
107 | 				datapointLabelMapping: {
108 | 					_dataset: 'dataset',
109 | 					_index: 'month',
110 | 					x: 'month',
111 | 					y: 'value'
112 | 				},
113 | 				data: '*.*'
114 | 			}
115 | 		}
116 | 	}
117 | };
118 | 
119 | window.onload = function() {
120 | 	var ctx = document.getElementById('myChart').getContext('2d');
121 | 	window.myChart = new Chart(ctx, config);
122 | };
123 |
124 |
125 |
[{
126 | 	"dataset": "Temperature",
127 | 	"month": "January",
128 | 	"value": 7
129 | }, {
130 | 	"dataset": "Temperature",
131 | 	"month": "February",
132 | 	"value": 7
133 | }, {
134 | 	"dataset": "Temperature",
135 | 	"month": "March",
136 | 	"value": 10
137 | }, {
138 | 	"dataset": "Temperature",
139 | 	"month": "April",
140 | 	"value": 15
141 | }, {
142 | 	"dataset": "Temperature",
143 | 	"month": "May",
144 | 	"value": 20
145 | }, {
146 | 	"dataset": "Temperature",
147 | 	"month": "June",
148 | 	"value": 23
149 | }, {
150 | 	"dataset": "Temperature",
151 | 	"month": "July",
152 | 	"value": 26
153 | }, {
154 | 	"dataset": "Precipitation",
155 | 	"month": "January",
156 | 	"value": 8.1
157 | }, {
158 | 	"dataset": "Precipitation",
159 | 	"month": "February",
160 | 	"value": 14.9
161 | }, {
162 | 	"dataset": "Precipitation",
163 | 	"month": "March",
164 | 	"value": 41.0
165 | }, {
166 | 	"dataset": "Precipitation",
167 | 	"month": "April",
168 | 	"value": 31.4
169 | }, {
170 | 	"dataset": "Precipitation",
171 | 	"month": "May",
172 | 	"value": 42.6
173 | }, {
174 | 	"dataset": "Precipitation",
175 | 	"month": "June",
176 | 	"value": 57.5
177 | }, {
178 | 	"dataset": "Precipitation",
179 | 	"month": "July",
180 | 	"value": 36.0
181 | }]
182 |
183 |
184 |
<head>
185 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
186 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
187 | </head>
188 | <body>
189 | 	<div>
190 | 		<canvas id="myChart"></canvas>
191 | 	</div>
192 | </body>
193 |
194 |
195 |
196 | 197 | 277 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /docs/samples/json-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON data source (dataset) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'json',
105 | 				url: 'sample-dataset.json',
106 | 				rowMapping: 'dataset',
107 | 				indexLabels: 'labels',
108 | 				datasetLabels: 'datasets[*].label',
109 | 				data: 'datasets[*].data'
110 | 			}
111 | 		}
112 | 	}
113 | };
114 | 
115 | window.onload = function() {
116 | 	var ctx = document.getElementById('myChart').getContext('2d');
117 | 	window.myChart = new Chart(ctx, config);
118 | };
119 |
120 |
121 |
{
122 | 	"labels": ["January", "February", "March", "April", "May", "June", "July"],
123 | 	"datasets": [{
124 | 		"label": "Temperature",
125 | 		"data": [7, 7, 10, 15, 20, 23, 26]
126 | 	}, {
127 | 		"label": "Precipitation",
128 | 		"data": [8.1, 14.9, 41.0, 31.4, 42.6, 57.5, 36.0]
129 | 	}]
130 | }
131 |
132 |
133 |
<head>
134 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
135 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
136 | </head>
137 | <body>
138 | 	<div>
139 | 		<canvas id="myChart"></canvas>
140 | 	</div>
141 | </body>
142 |
143 |
144 |
145 | 146 | 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /docs/samples/json-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON data source (index) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'json',
105 | 				url: 'sample-index.json',
106 | 				rowMapping: 'index',
107 | 				datasetLabels: 'labels',
108 | 				indexLabels: 'indices[*].label',
109 | 				data: 'indices[*].data'
110 | 			}
111 | 		}
112 | 	}
113 | };
114 | 
115 | window.onload = function() {
116 | 	var ctx = document.getElementById('myChart').getContext('2d');
117 | 	window.myChart = new Chart(ctx, config);
118 | };
119 |
120 |
121 |
{
122 | 	"labels": ["Temperature", "Precipitation"],
123 | 	"indices": [{
124 | 		"label": "January",
125 | 		"data": [7, 8.1]
126 | 	}, {
127 | 		"label": "February",
128 | 		"data": [7, 14.9]
129 | 	}, {
130 | 		"label": "March",
131 | 		"data": [10, 41.0]
132 | 	}, {
133 | 		"label": "April",
134 | 		"data": [15, 31.4]
135 | 	}, {
136 | 		"label": "May",
137 | 		"data": [20, 42.6]
138 | 	}, {
139 | 		"label": "June",
140 | 		"data": [23, 57.5]
141 | 	}, {
142 | 		"label": "July",
143 | 		"data": [26, 36.0]
144 | 	}]
145 | }
146 |
147 |
148 |
<head>
149 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
150 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
151 | </head>
152 | <body>
153 | 	<div>
154 | 		<canvas id="myChart"></canvas>
155 | 	</div>
156 | </body>
157 |
158 |
159 |
160 | 161 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /docs/samples/jsonl-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON Lines data source (datapoint) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'jsonl',
105 | 				url: 'sample-datapoint.jsonl',
106 | 				rowMapping: 'datapoint',
107 | 				datapointLabelMapping: {
108 | 					_dataset: 'dataset',
109 | 					_index: 'month',
110 | 					x: 'month',
111 | 					y: 'value'
112 | 				},
113 | 				data: '*.*'
114 | 			}
115 | 		}
116 | 	}
117 | };
118 | 
119 | window.onload = function() {
120 | 	var ctx = document.getElementById('myChart').getContext('2d');
121 | 	window.myChart = new Chart(ctx, config);
122 | };
123 |
124 |
125 |
{"dataset": "Temperature", "month": "January", "value": 7}
126 | {"dataset": "Temperature", "month": "February", "value": 7}
127 | {"dataset": "Temperature", "month": "March", "value": 10}
128 | {"dataset": "Temperature", "month": "April", "value": 15}
129 | {"dataset": "Temperature", "month": "May", "value": 20}
130 | {"dataset": "Temperature", "month": "June", "value": 23}
131 | {"dataset": "Temperature", "month": "July", "value": 26}
132 | {"dataset": "Precipitation", "month": "January", "value": 8.1}
133 | {"dataset": "Precipitation", "month": "February", "value": 14.9}
134 | {"dataset": "Precipitation", "month": "March", "value": 41.0}
135 | {"dataset": "Precipitation", "month": "April", "value": 31.4}
136 | {"dataset": "Precipitation", "month": "May", "value": 42.6}
137 | {"dataset": "Precipitation", "month": "June", "value": 57.5}
138 | {"dataset": "Precipitation", "month": "July", "value": 36.0}
139 |
140 |
141 |
<head>
142 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
143 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
144 | </head>
145 | <body>
146 | 	<div>
147 | 		<canvas id="myChart"></canvas>
148 | 	</div>
149 | </body>
150 |
151 |
152 |
153 | 154 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /docs/samples/jsonl-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON Lines data source (dataset) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'jsonl',
105 | 				url: 'sample-dataset.jsonl',
106 | 				rowMapping: 'dataset',
107 | 				datasetLabels: '*.label',
108 | 				data: '*.data.*'
109 | 			}
110 | 		}
111 | 	}
112 | };
113 | 
114 | window.onload = function() {
115 | 	var ctx = document.getElementById('myChart').getContext('2d');
116 | 	window.myChart = new Chart(ctx, config);
117 | };
118 |
119 |
120 |
{"label": "Temperature", "data": {"January": 7, "February": 7, "March": 10, "April": 15, "May": 20, "June": 23, "July": 26}}
121 | {"label": "Precipitation", "data": {"January": 8.1, "February": 14.9, "March": 41.0, "April": 31.4, "May": 42.6, "June": 57.5, "July": 36.0}}
122 |
123 |
124 |
<head>
125 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
126 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
127 | </head>
128 | <body>
129 | 	<div>
130 | 		<canvas id="myChart"></canvas>
131 | 	</div>
132 | </body>
133 |
134 |
135 |
136 | 137 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /docs/samples/jsonl-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 | 43 |
44 |
45 |
var chartColors = {
 46 | 	red: 'rgb(255, 99, 132)',
 47 | 	blue: 'rgb(54, 162, 235)'
 48 | };
 49 | 
 50 | var color = Chart.helpers.color;
 51 | var config = {
 52 | 	type: 'bar',
 53 | 	data: {
 54 | 		datasets: [{
 55 | 			type: 'line',
 56 | 			yAxisID: 'temperature',
 57 | 			backgroundColor: 'transparent',
 58 | 			borderColor: chartColors.red,
 59 | 			pointBackgroundColor: chartColors.red,
 60 | 			tension: 0,
 61 | 			fill: false
 62 | 		}, {
 63 | 			yAxisID: 'precipitation',
 64 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 65 | 			borderColor: 'transparent'
 66 | 		}]
 67 | 	},
 68 | 	plugins: [ChartDataSource],
 69 | 	options: {
 70 | 		title: {
 71 | 			display: true,
 72 | 			text: 'JSON Lines data source (index) sample'
 73 | 		},
 74 | 		scales: {
 75 | 			xAxes: [{
 76 | 				scaleLabel: {
 77 | 					display: true,
 78 | 					labelString: 'Month'
 79 | 				}
 80 | 			}],
 81 | 			yAxes: [{
 82 | 				id: 'temperature',
 83 | 				gridLines: {
 84 | 					drawOnChartArea: false
 85 | 				},
 86 | 				scaleLabel: {
 87 | 					display: true,
 88 | 					labelString: 'Temperature (°C)'
 89 | 				}
 90 | 			}, {
 91 | 				id: 'precipitation',
 92 | 				position: 'right',
 93 | 				gridLines: {
 94 | 					drawOnChartArea: false
 95 | 				},
 96 | 				scaleLabel: {
 97 | 					display: true,
 98 | 					labelString: 'Precipitation (mm)'
 99 | 				}
100 | 			}]
101 | 		},
102 | 		plugins: {
103 | 			datasource: {
104 | 				type: 'jsonl',
105 | 				url: 'sample-index.jsonl',
106 | 				rowMapping: 'index',
107 | 				indexLabels: '*.label',
108 | 				data: '*.data.*'
109 | 			}
110 | 		}
111 | 	}
112 | };
113 | 
114 | window.onload = function() {
115 | 	var ctx = document.getElementById('myChart').getContext('2d');
116 | 	window.myChart = new Chart(ctx, config);
117 | };
118 |
119 |
120 |
{"label": "January", "data": {"Temperature": 7, "Precipitation": 8.1}}
121 | {"label": "February", "data": {"Temperature": 7, "Precipitation": 14.9}}
122 | {"label": "March", "data": {"Temperature": 10, "Precipitation": 41.0}}
123 | {"label": "April", "data": {"Temperature": 15, "Precipitation": 31.4}}
124 | {"label": "May", "data": {"Temperature": 20, "Precipitation": 42.6}}
125 | {"label": "June", "data": {"Temperature": 23, "Precipitation": 57.5}}
126 | {"label": "July", "data": {"Temperature": 26, "Precipitation": 36.0}}
127 |
128 |
129 |
<head>
130 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
131 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
132 | </head>
133 | <body>
134 | 	<div>
135 | 		<canvas id="myChart"></canvas>
136 | 	</div>
137 | </body>
138 |
139 |
140 |
141 | 142 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /docs/samples/sample-datapoint.csv: -------------------------------------------------------------------------------- 1 | dataset,month,value 2 | Temperature,January,7 3 | Temperature,February,7 4 | Temperature,March,10 5 | Temperature,April,15 6 | Temperature,May,20 7 | Temperature,June,23 8 | Temperature,July,26 9 | Precipitation,January,8.1 10 | Precipitation,February,14.9 11 | Precipitation,March,41.0 12 | Precipitation,April,31.4 13 | Precipitation,May,42.6 14 | Precipitation,June,57.5 15 | Precipitation,July,36.0 16 | -------------------------------------------------------------------------------- /docs/samples/sample-datapoint.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "dataset": "Temperature", 3 | "month": "January", 4 | "value": 7 5 | }, { 6 | "dataset": "Temperature", 7 | "month": "February", 8 | "value": 7 9 | }, { 10 | "dataset": "Temperature", 11 | "month": "March", 12 | "value": 10 13 | }, { 14 | "dataset": "Temperature", 15 | "month": "April", 16 | "value": 15 17 | }, { 18 | "dataset": "Temperature", 19 | "month": "May", 20 | "value": 20 21 | }, { 22 | "dataset": "Temperature", 23 | "month": "June", 24 | "value": 23 25 | }, { 26 | "dataset": "Temperature", 27 | "month": "July", 28 | "value": 26 29 | }, { 30 | "dataset": "Precipitation", 31 | "month": "January", 32 | "value": 8.1 33 | }, { 34 | "dataset": "Precipitation", 35 | "month": "February", 36 | "value": 14.9 37 | }, { 38 | "dataset": "Precipitation", 39 | "month": "March", 40 | "value": 41.0 41 | }, { 42 | "dataset": "Precipitation", 43 | "month": "April", 44 | "value": 31.4 45 | }, { 46 | "dataset": "Precipitation", 47 | "month": "May", 48 | "value": 42.6 49 | }, { 50 | "dataset": "Precipitation", 51 | "month": "June", 52 | "value": 57.5 53 | }, { 54 | "dataset": "Precipitation", 55 | "month": "July", 56 | "value": 36.0 57 | }] 58 | -------------------------------------------------------------------------------- /docs/samples/sample-datapoint.jsonl: -------------------------------------------------------------------------------- 1 | {"dataset": "Temperature", "month": "January", "value": 7} 2 | {"dataset": "Temperature", "month": "February", "value": 7} 3 | {"dataset": "Temperature", "month": "March", "value": 10} 4 | {"dataset": "Temperature", "month": "April", "value": 15} 5 | {"dataset": "Temperature", "month": "May", "value": 20} 6 | {"dataset": "Temperature", "month": "June", "value": 23} 7 | {"dataset": "Temperature", "month": "July", "value": 26} 8 | {"dataset": "Precipitation", "month": "January", "value": 8.1} 9 | {"dataset": "Precipitation", "month": "February", "value": 14.9} 10 | {"dataset": "Precipitation", "month": "March", "value": 41.0} 11 | {"dataset": "Precipitation", "month": "April", "value": 31.4} 12 | {"dataset": "Precipitation", "month": "May", "value": 42.6} 13 | {"dataset": "Precipitation", "month": "June", "value": 57.5} 14 | {"dataset": "Precipitation", "month": "July", "value": 36.0} 15 | -------------------------------------------------------------------------------- /docs/samples/sample-datapoint.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/docs/samples/sample-datapoint.xlsx -------------------------------------------------------------------------------- /docs/samples/sample-dataset.csv: -------------------------------------------------------------------------------- 1 | ,January,February,March,April,May,June,July 2 | Temperature,7,7,10,15,20,23,26 3 | Precipitation,8.1,14.9,41.0,31.4,42.6,57.5,36.0 4 | -------------------------------------------------------------------------------- /docs/samples/sample-dataset.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": ["January", "February", "March", "April", "May", "June", "July"], 3 | "datasets": [{ 4 | "label": "Temperature", 5 | "data": [7, 7, 10, 15, 20, 23, 26] 6 | }, { 7 | "label": "Precipitation", 8 | "data": [8.1, 14.9, 41.0, 31.4, 42.6, 57.5, 36.0] 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /docs/samples/sample-dataset.jsonl: -------------------------------------------------------------------------------- 1 | {"label": "Temperature", "data": {"January": 7, "February": 7, "March": 10, "April": 15, "May": 20, "June": 23, "July": 26}} 2 | {"label": "Precipitation", "data": {"January": 8.1, "February": 14.9, "March": 41.0, "April": 31.4, "May": 42.6, "June": 57.5, "July": 36.0}} 3 | -------------------------------------------------------------------------------- /docs/samples/sample-dataset.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/docs/samples/sample-dataset.xlsx -------------------------------------------------------------------------------- /docs/samples/sample-index.csv: -------------------------------------------------------------------------------- 1 | ,Temperature,Precipitation 2 | January,7,8.1 3 | February,7,14.9 4 | March,10,41.0 5 | April,15,31.4 6 | May,20,42.6 7 | June,23,57.5 8 | July,26,36.0 9 | -------------------------------------------------------------------------------- /docs/samples/sample-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": ["Temperature", "Precipitation"], 3 | "indices": [{ 4 | "label": "January", 5 | "data": [7, 8.1] 6 | }, { 7 | "label": "February", 8 | "data": [7, 14.9] 9 | }, { 10 | "label": "March", 11 | "data": [10, 41.0] 12 | }, { 13 | "label": "April", 14 | "data": [15, 31.4] 15 | }, { 16 | "label": "May", 17 | "data": [20, 42.6] 18 | }, { 19 | "label": "June", 20 | "data": [23, 57.5] 21 | }, { 22 | "label": "July", 23 | "data": [26, 36.0] 24 | }] 25 | } 26 | -------------------------------------------------------------------------------- /docs/samples/sample-index.jsonl: -------------------------------------------------------------------------------- 1 | {"label": "January", "data": {"Temperature": 7, "Precipitation": 8.1}} 2 | {"label": "February", "data": {"Temperature": 7, "Precipitation": 14.9}} 3 | {"label": "March", "data": {"Temperature": 10, "Precipitation": 41.0}} 4 | {"label": "April", "data": {"Temperature": 15, "Precipitation": 31.4}} 5 | {"label": "May", "data": {"Temperature": 20, "Precipitation": 42.6}} 6 | {"label": "June", "data": {"Temperature": 23, "Precipitation": 57.5}} 7 | {"label": "July", "data": {"Temperature": 26, "Precipitation": 36.0}} 8 | -------------------------------------------------------------------------------- /docs/samples/sample-index.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/docs/samples/sample-index.xlsx -------------------------------------------------------------------------------- /docs/samples/sheet-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 33 | 34 | 35 | 36 |
37 | 38 |
39 |
40 | 51 |
52 |
53 |
var chartColors = {
 54 | 	red: 'rgb(255, 99, 132)',
 55 | 	blue: 'rgb(54, 162, 235)'
 56 | };
 57 | 
 58 | var color = Chart.helpers.color;
 59 | var config = {
 60 | 	type: 'bar',
 61 | 	data: {
 62 | 		datasets: [{
 63 | 			type: 'line',
 64 | 			yAxisID: 'temperature',
 65 | 			backgroundColor: 'transparent',
 66 | 			borderColor: chartColors.red,
 67 | 			pointBackgroundColor: chartColors.red,
 68 | 			tension: 0,
 69 | 			fill: false
 70 | 		}, {
 71 | 			yAxisID: 'precipitation',
 72 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 73 | 			borderColor: 'transparent'
 74 | 		}]
 75 | 	},
 76 | 	plugins: [ChartDataSource],
 77 | 	options: {
 78 | 		title: {
 79 | 			display: true,
 80 | 			text: 'Sheet data source (datapoint) sample'
 81 | 		},
 82 | 		scales: {
 83 | 			xAxes: [{
 84 | 				scaleLabel: {
 85 | 					display: true,
 86 | 					labelString: 'Month'
 87 | 				}
 88 | 			}],
 89 | 			yAxes: [{
 90 | 				id: 'temperature',
 91 | 				gridLines: {
 92 | 					drawOnChartArea: false
 93 | 				},
 94 | 				scaleLabel: {
 95 | 					display: true,
 96 | 					labelString: 'Temperature (°C)'
 97 | 				}
 98 | 			}, {
 99 | 				id: 'precipitation',
100 | 				position: 'right',
101 | 				gridLines: {
102 | 					drawOnChartArea: false
103 | 				},
104 | 				scaleLabel: {
105 | 					display: true,
106 | 					labelString: 'Precipitation (mm)'
107 | 				}
108 | 			}]
109 | 		},
110 | 		plugins: {
111 | 			datasource: {
112 | 				type: 'sheet',
113 | 				url: 'sample-datapoint.xlsx',
114 | 				rowMapping: 'datapoint',
115 | 				datapointLabels: 'Sheet1!A1:C1',
116 | 				datapointLabelMapping: {
117 | 					_dataset: 'dataset',
118 | 					_index: 'month',
119 | 					x: 'month',
120 | 					y: 'value'
121 | 				},
122 | 				data: 'Sheet1!A2:C15'
123 | 			}
124 | 		}
125 | 	}
126 | };
127 | 
128 | window.onload = function() {
129 | 	var ctx = document.getElementById('myChart').getContext('2d');
130 | 	window.myChart = new Chart(ctx, config);
131 | };
132 |
133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 |
ABC
1datasetmonthvalue
2TemperatureJanuary7
3TemperatureFebruary7
4TemperatureMarch10
5TemperatureApril15
6TemperatureMay20
7TemperatureJune23
8TemperatureJuly26
9PrecipitationJanuary8.1
10PrecipitationFebruary14.9
11PrecipitationMarch41.0
12PrecipitationApril31.4
13PrecipitationMay42.6
14PrecipitationJune57.5
15PrecipitationJuly36.0
236 |
237 |
238 |
<head>
239 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
240 | 	<script src="https://cdn.jsdelivr.net/npm/xlsx@0.14.3/dist/xlsx.full.min.js"></script>
241 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
242 | </head>
243 | <body>
244 | 	<div>
245 | 		<canvas id="myChart"></canvas>
246 | 	</div>
247 | </body>
248 |
249 |
250 |
251 | 252 | 333 | 334 | 335 | 336 | -------------------------------------------------------------------------------- /docs/samples/sheet-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 33 | 34 | 35 | 36 |
37 | 38 |
39 |
40 | 51 |
52 |
53 |
var chartColors = {
 54 | 	red: 'rgb(255, 99, 132)',
 55 | 	blue: 'rgb(54, 162, 235)'
 56 | };
 57 | 
 58 | var color = Chart.helpers.color;
 59 | var config = {
 60 | 	type: 'bar',
 61 | 	data: {
 62 | 		datasets: [{
 63 | 			type: 'line',
 64 | 			yAxisID: 'temperature',
 65 | 			backgroundColor: 'transparent',
 66 | 			borderColor: chartColors.red,
 67 | 			pointBackgroundColor: chartColors.red,
 68 | 			tension: 0,
 69 | 			fill: false
 70 | 		}, {
 71 | 			yAxisID: 'precipitation',
 72 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 73 | 			borderColor: 'transparent'
 74 | 		}]
 75 | 	},
 76 | 	plugins: [ChartDataSource],
 77 | 	options: {
 78 | 		title: {
 79 | 			display: true,
 80 | 			text: 'Sheet data source (dataset) sample'
 81 | 		},
 82 | 		scales: {
 83 | 			xAxes: [{
 84 | 				scaleLabel: {
 85 | 					display: true,
 86 | 					labelString: 'Month'
 87 | 				}
 88 | 			}],
 89 | 			yAxes: [{
 90 | 				id: 'temperature',
 91 | 				gridLines: {
 92 | 					drawOnChartArea: false
 93 | 				},
 94 | 				scaleLabel: {
 95 | 					display: true,
 96 | 					labelString: 'Temperature (°C)'
 97 | 				}
 98 | 			}, {
 99 | 				id: 'precipitation',
100 | 				position: 'right',
101 | 				gridLines: {
102 | 					drawOnChartArea: false
103 | 				},
104 | 				scaleLabel: {
105 | 					display: true,
106 | 					labelString: 'Precipitation (mm)'
107 | 				}
108 | 			}]
109 | 		},
110 | 		plugins: {
111 | 			datasource: {
112 | 				type: 'sheet',
113 | 				url: 'sample-dataset.xlsx',
114 | 				rowMapping: 'dataset',
115 | 				datasetLabels: 'Sheet1!A2:A3',
116 | 				indexLabels: 'Sheet1!B1:H1',
117 | 				data: 'Sheet1!B2:H3'
118 | 			}
119 | 		}
120 | 	}
121 | };
122 | 
123 | window.onload = function() {
124 | 	var ctx = document.getElementById('myChart').getContext('2d');
125 | 	window.myChart = new Chart(ctx, config);
126 | };
127 |
128 |
129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 |
ABCDEFGH
1JanuaryFebruaryMarchAprilMayJuneJuly
2Temperature771015202326
3Precipitation8.114.941.031.442.657.536.0
179 |
180 |
181 |
<head>
182 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
183 | 	<script src="https://cdn.jsdelivr.net/npm/xlsx@0.14.3/dist/xlsx.full.min.js"></script>
184 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
185 | </head>
186 | <body>
187 | 	<div>
188 | 		<canvas id="myChart"></canvas>
189 | 	</div>
190 | </body>
191 |
192 |
193 |
194 | 195 | 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /docs/samples/sheet-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 33 | 34 | 35 | 36 |
37 | 38 |
39 |
40 | 51 |
52 |
53 |
var chartColors = {
 54 | 	red: 'rgb(255, 99, 132)',
 55 | 	blue: 'rgb(54, 162, 235)'
 56 | };
 57 | 
 58 | var color = Chart.helpers.color;
 59 | var config = {
 60 | 	type: 'bar',
 61 | 	data: {
 62 | 		datasets: [{
 63 | 			type: 'line',
 64 | 			yAxisID: 'temperature',
 65 | 			backgroundColor: 'transparent',
 66 | 			borderColor: chartColors.red,
 67 | 			pointBackgroundColor: chartColors.red,
 68 | 			tension: 0,
 69 | 			fill: false
 70 | 		}, {
 71 | 			yAxisID: 'precipitation',
 72 | 			backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
 73 | 			borderColor: 'transparent'
 74 | 		}]
 75 | 	},
 76 | 	plugins: [ChartDataSource],
 77 | 	options: {
 78 | 		title: {
 79 | 			display: true,
 80 | 			text: 'Sheet data source (index) sample'
 81 | 		},
 82 | 		scales: {
 83 | 			xAxes: [{
 84 | 				scaleLabel: {
 85 | 					display: true,
 86 | 					labelString: 'Month'
 87 | 				}
 88 | 			}],
 89 | 			yAxes: [{
 90 | 				id: 'temperature',
 91 | 				gridLines: {
 92 | 					drawOnChartArea: false
 93 | 				},
 94 | 				scaleLabel: {
 95 | 					display: true,
 96 | 					labelString: 'Temperature (°C)'
 97 | 				}
 98 | 			}, {
 99 | 				id: 'precipitation',
100 | 				position: 'right',
101 | 				gridLines: {
102 | 					drawOnChartArea: false
103 | 				},
104 | 				scaleLabel: {
105 | 					display: true,
106 | 					labelString: 'Precipitation (mm)'
107 | 				}
108 | 			}]
109 | 		},
110 | 		plugins: {
111 | 			datasource: {
112 | 				type: 'sheet',
113 | 				url: 'sample-index.xlsx',
114 | 				rowMapping: 'index',
115 | 				datasetLabels: 'Sheet1!B1:C1',
116 | 				indexLabels: 'Sheet1!A2:A8',
117 | 				data: 'Sheet1!B2:C8'
118 | 			}
119 | 		}
120 | 	}
121 | };
122 | 
123 | window.onload = function() {
124 | 	var ctx = document.getElementById('myChart').getContext('2d');
125 | 	window.myChart = new Chart(ctx, config);
126 | };
127 |
128 |
129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 |
ABC
1TemperaturePrecipitation
2January78.1
3February714.9
4March1041.0
5April1531.4
6May2042.6
7June2357.5
8July2636.0
189 |
190 |
191 |
<head>
192 | 	<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
193 | 	<script src="https://cdn.jsdelivr.net/npm/xlsx@0.14.3/dist/xlsx.full.min.js"></script>
194 | 	<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datasource@0.1.0"></script>
195 | </head>
196 | <body>
197 | 	<div>
198 | 		<canvas id="myChart"></canvas>
199 | 	</div>
200 | </body>
201 |
202 |
203 |
204 | 205 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* global Promise */ 2 | 3 | var gulp = require('gulp'); 4 | var eslint = require('gulp-eslint'); 5 | var file = require('gulp-file'); 6 | var replace = require('gulp-replace'); 7 | var streamify = require('gulp-streamify'); 8 | var zip = require('gulp-zip'); 9 | var karma = require('karma'); 10 | var merge = require('merge2'); 11 | var path = require('path'); 12 | var {exec} = require('child_process'); 13 | var pkg = require('./package.json'); 14 | 15 | var argv = require('yargs') 16 | .option('output', {alias: 'o', default: 'dist'}) 17 | .option('samples-dir', {default: 'samples'}) 18 | .option('docs-dir', {default: 'docs'}) 19 | .argv; 20 | 21 | function run(bin, args) { 22 | return new Promise((resolve, reject) => { 23 | var exe = '"' + process.execPath + '"'; 24 | var src = require.resolve(bin); 25 | var ps = exec([exe, src].concat(args || []).join(' ')); 26 | 27 | ps.stdout.pipe(process.stdout); 28 | ps.stderr.pipe(process.stderr); 29 | ps.on('close', (error) => { 30 | if (error) { 31 | reject(error); 32 | } else { 33 | resolve(); 34 | } 35 | }); 36 | }); 37 | } 38 | 39 | gulp.task('build', function() { 40 | return run('rollup/bin/rollup', ['-c', argv.watch ? '--watch' : '']); 41 | }); 42 | 43 | gulp.task('test', function(done) { 44 | new karma.Server({ 45 | configFile: path.join(__dirname, 'karma.config.js'), 46 | singleRun: !argv.watch, 47 | args: { 48 | coverage: !!argv.coverage, 49 | inputs: (argv.inputs || 'test/specs/**/*.js').split(';'), 50 | watch: argv.watch 51 | } 52 | }, 53 | function(error) { 54 | // https://github.com/karma-runner/gulp-karma/issues/18 55 | error = error ? new Error('Karma returned with the error code: ' + error) : undefined; 56 | done(error); 57 | }).start(); 58 | }); 59 | 60 | gulp.task('lint', function() { 61 | var files = [ 62 | 'docs/**/*.html', 63 | 'samples/**/*.html', 64 | 'src/**/*.js', 65 | 'test/**/*.js', 66 | '*.js' 67 | ]; 68 | 69 | var options = { 70 | rules: { 71 | complexity: [1, 10], 72 | 'max-statements': [1, 30] 73 | } 74 | }; 75 | 76 | return gulp.src(files) 77 | .pipe(eslint(options)) 78 | .pipe(eslint.format()) 79 | .pipe(eslint.failAfterError()); 80 | }); 81 | 82 | gulp.task('samples', function() { 83 | // since we moved the dist files one folder up (package root), we need to rewrite 84 | // samples src="../dist/ to src="../ and then copy them in the /samples directory. 85 | var out = path.join(argv.output, argv.samplesDir); 86 | return gulp.src('samples/**/*', {base: 'samples'}) 87 | .pipe(streamify(replace(/src="((?:\.\.\/)+)dist\//g, 'src="$1', {skipBinary: true}))) 88 | .pipe(gulp.dest(out)); 89 | }); 90 | 91 | gulp.task('package', gulp.series(gulp.parallel('build', 'samples'), function() { 92 | var out = argv.output; 93 | var streams = merge( 94 | gulp.src(path.join(out, argv.samplesDir, '**/*'), {base: out}), 95 | gulp.src([path.join(out, '*.js'), 'LICENSE.md']) 96 | ); 97 | 98 | return streams 99 | .pipe(zip(pkg.name + '.zip')) 100 | .pipe(gulp.dest(out)); 101 | })); 102 | 103 | gulp.task('bower', function() { 104 | var json = JSON.stringify({ 105 | name: pkg.name, 106 | description: pkg.description, 107 | homepage: pkg.homepage, 108 | license: pkg.license, 109 | version: pkg.version, 110 | main: argv.output + '/' + pkg.name + '.js', 111 | ignore: [ 112 | '.codeclimate.yml', 113 | '.gitignore', 114 | '.npmignore', 115 | '.travis.yml', 116 | 'scripts' 117 | ] 118 | }, null, 2); 119 | 120 | return file('bower.json', json, {src: true}) 121 | .pipe(gulp.dest('./')); 122 | }); 123 | 124 | gulp.task('default', gulp.parallel('build')); 125 | -------------------------------------------------------------------------------- /karma.config.js: -------------------------------------------------------------------------------- 1 | const commonjs = require('rollup-plugin-commonjs'); 2 | const istanbul = require('rollup-plugin-istanbul'); 3 | const resolve = require('rollup-plugin-node-resolve'); 4 | const builds = require('./rollup.config'); 5 | 6 | module.exports = function(karma) { 7 | const args = karma.args || {}; 8 | const regex = args.watch ? /\.js$/ : /\.min\.js$/; 9 | const build = builds.filter((v) => v.output.file.match(regex))[0]; 10 | 11 | if (args.watch) { 12 | build.output.sourcemap = 'inline'; 13 | } 14 | 15 | karma.set({ 16 | browsers: ['firefox'], 17 | frameworks: ['jasmine'], 18 | reporters: ['spec', 'kjhtml'], 19 | logLevel: karma.LOG_WARN, 20 | 21 | files: [ 22 | 'node_modules/chart.js/dist/Chart.js', 23 | 'node_modules/xlsx/dist/xlsx.full.min.js', 24 | 'test/index.js', 25 | 'src/index.js' 26 | ].concat(args.inputs), 27 | 28 | // Explicitly disable hardware acceleration to make image 29 | // diff more stable when ran on Travis and dev machine. 30 | // https://github.com/chartjs/Chart.js/pull/5629 31 | customLaunchers: { 32 | firefox: { 33 | base: 'Firefox', 34 | prefs: { 35 | 'layers.acceleration.disabled': true 36 | } 37 | } 38 | }, 39 | 40 | preprocessors: { 41 | 'test/specs/**/*.js': ['rollup'], 42 | 'test/index.js': ['rollup'], 43 | 'src/index.js': ['sources'] 44 | }, 45 | 46 | rollupPreprocessor: { 47 | plugins: [ 48 | resolve(), 49 | commonjs() 50 | ], 51 | external: [ 52 | 'chart.js', 53 | 'xlsx' 54 | ], 55 | output: { 56 | name: 'test', 57 | format: 'umd', 58 | globals: { 59 | 'chart.js': 'Chart', 60 | xlsx: 'XLSX' 61 | } 62 | } 63 | }, 64 | 65 | customPreprocessors: { 66 | sources: { 67 | base: 'rollup', 68 | options: build 69 | } 70 | } 71 | }); 72 | 73 | if (args.coverage) { 74 | karma.reporters.push('coverage'); 75 | karma.coverageReporter = { 76 | dir: 'coverage/', 77 | reporters: [ 78 | {type: 'html', subdir: 'html'}, 79 | {type: 'lcovonly', subdir: '.'} 80 | ] 81 | }; 82 | [ 83 | karma.rollupPreprocessor, 84 | karma.customPreprocessors.sources.options 85 | ].forEach((v) => { 86 | (v.plugins || (v.plugins = [])).push( 87 | istanbul({ 88 | include: 'src/**/*.js' 89 | })); 90 | }); 91 | } 92 | }; 93 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chartjs-plugin-datasource", 3 | "homepage": "https://nagix.github.io/chartjs-plugin-datasource", 4 | "description": "Chart.js plugin for automatic data loading", 5 | "author": "Akihiko Kusanagi (https://nagix.github.io/)", 6 | "version": "0.1.0", 7 | "license": "MIT", 8 | "jsdelivr": "dist/chartjs-plugin-datasource.min.js", 9 | "unpkg": "dist/chartjs-plugin-datasource.min.js", 10 | "main": "dist/chartjs-plugin-datasource.js", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/nagix/chartjs-plugin-datasource.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/nagix/chartjs-plugin-datasource/issues" 17 | }, 18 | "keywords": [ 19 | "chart.js", 20 | "plugin", 21 | "datasource", 22 | "csv", 23 | "json", 24 | "excel" 25 | ], 26 | "files": [ 27 | "bower.json", 28 | "dist/*.js" 29 | ], 30 | "directories": { 31 | "doc": "docs", 32 | "test": "test" 33 | }, 34 | "devDependencies": { 35 | "chart.js": "~2.8.0", 36 | "eslint-config-chartjs": "^0.1.0", 37 | "eslint-plugin-es": "^1.4.0", 38 | "eslint-plugin-html": "^5.0.3", 39 | "gulp": "^4.0.0", 40 | "gulp-eslint": "^5.0.0", 41 | "gulp-file": "^0.4.0", 42 | "gulp-replace": "^1.0.0", 43 | "gulp-streamify": "^1.0.2", 44 | "gulp-zip": "^4.2.0", 45 | "jasmine-core": "^3.4.0", 46 | "karma": "^4.1.0", 47 | "karma-coverage": "^1.1.2", 48 | "karma-firefox-launcher": "^1.1.0", 49 | "karma-jasmine": "^2.0.1", 50 | "karma-jasmine-html-reporter": "^1.4.2", 51 | "karma-rollup-preprocessor": "^7.0.0", 52 | "karma-spec-reporter": "^0.0.32", 53 | "merge2": "^1.2.3", 54 | "rollup": "^1.11.2", 55 | "rollup-plugin-commonjs": "^9.3.4", 56 | "rollup-plugin-istanbul": "^2.0.1", 57 | "rollup-plugin-node-resolve": "^4.2.3", 58 | "rollup-plugin-terser": "^4.0.4", 59 | "xlsx": "~0.14.3", 60 | "yargs": "^13.2.2" 61 | }, 62 | "peerDependencies": { 63 | "chart.js": ">= 2.7.0 < 3", 64 | "xlsx": "^0.8.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const terser = require('rollup-plugin-terser').terser; 2 | const pkg = require('./package.json'); 3 | 4 | const banner = `/*! 5 | * ${pkg.name} v${pkg.version} 6 | * ${pkg.homepage} 7 | * (c) ${new Date().getFullYear()} Akihiko Kusanagi 8 | * Released under the ${pkg.license} license 9 | */`; 10 | 11 | module.exports = [ 12 | { 13 | input: 'src/index.js', 14 | output: { 15 | name: 'ChartDataSource', 16 | file: `dist/${pkg.name}.js`, 17 | banner: banner, 18 | format: 'umd', 19 | indent: false, 20 | globals: { 21 | 'chart.js': 'Chart', 22 | xlsx: 'XLSX' 23 | } 24 | }, 25 | external: [ 26 | 'chart.js', 27 | 'xlsx' 28 | ] 29 | }, 30 | { 31 | input: 'src/index.js', 32 | output: { 33 | name: 'ChartDataSource', 34 | file: `dist/${pkg.name}.min.js`, 35 | format: 'umd', 36 | indent: false, 37 | globals: { 38 | 'chart.js': 'Chart', 39 | xlsx: 'XLSX' 40 | } 41 | }, 42 | plugins: [ 43 | terser({ 44 | output: { 45 | preamble: banner 46 | } 47 | }) 48 | ], 49 | external: [ 50 | 'chart.js', 51 | 'xlsx' 52 | ] 53 | } 54 | ]; 55 | -------------------------------------------------------------------------------- /samples/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | plugins: [es, html] 2 | 3 | extends: [ 4 | plugin:es/no-2018, 5 | plugin:es/no-2017, 6 | plugin:es/no-2016, 7 | plugin:es/no-2015 8 | ] 9 | 10 | globals: 11 | Chart: true 12 | XLSX: true 13 | ChartDataSource: true 14 | 15 | parserOptions: 16 | sourceType: script 17 | 18 | rules: 19 | no-unused-vars: 0 20 | -------------------------------------------------------------------------------- /samples/csv-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /samples/csv-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /samples/csv-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /samples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource Samples 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |

chartjs-plugin-datasource
Samples

18 |

Tutorial | GitHub

19 |
20 |
21 | 43 |
44 | 45 |
46 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /samples/json-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /samples/json-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /samples/json-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /samples/jsonl-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /samples/jsonl-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /samples/jsonl-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /samples/sample-datapoint.csv: -------------------------------------------------------------------------------- 1 | dataset,month,value 2 | Temperature,January,7 3 | Temperature,February,7 4 | Temperature,March,10 5 | Temperature,April,15 6 | Temperature,May,20 7 | Temperature,June,23 8 | Temperature,July,26 9 | Precipitation,January,8.1 10 | Precipitation,February,14.9 11 | Precipitation,March,41.0 12 | Precipitation,April,31.4 13 | Precipitation,May,42.6 14 | Precipitation,June,57.5 15 | Precipitation,July,36.0 16 | -------------------------------------------------------------------------------- /samples/sample-datapoint.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "dataset": "Temperature", 3 | "month": "January", 4 | "value": 7 5 | }, { 6 | "dataset": "Temperature", 7 | "month": "February", 8 | "value": 7 9 | }, { 10 | "dataset": "Temperature", 11 | "month": "March", 12 | "value": 10 13 | }, { 14 | "dataset": "Temperature", 15 | "month": "April", 16 | "value": 15 17 | }, { 18 | "dataset": "Temperature", 19 | "month": "May", 20 | "value": 20 21 | }, { 22 | "dataset": "Temperature", 23 | "month": "June", 24 | "value": 23 25 | }, { 26 | "dataset": "Temperature", 27 | "month": "July", 28 | "value": 26 29 | }, { 30 | "dataset": "Precipitation", 31 | "month": "January", 32 | "value": 8.1 33 | }, { 34 | "dataset": "Precipitation", 35 | "month": "February", 36 | "value": 14.9 37 | }, { 38 | "dataset": "Precipitation", 39 | "month": "March", 40 | "value": 41.0 41 | }, { 42 | "dataset": "Precipitation", 43 | "month": "April", 44 | "value": 31.4 45 | }, { 46 | "dataset": "Precipitation", 47 | "month": "May", 48 | "value": 42.6 49 | }, { 50 | "dataset": "Precipitation", 51 | "month": "June", 52 | "value": 57.5 53 | }, { 54 | "dataset": "Precipitation", 55 | "month": "July", 56 | "value": 36.0 57 | }] 58 | -------------------------------------------------------------------------------- /samples/sample-datapoint.jsonl: -------------------------------------------------------------------------------- 1 | {"dataset": "Temperature", "month": "January", "value": 7} 2 | {"dataset": "Temperature", "month": "February", "value": 7} 3 | {"dataset": "Temperature", "month": "March", "value": 10} 4 | {"dataset": "Temperature", "month": "April", "value": 15} 5 | {"dataset": "Temperature", "month": "May", "value": 20} 6 | {"dataset": "Temperature", "month": "June", "value": 23} 7 | {"dataset": "Temperature", "month": "July", "value": 26} 8 | {"dataset": "Precipitation", "month": "January", "value": 8.1} 9 | {"dataset": "Precipitation", "month": "February", "value": 14.9} 10 | {"dataset": "Precipitation", "month": "March", "value": 41.0} 11 | {"dataset": "Precipitation", "month": "April", "value": 31.4} 12 | {"dataset": "Precipitation", "month": "May", "value": 42.6} 13 | {"dataset": "Precipitation", "month": "June", "value": 57.5} 14 | {"dataset": "Precipitation", "month": "July", "value": 36.0} 15 | -------------------------------------------------------------------------------- /samples/sample-datapoint.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/samples/sample-datapoint.xlsx -------------------------------------------------------------------------------- /samples/sample-dataset.csv: -------------------------------------------------------------------------------- 1 | ,January,February,March,April,May,June,July 2 | Temperature,7,7,10,15,20,23,26 3 | Precipitation,8.1,14.9,41.0,31.4,42.6,57.5,36.0 4 | -------------------------------------------------------------------------------- /samples/sample-dataset.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": ["January", "February", "March", "April", "May", "June", "July"], 3 | "datasets": [{ 4 | "label": "Temperature", 5 | "data": [7, 7, 10, 15, 20, 23, 26] 6 | }, { 7 | "label": "Precipitation", 8 | "data": [8.1, 14.9, 41.0, 31.4, 42.6, 57.5, 36.0] 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /samples/sample-dataset.jsonl: -------------------------------------------------------------------------------- 1 | {"label": "Temperature", "data": {"January": 7, "February": 7, "March": 10, "April": 15, "May": 20, "June": 23, "July": 26}} 2 | {"label": "Precipitation", "data": {"January": 8.1, "February": 14.9, "March": 41.0, "April": 31.4, "May": 42.6, "June": 57.5, "July": 36.0}} 3 | -------------------------------------------------------------------------------- /samples/sample-dataset.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/samples/sample-dataset.xlsx -------------------------------------------------------------------------------- /samples/sample-index.csv: -------------------------------------------------------------------------------- 1 | ,Temperature,Precipitation 2 | January,7,8.1 3 | February,7,14.9 4 | March,10,41.0 5 | April,15,31.4 6 | May,20,42.6 7 | June,23,57.5 8 | July,26,36.0 9 | -------------------------------------------------------------------------------- /samples/sample-index.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": ["Temperature", "Precipitation"], 3 | "indices": [{ 4 | "label": "January", 5 | "data": [7, 8.1] 6 | }, { 7 | "label": "February", 8 | "data": [7, 14.9] 9 | }, { 10 | "label": "March", 11 | "data": [10, 41.0] 12 | }, { 13 | "label": "April", 14 | "data": [15, 31.4] 15 | }, { 16 | "label": "May", 17 | "data": [20, 42.6] 18 | }, { 19 | "label": "June", 20 | "data": [23, 57.5] 21 | }, { 22 | "label": "July", 23 | "data": [26, 36.0] 24 | }] 25 | } 26 | -------------------------------------------------------------------------------- /samples/sample-index.jsonl: -------------------------------------------------------------------------------- 1 | {"label": "January", "data": {"Temperature": 7, "Precipitation": 8.1}} 2 | {"label": "February", "data": {"Temperature": 7, "Precipitation": 14.9}} 3 | {"label": "March", "data": {"Temperature": 10, "Precipitation": 41.0}} 4 | {"label": "April", "data": {"Temperature": 15, "Precipitation": 31.4}} 5 | {"label": "May", "data": {"Temperature": 20, "Precipitation": 42.6}} 6 | {"label": "June", "data": {"Temperature": 23, "Precipitation": 57.5}} 7 | {"label": "July", "data": {"Temperature": 26, "Precipitation": 36.0}} 8 | -------------------------------------------------------------------------------- /samples/sample-index.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nagix/chartjs-plugin-datasource/b4dbbd37daab104841291b7a8509414d38981f25/samples/sample-index.xlsx -------------------------------------------------------------------------------- /samples/sheet-datapoint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /samples/sheet-dataset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /samples/sheet-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | chartjs-plugin-datasource sample 7 | 8 | 9 | 10 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /samples/style.css: -------------------------------------------------------------------------------- 1 | html,body,div,span,object,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;outline:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0}ol li{list-style-type:decimal}body{box-sizing:border-box;font-family:'Helvetica Neue', '.HiraKakuInterface-W2', Helvetica, Arial, sans-serif;color:#333;line-height:1.4;font-size:14px}.octicon{font:normal normal 16px octicons;line-height:1;display:inline-block;text-decoration:none;-webkit-font-smoothing:antialiased}.mega-octicon{font:normal normal 48px octicons;display:inline-block;text-decoration:none;-webkit-font-smoothing:antialiased;color:#4183c4;line-height:100px}.wrapper{position:relative;width:980px;margin:0 auto}strong{font-weight:bold}a{color:#4183C4;text-decoration:none}a:hover{color:#156cc2}p code{background-color:#f9f9f9;border:1px solid #ddd;border-radius:4px;padding:2px 5px;font-family:Consolas, "Liberation Mono", Courier, monospace}h2{text-align:center;font-weight:200;line-height:38px;margin:40px auto 0;font-size:21px;max-width:740px}.page h1.title{margin-top:25px}h4{font-size:30px;font-weight:300;line-height:1em;-webkit-backface-visibility:hidden}p{margin:15px 0 30px;font-weight:300;line-height:1.7em}em{font-style:italic}textarea{border:none;background-color:transparent;width:400px;outline:none}.logo{display:block;width:169px;margin:0 auto}#hero-spot{padding:40px 0 0;position:relative;overflow:hidden;background:#222}.help-link{position:absolute;top:20px;right:20px;background-color:#333;color:#bbb;padding:5px 10px;border-radius:4px;font-size:12px;font-weight:bold;-webkit-backface-visibility:hidden;-webkit-transition:color 0.2s ease-in-out 0s;-moz-transition:color 0.2s ease-in-out 0s;-o-transition:color 0.2s ease-in-out 0s;transition:color 0.2s ease-in-out 0s}.help-link:hover{color:#fff}h1{margin:90px auto 0 auto;font-size:48px;font-weight:200;line-height:60px;text-align:center;max-width:910px;color:#333}#hero-spot h1{color:#fff;-webkit-backface-visibility:hidden;max-width:830px;margin-top:50px}.page #hero-spot img{margin-bottom:25px}#hero-spot h2{color:#a7a7a7;-webkit-backface-visibility:hidden;line-height:1.5em;max-width:none;margin:10px auto 60px;font-size:18px}.hero-spot h2>a{color:#dcdcdc;text-decoration:underline}.hero-spot h2>a:hover{text-decoration:none}#slideshow{margin:30px auto 0;position:relative}.slide{margin:0 auto;max-width:100%;position:absolute;left:0;right:0;bottom:0;opacity:0;z-index:100;-webkit-transition:opacity 0.6s ease-in-out 0s;-moz-transition:opacity 0.6s ease-in-out 0s;-o-transition:opacity 0.6s ease-in-out 0s;transition:opacity 0.6s ease-in-out 0s}.slide:first-child{position:relative;display:block}.slide.active{opacity:1;z-index:90}.shadow-overlay{position:absolute;bottom:0;width:100%;height:9px;background:url(../images/section-shadow.png) repeat-x}#video,#tutorial{text-align:center;background-color:#f5f5f5;overflow:hidden}#video iframe{margin-top:40px}#tutorial{padding-bottom:20px}.tabs{display:inline-block;margin:45px auto 0;font-size:0}.question .tabs{margin:30px auto 0}.tabs li{display:inline-block;margin:0;font-size:15px}.tabs li:first-child a{border-top-left-radius:5px;border-bottom-left-radius:5px}.tabs li:last-child a{border-top-right-radius:5px;border-bottom-right-radius:5px}.tabs li:nth-child(even) a{margin:0 -1px}.tabs a{color:#323232;background-color:#fff;padding:10px 20px;display:inline-block;border:1px solid #dddddd;position:relative;line-height:1em;-webkit-transition:all 0.2s ease-in-out 0s;-moz-transition:all 0.2s ease-in-out 0s;-o-transition:all 0.2s ease-in-out 0s;transition:all 0.2s ease-in-out 0s}.question .tabs a{background-color:#fcfcfc}.tabs a:hover{color:#327fc7;border-color:#327fc7;z-index:10}.tabs a.selected{z-index:20;color:#fff;background-color:#327fc7;border-color:#327fc7;outline:none}.tutorial-list{margin-top:90px;counter-reset:tutorialstep;display:none}.tutorial-list.active{display:block}.tutorial-list>li{position:relative;background-color:#fff;margin:0 0 70px 0px;padding:40px 0 60px;font-size:18px;border:1px solid #ddd;border-radius:5px;text-align:center;z-index:1;-webkit-transition:all 0.6s ease-in-out 0s;-moz-transition:all 0.6s ease-in-out 0s;-o-transition:all 0.6s ease-in-out 0s;transition:all 0.6s ease-in-out 0s}.tutorial-list .image-right{padding-right:440px}.tutorial-list .image-right p{margin-left:30px;margin-right:30px}#create-repo-step{background:#fff url(/images/user-repo@2x.png) right 0 no-repeat;background-size:446px 344px}#setup-in-desktop{background:#fff url(/images/setup-in-desktop@2x.png) no-repeat right 0;background-size:443px 303px}.tutorial-list .animate-in{-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-o-transform:translateY(40px);-ms-transform:translateY(40px);transform:translateY(40px);opacity:0}.tutorial-list p{margin:30px 120px 30px}.tutorial-list p:last-child{margin-bottom:0}.article-left p{margin-left:0;margin-right:0}.tutorial-list .right-image p,.tutorial-list .right-image h4{margin-left:30px}.tutorial-list li .full-size{margin-bottom:-66px;max-width:90%}.tutorial-list .hidden{display:none}.tutorial-list .question{text-align:center}.windows-download{color:#fff;display:inline-block;font-size:18px;margin:0 0 50px;background-color:#71bc22;padding:10px 14px;line-height:27px;font-family:"Segoe UI", "Segoe WP", "Helvetica Neue", '.HiraKakuInterface-W2', "Lucida Grande", sans-serif;font-weight:300;-webkit-backface-visibility:hidden}.windows-download:hover{color:#fff;background-color:#62b30e}.windows-download .icon{background:url("../images/download@2x.png") no-repeat center;background-size:21px 21px;height:21px;width:21px;margin:0 9px -4px 0;display:inline-block}.mac-download{display:inline-block;text-decoration:none;text-shadow:0 -1px 0 rgba(0,0,0,0.3);background-color:#3582df;background-image:-moz-linear-gradient(#45b3f3 0%, #3582df 100%);background-image:-webkit-linear-gradient(#45b3f3 0%, #3582df 100%);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#45b3f3', endColorstr='#3582df')";border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,0.3);margin:0 0 50px;padding:12px 20px 14px 15px;font-size:17px;-webkit-backface-visibility:hidden;font-weight:normal;color:#fff}.mac-download::before{content:"";width:23px;height:24px;display:inline-block;background-image:url(../images/download-arrow@2x.png);background-size:23px 24px;margin-right:11px;margin-bottom:-7px}.mac-download:hover:before{opacity:0.8}.mac-download:hover{color:#fff;background-image:-moz-linear-gradient(#56bdf9 0%, #358af0 100%);background-image:-webkit-linear-gradient(#56bdf9 0%, #358af0 100%);border-radius:4px}.tutorial-list>li:last-child:before{content:"";position:absolute;left:-55px;top:0;height:105%;width:10px;background-color:#f5f5f5}.tutorial-list .right{margin:-45px 0 0 30px;border-top-right-radius:5px;border-bottom-right-radius:5px}.details{font-size:14px;font-weight:400}.tutorial-list .question:after{content:"?"}.tutorial-list>li:not(.question):after{counter-increment:tutorialstep;content:counter(tutorialstep)}.tutorial-list>li:after{width:58px;height:58px;line-height:58px;background-color:#327fc7;border-radius:200px;font-size:30px;font-weight:300;color:#fff;position:absolute;left:-15px;top:-15px;text-align:center;-webkit-backface-visibility:hidden;z-index:100}.hero-octicon{width:100px;height:100px;border-radius:50px;text-align:center;border:solid 1px #e5e5e5;margin:0 auto 15px;display:block;-webkit-transition:all 0.2s ease-in-out 0s;-moz-transition:all 0.2s ease-in-out 0s;-o-transition:all 0.2s ease-in-out 0s;transition:all 0.2s ease-in-out 0s}.hero-octicon:hover{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-o-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.next-steps .hero-octicon{margin-bottom:35px}.terminal{width:700px;margin:30px auto 0}.header{height:25px;display:block;background:-moz-linear-gradient(top, #f7f7f7 0%, #cfcfcf 5%, #aaa 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #f7f7f7), color-stop(5%, #cfcfcf), color-stop(100%, #aaa));background:-webkit-linear-gradient(top, #f7f7f7 0%, #cfcfcf 5%, #aaa 100%);background:-o-linear-gradient(top, #f7f7f7 0%, #cfcfcf 5%, #aaa 100%);background:-ms-linear-gradient(top, #f7f7f7 0%, #cfcfcf 5%, #aaa 100%);background:linear-gradient(top, #f7f7f7 0%, #cfcfcf 5%, #aaa 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7f7f7', endColorstr='#aaaaaa',GradientType=0 );border:1px solid #9c9c9c;border-bottom-color:#111;border-top-left-radius:7px;border-top-right-radius:7px;text-align:center;font-size:13px;line-height:25px;text-shadow:0 1px 0 rgba(255,255,255,0.6);color:#444}.shell{font-family:Consolas, "Liberation Mono", Courier, monospace;font-size:17px;line-height:28px;color:#eeeb82;background-color:#3d3d3d;overflow:hidden;padding:20px;margin:0;border-bottom-left-radius:7px;border-bottom-right-radius:7px;text-align:left;display:block}.tutorial-list .shell p{margin:0;font-weight:bold;-webkit-backface-visibility:hidden}.path{color:#71cfee;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-right:0.6em}.prompt{color:#d74d52;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-right:0.6em}.next-steps{margin-top:80px;display:table}.next-steps p{font-weight:400}.next-steps li{display:table-cell;text-align:center;padding:0 20px 0;-webkit-transition:opacity 0.8s ease-in-out 0s;-moz-transition:opacity 0.8s ease-in-out 0s;-ms-transition:opacity 0.8s ease-in-out 0s;-o-transition:opacity 0.8s ease-in-out 0s;transition:opacity 0.8s ease-in-out 0s}.next-steps .animate-in{opacity:0}.next-steps li:first-child,.next-steps li:last-child{padding-left:0;padding-right:0}.next-steps .custom-urls{-webkit-transition-delay:0.15s;-moz-transition-delay:0.15s;-ms-transition-delay:0.15s;-o-transition-delay:0.15s;transition-delay:0.15s}.custom-urls .mega-octicon{-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-o-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.next-steps .guides{-webkit-transition-delay:0.3s;-moz-transition-delay:0.3s;-o-transition-delay:0.3s;transition-delay:0.3s}footer{position:relative;font-size:12px;line-height:1.5;color:#777;clear:both;width:980px;padding:40px 0;margin:70px auto 0 auto;border-top:1px solid #eee}.site-footer-links li{display:inline-block;margin-left:10px}.site-footer-links li:first-child{margin-left:0}footer .octicon-mark-github{position:absolute;top:38px;left:50%;color:#ccc;height:24px;width:24px;margin-left:-12px;font-size:24px;line-height:1}footer .right{float:right;margin:0}.left{float:left}.article-left{width:500px;margin-left:20px}@font-face{font-family:'octicons';src:url("octicons.eot");src:url("octicons.eot#iefix") format("embedded-opentype"),url("octicons.woff") format("woff"),url("octicons.ttf") format("truetype"),url("octicons.svg#octicons") format("svg");font-weight:normal;font-style:normal}.octicon-book:before{content:'\f007'}.octicon-check:before{content:'\f03a'}.octicon-link:before{content:'\f05c'}.octicon-mark-github:before{content:'\f00a'}.octicon-pencil:before{content:'\f058'}.page .content{padding-left:10%;padding-right:10%}.versions,.themes{font-size:1.1em}.versions table{margin-left:auto;margin-right:auto;margin-top:25px;font-size:1.1em}.versions table tr th{font-weight:bold;text-align:left}.versions table tr td{padding:5px 20px 5px 0}.themes .content{width:50%;margin-left:auto;margin-right:auto}.themes .content ul{width:8em;margin-left:auto;margin-right:auto} 2 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ "$TRAVIS_BRANCH" != "release" ]; then 6 | echo "Skipping release because this is not the 'release' branch" 7 | exit 0 8 | fi 9 | 10 | # Travis executes this script from the repository root, so at the same level than package.json 11 | VERSION=$(node -p -e "require('./package.json').version") 12 | 13 | # Make sure that the associated tag doesn't already exist 14 | GITTAG=$(git ls-remote origin refs/tags/v$VERSION) 15 | if [ "$GITTAG" != "" ]; then 16 | echo "Tag for package.json version already exists, aborting release" 17 | exit 1 18 | fi 19 | 20 | git remote add auth-origin https://$GITHUB_AUTH_TOKEN@github.com/$TRAVIS_REPO_SLUG.git 21 | git config --global user.email "$GITHUB_AUTH_EMAIL" 22 | git config --global user.name "nagix" 23 | git checkout --detach --quiet 24 | git add -f dist/*.js bower.json 25 | git commit -m "Release $VERSION" 26 | git tag -a "v$VERSION" -m "Version $VERSION" 27 | git push -q auth-origin refs/tags/v$VERSION 2>/dev/null 28 | git remote rm auth-origin 29 | git checkout -f @{-1} 30 | -------------------------------------------------------------------------------- /src/core/core.datasource.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | 5 | var helpers = Chart.helpers; 6 | 7 | // Base class for all data source (csv, json, etc) 8 | var DataSource = function(chart, options) { 9 | this.initialize(chart, options); 10 | }; 11 | 12 | helpers.extend(DataSource.prototype, { 13 | _defaultConfig: {}, 14 | 15 | _responseType: null, 16 | 17 | initialize: function(chart, options) { 18 | var me = this; 19 | 20 | me._chart = chart; 21 | me._options = helpers.extend({}, me._defaultConfig, options); 22 | }, 23 | 24 | request: function(callback) { 25 | var me = this; 26 | var url = me.getUrl(); 27 | var xhr = new XMLHttpRequest(); 28 | 29 | xhr.open('GET', url); 30 | xhr.responseType = me._responseType; 31 | xhr.onreadystatechange = function() { 32 | var data; 33 | 34 | if (xhr.readyState === 4) { 35 | if (xhr.status === 200) { 36 | data = me.convert(xhr.response); 37 | } 38 | callback.call(me, { 39 | success: xhr.status === 200, 40 | data: data 41 | }); 42 | } 43 | }; 44 | xhr.send(); 45 | }, 46 | 47 | convert: function() { 48 | // noop 49 | }, 50 | 51 | getType: function() { 52 | return this._options.type; 53 | }, 54 | 55 | getUrl: function() { 56 | return this._options.url; 57 | } 58 | }); 59 | 60 | DataSource.extend = helpers.inherits; 61 | 62 | export default DataSource; 63 | -------------------------------------------------------------------------------- /src/datasources/datasource.csv.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import DataSource from '../core/core.datasource'; 5 | import datasourceHelpers from '../helpers/helpers.datasource'; 6 | 7 | var helpers = Chart.helpers; 8 | 9 | function getDelimiter(url) { 10 | switch (datasourceHelpers.getExtension(url)) { 11 | default: 12 | return ','; 13 | case 'tsv': 14 | return '\t'; 15 | case 'psv': 16 | return '|'; 17 | } 18 | } 19 | 20 | function csvToArrays(str, delimiter) { 21 | var regex = new RegExp('(' + delimiter + 22 | '|\r?\n(?!$)|\r(?!$)|^(?!$))(?:"((?:\\.|""|[^\\"])*)"|([^' + delimiter + '"\r\n]*))', 'gi'); 23 | var array = []; 24 | var arrays = [array]; 25 | var max = 0; 26 | var matches, i, ilen, j; 27 | 28 | while ((matches = regex.exec(str))) { 29 | if (matches[1]) { 30 | if (matches[1] !== delimiter) { 31 | array = []; 32 | arrays.push(array); 33 | } else if (arrays.length === 1 && array.length === 0) { 34 | array.push(undefined); 35 | } 36 | } 37 | array.push(matches[2] !== undefined ? matches[2].replace(/[\\"](.)/g, '$1') : matches[3] ? matches[3] : undefined); 38 | max = Math.max(max, array.length); 39 | } 40 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 41 | array = arrays[i]; 42 | for (j = array.length; j < max; ++j) { 43 | array.push(undefined); 44 | } 45 | } 46 | return arrays; 47 | } 48 | 49 | function getRowHeader(arrays) { 50 | var array = arrays.shift() || []; 51 | 52 | return array.map(function(value) { 53 | return datasourceHelpers.valueOrDefault(value, ''); 54 | }); 55 | } 56 | 57 | function getColumnHeader(arrays) { 58 | return arrays.map(function(array) { 59 | return datasourceHelpers.valueOrDefault(array.shift(), ''); 60 | }); 61 | } 62 | 63 | function getIndex(value, array) { 64 | if (helpers.isFinite(value) && value >= 0 && Math.floor(value) === value) { 65 | return value; 66 | } 67 | return array.indexOf(value); 68 | } 69 | 70 | function getLabels(arrays, value, datapointLabels) { 71 | var index = getIndex(value, datapointLabels); 72 | var result = []; 73 | var i, ilen; 74 | 75 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 76 | result.push(arrays[i][index]); 77 | } 78 | return datasourceHelpers.dedup(result); 79 | } 80 | 81 | function convertDatapointLabels(labels, mapping) { 82 | var keys = Object.keys(mapping); 83 | var result = labels.slice(); 84 | var key, index, i, ilen; 85 | 86 | for (i = 0, ilen = keys.length; i < ilen; ++i) { 87 | key = keys[i]; 88 | index = getIndex(mapping[key], labels); 89 | if (index !== -1 && key !== '_index') { 90 | result[index] = key; 91 | } 92 | } 93 | return result; 94 | } 95 | 96 | function getPointData(arrays, datasetLabels, datapointLabels) { 97 | var lookup = {}; 98 | var result = []; 99 | var array, obj, datapointLabel, datapointValue, i, j, ilen, jlen; 100 | 101 | for (i = 0, ilen = datasetLabels.length; i < ilen; ++i) { 102 | lookup[datasetLabels[i]] = i; 103 | result[i] = []; 104 | } 105 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 106 | array = arrays[i]; 107 | obj = {}; 108 | for (j = 0, jlen = array.length; j < jlen; ++j) { 109 | datapointLabel = datapointLabels[j]; 110 | datapointValue = array[j]; 111 | if (datapointLabel === '_dataset') { 112 | result[lookup[datapointValue]].push(obj); 113 | } else { 114 | obj[datapointLabel] = datapointValue; 115 | } 116 | } 117 | } 118 | 119 | return result; 120 | } 121 | 122 | var CsvDataSource = DataSource.extend({ 123 | _defaultConfig: { 124 | type: 'csv', 125 | rowMapping: 'dataset', 126 | datasetLabels: true, 127 | indexLabels: true, 128 | datapointLabels: true, 129 | datapointLabelMapping: { 130 | _dataset: '_dataset', 131 | _index: 'x' 132 | } 133 | }, 134 | 135 | _responseType: 'text', 136 | 137 | initialize: function() { 138 | var me = this; 139 | var options; 140 | 141 | DataSource.prototype.initialize.apply(me, arguments); 142 | options = me._options; 143 | if (options.delimiter === undefined) { 144 | options.delimiter = getDelimiter(options.url); 145 | } 146 | }, 147 | 148 | convert: function(input) { 149 | var me = this; 150 | var options = me._options; 151 | var arrays = csvToArrays(input, options.delimiter); 152 | var datasets = []; 153 | var datapointLabels, datasetLabels, indexLabels, data, i, ilen; 154 | 155 | switch (options.rowMapping) { 156 | default: 157 | if (options.indexLabels === true) { 158 | indexLabels = getRowHeader(arrays); 159 | } 160 | if (options.datasetLabels === true) { 161 | if (indexLabels) { 162 | indexLabels.shift(); 163 | } 164 | datasetLabels = getColumnHeader(arrays); 165 | } 166 | data = arrays; 167 | break; 168 | case 'index': 169 | if (options.datasetLabels === true) { 170 | datasetLabels = getRowHeader(arrays); 171 | } 172 | if (options.indexLabels === true) { 173 | if (datasetLabels) { 174 | datasetLabels.shift(); 175 | } 176 | indexLabels = getColumnHeader(arrays); 177 | } 178 | data = datasourceHelpers.transpose(arrays); 179 | break; 180 | case 'datapoint': 181 | if (options.datapointLabels === true) { 182 | datapointLabels = getRowHeader(arrays); 183 | } 184 | if (datapointLabels === undefined) { 185 | datapointLabels = ['_dataset', 'x', 'y', 'r']; 186 | } 187 | datasetLabels = getLabels(arrays, options.datapointLabelMapping._dataset, datapointLabels); 188 | indexLabels = getLabels(arrays, options.datapointLabelMapping._index, datapointLabels); 189 | datapointLabels = convertDatapointLabels(datapointLabels, options.datapointLabelMapping); 190 | data = getPointData(arrays, datasetLabels, datapointLabels); 191 | break; 192 | } 193 | 194 | datasetLabels = datasetLabels || []; 195 | for (i = 0, ilen = data.length; i < ilen; ++i) { 196 | datasets.push({ 197 | label: datasetLabels[i], 198 | data: data[i] 199 | }); 200 | } 201 | 202 | return { 203 | labels: indexLabels, 204 | datasets: datasets 205 | }; 206 | } 207 | }); 208 | 209 | CsvDataSource._extensions = ['csv', 'tsv', 'psv']; 210 | 211 | export default CsvDataSource; 212 | -------------------------------------------------------------------------------- /src/datasources/datasource.json.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import DataSource from '../core/core.datasource'; 5 | import datasourceHelpers from '../helpers/helpers.datasource'; 6 | 7 | var helpers = Chart.helpers; 8 | 9 | function query(obj, expr) { 10 | var regex = /(?:,|^)\s*(?:"([^"]*)"|'([^']*)'|([^,\s]*))/gi; 11 | var result = []; 12 | var matches, bracketKey, dotKey, nextExprWithDot, nextExpr, quotedKey, subset, i, ilen, keys; 13 | 14 | if (obj === undefined || expr === undefined) { 15 | return obj; 16 | } 17 | 18 | // Allow up to two levels of [] nesting 19 | matches = expr.match(/(?:\[((?:\[[^\]]*\]|[^\]])*)\]|([^.[]*))(\.?(.*))/); 20 | if (!matches) { 21 | return; 22 | } 23 | bracketKey = matches[1]; 24 | dotKey = matches[2]; 25 | nextExprWithDot = matches[3]; 26 | nextExpr = nextExprWithDot ? matches[4] : undefined; 27 | 28 | // If the wildcard is used, return an array 29 | if (dotKey === '*' || bracketKey === '*') { 30 | if (helpers.isArray(obj)) { 31 | for (i = 0, ilen = obj.length; i < ilen; ++i) { 32 | result.push(query(obj[i], nextExpr)); 33 | } 34 | } else if (datasourceHelpers.isObject(obj)) { 35 | keys = result._labels = Object.keys(obj); 36 | for (i = 0, ilen = keys.length; i < ilen; ++i) { 37 | result.push(query(obj[keys[i]], nextExpr)); 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | // If the dot notation is used, return a single value 44 | if (dotKey !== undefined) { 45 | return query(obj[dotKey], nextExpr); 46 | } 47 | 48 | // If the bracket notation is used, process the list and return an array or a single value 49 | keys = result._labels = []; 50 | while ((matches = regex.exec(bracketKey))) { 51 | quotedKey = datasourceHelpers.valueOrDefault(matches[1], matches[2]); 52 | if (quotedKey !== undefined) { 53 | subset = query(obj[quotedKey], nextExpr); 54 | } else { 55 | subset = query(obj, matches[3] + nextExprWithDot); 56 | } 57 | result.push(subset); 58 | keys.push(datasourceHelpers.valueOrDefault(quotedKey, matches[3])); 59 | } 60 | return result.length > 1 ? result : result[0]; 61 | } 62 | 63 | function getSecondLevelLabels(data) { 64 | var dataLen = data.length; 65 | var array = []; 66 | var newArray, labels, labelLen, i, j; 67 | 68 | for (i = 0; i < dataLen; ++i) { 69 | Array.prototype.push.apply(array, data[i]._labels); 70 | } 71 | labels = datasourceHelpers.dedup(array); 72 | labelLen = labels.length; 73 | for (i = 0; i < dataLen; ++i) { 74 | array = data[i]; 75 | newArray = []; 76 | for (j = 0; j < labelLen; ++j) { 77 | newArray.push(array[array._labels.indexOf(labels[j])]); 78 | } 79 | data[i] = newArray; 80 | } 81 | return labels; 82 | } 83 | 84 | function getLabels(arrays, value) { 85 | var result = []; 86 | var array, labels, i, ilen; 87 | 88 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 89 | array = arrays[i]; 90 | labels = array._labels; 91 | result.push(arrays[i][labels ? labels.indexOf(value) : value]); 92 | } 93 | return datasourceHelpers.dedup(result); 94 | } 95 | 96 | function getPointData(arrays, datasetLabels, datapointLabelMapping) { 97 | var keys = Object.keys(datapointLabelMapping); 98 | var datapointLabelLookup = {}; 99 | var datasetLabelLookup = {}; 100 | var result = []; 101 | var array, labels, obj, key, datapointLabel, datapointValue, i, j, ilen, jlen; 102 | 103 | for (i = 0, ilen = keys.length; i < ilen; ++i) { 104 | key = keys[i]; 105 | if (key !== '_index') { 106 | datapointLabelLookup[datapointLabelMapping[key]] = key; 107 | } 108 | } 109 | for (i = 0, ilen = datasetLabels.length; i < ilen; ++i) { 110 | datasetLabelLookup[datasetLabels[i]] = i; 111 | result[i] = []; 112 | } 113 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 114 | array = arrays[i]; 115 | labels = array._labels; 116 | obj = {}; 117 | for (j = 0, jlen = array.length; j < jlen; ++j) { 118 | key = labels ? labels[j] : j; 119 | datapointLabel = datasourceHelpers.valueOrDefault(datapointLabelLookup[key], key); 120 | datapointValue = array[j]; 121 | if (datapointLabel === '_dataset') { 122 | result[datasetLabelLookup[datapointValue]].push(obj); 123 | } else { 124 | obj[datapointLabel] = datapointValue; 125 | } 126 | } 127 | } 128 | return result; 129 | } 130 | 131 | var JsonDataSource = DataSource.extend({ 132 | _defaultConfig: { 133 | type: 'json', 134 | rowMapping: 'dataset', 135 | datapointLabelMapping: { 136 | _dataset: '_dataset', 137 | _index: 'x' 138 | } 139 | }, 140 | 141 | _responseType: 'json', 142 | 143 | convert: function(input) { 144 | var me = this; 145 | var options = me._options; 146 | var datasets = []; 147 | var datasetLabels, indexLabels, data, arrays, i, ilen; 148 | 149 | if (options.data) { 150 | arrays = query(input, options.data); 151 | } 152 | 153 | switch (options.rowMapping) { 154 | default: 155 | if (options.datasetLabels) { 156 | datasetLabels = query(input, options.datasetLabels); 157 | } else if (arrays) { 158 | datasetLabels = arrays._labels; 159 | } 160 | if (options.indexLabels) { 161 | indexLabels = query(input, options.indexLabels); 162 | } else if (arrays) { 163 | indexLabels = getSecondLevelLabels(arrays); 164 | } 165 | data = arrays; 166 | break; 167 | case 'index': 168 | if (options.datasetLabels) { 169 | datasetLabels = query(input, options.datasetLabels); 170 | } else if (arrays) { 171 | datasetLabels = getSecondLevelLabels(arrays); 172 | } 173 | if (options.indexLabels) { 174 | indexLabels = query(input, options.indexLabels); 175 | } else if (arrays) { 176 | indexLabels = arrays._labels; 177 | } 178 | if (arrays) { 179 | data = datasourceHelpers.transpose(arrays); 180 | } 181 | break; 182 | case 'datapoint': 183 | if (arrays) { 184 | datasetLabels = getLabels(arrays, options.datapointLabelMapping._dataset); 185 | indexLabels = getLabels(arrays, options.datapointLabelMapping._index); 186 | data = getPointData(arrays, datasetLabels, options.datapointLabelMapping); 187 | } 188 | break; 189 | } 190 | 191 | datasetLabels = datasetLabels || []; 192 | data = data || []; 193 | for (i = 0, ilen = Math.max(datasetLabels.length, data.length); i < ilen; ++i) { 194 | datasets.push({ 195 | label: datasetLabels[i], 196 | data: data[i] 197 | }); 198 | } 199 | 200 | return { 201 | labels: indexLabels, 202 | datasets: datasets 203 | }; 204 | } 205 | }); 206 | 207 | JsonDataSource._extensions = ['json']; 208 | 209 | export default JsonDataSource; 210 | -------------------------------------------------------------------------------- /src/datasources/datasource.jsonLines.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import JsonDataSource from './datasource.json'; 4 | 5 | var JsonLinesDataSource = JsonDataSource.extend({ 6 | _defaultConfig: { 7 | type: 'jsonl', 8 | rowMapping: 'index', 9 | datapointLabelMapping: { 10 | _dataset: '_dataset', 11 | _index: 'x' 12 | } 13 | }, 14 | 15 | _responseType: 'text', 16 | 17 | convert: function(input) { 18 | var array = JSON.parse('[' + input.trim().split('\n').join(',') + ']'); 19 | 20 | return JsonDataSource.prototype.convert.call(this, array); 21 | } 22 | }); 23 | 24 | JsonLinesDataSource._extensions = ['jsonl']; 25 | 26 | export default JsonLinesDataSource; 27 | -------------------------------------------------------------------------------- /src/datasources/datasource.sheet.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import XLSX from 'xlsx'; 5 | import DataSource from '../core/core.datasource'; 6 | import datasourceHelpers from '../helpers/helpers.datasource'; 7 | 8 | var helpers = Chart.helpers; 9 | 10 | function parseExpression(workbook, expr) { 11 | var matches, sheetName, sheet, rangeExpr, ref, range, refRange; 12 | 13 | while (expr) { 14 | if (expr.match(/^(([A-Z]+\d*|[A-Z]*\d+):([A-Z]+\d*|[A-Z]*\d+)|[A-Z]+\d+)$/)) { 15 | rangeExpr = expr; 16 | break; 17 | } else if (sheetName) { 18 | break; 19 | } 20 | matches = expr.match(/^(?:'([^']*)'|([^!]*))(?:!(.*))?$/); 21 | sheetName = datasourceHelpers.valueOrDefault(matches[1], matches[2]); 22 | expr = matches[3]; 23 | } 24 | sheet = workbook.Sheets[datasourceHelpers.valueOrDefault(sheetName, workbook.SheetNames[0])]; 25 | ref = sheet ? sheet['!ref'] : ''; 26 | range = XLSX.utils.decode_range(datasourceHelpers.valueOrDefault(rangeExpr, ref)); 27 | 28 | if (ref) { 29 | refRange = XLSX.utils.decode_range(ref); 30 | if (range.s.c === -1) { 31 | range.s = {c: refRange.s.c, r: range.s.r}; 32 | } 33 | if (range.e.c === -1) { 34 | range.e = {c: refRange.e.c, r: range.e.r}; 35 | } 36 | if (isNaN(range.s.r)) { 37 | range.s = {c: range.s.c, r: refRange.s.r}; 38 | } 39 | if (isNaN(range.e.r)) { 40 | range.e = {c: range.e.c, r: refRange.e.r}; 41 | } 42 | } 43 | 44 | return { 45 | sheet: sheet, 46 | range: range, 47 | detected: rangeExpr === undefined 48 | }; 49 | } 50 | 51 | function query(sheetRange, options) { 52 | var sheet = sheetRange.sheet; 53 | var range = sheetRange.range; 54 | var r = options && options.columnOriented ? 'c' : 'r'; 55 | var c = options && options.columnOriented ? 'r' : 'c'; 56 | var results = []; 57 | var result, cellExpr, cell, value, i, j, ilen, jlen; 58 | 59 | if (!sheet) { 60 | return results; 61 | } 62 | 63 | for (i = range.s[r], ilen = range.e[r]; i <= ilen; ++i) { 64 | result = []; 65 | for (j = range.s[c], jlen = range.e[c]; j <= jlen; ++j) { 66 | cellExpr = {}; 67 | cellExpr[r] = i; 68 | cellExpr[c] = j; 69 | cell = sheet[XLSX.utils.encode_cell(cellExpr)] || {}; 70 | value = cell.v; 71 | if (options && options.header) { 72 | value = datasourceHelpers.valueOrDefault(value, ''); 73 | } 74 | result.push(value); 75 | } 76 | results.push(result.length > 1 ? result : result[0]); 77 | } 78 | return results; 79 | } 80 | 81 | function getRowHeader(sheetRange) { 82 | var range = helpers.clone(sheetRange.range); 83 | 84 | if (range.s.r >= range.e.r) { 85 | return; 86 | } 87 | range.e.r = range.s.r; 88 | sheetRange.range.s.r++; 89 | return query({ 90 | sheet: sheetRange.sheet, 91 | range: range 92 | }, { 93 | columnOriented: true, 94 | header: true 95 | }); 96 | } 97 | 98 | function getColumnHeader(sheetRange) { 99 | var range = helpers.clone(sheetRange.range); 100 | 101 | if (range.s.c >= range.e.c) { 102 | return; 103 | } 104 | range.e.c = range.s.c; 105 | sheetRange.range.s.c++; 106 | return query({ 107 | sheet: sheetRange.sheet, 108 | range: range 109 | }, { 110 | header: true 111 | }); 112 | } 113 | 114 | function getIndex(value, array, offset) { 115 | if (value.match(/^[A-Z]+$/)) { 116 | return XLSX.utils.decode_col(value) - offset; 117 | } 118 | return array.indexOf(value); 119 | } 120 | 121 | function getLables(sheetRange, value, datapointLabels) { 122 | var range = helpers.clone(sheetRange.range); 123 | var index = getIndex(value, datapointLabels, range.s.c); 124 | 125 | range.s.c = range.e.c = index !== -1 ? index + range.s.c : index; 126 | return datasourceHelpers.dedup(query({ 127 | sheet: sheetRange.sheet, 128 | range: range 129 | }, { 130 | header: true 131 | })); 132 | } 133 | 134 | function convertDatapointLabels(labels, mapping) { 135 | var keys = Object.keys(mapping); 136 | var result = labels.slice(); 137 | var key, index, i, ilen; 138 | 139 | for (i = 0, ilen = keys.length; i < ilen; ++i) { 140 | key = keys[i]; 141 | index = getIndex(mapping[key], labels); 142 | if (index !== -1 && key !== '_index') { 143 | result[index] = key; 144 | } 145 | } 146 | return result; 147 | } 148 | 149 | function getPointData(arrays, datasetLabels, datapointLabels) { 150 | var lookup = {}; 151 | var result = []; 152 | var array, obj, datapointLabel, datapointValue, i, j, ilen, jlen; 153 | 154 | for (i = 0, ilen = datasetLabels.length; i < ilen; ++i) { 155 | lookup[datasetLabels[i]] = i; 156 | result[i] = []; 157 | } 158 | for (i = 0, ilen = arrays.length; i < ilen; ++i) { 159 | array = arrays[i]; 160 | obj = {}; 161 | for (j = 0, jlen = array.length; j < jlen; ++j) { 162 | datapointLabel = datapointLabels[j]; 163 | datapointValue = array[j]; 164 | if (datapointLabel === '_dataset') { 165 | result[lookup[datapointValue]].push(obj); 166 | } else { 167 | obj[datapointLabel] = datapointValue; 168 | } 169 | } 170 | } 171 | 172 | return result; 173 | } 174 | 175 | var SheetDataSource = DataSource.extend({ 176 | _defaultConfig: { 177 | type: 'sheet', 178 | rowMapping: 'dataset', 179 | datapointLabelMapping: { 180 | _dataset: '_dataset', 181 | _index: 'x' 182 | } 183 | }, 184 | 185 | _responseType: 'arraybuffer', 186 | 187 | initialize: function() { 188 | if (!XLSX) { 189 | throw new Error('XLSX is not found. Please load the xlsx library before loading this plugin.'); 190 | } 191 | DataSource.prototype.initialize.apply(this, arguments); 192 | }, 193 | 194 | convert: function(input) { 195 | var me = this; 196 | var options = me._options; 197 | var workbook = XLSX.read(new Uint8Array(input), {type: 'array'}); 198 | var dataRange = parseExpression(workbook, datasourceHelpers.valueOrDefault(options.data, '')); 199 | var detected = dataRange.detected; 200 | var datasets = []; 201 | var datapointLabels, datasetLabels, indexLabels, data, i, ilen; 202 | 203 | switch (options.rowMapping) { 204 | default: 205 | if (options.indexLabels) { 206 | indexLabels = query(parseExpression(workbook, options.indexLabels), {columnOriented: true, header: true}); 207 | } else if (detected) { 208 | indexLabels = getRowHeader(dataRange); 209 | } 210 | if (options.datasetLabels) { 211 | datasetLabels = query(parseExpression(workbook, options.datasetLabels), {header: true}); 212 | } else if (detected) { 213 | if (indexLabels) { 214 | indexLabels.shift(); 215 | } 216 | datasetLabels = getColumnHeader(dataRange); 217 | } 218 | data = query(dataRange); 219 | break; 220 | case 'index': 221 | if (options.datasetLabels) { 222 | datasetLabels = query(parseExpression(workbook, options.datasetLabels), {columnOriented: true, header: true}); 223 | } else if (detected) { 224 | datasetLabels = getRowHeader(dataRange); 225 | } 226 | if (options.indexLabels) { 227 | indexLabels = query(parseExpression(workbook, options.indexLabels), {header: true}); 228 | } else if (detected) { 229 | if (datasetLabels) { 230 | datasetLabels.shift(); 231 | } 232 | indexLabels = getColumnHeader(dataRange); 233 | } 234 | data = query(dataRange, {columnOriented: true}); 235 | break; 236 | case 'datapoint': 237 | if (options.datapointLabels) { 238 | datapointLabels = query(parseExpression(workbook, options.datapointLabels), {columnOriented: true, header: true}); 239 | } else if (detected) { 240 | datapointLabels = getRowHeader(dataRange); 241 | } 242 | if (datapointLabels === undefined) { 243 | datapointLabels = ['_dataset', 'x', 'y', 'r']; 244 | } 245 | datasetLabels = getLables(dataRange, options.datapointLabelMapping._dataset, datapointLabels); 246 | indexLabels = getLables(dataRange, options.datapointLabelMapping._index, datapointLabels); 247 | datapointLabels = convertDatapointLabels(datapointLabels, options.datapointLabelMapping); 248 | data = getPointData(query(dataRange), datasetLabels, datapointLabels); 249 | break; 250 | } 251 | 252 | datasetLabels = datasetLabels || []; 253 | data = data || []; 254 | for (i = 0, ilen = Math.max(datasetLabels.length, data.length); i < ilen; ++i) { 255 | datasets.push({ 256 | label: datasetLabels[i], 257 | data: data[i] 258 | }); 259 | } 260 | 261 | return { 262 | labels: indexLabels, 263 | datasets: datasets 264 | }; 265 | } 266 | }); 267 | 268 | SheetDataSource._extensions = [ 269 | 'xlsx', 'xlsm', 'xlsb', 'xls', 'xlw', 'xml', 'csv', 'txt', 'dif', 'sylk', 'slk', 270 | 'prn', 'ods', 'fods', 'uos', 'dbf', 'wks', 'wk1', 'wk2', 'wk3', 'wk4', '123', 271 | 'wq1', 'wq2', 'wb1', 'wb2', 'wb3', 'qpw', 'html', 'htm', 'eth' 272 | ]; 273 | 274 | export default SheetDataSource; 275 | -------------------------------------------------------------------------------- /src/datasources/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import csv from './datasource.csv'; 4 | import json from './datasource.json'; 5 | import jsonLines from './datasource.jsonLines'; 6 | import sheet from './datasource.sheet'; 7 | 8 | export default { 9 | csv: csv, 10 | json: json, 11 | jsonl: jsonLines, 12 | sheet: sheet 13 | }; 14 | -------------------------------------------------------------------------------- /src/helpers/helpers.datasource.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | 5 | var helpers = Chart.helpers; 6 | 7 | var datasourceHelpers = { 8 | // For Chart.js 2.6.0 backward compatibility 9 | isObject: helpers.isObject || function(value) { 10 | return value !== null && Object.prototype.toString.call(value) === '[object Object]'; 11 | }, 12 | 13 | // For Chart.js 2.6.0 backward compatibility 14 | valueOrDefault: helpers.valueOrDefault || helpers.getValueOrDefault, 15 | 16 | getExtension: function(url) { 17 | var matches = url.match(/^[^?#]*\.([0-9a-z]+)(?:[?#]|$)/i); 18 | 19 | if (matches) { 20 | return matches[1]; 21 | } 22 | }, 23 | 24 | transpose: function(arrays) { 25 | var columns, rows, result, i, j, array; 26 | 27 | if (!arrays.length || !arrays[0].length) { 28 | return [[]]; 29 | } 30 | 31 | columns = arrays[0].length; 32 | rows = arrays.length; 33 | result = []; 34 | 35 | for (i = 0; i < columns; ++i) { 36 | array = []; 37 | for (j = 0; j < rows; ++j) { 38 | array.push(arrays[j][i]); 39 | } 40 | result.push(array); 41 | } 42 | return result; 43 | }, 44 | 45 | dedup: function(array) { 46 | return array.filter(function(value, i) { 47 | return array.indexOf(value) === i; 48 | }); 49 | } 50 | }; 51 | 52 | export default datasourceHelpers; 53 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import datasources from './datasources/index'; 5 | import DataSourcePlugin from './plugins/plugin.datasource'; 6 | 7 | Chart.helpers.each(datasources, function(datasource, type) { 8 | DataSourcePlugin.register(type, datasource, datasource._extensions, datasource._defaults); 9 | }); 10 | 11 | export default DataSourcePlugin; 12 | -------------------------------------------------------------------------------- /src/plugins/plugin.datasource.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import datasourceHelpers from '../helpers/helpers.datasource'; 5 | 6 | var helpers = Chart.helpers; 7 | 8 | var EXPANDO_KEY = '$datasource'; 9 | 10 | Chart.defaults.global.plugins.datasource = {}; 11 | 12 | function mergeData(target, source) { 13 | var sourceDatasets = source.datasets; 14 | var targetDatasets = target.datasets; 15 | var sourceLabels = source.labels; 16 | var targetLabels = target.labels; 17 | var max = 0; 18 | var sourceDataset, targetDataset, sourceLabel, sourceData, i, ilen; 19 | 20 | if (helpers.isArray(sourceDatasets)) { 21 | if (!helpers.isArray(targetDatasets)) { 22 | targetDatasets = target.datasets = []; 23 | } 24 | for (i = 0, ilen = sourceDatasets.length; i < ilen; ++i) { 25 | sourceDataset = sourceDatasets[i]; 26 | targetDataset = targetDatasets[i]; 27 | if (!datasourceHelpers.isObject(targetDataset)) { 28 | targetDataset = targetDatasets[i] = {}; 29 | } 30 | sourceLabel = sourceDataset.label; 31 | if (sourceLabel !== undefined) { 32 | targetDataset.label = sourceLabel; 33 | } else if (targetDataset.label === undefined) { 34 | targetDataset.label = 'Dataset ' + (i + 1); 35 | } 36 | sourceData = sourceDataset.data; 37 | if (helpers.isArray(sourceData)) { 38 | targetDataset.data = sourceData; 39 | max = Math.max(max, sourceData.length); 40 | } 41 | } 42 | } 43 | if (helpers.isArray(sourceLabels)) { 44 | target.labels = sourceLabels; 45 | } else if (!helpers.isArray(targetLabels) || !targetLabels.length) { 46 | targetLabels = target.labels = []; 47 | for (i = 0; i < max; ++i) { 48 | targetLabels[i] = '' + (i + 1); 49 | } 50 | } 51 | } 52 | 53 | export default { 54 | id: 'datasource', 55 | 56 | beforeInit: function(chart) { 57 | chart[EXPANDO_KEY] = {}; 58 | }, 59 | 60 | beforeUpdate: function(chart, options) { 61 | var me = this; 62 | var expando = chart[EXPANDO_KEY]; 63 | var url = options.url; 64 | var type = options.type || me.getType(url); 65 | var DataSourceClass = me.getConstructor(type); 66 | var datasource = expando._datasource; 67 | 68 | if (url && DataSourceClass && !chart[EXPANDO_KEY]._delayed) { 69 | if (!datasource || datasource.getType() !== type || datasource.getUrl() !== url) { 70 | datasource = expando._datasource = new DataSourceClass(chart, options); 71 | } 72 | datasource.request(function(response) { 73 | mergeData(chart.data, response.data); 74 | expando._delayed = true; 75 | chart.update(); 76 | delete expando._delayed; 77 | }); 78 | return false; 79 | } 80 | }, 81 | 82 | constructors: {}, 83 | extensions: {}, 84 | 85 | register: function(type, constructor, extensions) { 86 | var me = this; 87 | 88 | me.constructors[type] = constructor; 89 | helpers.each(extensions, function(extension) { 90 | me.extensions[extension] = type; 91 | }); 92 | }, 93 | 94 | getType: function(url) { 95 | if (url) { 96 | return this.extensions[datasourceHelpers.getExtension(url)] || 'json'; 97 | } 98 | }, 99 | 100 | getConstructor: function(type) { 101 | if (!this.constructors.hasOwnProperty(type)) { 102 | throw new Error('"' + type + '" is not a data source type.'); 103 | } 104 | return this.constructors[type]; 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | jasmine: true 3 | 4 | globals: 5 | __karma__: true 6 | 7 | # http://eslint.org/docs/rules/ 8 | rules: 9 | # Best Practices 10 | complexity: 0 11 | no-new-func: 0 12 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | import utils from './utils'; 5 | 6 | var charts = {}; 7 | 8 | // force ratio=1 for tests on high-res/retina devices 9 | window.devicePixelRatio = 1; 10 | 11 | jasmine.chart = { 12 | acquire: function() { 13 | var chart = utils.acquireChart.apply(utils, arguments); 14 | charts[chart.id] = chart; 15 | return chart; 16 | }, 17 | release: function(chart) { 18 | utils.releaseChart.apply(utils, arguments); 19 | delete charts[chart.id]; 20 | } 21 | }; 22 | 23 | jasmine.triggerMouseEvent = utils.triggerMouseEvent; 24 | 25 | beforeEach(function() { 26 | Chart.helpers.merge(Chart.defaults.global, { 27 | animation: false, 28 | legend: {display: false}, 29 | responsive: false, 30 | title: {display: false}, 31 | tooltips: false, 32 | elements: { 33 | arc: { 34 | backgroundColor: 'transparent', 35 | borderColor: 'rgba(0, 0, 0, 0.1)', 36 | borderWidth: 1 37 | }, 38 | point: { 39 | backgroundColor: 'transparent', 40 | borderColor: 'rgba(0, 0, 0, 0.1)', 41 | borderWidth: 1 42 | }, 43 | rectangle: { 44 | backgroundColor: 'transparent', 45 | borderColor: 'rgba(0, 0, 0, 0.1)', 46 | borderWidth: 1 47 | } 48 | } 49 | }); 50 | 51 | Chart.helpers.merge(Chart.defaults.scale, { 52 | display: false, 53 | ticks: { 54 | beginAtZero: true 55 | } 56 | }); 57 | }); 58 | 59 | afterEach(function() { 60 | // Auto releasing acquired charts 61 | Object.keys(charts).forEach(function(id) { 62 | var chart = charts[id]; 63 | if (!(chart.$test || {}).persistent) { 64 | jasmine.chart.release(chart); 65 | } 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /test/specs/helpers.datasource.spec.js: -------------------------------------------------------------------------------- 1 | import datasourceHelpers from '../../src/helpers/helpers.datasource'; 2 | 3 | describe('helpers.datasource', function() { 4 | describe('getExtension', function() { 5 | it('should return an extension', function() { 6 | var getExtension = datasourceHelpers.getExtension; 7 | 8 | expect(getExtension('file.csv')).toBe('csv'); 9 | expect(getExtension('file.1.csv')).toBe('csv'); 10 | expect(getExtension('file.csv?query.string')).toBe('csv'); 11 | expect(getExtension('file.csv#fragment.string')).toBe('csv'); 12 | expect(getExtension('./file.csv')).toBe('csv'); 13 | expect(getExtension('http://host.domain/path/to/file.csv')).toBe('csv'); 14 | }); 15 | 16 | it('should return undefined if no extestion is contained', function() { 17 | var getExtension = datasourceHelpers.getExtension; 18 | 19 | expect(getExtension('file')).toBeUndefined(); 20 | expect(getExtension('file?query.string')).toBeUndefined(); 21 | expect(getExtension('file#fragment.string')).toBeUndefined(); 22 | expect(getExtension('http://host.domain/path/to/file')).toBeUndefined(); 23 | }); 24 | }); 25 | 26 | describe('transpose', function() { 27 | it('should return a transposed array', function() { 28 | var transpose = datasourceHelpers.transpose; 29 | 30 | expect(transpose([])).toEqual([[]]); 31 | expect(transpose([[]])).toEqual([[]]); 32 | expect(transpose([[1]])).toEqual([[1]]); 33 | expect(transpose([[1, 2], [3, 4]])).toEqual([[1, 3], [2, 4]]); 34 | expect(transpose([[1, 2, 3], [4, 5, 6]])).toEqual([[1, 4], [2, 5], [3, 6]]); 35 | expect(transpose([['1', '2', '3'], ['4', '5', '6']])).toEqual([['1', '4'], ['2', '5'], ['3', '6']]); 36 | }); 37 | }); 38 | 39 | describe('dedup', function() { 40 | it('should return a deduped array', function() { 41 | var dedup = datasourceHelpers.dedup; 42 | 43 | expect(dedup([])).toEqual([]); 44 | expect(dedup([1, 2, 3])).toEqual([1, 2, 3]); 45 | expect(dedup([1, 1, 2, 2, 2, 3])).toEqual([1, 2, 3]); 46 | expect(dedup([1, 3, 2, 1, 2, 2])).toEqual([1, 3, 2]); 47 | expect(dedup(['1', '1', '2', '2', '2', '3'])).toEqual(['1', '2', '3']); 48 | expect(dedup([1, undefined, 2, undefined, 3])).toEqual([1, undefined, 2, 3]); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Chart from 'chart.js'; 4 | 5 | function createCanvas(w, h) { 6 | var canvas = document.createElement('CANVAS'); 7 | canvas.width = w; 8 | canvas.height = h; 9 | return canvas; 10 | } 11 | 12 | function createImageData(w, h) { 13 | var canvas = createCanvas(w, h); 14 | var context = canvas.getContext('2d'); 15 | return context.getImageData(0, 0, w, h); 16 | } 17 | 18 | function readImageData(url, callback) { 19 | var image = new Image(); 20 | 21 | image.onload = function() { 22 | var h = image.height; 23 | var w = image.width; 24 | var canvas = createCanvas(w, h); 25 | var ctx = canvas.getContext('2d'); 26 | ctx.drawImage(image, 0, 0, w, h); 27 | callback(ctx.getImageData(0, 0, w, h)); 28 | }; 29 | 30 | image.src = url; 31 | } 32 | 33 | function canvasFromImageData(data) { 34 | var canvas = createCanvas(data.width, data.height); 35 | var context = canvas.getContext('2d'); 36 | context.putImageData(data, 0, 0); 37 | return canvas; 38 | } 39 | 40 | function acquireChart(config, options) { 41 | var wrapper = document.createElement('DIV'); 42 | var canvas = document.createElement('CANVAS'); 43 | var chart, key; 44 | 45 | config = config || {}; 46 | options = options || {}; 47 | options.canvas = options.canvas || {height: 512, width: 512}; 48 | options.wrapper = options.wrapper || {class: 'chartjs-wrapper'}; 49 | 50 | for (key in options.canvas) { 51 | if (options.canvas.hasOwnProperty(key)) { 52 | canvas.setAttribute(key, options.canvas[key]); 53 | } 54 | } 55 | 56 | for (key in options.wrapper) { 57 | if (options.wrapper.hasOwnProperty(key)) { 58 | wrapper.setAttribute(key, options.wrapper[key]); 59 | } 60 | } 61 | 62 | // by default, remove chart animation and auto resize 63 | config.options = config.options || {}; 64 | config.options.animation = config.options.animation === undefined ? false : config.options.animation; 65 | config.options.responsive = config.options.responsive === undefined ? false : config.options.responsive; 66 | config.options.defaultFontFamily = config.options.defaultFontFamily || 'Arial'; 67 | 68 | wrapper.appendChild(canvas); 69 | window.document.body.appendChild(wrapper); 70 | 71 | try { 72 | chart = new Chart(canvas.getContext('2d'), config); 73 | } catch (e) { 74 | window.document.body.removeChild(wrapper); 75 | throw e; 76 | } 77 | 78 | chart.$test = { 79 | persistent: options.persistent, 80 | wrapper: wrapper 81 | }; 82 | 83 | return chart; 84 | } 85 | 86 | function releaseChart(chart) { 87 | chart.destroy(); 88 | 89 | var wrapper = (chart.$test || {}).wrapper; 90 | if (wrapper && wrapper.parentNode) { 91 | wrapper.parentNode.removeChild(wrapper); 92 | } 93 | } 94 | 95 | function triggerMouseEvent(chart, type, el) { 96 | var node = chart.canvas; 97 | var rect = node.getBoundingClientRect(); 98 | var x = el ? el.x !== undefined ? el.x : el._model.x : null; 99 | var y = el ? el.y !== undefined ? el.y : el._model.y : null; 100 | 101 | var event = new MouseEvent(type, { 102 | clientX: el ? rect.left + x : undefined, 103 | clientY: el ? rect.top + y : undefined, 104 | cancelable: true, 105 | bubbles: true, 106 | view: window 107 | }); 108 | 109 | node.dispatchEvent(event); 110 | } 111 | 112 | export default { 113 | acquireChart: acquireChart, 114 | releaseChart: releaseChart, 115 | createCanvas: createCanvas, 116 | createImageData: createImageData, 117 | canvasFromImageData: canvasFromImageData, 118 | readImageData: readImageData, 119 | triggerMouseEvent: triggerMouseEvent 120 | }; 121 | --------------------------------------------------------------------------------