Commit ed973f6e authored by Eduardo Cartre's avatar Eduardo Cartre

Merge pull request #1 from masayuki0812/master

Update
parents 6ffb1172 05ab78dc
This source diff could not be displayed because it is too large. You can view the blob instead.
var describe = window.describe,
expect = window.expect,
it = window.it,
beforeEach = window.beforeEach;
describe('c3 api data', function () {
'use strict';
var chart, d3;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 5000, 2000, 1000, 4000, 1500, 2500]
],
names: {
data1: 'Data Name 1',
data2: 'Data Name 2'
},
colors: {
data1: '#FF0000',
data2: '#00FF00'
},
axes: {
data1: 'y',
data2: 'y2'
}
},
axis: {
y2: {
show: true
}
}
};
beforeEach(function (done) {
if (typeof chart === 'undefined') {
window.initDom();
}
chart = window.c3.generate(args);
d3 = chart.internal.d3;
chart.internal.d3.select('.jasmine_html-reporter')
.style('position', 'absolute')
.style('right', 0);
window.setTimeout(function () {
done();
}, 10);
});
describe('data()', function () {
it('should return all of data if no argument given', function () {
var results = chart.data(),
expected = ['data1', 'data2'];
results.forEach(function (result, i) {
expect(result.id).toBe(expected[i]);
});
});
it('should return specifid data if string argument given', function () {
var results = chart.data('data1');
expect(results.length).toBe(1);
expect(results[0].id).toBe('data1');
});
it('should return specifid data if array argument given', function () {
var results = chart.data(['data1', 'data2']);
expect(results.length).toBe(2);
expect(results[0].id).toBe('data1');
expect(results[1].id).toBe('data2');
});
});
describe('data.shown()', function () {
it('should return only shown targets', function () {
var results;
chart.hide('data1');
results = chart.data.shown();
expect(results.length).toBe(1);
expect(results[0].id).toBe('data2');
});
});
describe('data.names()', function () {
it('should return data.names specified as argument', function () {
var results = chart.data.names();
expect(results.data1).toBe('Data Name 1');
expect(results.data2).toBe('Data Name 2');
});
it('should return data.names specified as api', function () {
var results = chart.data.names({
data1: 'New Data Name 1',
data2: 'New Data Name 2'
});
expect(results.data1).toBe('New Data Name 1');
expect(results.data2).toBe('New Data Name 2');
});
it('should set data.names specified as api', function () {
expect(d3.select('.c3-legend-item-data1 text').text()).toBe("New Data Name 1");
expect(d3.select('.c3-legend-item-data2 text').text()).toBe("New Data Name 2");
});
});
describe('data.colors()', function () {
it('should return data.colors specified as argument', function () {
var results = chart.data.colors();
expect(results.data1).toBe('#FF0000');
expect(results.data2).toBe('#00FF00');
});
it('should return data.colors specified as api', function () {
var results = chart.data.colors({
data1: '#00FF00',
data2: '#FF0000'
});
expect(results.data1).toBe('#00FF00');
expect(results.data2).toBe('#FF0000');
});
it('should set data.colors specified as api', function () {
expect(d3.select('.c3-line-data1').style('stroke')).toBe("#00ff00");
expect(d3.select('.c3-line-data2').style('stroke')).toBe("#ff0000");
expect(d3.select('.c3-legend-item-data1 .c3-legend-item-tile').style('fill')).toBe("#00ff00");
expect(d3.select('.c3-legend-item-data2 .c3-legend-item-tile').style('fill')).toBe("#ff0000");
});
});
describe('data.axes()', function () {
it('should return data.axes specified as argument', function () {
var results = chart.data.axes();
expect(results.data1).toBe('y');
expect(results.data2).toBe('y2');
expect(d3.select('.c3-axis-y g.tick text').text()).toBe('0');
expect(d3.select('.c3-axis-y2 g.tick text').text()).toBe('1000');
});
it('should return data.axes specified as api', function () {
var results = chart.data.axes({
data1: 'y2',
data2: 'y'
});
expect(results.data1).toBe('y2');
expect(results.data2).toBe('y');
expect(d3.select('.c3-axis-y g.tick text').text()).toBe('1000');
expect(d3.select('.c3-axis-y2 g.tick text').text()).toBe('0');
});
});
});
var describe = window.describe,
expect = window.expect,
it = window.it,
beforeEach = window.beforeEach;
describe('c3 chart axis', function () {
'use strict';
var chart, d3, args;
beforeEach(function (done) {
if (typeof chart === 'undefined') {
window.initDom();
}
chart = window.c3.generate(args);
d3 = chart.internal.d3;
chart.internal.d3.select('.jasmine_html-reporter')
.style('position', 'absolute')
.style('right', 0);
window.setTimeout(function () {
done();
}, 50);
});
describe('show pie chart', function () {
args = {
data: {
columns: [
['data1', 30],
['data2', 150],
['data3', 120]
],
type: 'pie'
}
};
it('should have correct classes', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.size()).toBe(1);
expect(arcs.data2.size()).toBe(1);
expect(arcs.data3.size()).toBe(1);
});
it('should have correct d', function () {
expect(d3.select('.c3-arc-data1').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
expect(d3.select('.c3-arc-data2').attr('d')).toMatch(/M1\..+,-211\..+A211\..+,211\..+ 0 0,1 1\..+,211\..+L0,0Z/);
expect(d3.select('.c3-arc-data3').attr('d')).toMatch(/M1\..+,211\..+A211\..+,211\..+ 0 0,1 -124\..+,-171\..+L0,0Z/);
});
it('should set args with data id that can be converted to a color', function () {
args.data.columns = [
['black', 30],
['data2', 150],
['data3', 120]
];
expect(true).toBeTruthy();
});
it('should have correct d even if data id can be converted to a color', function () {
expect(d3.select('.c3-arc-black').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
});
});
});
......@@ -21,3 +21,22 @@ function setEvent(chart, x, y) {
chart.internal.d3.event = evt;
}
typeof setEvent !== 'undefined';
function initChart(chart, args, done) {
'use strict';
if (typeof chart === 'undefined') {
window.initDom();
}
chart = window.c3.generate(args);
chart.internal.d3.select('.jasmine_html-reporter')
.style('position', 'absolute')
.style('right', 0);
window.setTimeout(function () {
done();
}, 10);
return chart;
}
typeof initChart !== 'undefined';
var describe = window.describe,
expect = window.expect,
it = window.it,
beforeEach = window.beforeEach;
describe('c3 chart class', function () {
'use strict';
var chart, d3;
var args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2 prefix', 50, 20, 10, 40, 15, 25],
['data3 мужчины', 150, 120, 110, 140, 115, 125]
]
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
d3 = chart.internal.d3;
});
describe('internal.getTargetSelectorSuffix', function () {
it('should not replace any characters', function () {
var input = 'data1',
expected = '-' + input,
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).toBe(expected);
});
it('should replace space to "-"', function () {
var input = 'data1 suffix',
expected = '-data1-suffix',
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).toBe(expected);
});
it('should replace space to "-" with multibyte characters', function () {
var input = 'data1 suffix 日本語',
expected = '-data1-suffix-日本語',
suffix = chart.internal.getTargetSelectorSuffix(input);
expect(suffix).toBe(expected);
});
});
describe('multibyte characters on chart', function () {
it('should replace space to "-" with multibyte characters', function () {
var selector = '.c3-target-data3-мужчины';
expect(chart.internal.main.select(selector).size()).toBe(1);
});
});
});
......@@ -114,7 +114,8 @@ describe('c3 chart data', function () {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d %H:%M:%S.%L'
format: '%Y-%m-%d %H:%M:%S.%L',
multiline: false
}
}
}
......
......@@ -15,5 +15,6 @@ c3_chart_fn.destroy = function () {
$$.data.targets = undefined;
$$.data.xs = {};
$$.selectChart.classed('c3', false).html("");
window.clearInterval($$.intervalForObserveInserted);
window.onresize = null;
};
c3_chart_fn.data = function (targetId) {
var targets = this.internal.data.targets.filter(function (t) { return t.id === targetId; });
return targets.length > 0 ? targets[0] : null;
c3_chart_fn.data = function (targetIds) {
var targets = this.internal.data.targets;
return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) {
return [].concat(targetIds).indexOf(t.id) >= 0;
});
};
c3_chart_fn.data.shown = function (targetId) {
return this.internal.filterTargetsToShow(this.data(targetId));
};
c3_chart_fn.data.values = function (targetId) {
var target = this.data(targetId);
return target ? target.values.map(function (d) { return d.value; }) : null;
};
c3_chart_fn.data.names = function (names) {
var $$ = this.internal, config = $$.config;
if (!arguments.length) { return config.data_names; }
Object.keys(names).forEach(function (id) {
config.data_names[id] = names[id];
});
$$.redraw({withLegend: true});
return config.data_names;
return this.internal.updateDataAttributes('names', names);
};
c3_chart_fn.data.colors = function (colors) {
var $$ = this.internal, config = $$.config;
if (!arguments.length) { return config.data_colors; }
Object.keys(colors).forEach(function (id) {
config.data_colors[id] = colors[id];
});
$$.redraw({withLegend: true});
return config.data_colors;
return this.internal.updateDataAttributes('colors', colors);
};
c3_chart_fn.data.axes = function (axes) {
return this.internal.updateDataAttributes('axes', axes);
};
......@@ -127,8 +127,10 @@ c3_chart_internal_fn.expandArc = function (targetIds) {
interval = window.setInterval(function () {
if (!$$.transiting) {
window.clearInterval(interval);
if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
$$.expandArc(targetIds);
}
}
}, 10);
return;
}
......@@ -311,7 +313,11 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
}
interpolate = d3.interpolate(this._current, updated);
this._current = interpolate(0);
return function (t) { return $$.getArc(interpolate(t), true); };
return function (t) {
var interpolated = interpolate(t);
interpolated.data = d.data; // data.id will be updated by interporator
return $$.getArc(interpolated, true);
};
})
.attr("transform", withTransform ? "scale(1)" : "")
.style("fill", function (d) {
......
......@@ -35,7 +35,8 @@ c3_chart_internal_fn.getXAxis = function (scale, orient, tickFormat, tickValues,
axisParams = {
isCategory: $$.isCategorized(),
withOuterTick: withOuterTick,
tickWidth: $$.isCategorized() ? config.axis_x_tick_width : undefined
tickMultiline: config.axis_x_tick_multiline,
tickWidth: config.axis_x_tick_width
},
axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient);
......@@ -242,7 +243,7 @@ c3_chart_internal_fn.textAnchorForY2AxisLabel = function () {
};
c3_chart_internal_fn.xForRotatedTickText = function (r) {
return 10 * Math.sin(Math.PI * (r / 180));
return 8 * Math.sin(Math.PI * (r / 180));
};
c3_chart_internal_fn.yForRotatedTickText = function (r) {
return 11.5 - 2.5 * (r / 15) * (r > 0 ? 1 : -1);
......@@ -252,8 +253,9 @@ c3_chart_internal_fn.rotateTickText = function (axis, transition, rotate) {
.style("text-anchor", rotate > 0 ? "start" : "end");
transition.selectAll('.tick text')
.attr("y", this.yForRotatedTickText(rotate))
.attr("x", this.xForRotatedTickText(rotate))
.attr("transform", "rotate(" + rotate + ")");
.attr("transform", "rotate(" + rotate + ")")
.selectAll('tspan')
.attr('dx', this.xForRotatedTickText(rotate));
};
c3_chart_internal_fn.getMaxTickWidth = function (id) {
......@@ -278,8 +280,8 @@ c3_chart_internal_fn.getMaxTickWidth = function (id) {
});
}).remove();
}
$$.currentMaxTickWidth = maxWidth <= 0 ? $$.currentMaxTickWidth : maxWidth;
return $$.currentMaxTickWidth;
$$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
return $$.currentMaxTickWidths[id];
};
c3_chart_internal_fn.updateAxisLabels = function (withTransition) {
......@@ -345,7 +347,7 @@ c3_chart_internal_fn.generateAxisTransitions = function (duration) {
};
};
c3_chart_internal_fn.redrawAxis = function (transitions, isHidden) {
var $$ = this;
var $$ = this, config = $$.config;
$$.axes.x.style("opacity", isHidden ? 0 : 1);
$$.axes.y.style("opacity", isHidden ? 0 : 1);
$$.axes.y2.style("opacity", isHidden ? 0 : 1);
......@@ -354,4 +356,8 @@ c3_chart_internal_fn.redrawAxis = function (transitions, isHidden) {
transitions.axisY.call($$.yAxis);
transitions.axisY2.call($$.y2Axis);
transitions.axisSubX.call($$.subXAxis);
// rotate tick text if needed
if (!config.axis_rotated && config.axis_x_tick_rotate) {
$$.rotateTickText($$.axes.x, transitions.axisX, config.axis_x_tick_rotate);
}
};
......@@ -102,11 +102,18 @@ function c3_axis(d3, params) {
isVertical = orient === 'left' || orient === 'right';
// this should be called only when category axis
function splitTickText(d) {
var tickText = textFormatted(d) + "",
maxWidth = isVertical ? params.tickWidth : tickOffset * 2 - 10,
function splitTickText(d, maxWidth) {
var tickText = textFormatted(d),
subtext, spaceIndex, textWidth, splitted = [];
if (Object.prototype.toString.call(tickText) === "[object Array]") {
return tickText;
}
if (!maxWidth || maxWidth <= 0) {
maxWidth = isVertical ? 95 : params.isCategory ? (tickOffset * 2 - 10) : 110;
}
function split(splitted, text) {
spaceIndex = undefined;
for (var i = 0; i < text.length; i++) {
......@@ -126,7 +133,7 @@ function c3_axis(d3, params) {
return splitted.concat(text);
}
return split(splitted, tickText);
return split(splitted, tickText + "");
}
function tspanDy(d, i) {
......@@ -149,7 +156,7 @@ function c3_axis(d3, params) {
text = tick.select("text");
tspan = text.selectAll('tspan')
.data(function (d, i) {
var splitted = params.tickWidth ? splitTickText(d) : [textFormatted(d)];
var splitted = params.tickMultiline ? splitTickText(d, params.tickWidth) : [].concat(textFormatted(d));
counts[i] = splitted.length;
return splitted.map(function (s) {
return { index: i, splitted: s };
......
......@@ -155,7 +155,7 @@ c3_chart_internal_fn.classChartArc = function (d) {
return CLASS.chartArc + this.classTarget(d.data.id);
};
c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
return targetId || targetId === 0 ? '-' + (targetId.replace ? targetId.replace(/([^a-zA-Z0-9-_])/g, '-') : targetId) : '';
return targetId || targetId === 0 ? ('-' + targetId).replace(/\s/g, '-') : '';
};
c3_chart_internal_fn.selectorTarget = function (id, prefix) {
return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
......
......@@ -11,7 +11,7 @@ c3_chart_internal_fn.getAxisClipX = function (forHorizontal) {
return forHorizontal ? -(1 + left) : -(left - 1);
};
c3_chart_internal_fn.getAxisClipY = function (forHorizontal) {
return forHorizontal ? -20 : -4;
return forHorizontal ? -10 : -4;
};
c3_chart_internal_fn.getXAxisClipX = function () {
var $$ = this;
......@@ -37,8 +37,7 @@ c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) {
return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
};
c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) {
var $$ = this, config = $$.config;
return forHorizontal ? (config.axis_x_height ? config.axis_x_height : 0) + 80 : $$.height + 8;
return forHorizontal ? this.margin.bottom : this.height + 8;
};
c3_chart_internal_fn.getXAxisClipWidth = function () {
var $$ = this;
......
......@@ -90,9 +90,10 @@ c3_chart_internal_fn.getDefaultConfig = function () {
axis_x_tick_count: undefined,
axis_x_tick_fit: true,
axis_x_tick_values: null,
axis_x_tick_rotate: undefined,
axis_x_tick_rotate: 0,
axis_x_tick_outer: true,
axis_x_tick_width: 80,
axis_x_tick_multiline: true,
axis_x_tick_width: null,
axis_x_max: undefined,
axis_x_min: undefined,
axis_x_padding: {},
......
......@@ -72,10 +72,12 @@ c3_chart_internal_fn.initParams = function () {
$$.clipIdForXAxis = $$.clipId + '-xaxis',
$$.clipIdForYAxis = $$.clipId + '-yaxis',
$$.clipIdForGrid = $$.clipId + '-grid',
$$.clipIdForSubchart = $$.clipId + '-subchart',
$$.clipPath = $$.getClipPath($$.clipId),
$$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis),
$$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
$$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid),
$$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart),
$$.dragStart = null;
$$.dragging = false;
......@@ -119,7 +121,11 @@ c3_chart_internal_fn.initParams = function () {
$$.legendItemHeight = 0;
$$.legendOpacityForHidden = 0.15;
$$.currentMaxTickWidth = 0;
$$.currentMaxTickWidths = {
x: 0,
y: 0,
y2: 0
};
$$.rotated_padding_left = 30;
$$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
......@@ -127,6 +133,8 @@ c3_chart_internal_fn.initParams = function () {
$$.withoutFadeIn = {};
$$.intervalForObserveInserted = undefined;
$$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
};
......@@ -197,6 +205,7 @@ c3_chart_internal_fn.initWithData = function (data) {
$$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
$$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
$$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
$$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
$$.updateSvgSize();
// Define regions
......@@ -454,9 +463,12 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
if (targetsToShow.length) {
$$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
// update axis tick values according to options
if (!config.axis_x_tick_values && (config.axis_x_tick_fit || config.axis_x_tick_count)) {
if (!config.axis_x_tick_values) {
if (config.axis_x_tick_fit || config.axis_x_tick_count) {
tickValues = $$.generateTickValues($$.mapTargetsToUniqueXs(targetsToShow), config.axis_x_tick_count, $$.isTimeSeries());
} else {
tickValues = undefined;
}
$$.xAxis.tickValues(tickValues);
$$.subXAxis.tickValues(tickValues);
}
......@@ -507,11 +519,6 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
}
}
// rotate tick text if needed
if (!config.axis_rotated && config.axis_x_tick_rotate) {
$$.rotateTickText($$.axes.x, transitions.axisX, config.axis_x_tick_rotate);
}
// setup drawer - MEMO: these must be called after axis updated
drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
......@@ -687,6 +694,9 @@ c3_chart_internal_fn.getTranslate = function (target) {
c3_chart_internal_fn.initialOpacity = function (d) {
return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
};
c3_chart_internal_fn.initialOpacityForCircle = function (d) {
return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
};
c3_chart_internal_fn.opacityForCircle = function (d) {
return isValue(d.value) && this.config.point_show ? (this.isScatterType(d) ? 0.5 : 1) : 0;
};
......@@ -744,7 +754,8 @@ c3_chart_internal_fn.transformAll = function (withTransition, transitions) {
};
c3_chart_internal_fn.updateSvgSize = function () {
var $$ = this;
var $$ = this,
brush = $$.svg.select(".c3-brush .background");
$$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
$$.svg.selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid]).select('rect')
.attr('width', $$.width)
......@@ -759,6 +770,9 @@ c3_chart_internal_fn.updateSvgSize = function () {
.attr('y', $$.getYAxisClipY.bind($$))
.attr('width', $$.getYAxisClipWidth.bind($$))
.attr('height', $$.getYAxisClipHeight.bind($$));
$$.svg.select('#' + $$.clipIdForSubchart).select('rect')
.attr('width', $$.width)
.attr('height', brush.size() ? brush.attr('height') : 0);
$$.svg.select('.' + CLASS.zoomRect)
.attr('width', $$.width)
.attr('height', $$.height);
......@@ -788,10 +802,10 @@ c3_chart_internal_fn.observeInserted = function (selection) {
if (mutation.type === 'childList' && mutation.previousSibling) {
observer.disconnect();
// need to wait for completion of load because size calculation requires the actual sizes determined after that completion
var interval = window.setInterval(function () {
$$.intervalForObserveInserted = window.setInterval(function () {
// parentNode will NOT be null when completed
if (selection.node().parentNode) {
window.clearInterval(interval);
window.clearInterval($$.intervalForObserveInserted);
$$.updateDimension();
$$.config.oninit.call($$);
$$.redraw({
......
......@@ -296,14 +296,25 @@ c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) {
return $$.findClosest(candidates, pos);
};
c3_chart_internal_fn.findClosest = function (values, pos) {
var $$ = this, minDist, closest;
values.forEach(function (v) {
var $$ = this, minDist = 100, closest;
// find mouseovering bar
values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) {
var shape = $$.d3.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();
if ($$.isWithinBar(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) {
if (d < minDist) {
minDist = d;
closest = v;
}
});
return closest;
};
c3_chart_internal_fn.dist = function (data, pos) {
......@@ -337,3 +348,12 @@ c3_chart_internal_fn.convertValuesToStep = function (values) {
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;
};
......@@ -231,12 +231,20 @@ c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
.on('drag', function () { $$.drag(d3.mouse(this)); })
.on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
.on('dragend', function () { $$.dragend(); })
)
.on("dblclick.zoom", null);
);
};
c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) {
var $$ = this, d3 = $$.d3, config = $$.config;
function mouseout() {
$$.svg.select('.' + CLASS.eventRect).style('cursor', null);
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
$$.unexpandBars();
}
eventRectEnter.append('rect')
.attr('x', 0)
.attr('y', 0)
......@@ -245,9 +253,7 @@ c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter)
.attr('class', CLASS.eventRect)
.on('mouseout', function () {
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
mouseout();
})
.on('mousemove', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
......@@ -259,9 +265,17 @@ c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter)
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
if (! closest) { return; }
if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {
config.data_onmouseout.call($$, $$.mouseover);
$$.mouseover = undefined;
}
if ($$.isScatterType(closest)) {
if (! closest) {
mouseout();
return;
}
if ($$.isScatterType(closest) || !config.tooltip_grouped) {
sameXData = [closest];
} else {
sameXData = $$.filterByX(targetsToShow, closest.x);
......@@ -277,21 +291,18 @@ c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter)
if (config.point_focus_expand_enabled) {
$$.expandCircles(closest.index, closest.id, true);
}
$$.expandBars(closest.index, closest.id, true);
// Show xgrid focus line
$$.showXGridFocus(selectedData);
// Show cursor as pointer if point is close to mouse position
if ($$.dist(closest, mouse) < 100) {
if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
$$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
if (!$$.mouseover) {
config.data_onmouseover.call($$, closest);
$$.mouseover = true;
$$.mouseover = closest;
}
} else if ($$.mouseover) {
$$.svg.select('.' + CLASS.eventRect).style('cursor', null);
config.data_onmouseout.call($$, closest);
$$.mouseover = false;
}
})
.on('click', function () {
......@@ -306,8 +317,8 @@ c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter)
if (! closest) { return; }
// select if selection enabled
if ($$.dist(closest, mouse) < 100 && $$.toggleShape) {
$$.main.select('.' + CLASS.circles + $$.getTargetSelectorSuffix(closest.id)).select('.' + CLASS.circle + '-' + closest.index).each(function () {
if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
$$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).select('.' + CLASS.shape + '-' + closest.index).each(function () {
if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
$$.toggleShape(this, closest, closest.index);
$$.config.data_onclick.call($$.api, closest, this);
......@@ -320,8 +331,7 @@ c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter)
.on('drag', function () { $$.drag(d3.mouse(this)); })
.on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
.on('dragend', function () { $$.dragend(); })
)
.on("dblclick.zoom", null);
);
};
c3_chart_internal_fn.dispatchEvent = function (type, index, mouse) {
var $$ = this,
......
......@@ -107,7 +107,7 @@ c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
var withTransition, withTransitionForTransform;
var hasFocused = $$.legend.selectAll('.' + CLASS.legendItemFocused).size();
var texts, rects, tiles;
var texts, rects, tiles, background;
options = options || {};
withTransition = getOption(options, "withTransition", true);
......@@ -225,9 +225,7 @@ c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
})
.on('mouseout', function (id) {
$$.d3.select(this).classed(CLASS.legendItemFocused, false);
if (!$$.transiting) {
$$.api.revert();
}
if (config.legend_item_onmouseout) {
config.legend_item_onmouseout.call($$, id);
}
......@@ -251,13 +249,13 @@ c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
.attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend)
.attr('width', 10)
.attr('height', 10);
// Set background for inset legend
if ($$.isLegendInset && maxWidth !== 0) {
$$.legend.insert('g', '.' + CLASS.legendItem)
background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
background = $$.legend.insert('g', '.' + CLASS.legendItem)
.attr("class", CLASS.legendBackground)
.append('rect')
.attr('height', $$.getLegendHeight() - 12)
.attr('width', maxWidth * (step + 1) + 10);
.append('rect');
}
texts = $$.legend.selectAll('text')
......@@ -283,6 +281,12 @@ c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
.attr('x', xForLegend)
.attr('y', yForLegend);
if (background) {
(withTransition ? background.transition() : background)
.attr('height', $$.getLegendHeight() - 12)
.attr('width', maxWidth * (step + 1) + 10);
}
// toggle legend state
$$.legend.selectAll('.' + CLASS.legendItem)
.classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); })
......
......@@ -52,14 +52,14 @@ c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) {
w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickOffset() * 2 * config.bar_width_ratio) / barTargetsNum : 0;
return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
};
c3_chart_internal_fn.getBars = function (i) {
c3_chart_internal_fn.getBars = function (i, id) {
var $$ = this;
return $$.main.selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
};
c3_chart_internal_fn.expandBars = function (i, id, reset) {
var $$ = this;
if (reset) { $$.unexpandBars(); }
$$.getBars(i).classed(CLASS.EXPANDED, true);
$$.getBars(i, id).classed(CLASS.EXPANDED, true);
};
c3_chart_internal_fn.unexpandBars = function (i) {
var $$ = this;
......@@ -112,8 +112,7 @@ c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
};
};
c3_chart_internal_fn.isWithinBar = function (that) {
var d3 = this.d3,
mouse = d3.mouse(that), box = that.getBoundingClientRect(),
var mouse = this.d3.mouse(that), box = that.getBoundingClientRect(),
seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1),
x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y),
w = box.width, h = box.height, offset = 2,
......
......@@ -289,7 +289,7 @@ c3_chart_internal_fn.redrawCircle = function () {
.attr("r", $$.pointR.bind($$))
.style("fill", $$.color);
$$.mainCircle
.style("opacity", $$.initialOpacity.bind($$));
.style("opacity", $$.initialOpacityForCircle.bind($$));
$$.mainCircle.exit().remove();
};
c3_chart_internal_fn.addTransitionForCircle = function (transitions, cx, cy) {
......
......@@ -15,14 +15,14 @@ c3_chart_internal_fn.getCurrentPaddingBottom = function () {
var config = this.config;
return isValue(config.padding_bottom) ? config.padding_bottom : 0;
};
c3_chart_internal_fn.getCurrentPaddingLeft = function () {
c3_chart_internal_fn.getCurrentPaddingLeft = function (withoutRecompute) {
var $$ = this, config = $$.config;
if (isValue(config.padding_left)) {
return config.padding_left;
} else if (config.axis_rotated) {
return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x')), 40);
return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
} else {
return !config.axis_y_show ? 1 : ceil10($$.getAxisWidthByAxisId('y'));
return !config.axis_y_show ? 1 : ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
}
};
c3_chart_internal_fn.getCurrentPaddingRight = function () {
......@@ -57,29 +57,37 @@ c3_chart_internal_fn.getParentHeight = function () {
};
c3_chart_internal_fn.getSvgLeft = function () {
c3_chart_internal_fn.getSvgLeft = function (withoutRecompute) {
var $$ = this, config = $$.config,
leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
leftAxis = $$.main.select('.' + leftAxisClass).node(),
svgRect = leftAxis ? leftAxis.getBoundingClientRect() : {right: 0},
chartRect = $$.selectChart.node().getBoundingClientRect(),
hasArc = $$.hasArcType(),
svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft());
svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
return svgLeft > 0 ? svgLeft : 0;
};
c3_chart_internal_fn.getAxisWidthByAxisId = function (id) {
c3_chart_internal_fn.getAxisWidthByAxisId = function (id, withoutRecompute) {
var $$ = this, position = $$.getAxisLabelPositionById(id);
return position.isInner ? 20 + $$.getMaxTickWidth(id) : 40 + $$.getMaxTickWidth(id);
if (withoutRecompute) {
var box = $$.d3.select('.c3-axis-y').node().getBoundingClientRect();
return Math.floor(box.left + box.width);
}
return $$.getMaxTickWidth(id) + (position.isInner ? 20 : 40);
};
c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) {
var $$ = this, config = $$.config;
var $$ = this, config = $$.config, h = 30;
if (axisId === 'x' && !config.axis_x_show) { return 8; }
if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; }
if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
return ($$.getAxisLabelPositionById(axisId).isInner ? 30 : 40) + (axisId === 'y2' ? -10 : 0);
// Calculate x axis height when tick rotated
if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
h = $$.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
}
return h + ($$.getAxisLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
};
c3_chart_internal_fn.getEventRectWidth = function () {
......
......@@ -19,7 +19,7 @@ c3_chart_internal_fn.initSubchart = function () {
// Define g for chart area
context.append('g')
.attr("clip-path", $$.clipPath)
.attr("clip-path", $$.clipPathForSubchart)
.attr('class', CLASS.chart);
// Define g for bar chart area
......
......@@ -67,15 +67,14 @@ c3_chart_internal_fn.showTooltip = function (selectedData, mouse) {
tooltipLeft = ($$.width / 2) + mouse[0];
tooltipTop = ($$.height / 2) + mouse[1] + 20;
} else {
svgLeft = $$.getSvgLeft(false);
if (config.axis_rotated) {
svgLeft = $$.getSvgLeft();
tooltipLeft = svgLeft + mouse[0] + 100;
tooltipRight = tooltipLeft + tWidth;
chartRight = $$.getCurrentWidth() - $$.getCurrentPaddingRight();
tooltipTop = $$.x(dataToShow[0].x) + 20;
} else {
svgLeft = $$.getSvgLeft();
tooltipLeft = svgLeft + $$.getCurrentPaddingLeft() + $$.x(dataToShow[0].x) + 20;
tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(false) + $$.x(dataToShow[0].x) + 20;
tooltipRight = tooltipLeft + tWidth;
chartRight = svgLeft + $$.getCurrentWidth() - $$.getCurrentPaddingRight();
tooltipTop = mouse[1] + 15;
......
c3_chart_internal_fn.initZoom = function () {
var $$ = this, d3 = $$.d3, config = $$.config;
var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
$$.zoom = d3.behavior.zoom()
.on("zoomstart", function () {
startEvent = d3.event.sourceEvent;
$$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null;
config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
})
......@@ -10,6 +11,11 @@ c3_chart_internal_fn.initZoom = function () {
$$.redrawForZoom.call($$);
})
.on('zoomend', function () {
var event = d3.event.sourceEvent;
// if click, do nothing. otherwise, click interaction will be canceled.
if (event && startEvent.x === event.x && startEvent.y === event.y) {
return;
}
$$.redrawEventRect();
$$.updateZoom();
config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
......@@ -30,8 +36,8 @@ c3_chart_internal_fn.initZoom = function () {
};
c3_chart_internal_fn.updateZoom = function () {
var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {};
$$.main.select('.' + CLASS.zoomRect).call(z);
$$.main.selectAll('.' + CLASS.eventRect).call(z);
$$.main.select('.' + CLASS.zoomRect).call(z).on("dblclick.zoom", null);
$$.main.selectAll('.' + CLASS.eventRect).call(z).on("dblclick.zoom", null);
};
c3_chart_internal_fn.redrawForZoom = function () {
var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment