Skip to content

Commit

Permalink
fix(api): Fix loading to maintain correct x index
Browse files Browse the repository at this point in the history
- Corrected to point correct x axis index value when the loaded x is already exists
- Fix on getting bubble radius when is used with area-range type

Fix #517
Close #519
  • Loading branch information
netil authored Jul 31, 2018
1 parent 3a1267e commit f3881bc
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 98 deletions.
181 changes: 115 additions & 66 deletions spec/api/api.load-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ describe("API load", function() {
["data1", 30, 200, 100, 400, 150, 250],
["data2", 5000, 2000, 1000, 4000, 1500, 2500]
]
},
point: {
show: true
}
};

Expand All @@ -32,103 +29,154 @@ describe("API load", function() {
chart.load({
columns: [
["data3", 800, 500, 900, 500, 1000, 700]
]
});

setTimeout(() => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const circles = main.selectAll(`.${CLASS.circles}.${CLASS.circles}-data3 circle`);
],
done: () => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const circles = main.selectAll(`.${CLASS.circles}.${CLASS.circles}-data3 circle`);

expect(target.size()).to.be.equal(1);
expect(legendItem.size()).to.be.equal(1);
expect(circles.size()).to.be.equal(6);
expect(target.size()).to.be.equal(1);
expect(legendItem.size()).to.be.equal(1);
expect(circles.size()).to.be.equal(6);

done();
}, 500);
done();
}
});
});
});

describe("category data", () => {
describe("timeseries data as column", () => {
let date = ["2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"];

before(() => {
args = {
data: {
x: "x",
columns: [
["x", "cat1", "cat2", "cat3", "cat4", "cat5", "cat6"],
["x"].concat(date),
["data1", 30, 200, 100, 400, 150, 250],
["data2", 5000, 2000, 1000, 4000, 1500, 2500]
]
},
axis: {
x: {
type: "category"
type: "timeseries",
tick: {
format: "%Y-%m-%d"
}
}
},
point: {
show: false
}
};
});

describe("as column", () => {
it("should load additional data", done => {
const main = chart.internal.main;
const legend = chart.internal.legend;

chart.load({
columns: [
["data3", 800, 500, 900, 500, 1000, 700]
]
});
it("should load additional data", done => {
const main = chart.internal.main;
const legend = chart.internal.legend;

setTimeout(() => {
chart.load({
columns: [
["x"].concat(date.concat().splice(1, 3)),
["data3", 400, 500, 450]
],
done: () => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const circles = main.selectAll(`.${CLASS.circles}.${CLASS.circles}-data3 circle`);
const tickTexts = main.selectAll(`.${CLASS.axisX} g.tick text`);
const expected = ["cat1", "cat2", "cat3", "cat4", "cat5", "cat6"];

expect(target.size()).to.be.equal(1);
expect(legendItem.size()).to.be.equal(1);
expect(circles.size()).to.be.equal(3);

tickTexts.each(function(d, i) {
const text = d3.select(this).select("tspan").text();

expect(text).to.be.equal(expected[i]);
expect(text).to.be.equal(date[i]);
});

done();
}, 500);
}
});
});
});

describe("category data", () => {
before(() => {
args = {
data: {
x: "x",
columns: [
["x", "cat1", "cat2", "cat3", "cat4", "cat5", "cat6"],
["data1", 30, 200, 100, 400, 150, 250],
["data2", 5000, 2000, 1000, 4000, 1500, 2500]
]
},
axis: {
x: {
type: "category"
}
}
};
});

describe("as column", () => {
it("should load additional data #1", done => {
const main = chart.internal.main;
const legend = chart.internal.legend;

chart.load({
columns: [
["x", "cat2", "cat3", "cat4"],
["data3", 800, 500, 900]
],
done: () => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const tickTexts = main.selectAll(`.${CLASS.axisX} g.tick text`);
const expected = ["cat1", "cat2", "cat3", "cat4", "cat5", "cat6"];

expect(target.size()).to.be.equal(1);
expect(target.selectAll("circle").size()).to.be.equal(3);
expect(legendItem.size()).to.be.equal(1);

tickTexts.each(function(d, i) {
const text = d3.select(this).select("tspan").text();

expect(text).to.be.equal(expected[i]);
});

done();
}
});
});

it("should load additional data", done => {
it("should load additional data #2", done => {
const main = chart.internal.main;
const legend = chart.internal.legend;

chart.load({
columns: [
["x", "new1", "new2", "new3", "new4", "new5", "new6"],
["data3", 800, 500, 900, 500, 1000, 700]
]
});
],
done: () => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const tickTexts = main.selectAll(`.${CLASS.axisX} g.tick text`);
const expected = ["new1", "new2", "new3", "new4", "new5", "new6"];

setTimeout(() => {
const target = main.select(`.${CLASS.chartLine}.${CLASS.target}.${CLASS.target}-data3`);
const legendItem = legend.select(`.${CLASS.legendItem}.${CLASS.legendItem}-data3`);
const tickTexts = main.selectAll(`.${CLASS.axisX} g.tick text`);
const expected = ["new1", "new2", "new3", "new4", "new5", "new6"];
expect(target.size()).to.be.equal(1);
expect(legendItem.size()).to.be.equal(1);

expect(target.size()).to.be.equal(1);
expect(legendItem.size()).to.be.equal(1);
tickTexts.each(function(d, i) {
const text = d3.select(this).select("tspan").text();

tickTexts.each(function(d, i) {
const text = d3.select(this).select("tspan").text();
expect(text).to.be.equal(expected[i]);
});

expect(text).to.be.equal(expected[i]);
});

done();
}, 500);
done();
}
});
});
});
});
Expand Down Expand Up @@ -157,21 +205,22 @@ describe("API load", function() {
{name: "www.site8.com", upload: 100, download: 500}
];

chart.load({json});

setTimeout(() => {
const categories = chart.categories();
const upload = chart.data.values("upload");
const download = chart.data.values("download");

json.forEach((v, i) => {
expect(v.name).to.be.equal(categories[i]);
expect(v.upload).to.be.equal(upload[i]);
expect(v.download).to.be.equal(download[i]);
});
chart.load({
json,
done: () => {
const categories = chart.categories();
const upload = chart.data.values("upload");
const download = chart.data.values("download");

json.forEach((v, i) => {
expect(v.name).to.be.equal(categories[i]);
expect(v.upload).to.be.equal(upload[i]);
expect(v.download).to.be.equal(download[i]);
});

done();
}, 1000);
done();
}
});
});
});
});
46 changes: 25 additions & 21 deletions src/data/data.convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ extend(ChartInternal.prototype, {
const config = $$.config;
const ids = d3Keys(data[0]).filter($$.isNotX, $$);
const xs = d3Keys(data[0]).filter($$.isX, $$);
let xsData;

// save x for update data by load when custom x and bb.x API
ids.forEach(id => {
Expand All @@ -200,51 +201,56 @@ extend(ChartInternal.prototype, {
if (this.isCustomX() || this.isTimeSeries()) {
// if included in input data
if (xs.indexOf(xKey) >= 0) {
this.data.xs[id] =
(appendXs && $$.data.xs[id] ? $$.data.xs[id] : [])
.concat(
data.map(d => d[xKey])
.filter(isValue)
.map((rawX, i) => $$.generateTargetX(rawX, id, i))
);
xsData = ((appendXs && $$.data.xs[id]) || [])
.concat(
data.map(d => d[xKey])
.filter(isValue)
.map((rawX, i) => $$.generateTargetX(rawX, id, i))
);
} else if (config.data_x) {
// if not included in input data, find from preloaded data of other id's x
this.data.xs[id] = this.getOtherTargetXs();
xsData = this.getOtherTargetXs();
} else if (notEmpty(config.data_xs)) {
// if not included in input data, find from preloaded data
$$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
xsData = $$.getXValuesOfXKey(xKey, $$.data.targets);
}
// MEMO: if no x included, use same x of current will be used
} else {
$$.data.xs[id] = data.map((d, i) => i);
xsData = data.map((d, i) => i);
}

xsData && (this.data.xs[id] = xsData);
});

// check x is defined
ids.forEach(id => {
if (!$$.data.xs[id]) {
if (!xsData) {
throw new Error(`x is not defined for id = "${id}".`);
}
});

// convert to target
const targets = ids.map((id, index) => {
const convertedId = config.data_idConverter(id);
const xKey = $$.getXKey(id);
const isCategorized = $$.isCustomX() && $$.isCategorized();
const hasCategory = isCategorized && data.map(v => v.x)
.every(v => config.axis_x_categories.indexOf(v) > -1);

return {
id: convertedId,
id_org: id,
values: data.map((d, i) => {
const xKey = $$.getXKey(id);
const rawX = d[xKey];
const value = d[id] !== null && !isNaN(d[id]) ?
+d[id] : (isArray(d[id]) || ($$.isObject(d[id]) && d[id].high) ? d[id] : null);

let value = d[id];
let x;

value = value !== null && !isNaN(value) ?
+d[id] : (isArray(value) || ($$.isObject(value) && value.high) ? value : null);

// use x as categories if custom x and categorized
if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) {
if (index === 0 && i === 0) {
if (isCategorized && index === 0 && !isUndefined(rawX)) {
if (!hasCategory && index === 0 && i === 0) {
config.axis_x_categories = [];
}

Expand All @@ -270,8 +276,6 @@ extend(ChartInternal.prototype, {

// finish targets
targets.forEach(t => {
let i;

// sort values by its x
if (config.data_xSort) {
t.values = t.values.sort((v1, v2) => {
Expand All @@ -283,10 +287,10 @@ extend(ChartInternal.prototype, {
}

// indexing each value
i = 0;
let i = 0;

t.values.forEach(v => {
v.index = i++;
v.index = $$.data.targets ? $$.getIndexByX(v.x) : i++;
});

// this needs to be sorted because its index and value.index is identical
Expand Down
19 changes: 10 additions & 9 deletions src/data/data.load.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extend(ChartInternal.prototype, {
// set type if args.types || args.type specified
if (args.type || args.types) {
targets.forEach(t => {
const type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
const type = (args.types && args.types[t.id]) || args.type;

$$.setTargetType(t.id, type);
});
Expand Down Expand Up @@ -55,25 +55,26 @@ extend(ChartInternal.prototype, {

loadFromArgs(args) {
const $$ = this;
let data;

// reset internally cached data
$$.resetCache();

if (args.data) {
$$.load($$.convertDataToTargets(args.data), args);
data = args.data;
} else if (args.url) {
$$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, data => {
$$.load($$.convertDataToTargets(data), args);
$$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, d => {
$$.load($$.convertDataToTargets(d), args);
});
} else if (args.json) {
$$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
data = $$.convertJsonToData(args.json, args.keys);
} else if (args.rows) {
$$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
data = $$.convertRowsToData(args.rows);
} else if (args.columns) {
$$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
} else {
$$.load(null, args);
data = $$.convertColumnsToData(args.columns);
}

$$.load(data ? $$.convertDataToTargets(data) : null, args);
},

unload(rawTargetIds, customDoneCb) {
Expand Down
Loading

0 comments on commit f3881bc

Please sign in to comment.