Skip to content

Commit

Permalink
Move utility methods in src/utils.js
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbrunel committed Jan 13, 2018
1 parent bd80224 commit 028840c
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 77 deletions.
81 changes: 4 additions & 77 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'use strict';

import Chart from 'chart.js';
import utils from './utils.js';
import defaults from './defaults.js';
import positioners from './positioners.js';

Expand All @@ -13,79 +14,6 @@ Chart.defaults.global.plugins.datalabels = defaults;
var helpers = Chart.helpers;
var MODEL_KEY = '$datalabels';

// @todo move this in Chart.helpers.toTextLines
function toTextLines(inputs) {
var lines = [];
var input;

inputs = [].concat(inputs);
while (inputs.length) {
input = inputs.pop();
if (typeof input === 'string') {
lines.unshift.apply(lines, input.split('\n'));
} else if (Array.isArray(input)) {
inputs.push.apply(inputs, input);
} else if (!helpers.isNullOrUndef(inputs)) {
lines.unshift('' + input);
}
}

return lines;
}

// @todo move this method in Chart.helpers.canvas.toFont (deprecates helpers.fontString)
// @see https://developer.mozilla.org/en-US/docs/Web/CSS/font
function toFontString(font) {
if (!font || helpers.isNullOrUndef(font.size) || helpers.isNullOrUndef(font.family)) {
return null;
}

return (font.style ? font.style + ' ' : '')
+ (font.weight ? font.weight + ' ' : '')
+ font.size + 'px '
+ font.family;
}

// @todo move this in Chart.helpers.canvas.textSize
// @todo cache calls of measureText if font doesn't change?!
function textSize(ctx, lines, font) {
var items = [].concat(lines);
var ilen = items.length;
var prev = ctx.font;
var width = 0;
var i;

ctx.font = font.string;

for (i = 0; i < ilen; ++i) {
width = Math.max(ctx.measureText(items[i]).width, width);
}

ctx.font = prev;

return {
height: ilen * font.lineHeight,
width: width
};
}

// @todo move this method in Chart.helpers.options.toFont
function parseFont(value) {
var global = Chart.defaults.global;
var size = helpers.valueOrDefault(value.size, global.defaultFontSize);
var font = {
family: helpers.valueOrDefault(value.family, global.defaultFontFamily),
lineHeight: helpers.options.toLineHeight(value.lineHeight, size),
size: size,
style: helpers.valueOrDefault(value.style, global.defaultFontStyle),
weight: helpers.valueOrDefault(value.weight, null),
string: ''
};

font.string = toFontString(font);
return font;
}

function coordinates(el, model, rect) {
var point = model.positioner(el._view, model.anchor, model.align, model.origin);
var vx = point.vx;
Expand All @@ -96,7 +24,6 @@ function coordinates(el, model, rect) {
return {x: point.x, y: point.y};
}


// include borders to the bounding rect
var borderWidth = model.borderWidth || 0;
var w = (rect.w + borderWidth * 2);
Expand Down Expand Up @@ -255,12 +182,12 @@ function modelize(el, index, ctx, config, context) {

var value = context.dataset.data[index];
var label = helpers.valueOrDefault(helpers.callback(config.formatter, [value, context]), value);
var lines = helpers.isNullOrUndef(label) ? [] : toTextLines(label);
var lines = helpers.isNullOrUndef(label) ? [] : utils.toTextLines(label);
if (!lines.length) {
return null;
}

var font = parseFont(resolve([config.font, {}], context, index));
var font = utils.parseFont(resolve([config.font, {}], context, index));
var model = {
align: resolve([config.align, 'center'], context, index),
anchor: resolve([config.anchor, 'center'], context, index),
Expand All @@ -277,7 +204,7 @@ function modelize(el, index, ctx, config, context) {
textAlign: resolve([config.textAlign, 'start'], context, index),
origin: getScaleOrigin(el),
positioner: getPositioner(el),
size: textSize(ctx, lines, font)
size: utils.textSize(ctx, lines, font)
};

return model;
Expand Down
82 changes: 82 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

import Chart from 'chart.js';

var helpers = Chart.helpers;

var utils = {
// @todo move this in Chart.helpers.toTextLines
toTextLines: function(inputs) {
var lines = [];
var input;

inputs = [].concat(inputs);
while (inputs.length) {
input = inputs.pop();
if (typeof input === 'string') {
lines.unshift.apply(lines, input.split('\n'));
} else if (Array.isArray(input)) {
inputs.push.apply(inputs, input);
} else if (!helpers.isNullOrUndef(inputs)) {
lines.unshift('' + input);
}
}

return lines;
},

// @todo move this method in Chart.helpers.canvas.toFont (deprecates helpers.fontString)
// @see https://developer.mozilla.org/en-US/docs/Web/CSS/font
toFontString: function(font) {
if (!font || helpers.isNullOrUndef(font.size) || helpers.isNullOrUndef(font.family)) {
return null;
}

return (font.style ? font.style + ' ' : '')
+ (font.weight ? font.weight + ' ' : '')
+ font.size + 'px '
+ font.family;
},

// @todo move this in Chart.helpers.canvas.textSize
// @todo cache calls of measureText if font doesn't change?!
textSize: function(ctx, lines, font) {
var items = [].concat(lines);
var ilen = items.length;
var prev = ctx.font;
var width = 0;
var i;

ctx.font = font.string;

for (i = 0; i < ilen; ++i) {
width = Math.max(ctx.measureText(items[i]).width, width);
}

ctx.font = prev;

return {
height: ilen * font.lineHeight,
width: width
};
},

// @todo move this method in Chart.helpers.options.toFont
parseFont: function(value) {
var global = Chart.defaults.global;
var size = helpers.valueOrDefault(value.size, global.defaultFontSize);
var font = {
family: helpers.valueOrDefault(value.family, global.defaultFontFamily),
lineHeight: helpers.options.toLineHeight(value.lineHeight, size),
size: size,
style: helpers.valueOrDefault(value.style, global.defaultFontStyle),
weight: helpers.valueOrDefault(value.weight, null),
string: ''
};

font.string = utils.toFontString(font);
return font;
}
};

export default utils;
105 changes: 105 additions & 0 deletions test/specs/utils.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import Chart from 'chart.js';
import utils from '../../src/utils';

describe('utils.js', function() {
describe('toTextLines', function() {
var toTextLines = utils.toTextLines;

it('should return an array containing the input string', function() {
expect(toTextLines('')).toEqual(['']);
expect(toTextLines('foo')).toEqual(['foo']);
expect(toTextLines('foo bar')).toEqual(['foo bar']);
});
it('should return an array with converted values', function() {
expect(toTextLines(null)).toEqual(['null']);
expect(toTextLines(undefined)).toEqual(['undefined']);
expect(toTextLines(42)).toEqual(['42']);
expect(toTextLines(true)).toEqual(['true']);
});
it('should return an array of strings if inputs is an array', function() {
expect(toTextLines([])).toEqual([]);
expect(toTextLines(['foo'])).toEqual(['foo']);
expect(toTextLines(['foo', 'bar'])).toEqual(['foo', 'bar']);
});
it('should split the input string if it contains \\n', function() {
expect(toTextLines('foo\nbar')).toEqual(['foo', 'bar']);
expect(toTextLines('foo\nbar\nbla')).toEqual(['foo', 'bar', 'bla']);
});
it('should preserve spaces when splitting strings', function() {
expect(toTextLines('foo \n bar')).toEqual(['foo ', ' bar']);
expect(toTextLines('foo \n bar \n bla')).toEqual(['foo ', ' bar ', ' bla']);
});
it('should flatten children arrays in the correct order', function() {
expect(toTextLines(['foo', [['bar', 'xxx'], 'bla']])).toEqual(['foo', 'bar', 'xxx', 'bla']);
});
it('should split strings children in the correct order', function() {
expect(toTextLines(['foo', [['bar\nxxx'], 'bla\nyyy']])).toEqual(['foo', 'bar', 'xxx', 'bla', 'yyy']);
});
});

describe('toFontString', function() {
var toFontString = utils.toFontString;

it('should return null if the given font is invalid', function() {
expect(toFontString({})).toBeNull();
expect(toFontString(null)).toBeNull();
expect(toFontString(undefined)).toBeNull();
expect(toFontString(42)).toBeNull();
expect(toFontString('foo')).toBeNull();
expect(toFontString(new Date())).toBeNull();
});
it('should return null if size or family are missing', function() {
expect(toFontString({style: 'italic', weight: 300, size: 12})).toBeNull();
expect(toFontString({style: 'italic', weight: 300, family: 'serif'})).toBeNull();
});
it('should return the string representation of the given font', function() {
expect(toFontString({style: 'italic', weight: 300, size: 12, family: 'serif'})).toBe('italic 300 12px serif');
});
it('weigth and style should be optional', function() {
expect(toFontString({size: 12, family: 'serif'})).toBe('12px serif');
expect(toFontString({style: 'italic', size: 12, family: 'serif'})).toBe('italic 12px serif');
expect(toFontString({weight: 300, size: 12, family: 'serif'})).toBe('300 12px serif');
});
});

describe('parseFont', function() {
var parseFont = utils.parseFont;

it ('should return a font with default values', function() {
var global = Chart.defaults.global;

Chart.defaults.global = {
defaultFontFamily: 'foobar',
defaultFontSize: 42,
defaultFontStyle: 'xxxyyy'
};

expect(parseFont({})).toEqual({
family: 'foobar',
lineHeight: 50.4,
size: 42,
string: 'xxxyyy 42px foobar',
style: 'xxxyyy',
weight: null
});

Chart.defaults.global = global;
});
it ('should return a font with given values', function() {
expect(parseFont({
family: 'bla',
lineHeight: 8,
size: 21,
style: 'zzz',
weight: 400
})).toEqual({
family: 'bla',
lineHeight: 8 * 21,
size: 21,
string: 'zzz 400 21px bla',
style: 'zzz',
weight: 400
});
});
});
});

0 comments on commit 028840c

Please sign in to comment.