diff --git a/docs/02-Scales.md b/docs/02-Scales.md index 83e52d49e..d0531a00d 100644 --- a/docs/02-Scales.md +++ b/docs/02-Scales.md @@ -74,7 +74,7 @@ The grid line configuration is nested under the scale configuration in the `tick Name | Type | Default | Description --- | --- | --- | --- autoSkip | Boolean | true | If true, automatically calculates how many labels that can be shown and hides labels accordingly. Turn it off to show all labels no matter what -callback | Function | `function(value) { return '' + value; } ` | Returns the string representation of the tick value as it should be displayed on the chart. See [callback](#scales-creating-custom-tick-formats) section below. +callback | Function | `function(value) { return helpers.isArray(value) ? value : '' + value; }` | Returns the string representation of the tick value as it should be displayed on the chart. See [callback](#scales-creating-custom-tick-formats) section below. display | Boolean | true | If true, show the ticks. fontColor | Color | "#666" | Font color for the tick labels. fontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Font family for the tick labels, follows CSS font-family options. @@ -359,8 +359,8 @@ The default configuration for a scale can be easily changed using the scale serv For example, to set the minimum value of 0 for all linear scales, you would do the following. Any linear scales created after this time would now have a minimum of 0. ``` Chart.scaleService.updateScaleDefaults('linear', { - ticks: { - min: 0 - } + ticks: { + min: 0 + } }) ``` diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js index 4a487b7b8..5808150f9 100644 --- a/src/core/core.helpers.js +++ b/src/core/core.helpers.js @@ -839,7 +839,7 @@ module.exports = function(Chart) { // to do maybe simplify this function a bit so we can do this more recursively? helpers.each(thing, function(nestedThing) { // Undefined strings and arrays should not be measured - if (nestedThing !== undefined && nestedThing !== null && helpers.isArray(nestedThing)) { + if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) { longest = helpers.measureText(ctx, data, gc, longest, nestedThing); } }); diff --git a/src/core/core.scale.js b/src/core/core.scale.js index e692ebc95..a3efa3f59 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -43,6 +43,7 @@ module.exports = function(Chart) { autoSkip: true, autoSkipPadding: 0, labelOffset: 0, + // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. callback: function(value) { return helpers.isArray(value) ? value : '' + value; } @@ -548,7 +549,6 @@ module.exports = function(Chart) { helpers.each(this.ticks, function (label, index) { // Blank optionTicks var isLastTick = this.ticks.length === index + 1; - var lineHeight; // Since we always show the last tick,we need may need to hide the last shown one before var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= this.ticks.length); @@ -597,13 +597,13 @@ module.exports = function(Chart) { context.font = tickLabelFont; context.textAlign = (isRotated) ? "right" : "center"; context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top"; - - lineHeight = context.measureText("M").width * 1.2; - + if (helpers.isArray(label)) { for (var i = 0, y = 0; i < label.length; ++i) { - context.fillText(label[i], 0, y); - y += lineHeight; + // We just make sure the multiline element is a string here.. + context.fillText('' + label[i], 0, y); + // apply same lineSpacing as calculated @ L#320 + y += (tickFontSize * 1.5); } } else { context.fillText(label, 0, 0); diff --git a/test/core.helpers.tests.js b/test/core.helpers.tests.js index de06e294d..ccc59c14a 100644 --- a/test/core.helpers.tests.js +++ b/test/core.helpers.tests.js @@ -454,6 +454,68 @@ describe('Core helper tests', function() { }]); }); + it('should return the width of the longest text in an Array and 2D Array', function() { + var context = window.createMockContext(); + var font = "normal 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"; + var arrayOfThings_1D = ['FooBar','Bar']; + var arrayOfThings_2D = [['FooBar_1','Bar_2'],'Foo_1']; + + + // Regardless 'FooBar' is the longest label it should return (charcters * 10) + expect(helpers.longestText(context, font, arrayOfThings_1D, {})).toEqual(60); + expect(helpers.longestText(context, font, arrayOfThings_2D, {})).toEqual(80); + // We check to make sure we made the right calls to the canvas. + expect(context.getCalls()).toEqual([{ + name: 'measureText', + args: ['FooBar'] + }, { + name: 'measureText', + args: ['Bar'] + }, { + name: 'measureText', + args: ['FooBar_1'] + }, { + name: 'measureText', + args: ['Bar_2'] + }, { + name: 'measureText', + args: ['Foo_1'] + }]); + }); + + it('compare text with current longest and update', function() { + var context = window.createMockContext(); + var data = {}; + var gc = []; + var longest = 70; + + expect(helpers.measureText(context, data, gc, longest, 'foobar')).toEqual(70); + expect(helpers.measureText(context, data, gc, longest, 'foobar_')).toEqual(70); + expect(helpers.measureText(context, data, gc, longest, 'foobar_1')).toEqual(80); + // We check to make sure we made the right calls to the canvas. + expect(context.getCalls()).toEqual([{ + name: 'measureText', + args: ['foobar'] + }, { + name: 'measureText', + args: ['foobar_'] + }, { + name: 'measureText', + args: ['foobar_1'] + }]); + }); + + it('count look at all the labels and return maximum number of lines', function() { + var context = window.createMockContext(); + var arrayOfThings_1 = ['Foo','Bar']; + var arrayOfThings_2 = [['Foo','Bar'],'Foo']; + var arrayOfThings_3 = [['Foo','Bar','Boo'],['Foo','Bar'],'Foo']; + + expect(helpers.numberOfLabelLines(arrayOfThings_1)).toEqual(1); + expect(helpers.numberOfLabelLines(arrayOfThings_2)).toEqual(2); + expect(helpers.numberOfLabelLines(arrayOfThings_3)).toEqual(3); + }); + it('should draw a rounded rectangle', function() { var context = window.createMockContext(); helpers.drawRoundedRectangle(context, 10, 20, 30, 40, 5);