mirror of https://github.com/masayuki0812/c3.git
Quite good looking graph derived from d3.js
http://c3js.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
333 lines
12 KiB
333 lines
12 KiB
import CLASS from './class'; |
|
import { c3_chart_internal_fn } from './core'; |
|
import { isValue, isFunction, isArray, notEmpty, hasValue } from './util'; |
|
|
|
c3_chart_internal_fn.isX = function (key) { |
|
var $$ = this, config = $$.config; |
|
return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key)); |
|
}; |
|
c3_chart_internal_fn.isNotX = function (key) { |
|
return !this.isX(key); |
|
}; |
|
c3_chart_internal_fn.getXKey = function (id) { |
|
var $$ = this, config = $$.config; |
|
return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null; |
|
}; |
|
c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) { |
|
var $$ = this, |
|
xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : []; |
|
ids.forEach(function (id) { |
|
if ($$.getXKey(id) === key) { |
|
xValues = $$.data.xs[id]; |
|
} |
|
}); |
|
return xValues; |
|
}; |
|
c3_chart_internal_fn.getXValue = function (id, i) { |
|
var $$ = this; |
|
return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i; |
|
}; |
|
c3_chart_internal_fn.getOtherTargetXs = function () { |
|
var $$ = this, |
|
idsForX = Object.keys($$.data.xs); |
|
return idsForX.length ? $$.data.xs[idsForX[0]] : null; |
|
}; |
|
c3_chart_internal_fn.getOtherTargetX = function (index) { |
|
var xs = this.getOtherTargetXs(); |
|
return xs && index < xs.length ? xs[index] : null; |
|
}; |
|
c3_chart_internal_fn.addXs = function (xs) { |
|
var $$ = this; |
|
Object.keys(xs).forEach(function (id) { |
|
$$.config.data_xs[id] = xs[id]; |
|
}); |
|
}; |
|
c3_chart_internal_fn.addName = function (data) { |
|
var $$ = this, name; |
|
if (data) { |
|
name = $$.config.data_names[data.id]; |
|
data.name = name !== undefined ? name : data.id; |
|
} |
|
return data; |
|
}; |
|
c3_chart_internal_fn.getValueOnIndex = function (values, index) { |
|
var valueOnIndex = values.filter(function (v) { return v.index === index; }); |
|
return valueOnIndex.length ? valueOnIndex[0] : null; |
|
}; |
|
c3_chart_internal_fn.updateTargetX = function (targets, x) { |
|
var $$ = this; |
|
targets.forEach(function (t) { |
|
t.values.forEach(function (v, i) { |
|
v.x = $$.generateTargetX(x[i], t.id, i); |
|
}); |
|
$$.data.xs[t.id] = x; |
|
}); |
|
}; |
|
c3_chart_internal_fn.updateTargetXs = function (targets, xs) { |
|
var $$ = this; |
|
targets.forEach(function (t) { |
|
if (xs[t.id]) { |
|
$$.updateTargetX([t], xs[t.id]); |
|
} |
|
}); |
|
}; |
|
c3_chart_internal_fn.generateTargetX = function (rawX, id, index) { |
|
var $$ = this, x; |
|
if ($$.isTimeSeries()) { |
|
x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index)); |
|
} |
|
else if ($$.isCustomX() && !$$.isCategorized()) { |
|
x = isValue(rawX) ? +rawX : $$.getXValue(id, index); |
|
} |
|
else { |
|
x = index; |
|
} |
|
return x; |
|
}; |
|
c3_chart_internal_fn.cloneTarget = function (target) { |
|
return { |
|
id : target.id, |
|
id_org : target.id_org, |
|
values : target.values.map(function (d) { |
|
return {x: d.x, value: d.value, id: d.id}; |
|
}) |
|
}; |
|
}; |
|
c3_chart_internal_fn.getMaxDataCount = function () { |
|
var $$ = this; |
|
return $$.d3.max($$.data.targets, function (t) { return t.values.length; }); |
|
}; |
|
c3_chart_internal_fn.mapToIds = function (targets) { |
|
return targets.map(function (d) { return d.id; }); |
|
}; |
|
c3_chart_internal_fn.mapToTargetIds = function (ids) { |
|
var $$ = this; |
|
return ids ? [].concat(ids) : $$.mapToIds($$.data.targets); |
|
}; |
|
c3_chart_internal_fn.hasTarget = function (targets, id) { |
|
var ids = this.mapToIds(targets), i; |
|
for (i = 0; i < ids.length; i++) { |
|
if (ids[i] === id) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
}; |
|
c3_chart_internal_fn.isTargetToShow = function (targetId) { |
|
return this.hiddenTargetIds.indexOf(targetId) < 0; |
|
}; |
|
c3_chart_internal_fn.isLegendToShow = function (targetId) { |
|
return this.hiddenLegendIds.indexOf(targetId) < 0; |
|
}; |
|
c3_chart_internal_fn.filterTargetsToShow = function (targets) { |
|
var $$ = this; |
|
return targets.filter(function (t) { return $$.isTargetToShow(t.id); }); |
|
}; |
|
c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) { |
|
var $$ = this; |
|
var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values(); |
|
xs = $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; }); |
|
return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; }); |
|
}; |
|
c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) { |
|
targetIds = (targetIds instanceof Array) ? targetIds : new Array(targetIds); |
|
for (var i = 0; i < targetIds.length; i++) { |
|
if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) { |
|
this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]); |
|
} |
|
} |
|
}; |
|
c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) { |
|
this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); |
|
}; |
|
c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) { |
|
targetIds = (targetIds instanceof Array) ? targetIds : new Array(targetIds); |
|
for (var i = 0; i < targetIds.length; i++) { |
|
if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) { |
|
this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]); |
|
} |
|
} |
|
}; |
|
c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) { |
|
this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); |
|
}; |
|
c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) { |
|
var ys = {}; |
|
targets.forEach(function (t) { |
|
ys[t.id] = []; |
|
t.values.forEach(function (v) { |
|
ys[t.id].push(v.value); |
|
}); |
|
}); |
|
return ys; |
|
}; |
|
c3_chart_internal_fn.checkValueInTargets = function (targets, checker) { |
|
var ids = Object.keys(targets), i, j, values; |
|
for (i = 0; i < ids.length; i++) { |
|
values = targets[ids[i]].values; |
|
for (j = 0; j < values.length; j++) { |
|
if (checker(values[j].value)) { |
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
}; |
|
c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) { |
|
return this.checkValueInTargets(targets, function (v) { return v < 0; }); |
|
}; |
|
c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) { |
|
return this.checkValueInTargets(targets, function (v) { return v > 0; }); |
|
}; |
|
c3_chart_internal_fn.isOrderDesc = function () { |
|
var config = this.config; |
|
return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc'; |
|
}; |
|
c3_chart_internal_fn.isOrderAsc = function () { |
|
var config = this.config; |
|
return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc'; |
|
}; |
|
c3_chart_internal_fn.getOrderFunction = function() { |
|
var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc(); |
|
if (orderAsc || orderDesc) { |
|
var reducer = function (p, c) { return p + Math.abs(c.value); }; |
|
return function (t1, t2) { |
|
var t1Sum = t1.values.reduce(reducer, 0), |
|
t2Sum = t2.values.reduce(reducer, 0); |
|
return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum; |
|
}; |
|
} else if (isFunction(config.data_order)) { |
|
return config.data_order; |
|
} else if (isArray(config.data_order)) { |
|
var order = config.data_order; |
|
return function (t1, t2) { |
|
return order.indexOf(t1.id) - order.indexOf(t2.id); |
|
}; |
|
} |
|
}; |
|
c3_chart_internal_fn.orderTargets = function (targets) { |
|
var fct = this.getOrderFunction(); |
|
if (fct) { |
|
targets.sort(fct); |
|
} |
|
return targets; |
|
}; |
|
c3_chart_internal_fn.filterByX = function (targets, x) { |
|
return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; }); |
|
}; |
|
c3_chart_internal_fn.filterRemoveNull = function (data) { |
|
return data.filter(function (d) { return isValue(d.value); }); |
|
}; |
|
c3_chart_internal_fn.filterByXDomain = function (targets, xDomain) { |
|
return targets.map(function (t) { |
|
return { |
|
id: t.id, |
|
id_org: t.id_org, |
|
values: t.values.filter(function (v) { |
|
return xDomain[0] <= v.x && v.x <= xDomain[1]; |
|
}) |
|
}; |
|
}); |
|
}; |
|
c3_chart_internal_fn.hasDataLabel = function () { |
|
var config = this.config; |
|
if (typeof config.data_labels === 'boolean' && config.data_labels) { |
|
return true; |
|
} else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) { |
|
return true; |
|
} |
|
return false; |
|
}; |
|
c3_chart_internal_fn.getDataLabelLength = function (min, max, key) { |
|
var $$ = this, |
|
lengths = [0, 0], paddingCoef = 1.3; |
|
$$.selectChart.select('svg').selectAll('.dummy') |
|
.data([min, max]) |
|
.enter().append('text') |
|
.text(function (d) { return $$.dataLabelFormat(d.id)(d); }) |
|
.each(function (d, i) { |
|
lengths[i] = this.getBoundingClientRect()[key] * paddingCoef; |
|
}) |
|
.remove(); |
|
return lengths; |
|
}; |
|
c3_chart_internal_fn.isNoneArc = function (d) { |
|
return this.hasTarget(this.data.targets, d.id); |
|
}, |
|
c3_chart_internal_fn.isArc = function (d) { |
|
return 'data' in d && this.hasTarget(this.data.targets, d.data.id); |
|
}; |
|
c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) { |
|
var $$ = this, candidates; |
|
|
|
// map to array of closest points of each target |
|
candidates = targets.map(function (target) { |
|
return $$.findClosest(target.values, pos); |
|
}); |
|
|
|
// decide closest point and return |
|
return $$.findClosest(candidates, pos); |
|
}; |
|
c3_chart_internal_fn.findClosest = function (values, pos) { |
|
var $$ = this, minDist = $$.config.point_sensitivity, closest; |
|
|
|
// find mouseovering bar |
|
values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) { |
|
var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node(); |
|
if (!closest && $$.isWithinBar($$.d3.mouse(shape), shape)) { |
|
closest = v; |
|
} |
|
}); |
|
|
|
// find closest point from non-bar |
|
values.filter(function (v) { return v && !$$.isBarType(v.id); }).forEach(function (v) { |
|
var d = $$.dist(v, pos); |
|
if (d < minDist) { |
|
minDist = d; |
|
closest = v; |
|
} |
|
}); |
|
|
|
return closest; |
|
}; |
|
c3_chart_internal_fn.dist = function (data, pos) { |
|
var $$ = this, config = $$.config, |
|
xIndex = config.axis_rotated ? 1 : 0, |
|
yIndex = config.axis_rotated ? 0 : 1, |
|
y = $$.circleY(data, data.index), |
|
x = $$.x(data.x); |
|
return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2)); |
|
}; |
|
c3_chart_internal_fn.convertValuesToStep = function (values) { |
|
var converted = [].concat(values), i; |
|
|
|
if (!this.isCategorized()) { |
|
return values; |
|
} |
|
|
|
for (i = values.length + 1; 0 < i; i--) { |
|
converted[i] = converted[i - 1]; |
|
} |
|
|
|
converted[0] = { |
|
x: converted[0].x - 1, |
|
value: converted[0].value, |
|
id: converted[0].id |
|
}; |
|
converted[values.length + 1] = { |
|
x: converted[values.length].x + 1, |
|
value: converted[values.length].value, |
|
id: converted[values.length].id |
|
}; |
|
|
|
return converted; |
|
}; |
|
c3_chart_internal_fn.updateDataAttributes = function (name, attrs) { |
|
var $$ = this, config = $$.config, current = config['data_' + name]; |
|
if (typeof attrs === 'undefined') { return current; } |
|
Object.keys(attrs).forEach(function (id) { |
|
current[id] = attrs[id]; |
|
}); |
|
$$.redraw({withLegend: true}); |
|
return current; |
|
};
|
|
|