]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Add support for per side border width for rectangle (#6077)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Mon, 25 Feb 2019 08:03:12 +0000 (10:03 +0200)
committerSimon Brunel <simonbrunel@users.noreply.github.com>
Mon, 25 Feb 2019 08:03:12 +0000 (09:03 +0100)
19 files changed:
docs/charts/bar.md
src/elements/element.rectangle.js
test/fixtures/controller.bar/borderSkipped/value.js
test/fixtures/controller.bar/borderSkipped/value.png
test/fixtures/controller.bar/borderWidth/indexable-object.js [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/indexable-object.png [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/indexable.png
test/fixtures/controller.bar/borderWidth/negative.js [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/negative.png [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/object.js [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/object.png [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/scriptable-object.js [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/scriptable-object.png [new file with mode: 0644]
test/fixtures/controller.bar/borderWidth/value.png
test/fixtures/controller.bar/chart-area-clip.js [new file with mode: 0644]
test/fixtures/controller.bar/chart-area-clip.png [new file with mode: 0644]
test/fixtures/controller.bar/horizontal-borders.js [new file with mode: 0644]
test/fixtures/controller.bar/horizontal-borders.png [new file with mode: 0644]
test/specs/element.rectangle.tests.js

index 3f6e5cdd202676293fbf1537b38bf35e9e109198..02f080614a104b80dd82aeb8a4456c2b92c28e95 100644 (file)
@@ -71,7 +71,7 @@ the color of the bars is generally set this way.
 | [`backgroundColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
 | [`borderColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
 | [`borderSkipped`](#borderskipped) | `string` | Yes | Yes | `'bottom'`
-| [`borderWidth`](#styling) | `number` | Yes | Yes | `0`
+| [`borderWidth`](#borderwidth) | <code>number&#124;object</code> | Yes | Yes | `0`
 | [`data`](#data-structure) | `object[]` | - | - | **required**
 | [`hoverBackgroundColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined`
 | [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined`
@@ -97,7 +97,7 @@ The style of each bar can be controlled with the following properties:
 | `backgroundColor` | The bar background color.
 | `borderColor` | The bar border color.
 | [`borderSkipped`](#borderskipped) | The edge to skip when drawing bar.
-| `borderWidth` | The bar border width (in pixels).
+| [`borderWidth`](#borderwidth) | The bar border width (in pixels).
 
 All these values, if `undefined`, fallback to the associated [`elements.rectangle.*`](../configuration/elements.md#rectangle-configuration) options.
 
@@ -107,11 +107,18 @@ This setting is used to avoid drawing the bar stroke at the base of the fill.
 In general, this does not need to be changed except when creating chart types
 that derive from a bar chart.
 
+**Note:** for negative bars in vertical chart, `top` and `bottom` are flipped. Same goes for `left` and `right` in horizontal chart.
+
 Options are:
 * `'bottom'`
 * `'left'`
 * `'top'`
 * `'right'`
+* `false`
+
+#### borderWidth
+
+If this value is a number, it is applied to all sides of the rectangle (left, top, right, bottom), except [`borderSkipped`](#borderskipped). If this value is an object, the `left` property defines the left border width. Similarly the `right`, `top` and `bottom` properties can also be specified. Omitted borders and [`borderSkipped`](#borderskipped) are skipped.
 
 ### Interactions
 
index fe3702cda4efaa119a582dfc574fa05bd7fe8579..5e5a2eac459963bebcb1b0f99ee75564a80fe074 100644 (file)
@@ -2,6 +2,7 @@
 
 var defaults = require('../core/core.defaults');
 var Element = require('../core/core.element');
+var helpers = require('../helpers/index');
 
 var defaultColor = defaults.global.defaultColor;
 
@@ -16,8 +17,8 @@ defaults._set('global', {
        }
 });
 
-function isVertical(bar) {
-       return bar._view.width !== undefined;
+function isVertical(vm) {
+       return vm && vm.width !== undefined;
 }
 
 /**
@@ -26,24 +27,21 @@ function isVertical(bar) {
  * @return {Bounds} bounds of the bar
  * @private
  */
-function getBarBounds(bar) {
-       var vm = bar._view;
-       var x1, x2, y1, y2;
-
-       if (isVertical(bar)) {
-               // vertical
-               var halfWidth = vm.width / 2;
-               x1 = vm.x - halfWidth;
-               x2 = vm.x + halfWidth;
+function getBarBounds(vm) {
+       var x1, x2, y1, y2, half;
+
+       if (isVertical(vm)) {
+               half = vm.width / 2;
+               x1 = vm.x - half;
+               x2 = vm.x + half;
                y1 = Math.min(vm.y, vm.base);
                y2 = Math.max(vm.y, vm.base);
        } else {
-               // horizontal bar
-               var halfHeight = vm.height / 2;
+               half = vm.height / 2;
                x1 = Math.min(vm.x, vm.base);
                x2 = Math.max(vm.x, vm.base);
-               y1 = vm.y - halfHeight;
-               y2 = vm.y + halfHeight;
+               y1 = vm.y - half;
+               y2 = vm.y + half;
        }
 
        return {
@@ -54,96 +52,107 @@ function getBarBounds(bar) {
        };
 }
 
-module.exports = Element.extend({
-       draw: function() {
-               var ctx = this._chart.ctx;
-               var vm = this._view;
-               var left, right, top, bottom, signX, signY, borderSkipped;
-               var borderWidth = vm.borderWidth;
-
-               if (!vm.horizontal) {
-                       // bar
-                       left = vm.x - vm.width / 2;
-                       right = vm.x + vm.width / 2;
-                       top = vm.y;
-                       bottom = vm.base;
-                       signX = 1;
-                       signY = bottom > top ? 1 : -1;
-                       borderSkipped = vm.borderSkipped || 'bottom';
-               } else {
-                       // horizontal bar
-                       left = vm.base;
-                       right = vm.x;
-                       top = vm.y - vm.height / 2;
-                       bottom = vm.y + vm.height / 2;
-                       signX = right > left ? 1 : -1;
-                       signY = 1;
-                       borderSkipped = vm.borderSkipped || 'left';
-               }
+function swap(orig, v1, v2) {
+       return orig === v1 ? v2 : orig === v2 ? v1 : orig;
+}
 
-               // Canvas doesn't allow us to stroke inside the width so we can
-               // adjust the sizes to fit if we're setting a stroke on the line
-               if (borderWidth) {
-                       // borderWidth shold be less than bar width and bar height.
-                       var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
-                       borderWidth = borderWidth > barSize ? barSize : borderWidth;
-                       var halfStroke = borderWidth / 2;
-                       // Adjust borderWidth when bar top position is near vm.base(zero).
-                       var borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0);
-                       var borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0);
-                       var borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0);
-                       var borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0);
-                       // not become a vertical line?
-                       if (borderLeft !== borderRight) {
-                               top = borderTop;
-                               bottom = borderBottom;
-                       }
-                       // not become a horizontal line?
-                       if (borderTop !== borderBottom) {
-                               left = borderLeft;
-                               right = borderRight;
-                       }
-               }
+function parseBorderSkipped(vm) {
+       var edge = vm.borderSkipped;
+       var res = {};
 
-               ctx.beginPath();
-               ctx.fillStyle = vm.backgroundColor;
-               ctx.strokeStyle = vm.borderColor;
-               ctx.lineWidth = borderWidth;
-
-               // Corner points, from bottom-left to bottom-right clockwise
-               // | 1 2 |
-               // | 0 3 |
-               var corners = [
-                       [left, bottom],
-                       [left, top],
-                       [right, top],
-                       [right, bottom]
-               ];
-
-               // Find first (starting) corner with fallback to 'bottom'
-               var borders = ['bottom', 'left', 'top', 'right'];
-               var startCorner = borders.indexOf(borderSkipped, 0);
-               if (startCorner === -1) {
-                       startCorner = 0;
-               }
+       if (!edge) {
+               return res;
+       }
 
-               function cornerAt(index) {
-                       return corners[(startCorner + index) % 4];
+       if (vm.horizontal) {
+               if (vm.base > vm.x) {
+                       edge = swap(edge, 'left', 'right');
                }
+       } else if (vm.base < vm.y) {
+               edge = swap(edge, 'bottom', 'top');
+       }
+
+       res[edge] = true;
+       return res;
+}
+
+function parseBorderWidth(vm, maxW, maxH) {
+       var value = vm.borderWidth;
+       var skip = parseBorderSkipped(vm);
+       var t, r, b, l;
+
+       if (helpers.isObject(value)) {
+               t = +value.top || 0;
+               r = +value.right || 0;
+               b = +value.bottom || 0;
+               l = +value.left || 0;
+       } else {
+               t = r = b = l = +value || 0;
+       }
+
+       return {
+               t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t,
+               r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r,
+               b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b,
+               l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l
+       };
+}
 
-               // Draw rectangle from 'startCorner'
-               var corner = cornerAt(0);
-               ctx.moveTo(corner[0], corner[1]);
+function boundingRects(vm) {
+       var bounds = getBarBounds(vm);
+       var width = bounds.right - bounds.left;
+       var height = bounds.bottom - bounds.top;
+       var border = parseBorderWidth(vm, width / 2, height / 2);
 
-               for (var i = 1; i < 4; i++) {
-                       corner = cornerAt(i);
-                       ctx.lineTo(corner[0], corner[1]);
+       return {
+               outer: {
+                       x: bounds.left,
+                       y: bounds.top,
+                       w: width,
+                       h: height
+               },
+               inner: {
+                       x: bounds.left + border.l,
+                       y: bounds.top + border.t,
+                       w: width - border.l - border.r,
+                       h: height - border.t - border.b
                }
+       };
+}
+
+function inRange(vm, x, y) {
+       var skipX = x === null;
+       var skipY = y === null;
+       var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm);
+
+       return bounds
+               && (skipX || x >= bounds.left && x <= bounds.right)
+               && (skipY || y >= bounds.top && y <= bounds.bottom);
+}
+
+module.exports = Element.extend({
+       draw: function() {
+               var ctx = this._chart.ctx;
+               var vm = this._view;
+               var rects = boundingRects(vm);
+               var outer = rects.outer;
+               var inner = rects.inner;
+
+               ctx.fillStyle = vm.backgroundColor;
+               ctx.fillRect(outer.x, outer.y, outer.w, outer.h);
 
-               ctx.fill();
-               if (borderWidth) {
-                       ctx.stroke();
+               if (outer.w === inner.w && outer.h === inner.h) {
+                       return;
                }
+
+               ctx.save();
+               ctx.beginPath();
+               ctx.rect(outer.x, outer.y, outer.w, outer.h);
+               ctx.clip();
+               ctx.fillStyle = vm.borderColor;
+               ctx.rect(inner.x, inner.y, inner.w, inner.h);
+               ctx.fill('evenodd');
+               ctx.restore();
        },
 
        height: function() {
@@ -152,48 +161,28 @@ module.exports = Element.extend({
        },
 
        inRange: function(mouseX, mouseY) {
-               var inRange = false;
-
-               if (this._view) {
-                       var bounds = getBarBounds(this);
-                       inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
-               }
-
-               return inRange;
+               return inRange(this._view, mouseX, mouseY);
        },
 
        inLabelRange: function(mouseX, mouseY) {
-               var me = this;
-               if (!me._view) {
-                       return false;
-               }
-
-               var inRange = false;
-               var bounds = getBarBounds(me);
-
-               if (isVertical(me)) {
-                       inRange = mouseX >= bounds.left && mouseX <= bounds.right;
-               } else {
-                       inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
-               }
-
-               return inRange;
+               var vm = this._view;
+               return isVertical(vm)
+                       ? inRange(vm, mouseX, null)
+                       : inRange(vm, null, mouseY);
        },
 
        inXRange: function(mouseX) {
-               var bounds = getBarBounds(this);
-               return mouseX >= bounds.left && mouseX <= bounds.right;
+               return inRange(this._view, mouseX, null);
        },
 
        inYRange: function(mouseY) {
-               var bounds = getBarBounds(this);
-               return mouseY >= bounds.top && mouseY <= bounds.bottom;
+               return inRange(this._view, null, mouseY);
        },
 
        getCenterPoint: function() {
                var vm = this._view;
                var x, y;
-               if (isVertical(this)) {
+               if (isVertical(vm)) {
                        x = vm.x;
                        y = (vm.y + vm.base) / 2;
                } else {
@@ -207,7 +196,7 @@ module.exports = Element.extend({
        getArea: function() {
                var vm = this._view;
 
-               return isVertical(this)
+               return isVertical(vm)
                        ? vm.width * Math.abs(vm.y - vm.base)
                        : vm.height * Math.abs(vm.x - vm.base);
        },
index 139a2c68905edbacd93b20f053505273af34cd9b..fed9592636bdef2542109b8422d4d546c4c221b6 100644 (file)
@@ -22,6 +22,11 @@ module.exports = {
                                {
                                        // option in element (fallback)
                                        data: [0, 5, -10, null],
+                               },
+                               {
+                                       // option in dataset
+                                       data: [0, 5, -10, null],
+                                       borderSkipped: false
                                }
                        ]
                },
index 56ef05a41fe65a38ffee53a6b4a25964e0eee2e7..7f4179c87b13b21345439be6f2f7266b2b9b46d4 100644 (file)
Binary files a/test/fixtures/controller.bar/borderSkipped/value.png and b/test/fixtures/controller.bar/borderSkipped/value.png differ
diff --git a/test/fixtures/controller.bar/borderWidth/indexable-object.js b/test/fixtures/controller.bar/borderWidth/indexable-object.js
new file mode 100644 (file)
index 0000000..97f9af5
--- /dev/null
@@ -0,0 +1,56 @@
+module.exports = {
+       config: {
+               type: 'bar',
+               data: {
+                       labels: [0, 1, 2, 3, 4, 5],
+                       datasets: [
+                               {
+                                       // option in dataset
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderSkipped: false,
+                                       borderWidth: [
+                                               {},
+                                               {bottom: 1, left: 1, top: 1, right: 1},
+                                               {bottom: 1, left: 2, top: 1, right: 2},
+                                               {bottom: 1, left: 3, top: 1, right: 3},
+                                               {bottom: 1, left: 4, top: 1, right: 4},
+                                               {bottom: 1, left: 5, top: 1, right: 5}
+                                       ]
+                               },
+                               {
+                                       // option in element (fallback)
+                                       data: [0, 5, 10, null, -10, -5],
+                               }
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: 'transparent',
+                                       borderColor: '#80808080',
+                                       borderSkipped: false,
+                                       borderWidth: [
+                                               {bottom: 1, left: 5, top: 1, right: 5},
+                                               {bottom: 1, left: 4, top: 1, right: 4},
+                                               {bottom: 1, left: 3, top: 1, right: 3},
+                                               {bottom: 1, left: 2, top: 1, right: 2},
+                                               {bottom: 1, left: 1, top: 1, right: 1},
+                                               {}
+                                       ]
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [{display: false}]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/borderWidth/indexable-object.png b/test/fixtures/controller.bar/borderWidth/indexable-object.png
new file mode 100644 (file)
index 0000000..75471f5
Binary files /dev/null and b/test/fixtures/controller.bar/borderWidth/indexable-object.png differ
index 30011d3b722e474f7ae790f8a1c477f3679195b8..d3f1b85c8675193c6deceae1afe9da63a6bab7ff 100644 (file)
Binary files a/test/fixtures/controller.bar/borderWidth/indexable.png and b/test/fixtures/controller.bar/borderWidth/indexable.png differ
diff --git a/test/fixtures/controller.bar/borderWidth/negative.js b/test/fixtures/controller.bar/borderWidth/negative.js
new file mode 100644 (file)
index 0000000..5a5189d
--- /dev/null
@@ -0,0 +1,49 @@
+module.exports = {
+       config: {
+               type: 'bar',
+               data: {
+                       labels: [0, 1, 2, 3, 4, 5],
+                       datasets: [
+                               {
+                                       // option in dataset
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderWidth: -2
+                               },
+                               {
+                                       // option in element (fallback)
+                                       data: [0, 5, 10, null, -10, -5],
+                               },
+                               {
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderWidth: {left: -5, top: -5, bottom: -5, right: -5},
+                                       borderSkipped: false
+                               },
+                               {
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderWidth: {}
+                               },
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: '#888',
+                                       borderColor: '#f00',
+                                       borderWidth: -4
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [{display: false}]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/borderWidth/negative.png b/test/fixtures/controller.bar/borderWidth/negative.png
new file mode 100644 (file)
index 0000000..ca2a445
Binary files /dev/null and b/test/fixtures/controller.bar/borderWidth/negative.png differ
diff --git a/test/fixtures/controller.bar/borderWidth/object.js b/test/fixtures/controller.bar/borderWidth/object.js
new file mode 100644 (file)
index 0000000..9133b30
--- /dev/null
@@ -0,0 +1,42 @@
+module.exports = {
+       config: {
+               type: 'bar',
+               data: {
+                       labels: [0, 1, 2, 3, 4, 5],
+                       datasets: [
+                               {
+                                       // option in dataset
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderSkipped: false,
+                                       borderWidth: {bottom: 1, left: 2, top: 3, right: 4}
+                               },
+                               {
+                                       // option in element (fallback)
+                                       data: [0, 5, 10, null, -10, -5],
+                               }
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: 'transparent',
+                                       borderColor: '#888',
+                                       borderSkipped: false,
+                                       borderWidth: {bottom: 4, left: 3, top: 2, right: 1}
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [{display: false}]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/borderWidth/object.png b/test/fixtures/controller.bar/borderWidth/object.png
new file mode 100644 (file)
index 0000000..0457600
Binary files /dev/null and b/test/fixtures/controller.bar/borderWidth/object.png differ
diff --git a/test/fixtures/controller.bar/borderWidth/scriptable-object.js b/test/fixtures/controller.bar/borderWidth/scriptable-object.js
new file mode 100644 (file)
index 0000000..5bd2903
--- /dev/null
@@ -0,0 +1,54 @@
+module.exports = {
+       config: {
+               type: 'bar',
+               data: {
+                       labels: [0, 1, 2, 3, 4, 5],
+                       datasets: [
+                               {
+                                       // option in dataset
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderSkipped: false,
+                                       borderWidth: function(ctx) {
+                                               var value = ctx.dataset.data[ctx.dataIndex] || 0;
+                                               return {top: Math.abs(value)};
+                                       }
+                               },
+                               {
+                                       // option in element (fallback)
+                                       data: [0, 5, 10, null, -10, -5]
+                               }
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: 'transparent',
+                                       borderColor: '#80808080',
+                                       borderSkipped: false,
+                                       borderWidth: function(ctx) {
+                                               return {left: ctx.dataIndex * 2};
+                                       }
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [
+                                       {
+                                               display: false,
+                                               ticks: {
+                                                       beginAtZero: true
+                                               }
+                                       }
+                               ]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/borderWidth/scriptable-object.png b/test/fixtures/controller.bar/borderWidth/scriptable-object.png
new file mode 100644 (file)
index 0000000..10e65f5
Binary files /dev/null and b/test/fixtures/controller.bar/borderWidth/scriptable-object.png differ
index 3c81aff7f2dfb863751bc423a7c8db002e959871..af89232e9723602b3b02106ba12e409b2a81ac8b 100644 (file)
Binary files a/test/fixtures/controller.bar/borderWidth/value.png and b/test/fixtures/controller.bar/borderWidth/value.png differ
diff --git a/test/fixtures/controller.bar/chart-area-clip.js b/test/fixtures/controller.bar/chart-area-clip.js
new file mode 100644 (file)
index 0000000..2d552dc
--- /dev/null
@@ -0,0 +1,42 @@
+module.exports = {
+       config: {
+               type: 'bar',
+               data: {
+                       labels: [0, 1, 3, 4],
+                       datasets: [
+                               {
+                                       data: [5, 20, -5, -20],
+                                       borderColor: '#ff0000'
+                               }
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       layout: {
+                               padding: {
+                                       left: 0,
+                                       right: 0,
+                                       top: 50,
+                                       bottom: 50
+                               }
+                       },
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: '#00ff00',
+                                       borderWidth: 8
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [{display: false, ticks: {min: -10, max: 10}}]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/chart-area-clip.png b/test/fixtures/controller.bar/chart-area-clip.png
new file mode 100644 (file)
index 0000000..8c59a70
Binary files /dev/null and b/test/fixtures/controller.bar/chart-area-clip.png differ
diff --git a/test/fixtures/controller.bar/horizontal-borders.js b/test/fixtures/controller.bar/horizontal-borders.js
new file mode 100644 (file)
index 0000000..c1f0712
--- /dev/null
@@ -0,0 +1,42 @@
+module.exports = {
+       threshold: 0.01,
+       config: {
+               type: 'horizontalBar',
+               data: {
+                       labels: [0, 1, 2, 3, 4, 5],
+                       datasets: [
+                               {
+                                       // option in dataset
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderWidth: 2
+                               },
+                               {
+                                       // option in element (fallback)
+                                       data: [0, 5, 10, null, -10, -5],
+                                       borderSkipped: false,
+                               }
+                       ]
+               },
+               options: {
+                       legend: false,
+                       title: false,
+                       elements: {
+                               rectangle: {
+                                       backgroundColor: '#AAAAAA80',
+                                       borderColor: '#80808080',
+                                       borderWidth: {bottom: 6, left: 15, top: 6, right: 15}
+                               }
+                       },
+                       scales: {
+                               xAxes: [{display: false}],
+                               yAxes: [{display: false}]
+                       }
+               }
+       },
+       options: {
+               canvas: {
+                       height: 256,
+                       width: 512
+               }
+       }
+};
diff --git a/test/fixtures/controller.bar/horizontal-borders.png b/test/fixtures/controller.bar/horizontal-borders.png
new file mode 100644 (file)
index 0000000..d6a10ea
Binary files /dev/null and b/test/fixtures/controller.bar/horizontal-borders.png differ
index d8d08476f493660ecb2131b466053d6021196ca4..d6932359ed9e4d1dd814d984f413d53f1724b486 100644 (file)
@@ -1,7 +1,7 @@
 // Test the rectangle element
 
 describe('Rectangle element tests', function() {
-       it ('Should be constructed', function() {
+       it('Should be constructed', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -12,7 +12,7 @@ describe('Rectangle element tests', function() {
                expect(rectangle._index).toBe(1);
        });
 
-       it ('Should correctly identify as in range', function() {
+       it('Should correctly identify as in range', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -61,7 +61,7 @@ describe('Rectangle element tests', function() {
                expect(negativeRectangle.inRange(10, -5)).toBe(true);
        });
 
-       it ('should get the correct height', function() {
+       it('should get the correct height', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -93,7 +93,7 @@ describe('Rectangle element tests', function() {
                expect(negativeRectangle.height()).toBe(5);
        });
 
-       it ('should get the correct tooltip position', function() {
+       it('should get the correct tooltip position', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -132,7 +132,7 @@ describe('Rectangle element tests', function() {
                });
        });
 
-       it ('should get the correct vertical area', function() {
+       it('should get the correct vertical area', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -149,7 +149,7 @@ describe('Rectangle element tests', function() {
                expect(rectangle.getArea()).toEqual(60);
        });
 
-       it ('should get the correct horizontal area', function() {
+       it('should get the correct horizontal area', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -166,7 +166,7 @@ describe('Rectangle element tests', function() {
                expect(rectangle.getArea()).toEqual(40);
        });
 
-       it ('should get the center', function() {
+       it('should get the center', function() {
                var rectangle = new Chart.elements.Rectangle({
                        _datasetIndex: 2,
                        _index: 1
@@ -182,173 +182,4 @@ describe('Rectangle element tests', function() {
 
                expect(rectangle.getCenterPoint()).toEqual({x: 10, y: 7.5});
        });
-
-       it ('should draw correctly', function() {
-               var mockContext = window.createMockContext();
-               var rectangle = new Chart.elements.Rectangle({
-                       _datasetIndex: 2,
-                       _index: 1,
-                       _chart: {
-                               ctx: mockContext,
-                       }
-               });
-
-               // Attach a view object as if we were the controller
-               rectangle._view = {
-                       backgroundColor: 'rgb(255, 0, 0)',
-                       base: 0,
-                       borderColor: 'rgb(0, 0, 255)',
-                       borderWidth: 1,
-                       ctx: mockContext,
-                       width: 4,
-                       x: 10,
-                       y: 15,
-               };
-
-               rectangle.draw();
-
-               expect(mockContext.getCalls()).toEqual([{
-                       name: 'beginPath',
-                       args: [],
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgb(255, 0, 0)']
-               }, {
-                       name: 'setStrokeStyle',
-                       args: ['rgb(0, 0, 255)'],
-               }, {
-                       name: 'setLineWidth',
-                       args: [1]
-               }, {
-                       name: 'moveTo',
-                       args: [8.5, 0]
-               }, {
-                       name: 'lineTo',
-                       args: [8.5, 14.5] // This is a minus bar. Not 15.5
-               }, {
-                       name: 'lineTo',
-                       args: [11.5, 14.5]
-               }, {
-                       name: 'lineTo',
-                       args: [11.5, 0]
-               }, {
-                       name: 'fill',
-                       args: [],
-               }, {
-                       name: 'stroke',
-                       args: []
-               }]);
-       });
-
-       it ('should draw correctly with no stroke', function() {
-               var mockContext = window.createMockContext();
-               var rectangle = new Chart.elements.Rectangle({
-                       _datasetIndex: 2,
-                       _index: 1,
-                       _chart: {
-                               ctx: mockContext,
-                       }
-               });
-
-               // Attach a view object as if we were the controller
-               rectangle._view = {
-                       backgroundColor: 'rgb(255, 0, 0)',
-                       base: 0,
-                       borderColor: 'rgb(0, 0, 255)',
-                       ctx: mockContext,
-                       width: 4,
-                       x: 10,
-                       y: 15,
-               };
-
-               rectangle.draw();
-
-               expect(mockContext.getCalls()).toEqual([{
-                       name: 'beginPath',
-                       args: [],
-               }, {
-                       name: 'setFillStyle',
-                       args: ['rgb(255, 0, 0)']
-               }, {
-                       name: 'setStrokeStyle',
-                       args: ['rgb(0, 0, 255)'],
-               }, {
-                       name: 'setLineWidth',
-                       args: [undefined]
-               }, {
-                       name: 'moveTo',
-                       args: [8, 0]
-               }, {
-                       name: 'lineTo',
-                       args: [8, 15]
-               }, {
-                       name: 'lineTo',
-                       args: [12, 15]
-               }, {
-                       name: 'lineTo',
-                       args: [12, 0]
-               }, {
-                       name: 'fill',
-                       args: [],
-               }]);
-       });
-
-       function testBorderSkipped(borderSkipped, expectedDrawCalls) {
-               var mockContext = window.createMockContext();
-               var rectangle = new Chart.elements.Rectangle({
-                       _chart: {ctx: mockContext}
-               });
-
-               // Attach a view object as if we were the controller
-               rectangle._view = {
-                       borderSkipped: borderSkipped, // set tested 'borderSkipped' parameter
-                       ctx: mockContext,
-                       base: 0,
-                       width: 4,
-                       x: 10,
-                       y: 15,
-               };
-
-               rectangle.draw();
-
-               var drawCalls = rectangle._view.ctx.getCalls().splice(4, 4);
-               expect(drawCalls).toEqual(expectedDrawCalls);
-       }
-
-       it ('should draw correctly respecting "borderSkipped" == "bottom"', function() {
-               testBorderSkipped ('bottom', [
-                       {name: 'moveTo', args: [8, 0]},
-                       {name: 'lineTo', args: [8, 15]},
-                       {name: 'lineTo', args: [12, 15]},
-                       {name: 'lineTo', args: [12, 0]},
-               ]);
-       });
-
-       it ('should draw correctly respecting "borderSkipped" == "left"', function() {
-               testBorderSkipped ('left', [
-                       {name: 'moveTo', args: [8, 15]},
-                       {name: 'lineTo', args: [12, 15]},
-                       {name: 'lineTo', args: [12, 0]},
-                       {name: 'lineTo', args: [8, 0]},
-               ]);
-       });
-
-       it ('should draw correctly respecting "borderSkipped" == "top"', function() {
-               testBorderSkipped ('top', [
-                       {name: 'moveTo', args: [12, 15]},
-                       {name: 'lineTo', args: [12, 0]},
-                       {name: 'lineTo', args: [8, 0]},
-                       {name: 'lineTo', args: [8, 15]},
-               ]);
-       });
-
-       it ('should draw correctly respecting "borderSkipped" == "right"', function() {
-               testBorderSkipped ('right', [
-                       {name: 'moveTo', args: [12, 0]},
-                       {name: 'lineTo', args: [8, 0]},
-                       {name: 'lineTo', args: [8, 15]},
-                       {name: 'lineTo', args: [12, 15]},
-               ]);
-       });
-
 });