]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Add support to fill between datasets (#4008)
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Sat, 18 Mar 2017 10:08:57 +0000 (11:08 +0100)
committerGitHub <noreply@github.com>
Sat, 18 Mar 2017 10:08:57 +0000 (11:08 +0100)
The `fill` option now accepts the index of the target dataset (number) or a string starting by "+" or "-" followed by a number representing the dataset index relative to the current one (e.g. `fill: "-2"` on dataset at index 3 will fill to dataset at index 1). It's also possible to "propagate" the filling to the target of an hidden dataset (`options.plugins.filler.propagate`). Fill boundaries `zero`, `top` and `bottom` have been deprecated and replaced by `origin`, `start` and `end`.

Implementation has been moved out of the line element into a new plugin (`src/plugins/plugin.filler.js`) and does not rely anymore on the deprecated model `scaleTop`, `scaleBottom` and `scaleZero` values. Drawing Bézier splines has been refactored in the canvas helpers (note that `Chart.helpers.canvas` is now an alias of `Chart.canvasHelpers`).

Add 3 new examples and extend utils with a pseudo-random number generator that can be initialized with `srand`. That makes possible to design examples starting always with the same initial data.

49 files changed:
samples/area/analyser.js [new file with mode: 0644]
samples/area/line-boundaries.html [new file with mode: 0644]
samples/area/line-datasets.html [new file with mode: 0644]
samples/area/radar.html [new file with mode: 0644]
samples/style.css [new file with mode: 0644]
samples/utils.js
src/chart.js
src/controllers/controller.line.js
src/controllers/controller.radar.js
src/core/core.canvasHelpers.js
src/elements/element.line.js
src/plugins/plugin.filler.js [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-boundary-end-span.json [moved from test/fixtures/element.line/fill-line-top-span.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-end-span.png [moved from test/fixtures/element.line/fill-line-top-span.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-end.json [moved from test/fixtures/element.line/fill-line-top.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-end.png [moved from test/fixtures/element.line/fill-line-top.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-span.json [moved from test/fixtures/element.line/fill-line-zero-span.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-span.png [moved from test/fixtures/element.line/fill-line-zero-span.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-spline-span.json [moved from test/fixtures/element.line/fill-line-spline-span.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-spline-span.png [moved from test/fixtures/element.line/fill-line-spline-span.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-spline.json [moved from test/fixtures/element.line/fill-line-spline.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-spline.png [moved from test/fixtures/element.line/fill-line-spline.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-stepped-span.json [moved from test/fixtures/element.line/fill-line-stepped-span.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-stepped-span.png [moved from test/fixtures/element.line/fill-line-stepped-span.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-stepped.json [moved from test/fixtures/element.line/fill-line-stepped.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin-stepped.png [moved from test/fixtures/element.line/fill-line-stepped.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin.json [moved from test/fixtures/element.line/fill-line-zero.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-origin.png [moved from test/fixtures/element.line/fill-line-zero.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-start-span.json [moved from test/fixtures/element.line/fill-line-bottom-span.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-start-span.png [moved from test/fixtures/element.line/fill-line-bottom-span.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-boundary-start.json [moved from test/fixtures/element.line/fill-line-bottom.json with 97% similarity]
test/fixtures/plugin.filler/fill-line-boundary-start.png [moved from test/fixtures/element.line/fill-line-bottom.png with 100% similarity]
test/fixtures/plugin.filler/fill-line-dataset-span.json [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset-span.png [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset-spline-span.json [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset-spline-span.png [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset-spline.json [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset-spline.png [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset.json [new file with mode: 0644]
test/fixtures/plugin.filler/fill-line-dataset.png [new file with mode: 0644]
test/fixtures/plugin.filler/fill-radar-boundary-origin-spline.json [moved from test/fixtures/element.line/fill-radar-spline.json with 97% similarity]
test/fixtures/plugin.filler/fill-radar-boundary-origin-spline.png [moved from test/fixtures/element.line/fill-radar-spline.png with 100% similarity]
test/fixtures/plugin.filler/fill-radar-boundary-origin.json [moved from test/fixtures/element.line/fill-radar-zero.json with 97% similarity]
test/fixtures/plugin.filler/fill-radar-boundary-origin.png [moved from test/fixtures/element.line/fill-radar-zero.png with 100% similarity]
test/specs/controller.line.tests.js
test/specs/controller.radar.tests.js
test/specs/element.line.tests.js
test/specs/global.deprecations.tests.js
test/specs/plugin.filler.tests.js [new file with mode: 0644]

diff --git a/samples/area/analyser.js b/samples/area/analyser.js
new file mode 100644 (file)
index 0000000..f9d001a
--- /dev/null
@@ -0,0 +1,66 @@
+/* global Chart */
+
+'use strict';
+
+(function() {
+       Chart.plugins.register({
+               id: 'samples_filler_analyser',
+
+               beforeInit: function(chart, options) {
+                       this.element = document.getElementById(options.target);
+               },
+
+               afterUpdate: function(chart) {
+                       var datasets = chart.data.datasets;
+                       var element = this.element;
+                       var stats = [];
+                       var meta, i, ilen, dataset;
+
+                       if (!element) {
+                               return;
+                       }
+
+                       for (i=0, ilen=datasets.length; i<ilen; ++i) {
+                               meta = chart.getDatasetMeta(i).$filler;
+                               if (meta) {
+                                       dataset = datasets[i];
+                                       stats.push({
+                                               fill: dataset.fill,
+                                               target: meta.fill,
+                                               visible: meta.visible,
+                                               index: i
+                                       });
+                               }
+                       }
+
+                       this.element.innerHTML = '<table>' +
+                               '<tr>' +
+                                       '<th>Dataset</th>' +
+                                       '<th>Fill</th>' +
+                                       '<th>Target (visibility)</th>' +
+                               '</tr>' +
+                               stats.map(function(stat) {
+                                       var target = stat.target;
+                                       var row =
+                                               '<td><b>' + stat.index + '</b></td>' +
+                                               '<td>' + JSON.stringify(stat.fill) + '</td>';
+
+                                       if (target === false) {
+                                               target = 'none';
+                                       } else if (isFinite(target)) {
+                                               target = 'dataset ' + target;
+                                       } else {
+                                               target = 'boundary "' + target + '"';
+                                       }
+
+                                       if (stat.visible) {
+                                               row += '<td>' + target + '</td>';
+                                       } else {
+                                               row += '<td>(hidden)</td>';
+                                       }
+
+                                       return '<tr>' + row + '</tr>';
+                               }).join('') + '</table>';
+               }
+       });
+}());
diff --git a/samples/area/line-boundaries.html b/samples/area/line-boundaries.html
new file mode 100644 (file)
index 0000000..ca0aab3
--- /dev/null
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=Edge">
+       <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>area > boundaries | Chart.js sample</title>
+       <link rel="stylesheet" type="text/css" href="../style.css">
+       <script src="../../dist/Chart.bundle.js"></script>
+       <script src="../utils.js"></script>
+       <script src="analyser.js"></script>
+</head>
+<body>
+       <div class="content">
+               <div class="wrapper col-2"><canvas id="chart-0"></canvas></div>
+               <div class="wrapper col-2"><canvas id="chart-1"></canvas></div>
+               <div class="wrapper col-2"><canvas id="chart-2"></canvas></div>
+               <div class="wrapper col-2"><canvas id="chart-3"></canvas></div>
+
+               <div class="toolbar">
+                       <button onclick="toggleSmooth(this)">Smooth</button>
+                       <button onclick="randomize(this)">Randomize</button>
+               </div>
+       </div>
+
+       <script>
+               var presets = window.chartColors;
+               var utils = Samples.utils;
+               var inputs = {
+                       min: -100,
+                       max: 100,
+                       count: 8,
+                       decimals: 2,
+                       continuity: 1
+               };
+
+               function generateData(config) {
+                       return utils.numbers(utils.merge(inputs, config || {}));
+               }
+
+               function generateLabels(config) {
+                       return utils.months(utils.merge({
+                               count: inputs.count,
+                               section: 3
+                       }, config || {}));
+               }
+
+               var options = {
+                       maintainAspectRatio: false,
+                       spanGaps: false,
+                       elements: {
+                               line: {
+                                       tension: 0.000001
+                               }
+                       },
+                       plugins: {
+                               filler: {
+                                       propagate: false
+                               }
+                       },
+                       scales: {
+                               xAxes: [{
+                                       ticks: {
+                                               autoSkip: false,
+                                               maxRotation: 0
+                                       }
+                               }]
+                       }
+               };
+
+               [false, 'origin', 'start', 'end'].forEach(function(boundary, index) {
+
+                       // reset the random seed to generate the same data for all charts
+                       utils.srand(8);
+
+                       new Chart('chart-' + index, {
+                               type: 'line',
+                               data: {
+                                       labels: generateLabels(),
+                                       datasets: [{
+                                               backgroundColor: utils.transparentize(presets.red),
+                                               borderColor: presets.red,
+                                               data: generateData(),
+                                               label: 'Dataset',
+                                               fill: boundary
+                                       }]
+                               },
+                               options: utils.merge(options, {
+                                       title: {
+                                               text: 'fill: ' + boundary,
+                                               display: true
+                                       }
+                               })
+                       });
+               });
+
+
+               function toggleSmooth(btn) {
+                       var value = btn.classList.toggle('btn-on');
+                       Chart.helpers.each(Chart.instances, function(chart) {
+                               chart.options.elements.line.tension = value? 0.4 : 0.000001;
+                               chart.update();
+                       });
+               }
+
+               function randomize() {
+                       var seed = utils.rand();
+                       Chart.helpers.each(Chart.instances, function(chart) {
+                               utils.srand(seed);
+
+                               chart.data.datasets.forEach(function(dataset) {
+                                       dataset.data = generateData();
+                               });
+
+                               chart.update();
+                       });
+               }
+       </script>
+</body>
+</html>
diff --git a/samples/area/line-datasets.html b/samples/area/line-datasets.html
new file mode 100644 (file)
index 0000000..37719df
--- /dev/null
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=Edge">
+       <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>area > datasets | Chart.js sample</title>
+       <link rel="stylesheet" type="text/css" href="../style.css">
+       <script src="../../dist/Chart.bundle.js"></script>
+       <script src="../utils.js"></script>
+       <script src="analyser.js"></script>
+</head>
+<body>
+       <div class="content">
+               <div class="wrapper">
+                       <canvas id="chart-0"></canvas>
+               </div>
+               <div class="toolbar">
+                       <button onclick="togglePropagate(this)">Propagate</button>
+                       <button onclick="toggleSmooth(this)">Smooth</button>
+                       <button onclick="randomize(this)">Randomize</button>
+               </div>
+               <div id="chart-analyser" class="analyser"></div>
+       </div>
+
+       <script>
+               var presets = window.chartColors;
+               var utils = Samples.utils;
+               var inputs = {
+                       min: 20,
+                       max: 80,
+                       count: 8,
+                       decimals: 2,
+                       continuity: 1
+               };
+
+               function generateData() {
+                       return utils.numbers(inputs);
+               }
+
+               function generateLabels(config) {
+                       return utils.months({count: inputs.count});
+               }
+
+               utils.srand(42);
+
+               var data = {
+                       labels: generateLabels(),
+                       datasets: [{
+                               backgroundColor: utils.transparentize(presets.red),
+                               borderColor: presets.red,
+                               data: generateData(),
+                               hidden: true,
+                               label: 'D0'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.orange),
+                               borderColor: presets.orange,
+                               data: generateData(),
+                               label: 'D1',
+                               fill: '-1'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.yellow),
+                               borderColor: presets.yellow,
+                               data: generateData(),
+                               hidden: true,
+                               label: 'D2',
+                               fill: 1
+                       }, {
+                               backgroundColor: utils.transparentize(presets.green),
+                               borderColor: presets.green,
+                               data: generateData(),
+                               label: 'D3',
+                               fill: '-1'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.blue),
+                               borderColor: presets.blue,
+                               data: generateData(),
+                               label: 'D4',
+                               fill: '-1'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.grey),
+                               borderColor: presets.grey,
+                               data: generateData(),
+                               label: 'D5',
+                               fill: '+2'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.purple),
+                               borderColor: presets.purple,
+                               data: generateData(),
+                               label: 'D6',
+                               fill: false
+                       }, {
+                               backgroundColor: utils.transparentize(presets.red),
+                               borderColor: presets.red,
+                               data: generateData(),
+                               label: 'D7',
+                               fill: 8
+                       }, {
+                               backgroundColor: utils.transparentize(presets.orange),
+                               borderColor: presets.orange,
+                               data: generateData(),
+                               hidden: true,
+                               label: 'D8',
+                               fill: 'end'
+                       }]
+               };
+
+               var options = {
+                       maintainAspectRatio: false,
+                       spanGaps: false,
+                       elements: {
+                               line: {
+                                       tension: 0.000001
+                               }
+                       },
+                       scales: {
+                               yAxes: [{
+                                       stacked: true
+                               }]
+                       },
+                       plugins: {
+                               filler: {
+                                       propagate: false
+                               },
+                               samples_filler_analyser: {
+                                       target: 'chart-analyser'
+                               }
+                       }
+               };
+
+               var chart = new Chart('chart-0', {
+                       type: 'line',
+                       data: data,
+                       options: options
+               });
+
+               function togglePropagate(btn) {
+                       var value = btn.classList.toggle('btn-on');
+                       chart.options.plugins.filler.propagate = value;
+                       chart.update();
+               }
+
+               function toggleSmooth(btn) {
+                       var value = btn.classList.toggle('btn-on');
+                       chart.options.elements.line.tension = value? 0.4 : 0.000001;
+                       chart.update();
+               }
+
+               function randomize() {
+                       chart.data.datasets.forEach(function(dataset) {
+                               dataset.data = generateData();
+                       });
+                       chart.update();
+               }
+       </script>
+</body>
+</html>
diff --git a/samples/area/radar.html b/samples/area/radar.html
new file mode 100644 (file)
index 0000000..23f2bdd
--- /dev/null
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+       <meta charset="utf-8">
+       <meta http-equiv="X-UA-Compatible" content="IE=Edge">
+       <meta name="viewport" content="width=device-width, initial-scale=1">
+       <title>area > radar | Chart.js sample</title>
+       <link rel="stylesheet" type="text/css" href="../style.css">
+       <script src="../../dist/Chart.bundle.js"></script>
+       <script src="../utils.js"></script>
+       <script src="analyser.js"></script>
+</head>
+<body>
+       <div class="content">
+               <div class="wrapper" style="max-width: 512px; margin: auto">
+                       <canvas id="chart-0"></canvas>
+               </div>
+               <div class="toolbar">
+                       <button onclick="togglePropagate(this)">Propagate</button>
+                       <button onclick="toggleSmooth(this)">Smooth</button>
+                       <button onclick="randomize(this)">Randomize</button>
+               </div>
+               <div id="chart-analyser" class="analyser"></div>
+       </div>
+
+       <script>
+               var presets = window.chartColors;
+               var utils = Samples.utils;
+               var inputs = {
+                       min: 8,
+                       max: 16,
+                       count: 8,
+                       decimals: 2,
+                       continuity: 1
+               };
+
+               function generateData() {
+                       // radar chart doesn't support stacked values, let's do it manually
+                       var values = utils.numbers(inputs);
+                       inputs.from = values;
+                       return values;
+               }
+
+               function generateLabels(config) {
+                       return utils.months({count: inputs.count});
+               }
+
+               utils.srand(42);
+
+               var data = {
+                       labels: generateLabels(),
+                       datasets: [{
+                               backgroundColor: utils.transparentize(presets.red),
+                               borderColor: presets.red,
+                               data: generateData(),
+                               label: 'D0'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.orange),
+                               borderColor: presets.orange,
+                               data: generateData(),
+                               hidden: true,
+                               label: 'D1',
+                               fill: '-1'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.yellow),
+                               borderColor: presets.yellow,
+                               data: generateData(),
+                               label: 'D2',
+                               fill: 1
+                       }, {
+                               backgroundColor: utils.transparentize(presets.green),
+                               borderColor: presets.green,
+                               data: generateData(),
+                               label: 'D3',
+                               fill: false
+                       }, {
+                               backgroundColor: utils.transparentize(presets.blue),
+                               borderColor: presets.blue,
+                               data: generateData(),
+                               label: 'D4',
+                               fill: '-1'
+                       }, {
+                               backgroundColor: utils.transparentize(presets.purple),
+                               borderColor: presets.purple,
+                               data: generateData(),
+                               label: 'D5',
+                               fill: '-1'
+                       }]
+               };
+
+               var options = {
+                       maintainAspectRatio: true,
+                       spanGaps: false,
+                       elements: {
+                               line: {
+                                       tension: 0.000001
+                               }
+                       },
+                       plugins: {
+                               filler: {
+                                       propagate: false
+                               },
+                               samples_filler_analyser: {
+                                       target: 'chart-analyser'
+                               }
+                       }
+               };
+
+               var chart = new Chart('chart-0', {
+                       type: 'radar',
+                       data: data,
+                       options: options
+               });
+
+               function togglePropagate(btn) {
+                       var value = btn.classList.toggle('btn-on');
+                       chart.options.plugins.filler.propagate = value;
+                       chart.update();
+               }
+
+               function toggleSmooth(btn) {
+                       var value = btn.classList.toggle('btn-on');
+                       chart.options.elements.line.tension = value? 0.4 : 0.000001;
+                       chart.update();
+               }
+
+               function randomize() {
+                       inputs.from = [];
+                       chart.data.datasets.forEach(function(dataset) {
+                               dataset.data = generateData();
+                       });
+                       chart.update();
+               }
+       </script>
+</body>
+</html>
diff --git a/samples/style.css b/samples/style.css
new file mode 100644 (file)
index 0000000..5b58650
--- /dev/null
@@ -0,0 +1,64 @@
+body, html {
+       font-family: sans-serif;
+       padding: 0;
+       margin: 0;
+}
+
+.content {
+       max-width: 800px;
+       margin: auto;
+       padding: 16px;
+}
+
+.wrapper {
+       min-height: 400px;
+       padding: 16px 0;
+       position: relative;
+}
+
+.wrapper.col-2 {
+       display: inline-block;
+       min-height: 256px;
+       width: 49%;
+}
+
+@media (max-width: 400px) {
+       .wrapper.col-2 {
+               width: 100%
+       }
+}
+
+.wrapper canvas {
+       -moz-user-select: none;
+       -webkit-user-select: none;
+       -ms-user-select: none;
+}
+
+.toolbar {
+       display: flex;
+}
+
+.toolbar > * {
+       margin: 0 8px 0 0;
+}
+
+.btn-on {
+       border-style: inset;
+}
+
+.analyser table {
+       color: #333;
+       font-size: 0.9rem;
+       margin: 8px 0;
+       width: 100%
+}
+
+.analyser th {
+       background-color: #f0f0f0;
+       padding: 2px;
+}
+
+.analyser td {
+       padding: 2px;
+       text-align: center;
+}
index 34965ce66cae6a74d6f42fa7cd08c3ca0d602063..dc5bd12aea2d07ba8de56684e5ea1809fa838bf0 100644 (file)
@@ -1,3 +1,7 @@
+/* global Chart */
+
+'use strict';
+
 window.chartColors = {
        red: 'rgb(255, 99, 132)',
        orange: 'rgb(255, 159, 64)',
@@ -5,9 +9,111 @@ window.chartColors = {
        green: 'rgb(75, 192, 192)',
        blue: 'rgb(54, 162, 235)',
        purple: 'rgb(153, 102, 255)',
-       grey: 'rgb(231,233,237)'
+       grey: 'rgb(201, 203, 207)'
 };
 
 window.randomScalingFactor = function() {
        return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
-}
\ No newline at end of file
+};
+
+(function(global) {
+       var Months = [
+               'January',
+               'February',
+               'March',
+               'April',
+               'May',
+               'June',
+               'July',
+               'August',
+               'September',
+               'October',
+               'November',
+               'December'
+       ];
+
+       var Samples = global.Samples || (global.Samples = {});
+       Samples.utils = {
+               // Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
+               srand: function(seed) {
+                       this._seed = seed;
+               },
+
+               rand: function(min, max) {
+                       var seed = this._seed;
+                       min = min === undefined? 0 : min;
+                       max = max === undefined? 1 : max;
+                       this._seed = (seed * 9301 + 49297) % 233280;
+                       return min + (this._seed / 233280) * (max - min);
+               },
+
+               numbers: function(config) {
+                       var cfg = config || {};
+                       var min = cfg.min || 0;
+                       var max = cfg.max || 1;
+                       var from = cfg.from || [];
+                       var count = cfg.count || 8;
+                       var decimals = cfg.decimals || 8;
+                       var continuity = cfg.continuity || 1;
+                       var dfactor = Math.pow(10, decimals) || 0;
+                       var data = [];
+                       var i, value;
+
+                       for (i=0; i<count; ++i) {
+                               value = (from[i] || 0) + this.rand(min, max);
+                               if (this.rand() <= continuity) {
+                                       data.push(Math.round(dfactor * value) / dfactor);
+                               } else {
+                                       data.push(null);
+                               }
+                       }
+
+                       return data;
+               },
+
+               labels: function(config) {
+                       var cfg = config || {};
+                       var min = cfg.min || 0;
+                       var max = cfg.max || 100;
+                       var count = cfg.count || 8;
+                       var step = (max-min) / count;
+                       var decimals = cfg.decimals || 8;
+                       var dfactor = Math.pow(10, decimals) || 0;
+                       var prefix = cfg.prefix || '';
+                       var values = [];
+                       var i;
+
+                       for (i=min; i<max; i+=step) {
+                               values.push(prefix + Math.round(dfactor * i) / dfactor);
+                       }
+
+                       return values;
+               },
+
+               months: function(config) {
+                       var cfg = config || {};
+                       var count = cfg.count || 12;
+                       var section = cfg.section;
+                       var values = [];
+                       var i, value;
+
+                       for (i=0; i<count; ++i) {
+                               value = Months[Math.ceil(i)%12];
+                               values.push(value.substring(0, section));
+                       }
+
+                       return values;
+               },
+
+               transparentize: function(color, opacity) {
+                       var alpha = opacity === undefined? 0.5 : 1 - opacity;
+                       return Chart.helpers.color(color).alpha(alpha).rgbString();
+               },
+
+               merge: Chart.helpers.configMerge
+       };
+
+       Samples.utils.srand(Date.now());
+
+}(this));
+
index 72d5bdf735cd270c17c7c592d36cb9c54bfa2156..0ee96bd57d43279e135ec124d2f3d83ae2210a20 100644 (file)
@@ -49,4 +49,11 @@ require('./charts/Chart.PolarArea')(Chart);
 require('./charts/Chart.Radar')(Chart);
 require('./charts/Chart.Scatter')(Chart);
 
+// Loading built-it plugins
+var plugins = [];
+
+plugins.push(require('./plugins/plugin.filler.js')(Chart));
+
+Chart.plugins.register(plugins);
+
 window.Chart = module.exports = Chart;
index 72e49ce92e6aa74d43e6808194ca8ee81a6793e6..1a26a04b7ef5b32558c5d6f11f16eac1272822c2 100644 (file)
@@ -78,10 +78,6 @@ module.exports = function(Chart) {
                                        fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
                                        steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
                                        cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.getValueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode),
-                                       // Scale
-                                       scaleTop: scale.top,
-                                       scaleBottom: scale.bottom,
-                                       scaleZero: scale.getBasePixel()
                                };
 
                                line.pivot();
index db8396a21c3a9c9157a7e964863519f1116e51cb..f0c04464a70485cff69e10424db9b9b5af0f8858 100644 (file)
@@ -42,6 +42,7 @@ module.exports = function(Chart) {
                        helpers.extend(meta.dataset, {
                                // Utility
                                _datasetIndex: me.index,
+                               _scale: scale,
                                // Data
                                _children: points,
                                _loop: true,
@@ -57,11 +58,6 @@ module.exports = function(Chart) {
                                        borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
                                        borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
                                        borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
-
-                                       // Scale
-                                       scaleTop: scale.top,
-                                       scaleBottom: scale.bottom,
-                                       scaleZero: scale.getBasePosition()
                                }
                        });
 
index 553730c7373638a2ff0e02d6e5306ac934ba1d44..fad37e3c0f0ddac4abf7d2a44c304c5c4c177918 100644 (file)
@@ -121,4 +121,26 @@ module.exports = function(Chart) {
                ctx.restore();
        };
 
+       helpers.lineTo = function(ctx, previous, target, flip) {
+               if (target.steppedLine) {
+                       ctx.lineTo(target.x, previous.y);
+                       ctx.lineTo(target.x, target.y);
+                       return;
+               }
+
+               if (!target.tension) {
+                       ctx.lineTo(target.x, target.y);
+                       return;
+               }
+
+               ctx.bezierCurveTo(
+                       flip? previous.controlPointPreviousX : previous.controlPointNextX,
+                       flip? previous.controlPointPreviousY : previous.controlPointNextY,
+                       flip? target.controlPointNextX : target.controlPointPreviousX,
+                       flip? target.controlPointNextY : target.controlPointPreviousY,
+                       target.x,
+                       target.y);
+       };
+
+       Chart.helpers.canvas = helpers;
 };
index b63ece78c900d9da1c097e2339bf464350c3afc5..1718331d5f29104a03672c698fde6e324321540d 100644 (file)
@@ -22,118 +22,21 @@ module.exports = function(Chart) {
                draw: function() {
                        var me = this;
                        var vm = me._view;
-                       var spanGaps = vm.spanGaps;
-                       var fillPoint = vm.scaleZero;
-                       var loop = me._loop;
-
-                       // Handle different fill modes for cartesian lines
-                       if (!loop) {
-                               if (vm.fill === 'top') {
-                                       fillPoint = vm.scaleTop;
-                               } else if (vm.fill === 'bottom') {
-                                       fillPoint = vm.scaleBottom;
-                               }
-                       }
-
                        var ctx = me._chart.ctx;
-                       ctx.save();
-
-                       // Helper function to draw a line to a point
-                       function lineToPoint(previousPoint, point) {
-                               var pointVM = point._view;
-                               if (point._view.steppedLine === true) {
-                                       ctx.lineTo(pointVM.x, previousPoint._view.y);
-                                       ctx.lineTo(pointVM.x, pointVM.y);
-                               } else if (point._view.tension === 0) {
-                                       ctx.lineTo(pointVM.x, pointVM.y);
-                               } else {
-                                       ctx.bezierCurveTo(
-                                               previousPoint._view.controlPointNextX,
-                                               previousPoint._view.controlPointNextY,
-                                               pointVM.controlPointPreviousX,
-                                               pointVM.controlPointPreviousY,
-                                               pointVM.x,
-                                               pointVM.y
-                                       );
-                               }
-                       }
-
+                       var spanGaps = vm.spanGaps;
                        var points = me._children.slice(); // clone array
+                       var globalOptionLineElements = globalDefaults.elements.line;
                        var lastDrawnIndex = -1;
+                       var index, current, previous, currentVM;
 
                        // If we are looping, adding the first point again
-                       if (loop && points.length) {
+                       if (me._loop && points.length) {
                                points.push(points[0]);
                        }
 
-                       var index, current, previous, currentVM;
-
-                       // Fill Line
-                       if (points.length && vm.fill) {
-                               ctx.beginPath();
-
-                               for (index = 0; index < points.length; ++index) {
-                                       current = points[index];
-                                       previous = helpers.previousItem(points, index);
-                                       currentVM = current._view;
-
-                                       // First point moves to it's starting position no matter what
-                                       if (index === 0) {
-                                               if (loop) {
-                                                       ctx.moveTo(fillPoint.x, fillPoint.y);
-                                               } else {
-                                                       ctx.moveTo(currentVM.x, fillPoint);
-                                               }
-
-                                               if (!currentVM.skip) {
-                                                       lastDrawnIndex = index;
-                                                       ctx.lineTo(currentVM.x, currentVM.y);
-                                               }
-                                       } else {
-                                               previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
-
-                                               if (currentVM.skip) {
-                                                       // Only do this if this is the first point that is skipped
-                                                       if (!spanGaps && lastDrawnIndex === (index - 1)) {
-                                                               if (loop) {
-                                                                       ctx.lineTo(fillPoint.x, fillPoint.y);
-                                                               } else {
-                                                                       ctx.lineTo(previous._view.x, fillPoint);
-                                                               }
-                                                       }
-                                               } else {
-                                                       if (lastDrawnIndex !== (index - 1)) {
-                                                               // There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case.
-                                                               // If the first data point is NaN, then there is no real gap to skip
-                                                               if (spanGaps && lastDrawnIndex !== -1) {
-                                                                       // We are spanning the gap, so simple draw a line to this point
-                                                                       lineToPoint(previous, current);
-                                                               } else if (loop) {
-                                                                       ctx.lineTo(currentVM.x, currentVM.y);
-                                                               } else {
-                                                                       ctx.lineTo(currentVM.x, fillPoint);
-                                                                       ctx.lineTo(currentVM.x, currentVM.y);
-                                                               }
-                                                       } else {
-                                                               // Line to next point
-                                                               lineToPoint(previous, current);
-                                                       }
-                                                       lastDrawnIndex = index;
-                                               }
-                                       }
-                               }
-
-                               if (!loop && lastDrawnIndex !== -1) {
-                                       ctx.lineTo(points[lastDrawnIndex]._view.x, fillPoint);
-                               }
-
-                               ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
-                               ctx.closePath();
-                               ctx.fill();
-                       }
+                       ctx.save();
 
                        // Stroke Line Options
-                       var globalOptionLineElements = globalDefaults.elements.line;
                        ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
 
                        // IE 9 and 10 do not support line dash
@@ -170,7 +73,7 @@ module.exports = function(Chart) {
                                                        ctx.moveTo(currentVM.x, currentVM.y);
                                                } else {
                                                        // Line to next point
-                                                       lineToPoint(previous, current);
+                                                       helpers.canvas.lineTo(ctx, previous._view, current._view);
                                                }
                                                lastDrawnIndex = index;
                                        }
diff --git a/src/plugins/plugin.filler.js b/src/plugins/plugin.filler.js
new file mode 100644 (file)
index 0000000..c0219a0
--- /dev/null
@@ -0,0 +1,309 @@
+'use strict';
+
+module.exports = function(Chart) {
+       /**
+        * Plugin based on discussion from the following Chart.js issues:
+        * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569
+        * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897
+        */
+       Chart.defaults.global.plugins.filler = {
+               propagate: true
+       };
+
+       var defaults = Chart.defaults;
+       var helpers = Chart.helpers;
+       var mappers = {
+               dataset: function(source) {
+                       var index = source.fill;
+                       var chart = source.chart;
+                       var meta = chart.getDatasetMeta(index);
+                       var visible = meta && chart.isDatasetVisible(index);
+                       var points = (visible && meta.dataset._children) || [];
+
+                       return !points.length? null : function(point, i) {
+                               return points[i]._view || null;
+                       };
+               },
+
+               boundary: function(source) {
+                       var boundary = source.boundary;
+                       var x = boundary? boundary.x : null;
+                       var y = boundary? boundary.y : null;
+
+                       return function(point) {
+                               return {
+                                       x: x === null? point.x : x,
+                                       y: y === null? point.y : y,
+                               };
+                       };
+               }
+       };
+
+       // @todo if (fill[0] === '#')
+       function decodeFill(el, index, count) {
+               var model = el._model || {};
+               var fill = model.fill;
+               var target;
+
+               if (fill === undefined) {
+                       fill = !!model.backgroundColor;
+               }
+
+               if (fill === false || fill === null) {
+                       return false;
+               }
+
+               if (fill === true) {
+                       return 'origin';
+               }
+
+               target = parseFloat(fill, 10);
+               if (isFinite(target) && Math.floor(target) === target) {
+                       if (fill[0] === '-' || fill[0] === '+') {
+                               target = index + target;
+                       }
+
+                       if (target === index || target < 0 || target >= count) {
+                               return false;
+                       }
+
+                       return target;
+               }
+
+               switch (fill) {
+               // compatibility
+               case 'bottom':
+                       return 'start';
+               case 'top':
+                       return 'end';
+               case 'zero':
+                       return 'origin';
+               // supported boundaries
+               case 'origin':
+               case 'start':
+               case 'end':
+                       return fill;
+               // invalid fill values
+               default:
+                       return false;
+               }
+       }
+
+       function computeBoundary(source) {
+               var model = source.el._model || {};
+               var scale = source.el._scale || {};
+               var fill = source.fill;
+               var target = null;
+               var horizontal;
+
+               if (isFinite(fill)) {
+                       return null;
+               }
+
+               // Backward compatibility: until v3, we still need to support boundary values set on
+               // the model (scaleTop, scaleBottom and scaleZero) because some external plugins and
+               // controllers might still use it (e.g. the Smith chart).
+
+               if (fill === 'start') {
+                       target = model.scaleBottom === undefined? scale.bottom : model.scaleBottom;
+               } else if (fill === 'end') {
+                       target = model.scaleTop === undefined? scale.top : model.scaleTop;
+               } else if (model.scaleZero !== undefined) {
+                       target = model.scaleZero;
+               } else if (scale.getBasePosition) {
+                       target = scale.getBasePosition();
+               } else if (scale.getBasePixel) {
+                       target = scale.getBasePixel();
+               }
+
+               if (target !== undefined && target !== null) {
+                       if (target.x !== undefined && target.y !== undefined) {
+                               return target;
+                       }
+
+                       if (typeof target === 'number' && isFinite(target)) {
+                               horizontal = scale.isHorizontal();
+                               return {
+                                       x: horizontal? target : null,
+                                       y: horizontal? null : target
+                               };
+                       }
+               }
+
+               return null;
+       }
+
+       function resolveTarget(sources, index, propagate) {
+               var source = sources[index];
+               var fill = source.fill;
+               var visited = [index];
+               var target;
+
+               if (!propagate) {
+                       return fill;
+               }
+
+               while (fill !== false && visited.indexOf(fill) === -1) {
+                       if (!isFinite(fill)) {
+                               return fill;
+                       }
+
+                       target = sources[fill];
+                       if (!target) {
+                               return false;
+                       }
+
+                       if (target.visible) {
+                               return fill;
+                       }
+
+                       visited.push(fill);
+                       fill = target.fill;
+               }
+
+               return false;
+       }
+
+       function createMapper(source) {
+               var fill = source.fill;
+               var type = 'dataset';
+
+               if (fill === false) {
+                       return null;
+               }
+
+               if (!isFinite(fill)) {
+                       type = 'boundary';
+               }
+
+               return mappers[type](source);
+       }
+
+       function isDrawable(point) {
+               return point && !point.skip;
+       }
+
+       function drawArea(ctx, curve0, curve1, len0, len1) {
+               var i;
+
+               if (!len0 || !len1) {
+                       return;
+               }
+
+               // building first area curve (normal)
+               ctx.moveTo(curve0[0].x, curve0[0].y);
+               for (i=1; i<len0; ++i) {
+                       helpers.canvas.lineTo(ctx, curve0[i-1], curve0[i]);
+               }
+
+               // joining the two area curves
+               ctx.lineTo(curve1[len1-1].x, curve1[len1-1].y);
+
+               // building opposite area curve (reverse)
+               for (i=len1-1; i>0; --i) {
+                       helpers.canvas.lineTo(ctx, curve1[i], curve1[i-1], true);
+               }
+       }
+
+       function doFill(ctx, points, mapper, view, color, loop) {
+               var count = points.length;
+               var span = view.spanGaps;
+               var curve0 = [];
+               var curve1 = [];
+               var len0 = 0;
+               var len1 = 0;
+               var i, ilen, index, p0, p1, d0, d1;
+
+               ctx.beginPath();
+
+               for (i = 0, ilen = (count + !!loop); i < ilen; ++i) {
+                       index = i%count;
+                       p0 = points[index]._view;
+                       p1 = mapper(p0, index, view);
+                       d0 = isDrawable(p0);
+                       d1 = isDrawable(p1);
+
+                       if (d0 && d1) {
+                               len0 = curve0.push(p0);
+                               len1 = curve1.push(p1);
+                       } else if (len0 && len1) {
+                               if (!span) {
+                                       drawArea(ctx, curve0, curve1, len0, len1);
+                                       len0 = len1 = 0;
+                                       curve0 = [];
+                                       curve1 = [];
+                               } else {
+                                       if (d0) {
+                                               curve0.push(p0);
+                                       }
+                                       if (d1) {
+                                               curve1.push(p1);
+                                       }
+                               }
+                       }
+               }
+
+               drawArea(ctx, curve0, curve1, len0, len1);
+
+               ctx.closePath();
+               ctx.fillStyle = color;
+               ctx.fill();
+       }
+
+       return {
+               id: 'filler',
+
+               afterDatasetsUpdate: function(chart, options) {
+                       var count = (chart.data.datasets || []).length;
+                       var propagate = options.propagate;
+                       var sources = [];
+                       var meta, i, el, source;
+
+                       for (i = 0; i < count; ++i) {
+                               meta = chart.getDatasetMeta(i);
+                               el = meta.dataset;
+                               source = null;
+
+                               if (el && el._model && el instanceof Chart.elements.Line) {
+                                       source = {
+                                               visible: chart.isDatasetVisible(i),
+                                               fill: decodeFill(el, i, count),
+                                               chart: chart,
+                                               el: el
+                                       };
+                               }
+
+                               meta.$filler = source;
+                               sources.push(source);
+                       }
+
+                       for (i=0; i<count; ++i) {
+                               source = sources[i];
+                               if (!source) {
+                                       continue;
+                               }
+
+                               source.fill = resolveTarget(sources, i, propagate);
+                               source.boundary = computeBoundary(source);
+                               source.mapper = createMapper(source);
+                       }
+               },
+
+               beforeDatasetDraw: function(chart, args) {
+                       var meta = args.meta.$filler;
+                       if (!meta) {
+                               return;
+                       }
+
+                       var el = meta.el;
+                       var view = el._view;
+                       var points = el._children || [];
+                       var mapper = meta.mapper;
+                       var color = view.backgroundColor || defaults.global.defaultColor;
+
+                       if (mapper && color && points.length) {
+                               doFill(chart.ctx, points, mapper, view, color, el._loop);
+                       }
+               }
+       };
+};
similarity index 97%
rename from test/fixtures/element.line/fill-line-top-span.json
rename to test/fixtures/plugin.filler/fill-line-boundary-end-span.json
index b74b1f5cac3ed03d4a033336be7df62994958813..3c151a14ffd8a38c9f6179ab8f2cbf1209dd289a 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "top",
+                    "fill": "end",
                     "tension": 0
                 }
             }
similarity index 97%
rename from test/fixtures/element.line/fill-line-top.json
rename to test/fixtures/plugin.filler/fill-line-boundary-end.json
index e0696ba066183f95b1f2669088e87464b7a19194..297fe6e25e697c6ff937fadac4b8c0ef71b8a744 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "top",
+                    "fill": "end",
                     "tension": 0
                 }
             }
similarity index 97%
rename from test/fixtures/element.line/fill-line-zero-span.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin-span.json
index 64fbbb315c59e537c37972c9d7d0353a2804da2f..8a09d635e98e94afe91585583ece14da2aa760c8 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "zero",
+                    "fill": "origin",
                     "tension": 0
                 }
             }
similarity index 97%
rename from test/fixtures/element.line/fill-line-spline-span.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin-spline-span.json
index c87833b6e23bbd3b4d7faa758957017dbd76d5f7..f433aa444b5c04d9fa5be28830a69997340b9109 100644 (file)
@@ -41,7 +41,7 @@
                 "line": {
                     "cubicInterpolationMode": "monotone",
                     "borderColor": "transparent",
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
similarity index 97%
rename from test/fixtures/element.line/fill-line-spline.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin-spline.json
index 543b8cd06003c553ac16635266f50aa8b18d1e46..a714b7e500b100a54c4acf0155289c684c59e4fb 100644 (file)
@@ -41,7 +41,7 @@
                 "line": {
                     "cubicInterpolationMode": "monotone",
                     "borderColor": "transparent",
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
similarity index 97%
rename from test/fixtures/element.line/fill-line-stepped-span.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin-stepped-span.json
index c6f24e1c12b787191cc23feb8bb5945b9c1ffd92..bd1abc29efccb5529ee42fa51b3ad0d0f404de7a 100644 (file)
@@ -42,7 +42,7 @@
                     "cubicInterpolationMode": "monotone",
                     "borderColor": "transparent",
                     "stepped": true,
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
similarity index 97%
rename from test/fixtures/element.line/fill-line-stepped.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin-stepped.json
index 3fbdd7677cceec8b00f05e980e4ef47e086e2fe6..95203904d1f0f933e6ec7bd8017e719ee6b964dd 100644 (file)
@@ -42,7 +42,7 @@
                     "cubicInterpolationMode": "monotone",
                     "borderColor": "transparent",
                     "stepped": true,
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
similarity index 97%
rename from test/fixtures/element.line/fill-line-zero.json
rename to test/fixtures/plugin.filler/fill-line-boundary-origin.json
index 1958fc5d0a1824e4571f61ef6cb0cff6e7fb7a1d..094653639471491ef545272265077ae313cf7444 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "zero",
+                    "fill": "origin",
                     "tension": 0
                 }
             }
similarity index 97%
rename from test/fixtures/element.line/fill-line-bottom-span.json
rename to test/fixtures/plugin.filler/fill-line-boundary-start-span.json
index ec6bb4b0d0ace6520d510589585a0ca41b9a6546..de1022da744fda24fd97130399d0c5712fdbf33f 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "bottom",
+                    "fill": "start",
                     "tension": 0
                 }
             }
similarity index 97%
rename from test/fixtures/element.line/fill-line-bottom.json
rename to test/fixtures/plugin.filler/fill-line-boundary-start.json
index a0557fe78c5b8f126272f15578c2dc6dfca51ac8..893db5c171df576524cdd48af25bd6d97e818cd8 100644 (file)
@@ -40,7 +40,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "bottom",
+                    "fill": "start",
                     "tension": 0
                 }
             }
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-span.json b/test/fixtures/plugin.filler/fill-line-dataset-span.json
new file mode 100644 (file)
index 0000000..7cd4e7c
--- /dev/null
@@ -0,0 +1,62 @@
+{
+    "config": {
+        "type": "line",
+        "data": {
+            "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"],
+            "datasets": [{
+                "backgroundColor": "rgba(255, 0, 0, 0.25)",
+                "data": [null, null, 0, -1, 0, 1, 0, -1, 0],
+                "fill": 1
+            }, {
+                "backgroundColor": "rgba(0, 255, 0, 0.25)",
+                "data": [1, 0, null, 1, 0, null, -1, 0, 1],
+                "fill": "+1"
+            }, {
+                "backgroundColor": "rgba(0, 0, 255, 0.25)",
+                "data": [0, 2, 0, -2, 0, 2, 0, null, null],
+                "fill": 3
+            }, {
+                "backgroundColor": "rgba(255, 0, 255, 0.25)",
+                "data": [2, 0, -2, 0, 2, 0, -2, 0, 2],
+                "fill": "-2"
+            }, {
+                "backgroundColor": "rgba(255, 255, 0, 0.25)",
+                "data": [3, 1, -1, -3, -1, 1, 3, 1, -1],
+                "fill": "-1"
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "spanGaps": true,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }],
+                "yAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }]
+            },
+            "elements": {
+                "point": {
+                    "radius": 0
+                },
+                "line": {
+                    "borderColor": "transparent",
+                    "tension": 0
+                }
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-span.png b/test/fixtures/plugin.filler/fill-line-dataset-span.png
new file mode 100644 (file)
index 0000000..a6de728
Binary files /dev/null and b/test/fixtures/plugin.filler/fill-line-dataset-span.png differ
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-spline-span.json b/test/fixtures/plugin.filler/fill-line-dataset-spline-span.json
new file mode 100644 (file)
index 0000000..6f89e62
--- /dev/null
@@ -0,0 +1,62 @@
+{
+    "config": {
+        "type": "line",
+        "data": {
+            "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"],
+            "datasets": [{
+                "backgroundColor": "rgba(255, 0, 0, 0.25)",
+                "data": [null, null, 0, -1, 0, 1, 0, -1, 0],
+                "fill": 1
+            }, {
+                "backgroundColor": "rgba(0, 255, 0, 0.25)",
+                "data": [1, 0, null, 1, 0, null, -1, 0, 1],
+                "fill": "+1"
+            }, {
+                "backgroundColor": "rgba(0, 0, 255, 0.25)",
+                "data": [0, 2, 0, -2, 0, 2, 0, null, null],
+                "fill": 3
+            }, {
+                "backgroundColor": "rgba(255, 0, 255, 0.25)",
+                "data": [2, 0, -2, 0, 2, 0, -2, 0, 2],
+                "fill": "-2"
+            }, {
+                "backgroundColor": "rgba(255, 255, 0, 0.25)",
+                "data": [3, 1, -1, -3, -1, 1, 3, 1, -1],
+                "fill": "-1"
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "spanGaps": true,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }],
+                "yAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }]
+            },
+            "elements": {
+                "point": {
+                    "radius": 0
+                },
+                "line": {
+                    "cubicInterpolationMode": "monotone",
+                    "borderColor": "transparent"
+                }
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-spline-span.png b/test/fixtures/plugin.filler/fill-line-dataset-spline-span.png
new file mode 100644 (file)
index 0000000..7fb4e40
Binary files /dev/null and b/test/fixtures/plugin.filler/fill-line-dataset-spline-span.png differ
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-spline.json b/test/fixtures/plugin.filler/fill-line-dataset-spline.json
new file mode 100644 (file)
index 0000000..55054f1
--- /dev/null
@@ -0,0 +1,62 @@
+{
+    "config": {
+        "type": "line",
+        "data": {
+            "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"],
+            "datasets": [{
+                "backgroundColor": "rgba(255, 0, 0, 0.25)",
+                "data": [null, null, 0, -1, 0, 1, 0, -1, 0],
+                "fill": 1
+            }, {
+                "backgroundColor": "rgba(0, 255, 0, 0.25)",
+                "data": [1, 0, null, 1, 0, null, -1, 0, 1],
+                "fill": "+1"
+            }, {
+                "backgroundColor": "rgba(0, 0, 255, 0.25)",
+                "data": [0, 2, 0, -2, 0, 2, 0, null, null],
+                "fill": 3
+            }, {
+                "backgroundColor": "rgba(255, 0, 255, 0.25)",
+                "data": [2, 0, -2, 0, 2, 0, -2, 0, 2],
+                "fill": "-2"
+            }, {
+                "backgroundColor": "rgba(255, 255, 0, 0.25)",
+                "data": [3, 1, -1, -3, -1, 1, 3, 1, -1],
+                "fill": "-1"
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "spanGaps": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }],
+                "yAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }]
+            },
+            "elements": {
+                "point": {
+                    "radius": 0
+                },
+                "line": {
+                    "cubicInterpolationMode": "monotone",
+                    "borderColor": "transparent"
+                }
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/plugin.filler/fill-line-dataset-spline.png b/test/fixtures/plugin.filler/fill-line-dataset-spline.png
new file mode 100644 (file)
index 0000000..41d52bc
Binary files /dev/null and b/test/fixtures/plugin.filler/fill-line-dataset-spline.png differ
diff --git a/test/fixtures/plugin.filler/fill-line-dataset.json b/test/fixtures/plugin.filler/fill-line-dataset.json
new file mode 100644 (file)
index 0000000..d82bd74
--- /dev/null
@@ -0,0 +1,62 @@
+{
+    "config": {
+        "type": "line",
+        "data": {
+            "labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8"],
+            "datasets": [{
+                "backgroundColor": "rgba(255, 0, 0, 0.25)",
+                "data": [null, null, 0, -1, 0, 1, 0, -1, 0],
+                "fill": 1
+            }, {
+                "backgroundColor": "rgba(0, 255, 0, 0.25)",
+                "data": [1, 0, null, 1, 0, null, -1, 0, 1],
+                "fill": "+1"
+            }, {
+                "backgroundColor": "rgba(0, 0, 255, 0.25)",
+                "data": [0, 2, 0, -2, 0, 2, 0, null, null],
+                "fill": 3
+            }, {
+                "backgroundColor": "rgba(255, 0, 255, 0.25)",
+                "data": [2, 0, -2, 0, 2, 0, -2, 0, 2],
+                "fill": "-2"
+            }, {
+                "backgroundColor": "rgba(255, 255, 0, 0.25)",
+                "data": [3, 1, -1, -3, -1, 1, 3, 1, -1],
+                "fill": "-1"
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "spanGaps": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }],
+                "yAxes": [{
+                    "ticks": {
+                        "display": false
+                    }
+                }]
+            },
+            "elements": {
+                "point": {
+                    "radius": 0
+                },
+                "line": {
+                    "borderColor": "transparent",
+                    "tension": 0
+                }
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/plugin.filler/fill-line-dataset.png b/test/fixtures/plugin.filler/fill-line-dataset.png
new file mode 100644 (file)
index 0000000..d8a7e09
Binary files /dev/null and b/test/fixtures/plugin.filler/fill-line-dataset.png differ
similarity index 97%
rename from test/fixtures/element.line/fill-radar-spline.json
rename to test/fixtures/plugin.filler/fill-radar-boundary-origin-spline.json
index c22d8a6517cad8cc6467f1c7a2eb23b9ac13e4eb..8640adcf89ccfe881a0e1a16d577d40e33aad82d 100644 (file)
@@ -36,7 +36,7 @@
                 "line": {
                     "borderColor": "transparent",
                     "tension": 0.5,
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
similarity index 97%
rename from test/fixtures/element.line/fill-radar-zero.json
rename to test/fixtures/plugin.filler/fill-radar-boundary-origin.json
index 172007943a7cea89e5fcc4a67ec63ce5f3467cd6..fafe29791aff43ad04cc3bcd142be54e8b53e9ce 100644 (file)
@@ -35,7 +35,7 @@
                 },
                 "line": {
                     "borderColor": "transparent",
-                    "fill": "zero"
+                    "fill": "origin"
                 }
             }
         }
index 2341b403cd822d062d9a0d84ff9d259dc4f61ef2..f1fe61facc5f2ab82323e17c553469153d0fb763 100644 (file)
@@ -509,48 +509,6 @@ describe('Line controller tests', function() {
 
        });
 
-       it('should find the correct scale zero when the data is all positive', function() {
-               var chart = window.acquireChart({
-                       type: 'line',
-                       data: {
-                               datasets: [{
-                                       data: [10, 15, 20, 20],
-                                       label: 'dataset1',
-                               }],
-                               labels: ['label1', 'label2', 'label3', 'label4']
-                       },
-               });
-
-               var meta = chart.getDatasetMeta(0);
-
-               expect(meta.dataset._model).toEqual(jasmine.objectContaining({
-                       scaleTop: 32,
-                       scaleBottom: 484,
-                       scaleZero: 484,
-               }));
-       });
-
-       it('should find the correct scale zero when the data is all negative', function() {
-               var chart = window.acquireChart({
-                       type: 'line',
-                       data: {
-                               datasets: [{
-                                       data: [-10, -15, -20, -20],
-                                       label: 'dataset1',
-                               }],
-                               labels: ['label1', 'label2', 'label3', 'label4']
-                       },
-               });
-
-               var meta = chart.getDatasetMeta(0);
-
-               expect(meta.dataset._model).toEqual(jasmine.objectContaining({
-                       scaleTop: 32,
-                       scaleBottom: 484,
-                       scaleZero: 32,
-               }));
-       });
-
        it('should fall back to the line styles for points', function() {
                var chart = window.acquireChart({
                        type: 'line',
index 4b9c1f696dc271228cc532bdcb09e5e19ac2f1aa..8f621c96bb488807d172d1e371b41c2e397b0a9d 100644 (file)
@@ -111,10 +111,6 @@ describe('Radar controller tests', function() {
                meta.controller.reset(); // reset first
 
                // Line element
-               expect(meta.dataset._model.scaleTop).toBeCloseToPixel(32);
-               expect(meta.dataset._model.scaleBottom).toBeCloseToPixel(512);
-               expect(meta.dataset._model.scaleZero.x).toBeCloseToPixel(256);
-               expect(meta.dataset._model.scaleZero.y).toBeCloseToPixel(272);
                expect(meta.dataset._model).toEqual(jasmine.objectContaining({
                        backgroundColor: 'rgb(255, 0, 0)',
                        borderCapStyle: 'round',
@@ -198,10 +194,6 @@ describe('Radar controller tests', function() {
 
                meta.controller.update();
 
-               expect(meta.dataset._model.scaleTop).toBeCloseToPixel(32);
-               expect(meta.dataset._model.scaleBottom).toBeCloseToPixel(512);
-               expect(meta.dataset._model.scaleZero.x).toBeCloseToPixel(256);
-               expect(meta.dataset._model.scaleZero.y).toBeCloseToPixel(272);
                expect(meta.dataset._model).toEqual(jasmine.objectContaining({
                        backgroundColor: 'rgb(98, 98, 98)',
                        borderCapStyle: 'butt',
@@ -262,10 +254,6 @@ describe('Radar controller tests', function() {
 
                meta.controller.update();
 
-               expect(meta.dataset._model.scaleTop).toBeCloseToPixel(32);
-               expect(meta.dataset._model.scaleBottom).toBeCloseToPixel(512);
-               expect(meta.dataset._model.scaleZero.x).toBeCloseToPixel(256);
-               expect(meta.dataset._model.scaleZero.y).toBeCloseToPixel(272);
                expect(meta.dataset._model).toEqual(jasmine.objectContaining({
                        backgroundColor: 'rgb(55, 55, 54)',
                        borderCapStyle: 'square',
index 52d94cd377cddc81f7280b38d9bd29b17c1b25b8..c4d1722b4ad84a6447611741bb9192b05f09f1bd 100644 (file)
@@ -1,7 +1,5 @@
 // Tests for the line element
 describe('Chart.elements.Line', function() {
-       describe('auto', jasmine.specsFromFixtures('element.line'));
-
        it('should be constructed', function() {
                var line = new Chart.elements.Line({
                        _datasetindex: 2,
@@ -74,8 +72,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: false, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: 0
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -111,14 +108,14 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: [],
@@ -193,8 +190,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: false, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: 0
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -312,8 +308,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: false, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: 0
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -436,8 +431,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
 
                                borderCapStyle: 'round',
                                borderColor: 'rgb(255, 255, 0)',
@@ -454,36 +448,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgb(0, 0, 0)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['round']
@@ -510,327 +474,15 @@ describe('Chart.elements.Line', function() {
                }, {
                        name: 'moveTo',
                        args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'stroke',
-                       args: []
-               }, {
-                       name: 'restore',
-                       args: []
-               }];
-               expect(mockContext.getCalls()).toEqual(expected);
-       });
-
-       it('should draw with fillMode top', function() {
-               var mockContext = window.createMockContext();
-
-               // Create our points
-               var points = [];
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 0,
-                       _view: {
-                               x: 0,
-                               y: 10,
-                               controlPointNextX: 0,
-                               controlPointNextY: 10
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 1,
-                       _view: {
-                               x: 5,
-                               y: 0,
-                               controlPointPreviousX: 5,
-                               controlPointPreviousY: 0,
-                               controlPointNextX: 5,
-                               controlPointNextY: 0
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 2,
-                       _view: {
-                               x: 15,
-                               y: -10,
-                               controlPointPreviousX: 15,
-                               controlPointPreviousY: -10,
-                               controlPointNextX: 15,
-                               controlPointNextY: -10
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 3,
-                       _view: {
-                               x: 19,
-                               y: -5,
-                               controlPointPreviousX: 19,
-                               controlPointPreviousY: -5,
-                               controlPointNextX: 19,
-                               controlPointNextY: -5
-                       }
-               }));
-
-               var line = new Chart.elements.Line({
-                       _datasetindex: 2,
-                       _chart: {
-                               ctx: mockContext,
-                       },
-                       _children: points,
-                       // Need to provide some settings
-                       _view: {
-                               fill: 'top',
-                               scaleZero: 2, // for filling lines
-                               scaleTop: -2,
-                               scaleBottom: 10,
-                               tension: 0.0, // no bezier curve for now
-
-                               borderCapStyle: 'round',
-                               borderColor: 'rgb(255, 255, 0)',
-                               borderDash: [2, 2],
-                               borderDashOffset: 1.5,
-                               borderJoinStyle: 'bevel',
-                               borderWidth: 4,
-                               backgroundColor: 'rgb(0, 0, 0)'
-                       }
-               });
-
-               line.draw();
-
-               var expected = [{
-                       name: 'save',
-                       args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, -2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
                }, {
                        name: 'lineTo',
-                       args: [19, -2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgb(0, 0, 0)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
-               }, {
-                       name: 'setLineCap',
-                       args: ['round']
-               }, {
-                       name: 'setLineDash',
-                       args: [
-                               [2, 2]
-                       ]
-               }, {
-                       name: 'setLineDashOffset',
-                       args: [1.5]
-               }, {
-                       name: 'setLineJoin',
-                       args: ['bevel']
-               }, {
-                       name: 'setLineWidth',
-                       args: [4]
-               }, {
-                       name: 'setStrokeStyle',
-                       args: ['rgb(255, 255, 0)']
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'stroke',
-                       args: []
-               }, {
-                       name: 'restore',
-                       args: []
-               }];
-               expect(mockContext.getCalls()).toEqual(expected);
-       });
-
-       it('should draw with fillMode bottom', function() {
-               var mockContext = window.createMockContext();
-
-               // Create our points
-               var points = [];
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 0,
-                       _view: {
-                               x: 0,
-                               y: 10,
-                               controlPointNextX: 0,
-                               controlPointNextY: 10
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 1,
-                       _view: {
-                               x: 5,
-                               y: 0,
-                               controlPointPreviousX: 5,
-                               controlPointPreviousY: 0,
-                               controlPointNextX: 5,
-                               controlPointNextY: 0
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 2,
-                       _view: {
-                               x: 15,
-                               y: -10,
-                               controlPointPreviousX: 15,
-                               controlPointPreviousY: -10,
-                               controlPointNextX: 15,
-                               controlPointNextY: -10
-                       }
-               }));
-               points.push(new Chart.elements.Point({
-                       _datasetindex: 2,
-                       _index: 3,
-                       _view: {
-                               x: 19,
-                               y: -5,
-                               controlPointPreviousX: 19,
-                               controlPointPreviousY: -5,
-                               controlPointNextX: 19,
-                               controlPointNextY: -5
-                       }
-               }));
-
-               var line = new Chart.elements.Line({
-                       _datasetindex: 2,
-                       _chart: {
-                               ctx: mockContext,
-                       },
-                       _children: points,
-                       // Need to provide some settings
-                       _view: {
-                               fill: 'bottom',
-                               scaleZero: 2, // for filling lines
-                               scaleTop: -2,
-                               scaleBottom: 10,
-                               tension: 0.0, // no bezier curve for now
-
-                               borderCapStyle: 'round',
-                               borderColor: 'rgb(255, 255, 0)',
-                               borderDash: [2, 2],
-                               borderDashOffset: 1.5,
-                               borderJoinStyle: 'bevel',
-                               borderWidth: 4,
-                               backgroundColor: 'rgb(0, 0, 0)'
-                       }
-               });
-
-               line.draw();
-
-               var expected = [{
-                       name: 'save',
-                       args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 10]
+                       args: [5, 0]
                }, {
                        name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       args: [15, -10]
                }, {
                        name: 'lineTo',
-                       args: [19, 10]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgb(0, 0, 0)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
-               }, {
-                       name: 'setLineCap',
-                       args: ['round']
-               }, {
-                       name: 'setLineDash',
-                       args: [
-                               [2, 2]
-                       ]
-               }, {
-                       name: 'setLineDashOffset',
-                       args: [1.5]
-               }, {
-                       name: 'setLineJoin',
-                       args: ['bevel']
-               }, {
-                       name: 'setLineWidth',
-                       args: [4]
-               }, {
-                       name: 'setStrokeStyle',
-                       args: ['rgb(255, 255, 0)']
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: []
@@ -903,48 +555,14 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                        }
-               });
-
-               line.draw();
-
-               var expected = [{
-                       name: 'save',
-                       args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
+               });
+
+               line.draw();
+
+               var expected = [{
+                       name: 'save',
                        args: []
                }, {
                        name: 'setLineCap',
@@ -973,8 +591,8 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
                        name: 'moveTo',
                        args: [19, -5]
@@ -1050,8 +668,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                                spanGaps: true
                        }
                });
@@ -1061,33 +678,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 19, -5, 19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1115,11 +705,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: []
@@ -1195,8 +785,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                                spanGaps: true
                        }
                });
@@ -1206,21 +795,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1316,8 +890,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -1326,36 +899,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1383,11 +926,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: []
@@ -1460,8 +1003,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                                spanGaps: true
                        }
                });
@@ -1471,36 +1013,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [19, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1528,11 +1040,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: []
@@ -1605,8 +1117,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -1615,36 +1126,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'lineTo',
-                       args: [15, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [15, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1672,11 +1153,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
                        name: 'stroke',
                        args: []
@@ -1749,8 +1230,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true,
-                               scaleZero: 2, // for filling lines
-                               tension: 0.0, // no bezier curve for now
+                               tension: 0, // no bezier curve for now
                                spanGaps: true
                        }
                });
@@ -1760,33 +1240,6 @@ describe('Chart.elements.Line', function() {
                var expected = [{
                        name: 'save',
                        args: []
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [0, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'lineTo',
-                       args: [15, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1814,11 +1267,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
                        name: 'stroke',
                        args: []
@@ -1893,11 +1346,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: {
-                                       x: 3,
-                                       y: 2
-                               },
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -1906,36 +1355,6 @@ describe('Chart.elements.Line', function() {
                expect(mockContext.getCalls()).toEqual([{
                        name: 'save',
                        args: [],
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -1963,17 +1382,17 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
+                       name: 'lineTo',
+                       args: [0, 10]
                }, {
                        name: 'stroke',
                        args: [],
@@ -2048,11 +1467,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: {
-                                       x: 3,
-                                       y: 2
-                               },
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -2061,36 +1476,6 @@ describe('Chart.elements.Line', function() {
                expect(mockContext.getCalls()).toEqual([{
                        name: 'save',
                        args: [],
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'lineTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -2121,11 +1506,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
+                       name: 'lineTo',
+                       args: [0, 10]
                }, {
                        name: 'stroke',
                        args: [],
@@ -2200,11 +1585,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: {
-                                       x: 3,
-                                       y: 2
-                               },
+                               tension: 0, // no bezier curve for now
                                spanGaps: true
                        }
                });
@@ -2214,33 +1595,6 @@ describe('Chart.elements.Line', function() {
                expect(mockContext.getCalls()).toEqual([{
                        name: 'save',
                        args: [],
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -2268,14 +1622,14 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [19, -5, 0, 10, 0, 10]
+                       name: 'lineTo',
+                       args: [0, 10]
                }, {
                        name: 'stroke',
                        args: [],
@@ -2350,11 +1704,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: {
-                                       x: 3,
-                                       y: 2
-                               },
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -2363,33 +1713,6 @@ describe('Chart.elements.Line', function() {
                expect(mockContext.getCalls()).toEqual([{
                        name: 'save',
                        args: [],
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
-               }, {
-                       name: 'lineTo',
-                       args: [3, 2]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -2417,11 +1740,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [15, -10, 19, -5, 19, -5]
+                       name: 'lineTo',
+                       args: [19, -5]
                }, {
                        name: 'stroke',
                        args: [],
@@ -2496,11 +1819,7 @@ describe('Chart.elements.Line', function() {
                        // Need to provide some settings
                        _view: {
                                fill: true, // don't want to fill
-                               tension: 0.0, // no bezier curve for now
-                               scaleZero: {
-                                       x: 3,
-                                       y: 2
-                               },
+                               tension: 0, // no bezier curve for now
                        }
                });
 
@@ -2509,36 +1828,6 @@ describe('Chart.elements.Line', function() {
                expect(mockContext.getCalls()).toEqual([{
                        name: 'save',
                        args: [],
-               }, {
-                       name: 'beginPath',
-                       args: []
-               }, {
-                       name: 'moveTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
-               }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
-               }, {
-                       name: 'lineTo',
-                       args: [3, 2]
-               }, {
-                       name: 'lineTo',
-                       args: [0, 10]
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgba(0,0,0,0.1)']
-               }, {
-                       name: 'closePath',
-                       args: []
-               }, {
-                       name: 'fill',
-                       args: []
                }, {
                        name: 'setLineCap',
                        args: ['butt']
@@ -2566,11 +1855,11 @@ describe('Chart.elements.Line', function() {
                        name: 'moveTo',
                        args: [0, 10]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [0, 10, 5, 0, 5, 0]
+                       name: 'lineTo',
+                       args: [5, 0]
                }, {
-                       name: 'bezierCurveTo',
-                       args: [5, 0, 15, -10, 15, -10]
+                       name: 'lineTo',
+                       args: [15, -10]
                }, {
                        name: 'moveTo',
                        args: [0, 10]
index 63f383ed6cda904c0aef4e1bcd48f137fcda83b7..3c21d784aac701f939cbb3faae84ca13eab37f34 100644 (file)
@@ -86,6 +86,27 @@ describe('Deprecations', function() {
                                }, 200);
                        });
                });
+
+               describe('Chart.elements.Line: fill option', function() {
+                       it('should decode "zero", "top" and "bottom" as "origin", "start" and "end"', function() {
+                               var chart = window.acquireChart({
+                                       type: 'line',
+                                       data: {
+                                               datasets: [
+                                                       {fill: 'zero'},
+                                                       {fill: 'bottom'},
+                                                       {fill: 'top'},
+                                               ]
+                                       }
+                               });
+
+                               ['origin', 'start', 'end'].forEach(function(expected, index) {
+                                       var meta = chart.getDatasetMeta(index);
+                                       expect(meta.$filler).toBeDefined();
+                                       expect(meta.$filler.fill).toBe(expected);
+                               });
+                       });
+               });
        });
 
        describe('Version 2.5.0', function() {
diff --git a/test/specs/plugin.filler.tests.js b/test/specs/plugin.filler.tests.js
new file mode 100644 (file)
index 0000000..117f680
--- /dev/null
@@ -0,0 +1,265 @@
+describe('Plugin.filler', function() {
+       function decodedFillValues(chart) {
+               return chart.data.datasets.map(function(dataset, index) {
+                       var meta = chart.getDatasetMeta(index) || {};
+                       expect(meta.$filler).toBeDefined();
+                       return meta.$filler.fill;
+               });
+       }
+
+       describe('auto', jasmine.specsFromFixtures('plugin.filler'));
+
+       describe('dataset.fill', function() {
+               it('should support boundaries', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 'origin'},
+                                               {fill: 'start'},
+                                               {fill: 'end'},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual(['origin', 'start', 'end']);
+               });
+
+               it('should support absolute dataset index', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 1},
+                                               {fill: 3},
+                                               {fill: 0},
+                                               {fill: 2},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([1, 3, 0, 2]);
+               });
+
+               it('should support relative dataset index', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: '+3'},
+                                               {fill: '-1'},
+                                               {fill: '+1'},
+                                               {fill: '-2'},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               3, // 0 + 3
+                               0, // 1 - 1
+                               3, // 2 + 1
+                               1, // 3 - 2
+                       ]);
+               });
+
+               it('should handle default fill when true (origin)', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: true},
+                                               {fill: false},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual(['origin', false]);
+               });
+
+               it('should ignore self dataset index', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 0},
+                                               {fill: '-0'},
+                                               {fill: '+0'},
+                                               {fill: 3},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               false, // 0 === 0
+                               false, // 1 === 1 - 0
+                               false, // 2 === 2 + 0
+                               false, // 3 === 3
+                       ]);
+               });
+
+               it('should ignore out of bounds dataset index', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: -2},
+                                               {fill: 4},
+                                               {fill: '-3'},
+                                               {fill: '+1'},
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               false, // 0 - 2 < 0
+                               false, // 1 + 4 > 3
+                               false, // 2 - 3 < 0
+                               false, // 3 + 1 > 3
+                       ]);
+               });
+
+               it('should ignore invalid values', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 'foo'},
+                                               {fill: '+foo'},
+                                               {fill: '-foo'},
+                                               {fill: '+1.1'},
+                                               {fill: '-2.2'},
+                                               {fill: 3.3},
+                                               {fill: -4.4},
+                                               {fill: NaN},
+                                               {fill: Infinity},
+                                               {fill: ''},
+                                               {fill: null},
+                                               {fill: []},
+                                               {fill: {}},
+                                               {fill: function() {}}
+                                       ]
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               false, // NaN (string)
+                               false, // NaN (string)
+                               false, // NaN (string)
+                               false, // float (string)
+                               false, // float (string)
+                               false, // float (number)
+                               false, // float (number)
+                               false, // NaN
+                               false, // !isFinite
+                               false, // empty string
+                               false, // null
+                               false, // array
+                               false, // object
+                               false, // function
+                       ]);
+               });
+       });
+
+       describe('options.plugins.filler.propagate', function() {
+               it('should compute propagated fill targets if true', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 'start', hidden: true},
+                                               {fill: '-1', hidden: true},
+                                               {fill: 1, hidden: true},
+                                               {fill: '-2', hidden: true},
+                                               {fill: '+1'},
+                                               {fill: '+2'},
+                                               {fill: '-1'},
+                                               {fill: 'end', hidden: true},
+                                       ]
+                               },
+                               options: {
+                                       plugins: {
+                                               filler: {
+                                                       propagate: true
+                                               }
+                                       }
+                               }
+                       });
+
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               'start', // 'start'
+                               'start', // 1 - 1 -> 0 (hidden) -> 'start'
+                               'start', // 1 (hidden) -> 0 (hidden) -> 'start'
+                               'start', // 3 - 2 -> 1 (hidden) -> 0 (hidden) -> 'start'
+                               5,       // 4 + 1
+                               'end',   // 5 + 2 -> 7 (hidden) -> 'end'
+                               5,       // 6 - 1 -> 5
+                               'end',   // 'end'
+                       ]);
+               });
+
+               it('should preserve initial fill targets if false', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: 'start', hidden: true},
+                                               {fill: '-1', hidden: true},
+                                               {fill: 1, hidden: true},
+                                               {fill: '-2', hidden: true},
+                                               {fill: '+1'},
+                                               {fill: '+2'},
+                                               {fill: '-1'},
+                                               {fill: 'end', hidden: true},
+                                       ]
+                               },
+                               options: {
+                                       plugins: {
+                                               filler: {
+                                                       propagate: false
+                                               }
+                                       }
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               'start', // 'origin'
+                               0,       // 1 - 1
+                               1,       // 1
+                               1,       // 3 - 2
+                               5,       // 4 + 1
+                               7,       // 5 + 2
+                               5,       // 6 - 1
+                               'end',   // 'end'
+                       ]);
+               });
+
+               it('should prevent recursive propagation', function() {
+                       var chart = window.acquireChart({
+                               type: 'line',
+                               data: {
+                                       datasets: [
+                                               {fill: '+2', hidden: true},
+                                               {fill: '-1', hidden: true},
+                                               {fill: '-1', hidden: true},
+                                               {fill: '-2'}
+                                       ]
+                               },
+                               options: {
+                                       plugins: {
+                                               filler: {
+                                                       propagate: true
+                                               }
+                                       }
+                               }
+                       });
+
+                       expect(decodedFillValues(chart)).toEqual([
+                               false, // 0 + 2 -> 2 (hidden) -> 1 (hidden) -> 0 (loop)
+                               false, // 1 - 1 -> 0 (hidden) -> 2 (hidden) -> 1 (loop)
+                               false, // 2 - 1 -> 1 (hidden) -> 0 (hidden) -> 2 (loop)
+                               false, // 3 - 2 -> 1 (hidden) -> 0 (hidden) -> 2 (hidden) -> 1 (loop)
+                       ]);
+               });
+       });
+});