Browse Source

Refactors circular dependencies (#2389)

* Refactors circular dependencies

 - Adds src/chart-internal.js
 - doesn't need to pass c3.js as argument to rollup
 - don't commit c3.js nor c3.min.js
 - formatting rollup.config.js
 - keep util.js format
 - remove unused imports from axis, core and util

* adds more tests for axis and zoom

* restores the way in which chart-internal calls d3 #2060

* fixes linter warnings on axis-spec
pull/2400/head
Felipe Figueroa 7 years ago committed by Yoshiya Hinosawa
parent
commit
22b06bb28b
  1. 2
      package.json
  2. 9
      rollup.config.js
  3. 24
      spec/api.axis-spec.js
  4. 11
      spec/api.zoom-spec.js
  5. 429
      spec/axis-spec.js
  6. 3
      src/axis.js
  7. 9
      src/chart-internal.js
  8. 66
      src/core.js
  9. 43
      src/util.js

2
package.json

@ -9,7 +9,7 @@
"docs": "bundle exec middleman", "docs": "bundle exec middleman",
"build": "npm run build:js && npm run build:css", "build": "npm run build:js && npm run build:css",
"build:js": "npm run build:js:rollup && npm run build:js:uglify", "build:js": "npm run build:js:rollup && npm run build:js:uglify",
"build:js:rollup": "rollup -c > c3.js", "build:js:rollup": "rollup -c",
"build:js:uglify": "uglifyjs c3.js --compress --mangle --comments -o c3.min.js", "build:js:uglify": "uglifyjs c3.js --compress --mangle --comments -o c3.min.js",
"build:css": "npm run build:css:sass && npm run build:css:min", "build:css": "npm run build:css:sass && npm run build:css:min",
"build:css:sass": "node-sass src/scss/main.scss > c3.css", "build:css:sass": "node-sass src/scss/main.scss > c3.css",

9
rollup.config.js

@ -4,9 +4,13 @@ import pkg from './package.json'
export default { export default {
input: 'src/index.js', input: 'src/index.js',
output: { output: {
file: 'c3.js',
name: 'c3', name: 'c3',
format: 'umd', format: 'umd',
banner: `/* @license C3.js v${pkg.version} | (c) C3 Team and other contributors | http://c3js.org/ */` banner: `/* @license C3.js v${pkg.version} | (c) C3 Team and other contributors | http://c3js.org/ */`,
globals:{
d3:'d3'
}
}, },
plugins: [babel({ plugins: [babel({
presets: [['es2015', { presets: [['es2015', {
@ -15,5 +19,6 @@ export default {
plugins: [ plugins: [
'external-helpers' 'external-helpers'
] ]
})] })],
external: ['d3'],
}; };

24
spec/api.axis-spec.js

@ -49,5 +49,29 @@ describe('c3 api axis', function () {
expect(label.attr('dy')).toBe('-0.5em'); expect(label.attr('dy')).toBe('-0.5em');
}); });
it('updates axis max values', function () {
chart.axis.max({x: 100, y: 300, y2: 100});
var max_values = chart.axis.max();
expect(max_values.x).toBe(100);
expect(max_values.y).toBe(300);
expect(max_values.y2).toBe(100);
});
it('updates axis min values', function () {
chart.axis.min({x: 0, y: 20, y2: 50});
var min_values = chart.axis.min();
expect(min_values.x).toBe(0);
expect(min_values.y).toBe(20);
expect(min_values.y2).toBe(50);
});
it('updates axis range', function () {
chart.axis.range({min: 5, max: 250});
var range = chart.axis.range();
expect(range.max.y).toBe(250);
expect(range.min.y).toBe(5);
});
}); });
}); });

11
spec/api.zoom-spec.js

@ -48,6 +48,17 @@ describe('c3 api zoom', function () {
expect(domain[1]).toBe(target[1]); expect(domain[1]).toBe(target[1]);
}); });
it('should set the max zoom properly', function () {
chart.zoom.max(100);
expect(chart.zoom.max()).toBe(100);
});
it('should set the min zoom properly', function () {
chart.zoom.min(-1);
expect(chart.zoom.min()).toBe(-1);
});
describe('with timeseries data', function () { describe('with timeseries data', function () {
beforeAll(function(){ beforeAll(function(){
args = { args = {

429
spec/axis-spec.js

@ -1,4 +1,4 @@
describe('c3 chart axis', function () { describe('c3 chart axis', function() {
'use strict'; 'use strict';
var chart; var chart;
@ -27,62 +27,62 @@ describe('c3 chart axis', function () {
} }
}; };
beforeEach(function (done) { beforeEach(function(done) {
chart = window.initChart(chart, args, done); chart = window.initChart(chart, args, done);
}); });
describe('axis.y.tick.count', function () { describe('axis.y.tick.count', function() {
describe('with only 1 tick on y axis', function () { describe('with only 1 tick on y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.tick.count = 1; args.axis.y.tick.count = 1;
}); });
it('should have only 1 tick on y axis', function () { it('should have only 1 tick on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(1); expect(ticksSize).toBe(1);
}); });
}); });
describe('with 2 ticks on y axis', function () { describe('with 2 ticks on y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.tick.count = 2; args.axis.y.tick.count = 2;
}); });
it('should have 2 ticks on y axis', function () { it('should have 2 ticks on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(2); expect(ticksSize).toBe(2);
}); });
}); });
describe('with 3 ticks on y axis', function () { describe('with 3 ticks on y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.tick.count = 3; args.axis.y.tick.count = 3;
}); });
it('should have 3 ticks on y axis', function () { it('should have 3 ticks on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(3); expect(ticksSize).toBe(3);
}); });
}); });
}); });
describe('axis.y.tick.values', function () { describe('axis.y.tick.values', function() {
var values = [100, 500]; var values = [100, 500];
describe('with only 2 ticks on y axis', function () { describe('with only 2 ticks on y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.tick.values = values; args.axis.y.tick.values = values;
}); });
it('should have only 2 tick on y axis', function () { it('should have only 2 tick on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(2); expect(ticksSize).toBe(2);
}); });
it('should have specified tick texts', function () { it('should have specified tick texts', function() {
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-y').selectAll('g.tick').each(function(d, i) {
var text = d3.select(this).select('text').text(); var text = d3.select(this).select('text').text();
expect(+text).toBe(values[i]); expect(+text).toBe(values[i]);
}); });
@ -90,8 +90,147 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis y timeseries', function () { describe('axis x timeseries with seconds', function() {
beforeAll(function () { beforeAll(function() {
args = {
data: {
type: 'line',
columns: [
["epoch", 1401879600000, 1401883200000, 1401886800000],
["y", 1955, 2419, 2262]
],
xs: {
y: "epoch"
}
},
axis: {
x: {
type: "timeseries",
min: new Date(1401879600000),
max: new Date(1401969600000),
localtime: false
}
}
};
});
it('should have 3 ticks on x axis', function() {
var ticksSize = d3.select('.c3-axis-x').selectAll('g.tick').size();
expect(ticksSize).toBe(3);
});
it('should have specified 1 hour intervals', function() {
var prevValue;
d3.select('.c3-axis-x').selectAll('g.tick').each(function(d, i) {
if (i !== 0) {
var result = d - prevValue;
expect(result).toEqual(3600000); // expressed in milliseconds
}
prevValue = d;
});
});
describe('changing min x time and columns', function() {
beforeAll(function() {
args.axis.x.min = new Date(1401876000000);
args.axis.x.max = new Date(1401876075000);
args.data.columns = [
["epoch", 1401876000000, 1401876015000, 1401876030000, 1401876045000, 1401876060000, 1401876075000],
["y", 1968, 1800, 1955, 2419, 2262, 1940]
];
});
it('should have 6 ticks on x axis', function() {
var ticksSize = d3.select('.c3-axis-x').selectAll('g.tick').size();
expect(ticksSize).toBe(6); // the count starts at initial value and increments by the set interval
});
it('should have specified 15 seconds intervals', function() {
var prevValue;
d3.select('.c3-axis-x').selectAll('g.tick').each(function(d, i) {
if (i !== 0) {
var result = d - prevValue;
expect(result).toEqual(15000); // expressed in milliseconds
}
prevValue = d;
});
});
describe('with axis.x.time.format %Y-%m-%d %H:%M:%S', function() {
beforeAll(function() {
args.axis.x.tick = {
format: "%M:%S" // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format
};
});
var textDates = [
'00:00',
'00:15',
'00:30',
'00:45',
'01:00',
'01:15'
];
it('should format x ticks as dates with time', function() {
var ticks = d3.select('.c3-axis-x').selectAll('g.tick').selectAll('tspan').each(function(d) {
expect(d.splitted).toEqual(textDates[d.index]);
});
expect(ticks.size()).toBe(6);
});
});
});
});
describe('axis x timeseries with iso dates', function() {
beforeAll(function() {
args = {
data: {
type: 'line',
columns: [
["epoch", 1527811200000, 1527897600000, 1527984000000],
["y", 1955, 2419, 2262]
],
xs: {
y: "epoch"
}
},
axis: {
x: {
type: "timeseries",
min: new Date('2018-06-01'),
max: new Date('2018-06-03'),
localtime: false,
tick: {
format: "%Y-%m-%dT%H:%M:%S" // https://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format
}
}
}
};
});
var textDates = [
'2018-06-01T00:00:00',
'2018-06-02T00:00:00',
'2018-06-03T00:00:00'
];
it('should format x ticks as dates', function() {
var ticks = d3.select('.c3-axis-x').selectAll('g.tick').selectAll('tspan').each(function(d) {
expect(d.splitted).toEqual(textDates[d.index]);
});
expect(ticks.size()).toBe(3);
});
});
describe('axis y timeseries', function() {
beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -100,24 +239,23 @@ describe('c3 chart axis', function () {
}, },
axis: { axis: {
y: { y: {
type : 'timeseries', type: 'timeseries',
tick: { tick: {
time: { time: {}
}
} }
} }
} }
}; };
}); });
it('should have 7 ticks on y axis', function () { it('should have 7 ticks on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(7); // the count starts at initial value and increments by the set interval expect(ticksSize).toBe(7); // the count starts at initial value and increments by the set interval
}); });
it('should have specified 30 second intervals', function () { it('should have specified 30 second intervals', function() {
var prevValue; var prevValue;
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-y').selectAll('g.tick').each(function(d, i) {
if (i !== 0) { if (i !== 0) {
var result = d - prevValue; var result = d - prevValue;
expect(result).toEqual(30000); // expressed in milliseconds expect(result).toEqual(30000); // expressed in milliseconds
@ -126,22 +264,22 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('with axis.y.time', function () { describe('with axis.y.time', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.tick.time = { args.axis.y.tick.time = {
type : d3.timeSecond, type: d3.timeSecond,
interval : 60 interval: 60
}; };
}); });
it('should have 4 ticks on y axis', function () { it('should have 4 ticks on y axis', function() {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(4); // the count starts at initial value and increments by the set interval expect(ticksSize).toBe(4); // the count starts at initial value and increments by the set interval
}); });
it('should have specified 60 second intervals', function () { it('should have specified 60 second intervals', function() {
var prevValue; var prevValue;
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-y').selectAll('g.tick').each(function(d, i) {
if (i !== 0) { if (i !== 0) {
var result = d - prevValue; var result = d - prevValue;
expect(result).toEqual(60000); // expressed in milliseconds expect(result).toEqual(60000); // expressed in milliseconds
@ -152,35 +290,34 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.x.tick.values', function () { describe('axis.x.tick.values', function() {
describe('formatted correctly when negative', function() { describe('formatted correctly when negative', function() {
var xValues = [-3.3, -2.2, -1.1, 1.1, 2.2, 3.3]; var xValues = [-3.3, -2.2, -1.1, 1.1, 2.2, 3.3];
beforeEach(function() { beforeEach(function() {
args.data = { args.data = {
x: 'x', x: 'x',
columns: [ columns: [
['x'].concat(xValues), ['x'].concat(xValues), ['data1', 30, 200, 100, 400, 150, 250],
['data1', 30, 200, 100, 400, 150, 250],
] ]
}; };
}); });
it ('should not generate whole number for negative values', function() { it('should not generate whole number for negative values', function() {
var tickValues = []; var tickValues = [];
d3.select('.c3-axis-x').selectAll('g.tick').selectAll('tspan').each(function(d, i) { expect(tickValues.push(parseFloat(d.splitted)) === xValues[i]); }); d3.select('.c3-axis-x').selectAll('g.tick').selectAll('tspan').each(function(d, i) { expect(tickValues.push(parseFloat(d.splitted)) === xValues[i]); });
}); });
}); });
describe('function is provided', function () { describe('function is provided', function() {
var tickGenerator = function () { var tickGenerator = function() {
var values = []; var values = [];
for (var i = 0; i <= 300; i += 50) { for (var i = 0; i <= 300; i += 50) {
values.push(i); values.push(i);
} }
return values; return values;
}; };
beforeEach(function () { beforeEach(function() {
args.axis.x = { args.axis.x = {
tick: { tick: {
values: tickGenerator values: tickGenerator
@ -190,8 +327,8 @@ describe('c3 chart axis', function () {
window.generatedTicks = tickGenerator(); // This should be removed from window window.generatedTicks = tickGenerator(); // This should be removed from window
}); });
it('should use function to generate ticks', function () { it('should use function to generate ticks', function() {
d3.select('.c3-axis-x').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-x').selectAll('g.tick').each(function(d, i) {
var tick = d3.select(this).select('text').text(); var tick = d3.select(this).select('text').text();
expect(+tick).toBe(window.generatedTicks[i]); expect(+tick).toBe(window.generatedTicks[i]);
}); });
@ -199,13 +336,13 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.x.tick.width', function () { describe('axis.x.tick.width', function() {
describe('indexed x axis and y/y2 axis', function () { describe('indexed x axis and y/y2 axis', function() {
describe('not rotated', function () { describe('not rotated', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -224,15 +361,15 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should construct indexed x axis properly', function () { it('should construct indexed x axis properly', function() {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedX = '0', expectedX = '0',
expectedDy = '.71em'; expectedDy = '.71em';
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
ticks.each(function (d, i) { ticks.each(function(d, i) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(i + ''); expect(tspan.text()).toBe(i + '');
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -241,26 +378,26 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('should set axis.x.tick.format', function () { describe('should set axis.x.tick.format', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.x = { args.axis.x = {
tick: { tick: {
format: function () { format: function() {
return 'very long tick text on x axis'; return 'very long tick text on x axis';
} }
} }
}; };
}); });
it('should split x axis tick text to multiple lines', function () { it('should split x axis tick text to multiple lines', function() {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedTexts = ['very long tick text', 'on x axis'], expectedTexts = ['very long tick text', 'on x axis'],
expectedX = '0'; expectedX = '0';
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
ticks.each(function () { ticks.each(function() {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTexts[i]); expect(tspan.text()).toBe(expectedTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -273,15 +410,15 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should construct y axis properly', function () { it('should construct y axis properly', function() {
var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'),
expectedX = '-9', expectedX = '-9',
expectedDy = '3'; expectedDy = '3';
expect(ticks.size()).toBe(9); expect(ticks.size()).toBe(9);
ticks.each(function (d) { ticks.each(function(d) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(d + ''); expect(tspan.text()).toBe(d + '');
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -290,15 +427,15 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should construct y2 axis properly', function () { it('should construct y2 axis properly', function() {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'),
expectedX = '9', expectedX = '9',
expectedDy = '3'; expectedDy = '3';
expect(ticks.size()).toBe(9); expect(ticks.size()).toBe(9);
ticks.each(function (d) { ticks.each(function(d) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(d + ''); expect(tspan.text()).toBe(d + '');
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -308,17 +445,17 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('should set big values in y', function () { describe('should set big values in y', function() {
beforeAll(function(){ beforeAll(function() {
args.data.columns = [ args.data.columns = [
['data1', 3000000000000000, 200, 100, 400, 150, 250], ['data1', 3000000000000000, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25] ['data2', 50, 20, 10, 40, 15, 25]
]; ];
}); });
it('should not split y axis tick text to multiple lines', function () { it('should not split y axis tick text to multiple lines', function() {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'); var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick');
ticks.each(function () { ticks.each(function() {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
}); });
@ -326,21 +463,21 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('rotated', function () { describe('rotated', function() {
beforeAll(function () { beforeAll(function() {
args.axis.rotated = true; args.axis.rotated = true;
}); });
it('should split x axis tick text to multiple lines', function () { it('should split x axis tick text to multiple lines', function() {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedTexts = ['very long tick text on', 'x axis'], expectedTexts = ['very long tick text on', 'x axis'],
expectedX = '-9'; expectedX = '-9';
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
ticks.each(function () { ticks.each(function() {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTexts[i]); expect(tspan.text()).toBe(expectedTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -353,7 +490,7 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should not split y axis tick text to multiple lines', function () { it('should not split y axis tick text to multiple lines', function() {
var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'),
expectedTexts = [ expectedTexts = [
'0', '0',
@ -367,10 +504,10 @@ describe('c3 chart axis', function () {
expectedX = '0', expectedX = '0',
expectedDy = '.71em'; expectedDy = '.71em';
expect(ticks.size()).toBe(7); expect(ticks.size()).toBe(7);
ticks.each(function (d, i) { ticks.each(function(d, i) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTexts[i]); expect(tspan.text()).toBe(expectedTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -382,11 +519,11 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('category axis', function () { describe('category axis', function() {
describe('not rotated', function () { describe('not rotated', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -404,15 +541,15 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should locate ticks properly', function () { it('should locate ticks properly', function() {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'); var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
ticks.each(function (d, i) { ticks.each(function(d, i) {
var tspans = d3.select(this).selectAll('tspan'), var tspans = d3.select(this).selectAll('tspan'),
expectedX = '0', expectedX = '0',
expectedDy = '.71em'; expectedDy = '.71em';
if (i > 0) { // i === 0 should be checked in next test if (i > 0) { // i === 0 should be checked in next test
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
expect(tspan.attr('dy')).toBe(expectedDy); expect(tspan.attr('dy')).toBe(expectedDy);
@ -421,7 +558,7 @@ describe('c3 chart axis', function () {
}); });
}); });
xit('should split tick text properly', function () { xit('should split tick text properly', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'), tspans = tick.selectAll('tspan'),
expectedTickTexts = [ expectedTickTexts = [
@ -431,7 +568,7 @@ describe('c3 chart axis', function () {
], ],
expectedX = '0'; expectedX = '0';
expect(tspans.size()).toBe(3); expect(tspans.size()).toBe(3);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickTexts[i]); expect(tspan.text()).toBe(expectedTickTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -445,21 +582,21 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('rotated', function () { describe('rotated', function() {
beforeAll(function () { beforeAll(function() {
args.axis.rotated = true; args.axis.rotated = true;
}); });
it('should locate ticks on rotated axis properly', function () { it('should locate ticks on rotated axis properly', function() {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'); var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
ticks.each(function (d, i) { ticks.each(function(d, i) {
var tspans = d3.select(this).selectAll('tspan'), var tspans = d3.select(this).selectAll('tspan'),
expectedX = '-9', expectedX = '-9',
expectedDy = '3'; expectedDy = '3';
if (i > 0) { // i === 0 should be checked in next test if (i > 0) { // i === 0 should be checked in next test
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function() {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
expect(tspan.attr('dy')).toBe(expectedDy); expect(tspan.attr('dy')).toBe(expectedDy);
@ -468,7 +605,7 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should split tick text on rotated axis properly', function () { it('should split tick text on rotated axis properly', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'), tspans = tick.selectAll('tspan'),
expectedTickTexts = [ expectedTickTexts = [
@ -478,7 +615,7 @@ describe('c3 chart axis', function () {
], ],
expectedX = '-9'; expectedX = '-9';
expect(tspans.size()).toBe(3); expect(tspans.size()).toBe(3);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickTexts[i]); expect(tspan.text()).toBe(expectedTickTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -493,17 +630,17 @@ describe('c3 chart axis', function () {
}); });
describe('option used', function () { describe('option used', function() {
describe('as null', function () { describe('as null', function() {
beforeAll(function () { //'without split ticks', beforeAll(function() { //'without split ticks',
args.axis.x.tick = { args.axis.x.tick = {
multiline: false multiline: false
}; };
}); });
it('should split x tick', function () { it('should split x tick', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'); tspans = tick.selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
@ -511,15 +648,15 @@ describe('c3 chart axis', function () {
}); });
describe('as value', function () { describe('as value', function() {
beforeAll(function () { // 'without split ticks', beforeAll(function() { // 'without split ticks',
args.axis.x.tick = { args.axis.x.tick = {
width: 150 width: 150
}; };
}); });
it('should split x tick to 2 lines properly', function () { it('should split x tick to 2 lines properly', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'), tspans = tick.selectAll('tspan'),
expectedTickTexts = [ expectedTickTexts = [
@ -528,7 +665,7 @@ describe('c3 chart axis', function () {
], ],
expectedX = '-9'; expectedX = '-9';
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickTexts[i]); expect(tspan.text()).toBe(expectedTickTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
@ -560,7 +697,7 @@ describe('c3 chart axis', function () {
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickText[i]); expect(tspan.text()).toBe(expectedTickText[i]);
}); });
@ -569,20 +706,20 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('with axis.x.tick.format', function () { describe('with axis.x.tick.format', function() {
beforeAll(function () { // 'with axis.x.tick.format', beforeAll(function() { // 'with axis.x.tick.format',
args.axis.x.tick.format = function () { args.axis.x.tick.format = function() {
return ['this is a very long tick text', 'on category axis']; return ['this is a very long tick text', 'on category axis'];
}; };
}); });
it('should have multiline tick text', function () { it('should have multiline tick text', function() {
var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'), var tick = chart.internal.main.select('.c3-axis-x').select('g.tick'),
tspans = tick.selectAll('tspan'), tspans = tick.selectAll('tspan'),
expectedTickTexts = ['this is a very long tick text', 'on category axis']; expectedTickTexts = ['this is a very long tick text', 'on category axis'];
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function(d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTickTexts[i]); expect(tspan.text()).toBe(expectedTickTexts[i]);
}); });
@ -591,11 +728,11 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.x.tick.rotate', function () { describe('axis.x.tick.rotate', function() {
describe('not rotated', function () { describe('not rotated', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -616,8 +753,8 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should rotate tick texts', function () { it('should rotate tick texts', function() {
chart.internal.main.selectAll('.c3-axis-x g.tick').each(function () { chart.internal.main.selectAll('.c3-axis-x g.tick').each(function() {
var tick = d3.select(this), var tick = d3.select(this),
text = tick.select('text'), text = tick.select('text'),
tspan = text.select('tspan'); tspan = text.select('tspan');
@ -627,7 +764,7 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should have automatically calculated x axis height', function () { it('should have automatically calculated x axis height', function() {
var box = chart.internal.main.select('.c3-axis-x').node().getBoundingClientRect(), var box = chart.internal.main.select('.c3-axis-x').node().getBoundingClientRect(),
height = chart.internal.getHorizontalAxisHeight('x'); height = chart.internal.getHorizontalAxisHeight('x');
expect(box.height).toBeGreaterThan(50); expect(box.height).toBeGreaterThan(50);
@ -637,11 +774,11 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.y.tick.rotate', function () { describe('axis.y.tick.rotate', function() {
describe('not rotated', function () { describe('not rotated', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -660,8 +797,8 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should rotate tick texts', function () { it('should rotate tick texts', function() {
chart.internal.main.selectAll('.c3-axis-y g.tick').each(function () { chart.internal.main.selectAll('.c3-axis-y g.tick').each(function() {
var tick = d3.select(this), var tick = d3.select(this),
text = tick.select('text'), text = tick.select('text'),
tspan = text.select('tspan'); tspan = text.select('tspan');
@ -671,7 +808,7 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should have automatically calculated y axis width', function () { it('should have automatically calculated y axis width', function() {
var box = chart.internal.main.select('.c3-axis-y').node().getBoundingClientRect(); var box = chart.internal.main.select('.c3-axis-y').node().getBoundingClientRect();
expect(box.width).toBeCloseTo(590, 1); expect(box.width).toBeCloseTo(590, 1);
}); });
@ -679,11 +816,11 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.x.tick.fit', function () { describe('axis.x.tick.fit', function() {
describe('axis.x.tick.fit = true', function () { describe('axis.x.tick.fit = true', function() {
beforeAll(function () { // 'should set args for indexed data', beforeAll(function() { // 'should set args for indexed data',
args = { args = {
data: { data: {
columns: [ columns: [
@ -695,13 +832,13 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function() {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
}); });
describe('should set args for x-based data', function () { describe('should set args for x-based data', function() {
beforeAll(function(){ beforeAll(function() {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -715,12 +852,12 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function() {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
}); });
it('should show fitted ticks after hide and show', function () { it('should show fitted ticks after hide and show', function() {
chart.hide(); chart.hide();
chart.show(); chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
@ -729,10 +866,10 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.x.tick.fit = false', function () { describe('axis.x.tick.fit = false', function() {
describe('should set args for indexed data', function () { describe('should set args for indexed data', function() {
beforeAll(function(){ beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -751,15 +888,15 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function() {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(11); expect(ticks.size()).toBe(11);
}); });
}); });
describe('should set args for x-based data', function () { describe('should set args for x-based data', function() {
beforeAll(function(){ beforeAll(function() {
args.data = { args.data = {
x: 'x', x: 'x',
columns: [ columns: [
@ -771,12 +908,12 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function() {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(10); expect(ticks.size()).toBe(10);
}); });
it('should show fitted ticks after hide and show', function () { it('should show fitted ticks after hide and show', function() {
chart.hide(); chart.hide();
chart.show(); chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
@ -786,9 +923,9 @@ describe('c3 chart axis', function () {
}); });
}); });
describe('axis.y.inner', function () { describe('axis.y.inner', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -804,34 +941,34 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should not have inner y axis', function () { it('should not have inner y axis', function() {
var paddingLeft = chart.internal.getCurrentPaddingLeft(), var paddingLeft = chart.internal.getCurrentPaddingLeft(),
tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text');
expect(paddingLeft).toBeGreaterThan(19); expect(paddingLeft).toBeGreaterThan(19);
tickTexts.each(function () { tickTexts.each(function() {
expect(+d3.select(this).attr('x')).toBeLessThan(0); expect(+d3.select(this).attr('x')).toBeLessThan(0);
}); });
}); });
describe('with inner y axis', function () { describe('with inner y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y.inner = true; args.axis.y.inner = true;
}); });
it('should have inner y axis', function () { it('should have inner y axis', function() {
var paddingLeft = chart.internal.getCurrentPaddingLeft(), var paddingLeft = chart.internal.getCurrentPaddingLeft(),
tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text');
expect(paddingLeft).toBe(1); expect(paddingLeft).toBe(1);
tickTexts.each(function () { tickTexts.each(function() {
expect(+d3.select(this).attr('x')).toBeGreaterThan(0); expect(+d3.select(this).attr('x')).toBeGreaterThan(0);
}); });
}); });
}); });
}); });
describe('axis.y2.inner', function () { describe('axis.y2.inner', function() {
beforeAll(function () { beforeAll(function() {
args = { args = {
data: { data: {
columns: [ columns: [
@ -848,25 +985,25 @@ describe('c3 chart axis', function () {
}; };
}); });
it('should not have inner y axis', function () { it('should not have inner y axis', function() {
var paddingRight = chart.internal.getCurrentPaddingRight(), var paddingRight = chart.internal.getCurrentPaddingRight(),
tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text');
expect(paddingRight).toBeGreaterThan(19); expect(paddingRight).toBeGreaterThan(19);
tickTexts.each(function () { tickTexts.each(function() {
expect(+d3.select(this).attr('x')).toBeGreaterThan(0); expect(+d3.select(this).attr('x')).toBeGreaterThan(0);
}); });
}); });
describe('with inner y axis', function () { describe('with inner y axis', function() {
beforeAll(function(){ beforeAll(function() {
args.axis.y2.inner = true; args.axis.y2.inner = true;
}); });
it('should have inner y axis', function () { it('should have inner y axis', function() {
var paddingRight = chart.internal.getCurrentPaddingRight(), var paddingRight = chart.internal.getCurrentPaddingRight(),
tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text');
expect(paddingRight).toBe(2); expect(paddingRight).toBe(2);
tickTexts.each(function () { tickTexts.each(function() {
expect(+d3.select(this).attr('x')).toBeLessThan(0); expect(+d3.select(this).attr('x')).toBeLessThan(0);
}); });
}); });

3
src/axis.js

@ -1,6 +1,5 @@
import CLASS from './class'; import CLASS from './class';
import { Component } from './core'; import {isValue, isFunction, isString, isEmpty, Component } from './util';
import { isValue, isFunction, isString, isEmpty } from './util';
export var c3_axis_fn; export var c3_axis_fn;
export var c3_axis_internal_fn; export var c3_axis_internal_fn;

9
src/chart-internal.js

@ -0,0 +1,9 @@
export function ChartInternal(api) {
var $$ = this;
$$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
$$.api = api;
$$.config = $$.getDefaultConfig();
$$.data = {};
$$.cache = {};
$$.axes = {};
}

66
src/core.js

@ -1,56 +1,28 @@
import Axis from './axis'; import Axis from './axis';
import CLASS from './class'; import CLASS from './class';
import { isValue, isFunction, isString, isUndefined, isDefined, ceil10, asHalfPixel, diffDomain, isEmpty, notEmpty, getOption, hasValue, sanitise, getPathBox } from './util'; import {
c3,
export var c3 = { version: "0.6.2" }; isEmpty,
notEmpty,
isValue,
isFunction,
isString,
isUndefined,
isDefined,
ceil10,
asHalfPixel,
diffDomain,
getOption,
hasValue,
sanitise,
getPathBox
} from './util';
export {c3};
export var c3_chart_fn; export var c3_chart_fn;
export var c3_chart_internal_fn; export var c3_chart_internal_fn;
export function Component(owner, componentKey, fn) {
this.owner = owner;
c3.chart.internal[componentKey] = fn;
}
function Chart(config) {
var $$ = this.internal = new ChartInternal(this);
$$.loadConfig(config);
$$.beforeInit(config);
$$.init();
$$.afterInit(config);
// bind "this" to nested API
(function bindThis(fn, target, argThis) {
Object.keys(fn).forEach(function (key) {
target[key] = fn[key].bind(argThis);
if (Object.keys(fn[key]).length > 0) {
bindThis(fn[key], target[key], argThis);
}
});
})(c3_chart_fn, this, this);
}
function ChartInternal(api) {
var $$ = this;
$$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
$$.api = api;
$$.config = $$.getDefaultConfig();
$$.data = {};
$$.cache = {};
$$.axes = {};
}
c3.generate = function (config) {
return new Chart(config);
};
c3.chart = {
fn: Chart.prototype,
internal: {
fn: ChartInternal.prototype,
}
};
c3_chart_fn = c3.chart.fn; c3_chart_fn = c3.chart.fn;
c3_chart_internal_fn = c3.chart.internal.fn; c3_chart_internal_fn = c3.chart.internal.fn;

43
src/util.js

@ -1,4 +1,41 @@
import { c3_chart_internal_fn } from './core'; import {ChartInternal} from './chart-internal';
export var c3 = { version: "0.6.2" ,
chart: {
fn: Chart.prototype,
internal: {
fn: ChartInternal.prototype,
}
}
};
export function Chart(config) {
var $$ = this.internal = new ChartInternal(this);
$$.loadConfig(config);
$$.beforeInit(config);
$$.init();
$$.afterInit(config);
// bind "this" to nested API
(function bindThis(fn, target, argThis) {
Object.keys(fn).forEach(function (key) {
target[key] = fn[key].bind(argThis);
if (Object.keys(fn[key]).length > 0) {
bindThis(fn[key], target[key], argThis);
}
});
})(c3.chart.fn, this, this);
}
c3.generate = function (config) {
return new Chart(config);
};
export function Component(owner, componentKey, fn) {
this.owner = owner;
c3.chart.internal[componentKey] = fn;
}
export var isValue = function (v) { export var isValue = function (v) {
return v || v === 0; return v || v === 0;
@ -13,7 +50,7 @@ export var isString = function (o) {
return typeof o === 'string'; return typeof o === 'string';
}; };
export var isUndefined = function (v) { export var isUndefined = function (v) {
return typeof v === 'undefined'; return typeof v === 'undefined';
}; };
export var isDefined = function (v) { export var isDefined = function (v) {
return typeof v !== 'undefined'; return typeof v !== 'undefined';
@ -31,7 +68,7 @@ export var isEmpty = function (o) {
return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0); return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
}; };
export var notEmpty = function (o) { export var notEmpty = function (o) {
return !c3_chart_internal_fn.isEmpty(o); return !c3.chart.internal.fn.isEmpty(o);
}; };
export var getOption = function (options, key, defaultValue) { export var getOption = function (options, key, defaultValue) {
return isDefined(options[key]) ? options[key] : defaultValue; return isDefined(options[key]) ? options[key] : defaultValue;

Loading…
Cancel
Save