Browse Source

Add APIs to show/hide legends - #118

pull/155/head
Masayuki Tanaka 11 years ago
parent
commit
a3096bda84
  1. 151
      c3.js
  2. 5
      c3.min.js

151
c3.js

@ -71,7 +71,7 @@
var d3 = window.d3 ? window.d3 : window.require ? window.require("d3") : undefined;
var c3 = { data : {}, axis: {} },
var c3 = { data : {}, axis: {}, legend: {} },
cache = {};
/*-- Handle Config --*/
@ -295,7 +295,7 @@
};
})();
var hiddenTargetIds = [];
var hiddenTargetIds = [], hiddenLegendIds = [];
/*-- Set Chart Params --*/
@ -329,10 +329,11 @@
return "url(" + document.URL.split('#')[0] + "#" + id + ")";
}
function transformMain() {
function transformMain(withTransition) {
var duration = withTransition !== false ? 250 : 0;
main.attr("transform", translate.main);
main.select('.' + CLASS.axisX).attr("transform", translate.x);
main.select('.' + CLASS.axisY).attr("transform", translate.y);
main.select('.' + CLASS.axisX).transition().duration(duration).attr("transform", translate.x);
main.select('.' + CLASS.axisY).transition().duration(duration).attr("transform", translate.y);
main.select('.' + CLASS.axisY2).attr("transform", translate.y2);
main.select('.' + CLASS.chartArcs).attr("transform", translate.arc);
}
@ -1460,6 +1461,9 @@
function isTargetToShow(targetId) {
return hiddenTargetIds.indexOf(targetId) < 0;
}
function isLegendToShow(targetId) {
return hiddenLegendIds.indexOf(targetId) < 0;
}
function filterTargetsToShow(targets) {
return targets.filter(function (t) { return isTargetToShow(t.id); });
}
@ -1499,6 +1503,12 @@
function removeHiddenTargetIds(targetIds) {
hiddenTargetIds = hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
}
function addHiddenLegendIds(targetIds) {
hiddenLegendIds = hiddenLegendIds.concat(targetIds);
}
function removeHiddenLegendIds(targetIds) {
hiddenLegendIds = hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
}
function getValuesAsIdKeyed(targets) {
var ys = {};
targets.forEach(function (t) {
@ -1552,6 +1562,8 @@
}
function selectorTarget(id) { return '.' + CLASS.target + getTargetSelectorSuffix(id); }
function selectorTargets(ids) { return ids.map(function (id) { return selectorTarget(id); }); }
function selectorLegend(id) { return '.' + CLASS.legendItem + getTargetSelectorSuffix(id); }
function selectorLegends(ids) { return ids.map(function (id) { return selectorLegend(id); }); }
function initialOpacity(d) {
return d.value !== null && withoutFadeIn[d.id] ? 1 : 0;
@ -2400,6 +2412,10 @@
.style("z-index", "10")
.style("display", "none");
// MEMO: call here to update legend box and tranlate for all
// MEMO: translate will be upated by this, so transform not needed in updateLegend()
updateLegend(mapToIds(c3.data.targets), {withTransform: false, withTransitionForTransform: false});
/*-- Main Region --*/
// Add Axis
@ -2418,6 +2434,7 @@
main.append("g")
.attr("class", CLASS.axisY)
.attr("clip-path", __axis_rotated ? clipPathForYAxis : "")
.attr("transform", translate.y)
.append("text")
.attr("class", CLASS.axisYLabel)
.attr("transform", __axis_rotated ? "" : "rotate(-90)")
@ -2561,7 +2578,7 @@
}
// Draw with targets
updateAndRedraw({withTransform: true, withLegend: true, withTransitionForAxis: false});
redraw({withTransform: true, withUpdateXDomain: true, withUpdateOrgXDomain: true, withTransitionForAxis: false});
// Show tooltip if needed
if (__tooltip_init_show) {
@ -2879,11 +2896,11 @@
}
function redraw(options) {
var xgrid, xgridData, xgridLines, xgridLine, ygrid, ygridLines, ygridLine;
var xaxis, yaxis, xgrid, xgridData, xgridLines, xgridLine, ygrid, ygridLines, ygridLine;
var mainCircle, mainBar, mainRegion, mainText, contextBar, eventRectUpdate;
var barIndices = getBarIndices(), maxDataCountTarget;
var rectX, rectW;
var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransitionForHorizontalAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
var hideAxis = hasArcType(c3.data.targets);
var drawBar, drawBarOnSub, xForText, yForText;
var duration, durationForExit, durationForAxis;
@ -2905,6 +2922,7 @@
withTransitionForExit = isDefined(options.withTransitionForExit) ? options.withTransitionForExit : withTransition;
withTransitionForAxis = isDefined(options.withTransitionForAxis) ? options.withTransitionForAxis : withTransition;
withTransitionForHorizontalAxis = isDefined(options.withTransitionForHorizontalAxis) ? options.withTransitionForHorizontalAxis : withTransition;
duration = withTransition ? __transition_duration : 0;
durationForExit = withTransitionForExit ? duration : 0;
@ -2912,7 +2930,7 @@
// update legend and transform each g
if (withLegend && __legend_show) {
updateLegend(c3.data.targets, options);
updateLegend(mapToIds(c3.data.targets), options);
}
if (withUpdateOrgXDomain) {
@ -2927,19 +2945,30 @@
if (withUpdateXDomain) {
x.domain(brush.empty() ? orgXDomain : brush.extent());
if (__zoom_enabled) { zoom.scale(x).updateScaleExtent(); }
// update axis tick values according to options, except for scatter plot
if (! hasScatterType(targetsToShow)) { // TODO: fix this
tickValues = generateTickValues(mapTargetsToUniqueXs(targetsToShow)).sort();
xAxis.tickValues(tickValues);
subXAxis.tickValues(tickValues);
}
}
y.domain(getYDomain(targetsToShow, 'y'));
y2.domain(getYDomain(targetsToShow, 'y2'));
// axis
main.select('.' + CLASS.axisX).style("opacity", hideAxis ? 0 : 1).transition().duration(durationForAxis).call(xAxis);
main.select('.' + CLASS.axisY).style("opacity", hideAxis ? 0 : 1).transition().duration(durationForAxis).call(yAxis);
// update axis tick values according to options, except for scatter plot
if (! hasScatterType(targetsToShow)) { // TODO: fix this
tickValues = generateTickValues(mapTargetsToUniqueXs(targetsToShow)).sort();
xAxis.tickValues(tickValues);
subXAxis.tickValues(tickValues);
}
// x axis
xaxis = main.select('.' + CLASS.axisX).style("opacity", hideAxis ? 0 : 1);
if (__axis_rotated || withTransitionForHorizontalAxis) {
xaxis = xaxis.transition().duration(durationForAxis);
}
xaxis.call(xAxis);
// y axis
yaxis = main.select('.' + CLASS.axisY).style("opacity", hideAxis ? 0 : 1);
if (!__axis_rotated || withTransitionForHorizontalAxis) {
yaxis = yaxis.transition().duration(durationForAxis);
}
yaxis.call(yAxis);
// y2 axis
main.select('.' + CLASS.axisY2).style("opacity", hideAxis ? 0 : 1).transition().duration(durationForAxis).call(yAxis2);
// show/hide if manual culling needed
@ -3343,10 +3372,12 @@
}
function updateAndRedraw(options) {
options = isDefined(options) ? options : {};
options = options || {};
// same with redraw
options.withTransition = isDefined(options.withTransition) ? options.withTransition : true;
options.withTransform = isDefined(options.withTransform) ? options.withTransform : false;
options.withLegend = isDefined(options.withLegend) ? options.withLegend : false;
// NOT same with redraw
options.withUpdateXDomain = true;
options.withUpdateOrgXDomain = true;
options.withTransitionForExit = false;
@ -3578,7 +3609,7 @@
var legendItem, isTarget, notTarget;
if (!__legend_show) { return; }
legendItem = legend.selectAll('.' + CLASS.legendItem);
isTarget = function (d) { return !id || d === id; };
isTarget = function (d) { return (!id || d === id); };
notTarget = function (d) { return !isTarget(d); };
legendItem.filter(notTarget).transition().duration(100).style('opacity', focus ? 0.3 : 1);
legendItem.filter(isTarget).transition().duration(100).style('opacity', focus ? 1 : 0.3);
@ -3595,16 +3626,32 @@
.transition().duration(100)
.style('opacity', 1);
}
function showLegend(targetIds) {
removeHiddenLegendIds(targetIds);
legend.selectAll(selectorLegends(targetIds))
.style('visibility', 'visible')
.transition()
.style('opacity', 1);
updateLegend(mapToIds(c3.data.targets));
}
function hideLegend(targetIds) {
addHiddenLegendIds(targetIds);
legend.selectAll(selectorLegends(targetIds))
.style('opacity', 0)
.style('visibility', 'hidden');
updateLegend(mapToIds(c3.data.targets));
}
function updateLegend(targets, options) {
var ids = mapToIds(targets), l;
function updateLegend(targetIds, options) {
var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
var paddingTop = 4, paddingRight = 26, maxWidth = 0, maxHeight = 0, posMin = 10;
var totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = {}, steps = {}, step = 0;
var withTransition;
var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
var withTransition, withTransitionForTransform, withTransformAll;
options = isUndefined(options) ? {} : options;
withTransition = isDefined(options.withTransition) ? options.withTransition : true;
withTransitionForTransform = isDefined(options.withTransitionForTransform) ? options.withTransitionForTransform : true;
withTransformAll = isDefined(options.withTransformAll) ? options.withTransformAll : true;
function updatePositions(textElement, id, reset) {
var box = textElement.getBBox(),
@ -3637,6 +3684,11 @@
maxHeight = 0;
}
if (!isLegendToShow(id)) {
widths[id] = heights[id] = steps[id] = offsets[id] = 0;
return;
}
widths[id] = itemWidth;
heights[id] = itemHeight;
@ -3647,11 +3699,11 @@
if (__legend_equally) {
Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; });
Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; });
margin = (areaLength - maxLength * ids.length) / 2;
margin = (areaLength - maxLength * targetIds.length) / 2;
if (margin < posMin) {
totalLength = 0;
step = 0;
ids.forEach(function (id) { updateValues(id); });
targetIds.forEach(function (id) { updateValues(id); });
}
else {
updateValues(id, true);
@ -3675,7 +3727,7 @@
// Define g for legend area
l = legend.selectAll('.' + CLASS.legendItem)
.data(ids)
.data(targetIds)
.enter().append('g')
.attr('class', function (id) { return generateClass(CLASS.legendItem, id); })
.style('cursor', 'pointer')
@ -3711,7 +3763,7 @@
.attr('height', 10);
legend.selectAll('text')
.data(ids)
.data(targetIds)
.text(function (id) { return isDefined(__data_names[id]) ? __data_names[id] : id; }) // MEMO: needed for update
.each(function (id, i) { updatePositions(this, id, i === 0); })
.transition().duration(withTransition ? 250 : 0)
@ -3719,13 +3771,13 @@
.attr('y', yForLegendText);
legend.selectAll('rect.' + CLASS.legendItemEvent)
.data(ids)
.data(targetIds)
.transition().duration(withTransition ? 250 : 0)
.attr('x', xForLegendRect)
.attr('y', yForLegendRect);
legend.selectAll('rect.' + CLASS.legendItemTile)
.data(ids)
.data(targetIds)
.transition().duration(withTransition ? 250 : 0)
.attr('x', xForLegend)
.attr('y', yForLegend);
@ -3739,7 +3791,9 @@
updateScales();
updateSvgSize();
// Update g positions
transformAll(false);
if (withTransformAll) {
transformAll(withTransitionForTransform);
}
}
/*-- Event Handling --*/
@ -3809,22 +3863,36 @@
revertLegend();
};
c3.show = function (targetIds) {
c3.show = function (targetIds, options) {
targetIds = mapToTargetIds(targetIds);
options = options || {};
removeHiddenTargetIds(targetIds);
svg.selectAll(selectorTargets(targetIds))
.transition()
.style('opacity', 1);
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: false});
if (options.withLegend) {
showLegend(targetIds);
}
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withTransitionForHorizontalAxis: false});
};
c3.hide = function (targetIds) {
c3.hide = function (targetIds, options) {
targetIds = mapToTargetIds(targetIds);
options = options || {};
addHiddenTargetIds(targetIds);
svg.selectAll(selectorTargets(targetIds))
.transition()
.style('opacity', 0);
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: false});
if (options.withLegend) {
hideLegend(targetIds);
}
redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withTransitionForHorizontalAxis: false});
};
c3.toggle = function (targetId) {
@ -4025,7 +4093,7 @@
Object.keys(names).forEach(function (id) {
__data_names[id] = names[id];
});
updateLegend(c3.data.targets, {withTransition: true});
updateLegend(mapToIds(c3.data.targets), {withTransition: true});
return __data_names;
};
@ -4082,6 +4150,17 @@
}
};
c3.legend.show = function (targetIds) {
if (!__legend_show) { return; }
showLegend(mapToTargetIds(targetIds));
redraw({withTransitionForHorizontalAxis: false});
};
c3.legend.hide = function (targetIds) {
if (!__legend_show) { return; }
hideLegend(mapToTargetIds(targetIds));
redraw({withTransitionForHorizontalAxis: false});
};
c3.resize = function (size) {
__size_width = size ? size.width : null;
__size_height = size ? size.height : null;

5
c3.min.js vendored

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save