Browse Source

Modularize event rect

pull/486/head
Masayuki Tanaka 10 years ago
parent
commit
0516616d41
  1. 1
      Gruntfile.coffee
  2. 626
      c3.js
  3. 6
      c3.min.js
  4. 316
      src/core.js
  5. 8
      src/data.js
  6. 301
      src/interaction.js

1
Gruntfile.coffee

@ -27,6 +27,7 @@ module.exports = (grunt) ->
'src/data.convert.js',
'src/data.load.js',
'src/category.js',
'src/interaction.js',
'src/size.js',
'src/shape.js',
'src/shape.line.js',

626
c3.js

@ -132,7 +132,7 @@
c3_chart_internal_fn.initWithData = function (data) {
var $$ = this, d3 = $$.d3, config = $$.config;
var main, eventRect, binding = true;
var main, binding = true;
if ($$.initPie) { $$.initPie(); }
if ($$.initBrush) { $$.initBrush(); }
@ -225,9 +225,7 @@
.attr('class', CLASS[_chart]);
// Cover whole with rects for events
eventRect = main.select('.' + CLASS[_chart]).append("g")
.attr("class", CLASS[_eventRects])
.style('fill-opacity', 0);
$$.initEventRect();
// Define g for bar chart area
if ($$.initBar) { $$.initBar(); }
@ -405,9 +403,7 @@
c3_chart_internal_fn.redraw = function (options, transitions) {
var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
var eventRect, eventRectUpdate;
var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType), maxDataCountTarget;
var rectX, rectW;
var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
var hideAxis = $$.hasArcType();
var drawArea, drawBar, drawLine, xForText, yForText;
@ -549,70 +545,9 @@
.selectAll('circle')
.remove();
// event rect
if (config[__interaction_enabled]) {
// rect for mouseover
eventRect = main.select('.' + CLASS[_eventRects])
.style('cursor', config[__zoom_enabled] ? config[__axis_rotated] ? 'ns-resize' : 'ew-resize' : null);
if (notEmpty(config[__data_xs]) && !$$.isSingleX(config[__data_xs])) {
if (!eventRect.classed(CLASS[_eventRectsMultiple])) {
eventRect.classed(CLASS[_eventRectsMultiple], true).classed(CLASS[_eventRectsSingle], false)
.selectAll('.' + CLASS[_eventRect]).remove();
}
eventRectUpdate = main.select('.' + CLASS[_eventRects]).selectAll('.' + CLASS[_eventRect])
.data([0]);
// enter : only one rect will be added
$$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
// update
eventRectUpdate
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height);
// exit : not needed because always only one rect exists
} else {
if (!eventRect.classed(CLASS[_eventRectsSingle])) {
eventRect.classed(CLASS[_eventRectsMultiple], false).classed(CLASS[_eventRectsSingle], true)
.selectAll('.' + CLASS[_eventRect]).remove();
}
if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
rectW = function (d) {
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index],
w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2;
return w < 0 ? 0 : w;
};
rectX = function (d) {
var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index];
return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2;
};
} else {
rectW = $$.getEventRectWidth();
rectX = function (d) {
return $$.x(d.x) - (rectW / 2);
};
}
// Set data
maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
main.select('.' + CLASS[_eventRects])
.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
// Update rects
eventRectUpdate = main.select('.' + CLASS[_eventRects]).selectAll('.' + CLASS[_eventRect])
.data(function (d) { return d; });
// enter
$$.generateEventRectsForSingleX(eventRectUpdate.enter());
// update
eventRectUpdate
.attr('class', generateCall($$.classEvent, $$))
.attr("x", config[__axis_rotated] ? 0 : rectX)
.attr("y", config[__axis_rotated] ? rectX : 0)
.attr("width", config[__axis_rotated] ? $$.width : rectW)
.attr("height", config[__axis_rotated] ? rectW : $$.height);
// exit
eventRectUpdate.exit().remove();
}
$$.redrawEventRect();
}
// transition should be derived from one transition
@ -621,30 +556,8 @@
$$.addTransitionForBar(transitions, drawBar);
$$.addTransitionForLine(transitions, drawLine);
/*
transitions.push(mainLine.transition()
.attr("d", drawLine)
.style("stroke", $$.color)
.style("opacity", 1));
*/
$$.addTransitionForArea(transitions, drawArea);
/*
transitions.push(mainArea.transition()
.attr("d", drawArea)
.style("fill", $$.color)
.style("opacity", $$.orgAreaOpacity));
*/
$$.addTransitionForCircle(transitions, cx, cy);
/*
transitions.push(mainCircle.transition()
.style('opacity', generateCall($$.opacityForCircle, $$))
.style("fill", $$.color)
.attr("cx", cx)
.attr("cy", cy));
transitions.push(main.selectAll('.' + CLASS[_selectedCircle]).transition()
.attr("cx", cx)
.attr("cy", cy));
*/
$$.addTransitionForText(transitions, xForText, yForText, options.flow);
$$.addTransitionForRegion(transitions);
$$.addTransitionForGrid(transitions);
@ -774,11 +687,7 @@
mainRegion.select('rect').filter($$.isRegionOnX)
.attr("x", generateCall($$.regionX, $$))
.attr("width", generateCall($$.regionWidth, $$));
eventRectUpdate
.attr("x", config[__axis_rotated] ? 0 : rectX)
.attr("y", config[__axis_rotated] ? rectX : 0)
.attr("width", config[__axis_rotated] ? $$.width : rectW)
.attr("height", config[__axis_rotated] ? rectW : $$.height);
$$.updateEventRect();
// callback for end of flow
done();
@ -820,219 +729,6 @@
$$.redraw(options, transitions);
};
c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
var $$ = this, d3 = $$.d3, config = $$.config;
eventRectEnter.append("rect")
.attr("class", generateCall($$.classEvent, $$))
.style("cursor", config[__data_selection_enabled] && config[__data_selection_grouped] ? "pointer" : null)
.on('mouseover', function (d) {
var index = d.index, selectedData, newData;
if ($$.dragging) { return; } // do nothing if dragging
if ($$.hasArcType()) { return; }
selectedData = $$.data.targets.map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
// Sort selectedData as names order
newData = [];
Object.keys(config[__data_names]).forEach(function (id) {
for (var j = 0; j < selectedData.length; j++) {
if (selectedData[j] && selectedData[j].id === id) {
newData.push(selectedData[j]);
selectedData.shift(j);
break;
}
}
});
selectedData = newData.concat(selectedData); // Add remained
// Expand shapes for selection
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index); }
$$.expandBars(index);
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseover].call(c3, d);
});
})
.on('mouseout', function (d) {
var index = d.index;
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
// Undo expanded shapes
$$.unexpandCircles(index);
$$.unexpandBars();
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseout].call($$, d);
});
})
.on('mousemove', function (d) {
var selectedData, index = d.index,
eventRect = $$.svg.select('.' + CLASS[_eventRect] + '-' + index);
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType()) { return; }
// Show tooltip
selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
if (config[__tooltip_grouped]) {
$$.showTooltip(selectedData, d3.mouse(this));
$$.showXGridFocus(selectedData);
}
if (config[__tooltip_grouped] && (!config[__data_selection_enabled] || config[__data_selection_grouped])) {
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index)
.each(function () {
d3.select(this).classed(CLASS[_EXPANDED], true);
if (config[__data_selection_enabled]) {
eventRect.style('cursor', config[__data_selection_grouped] ? 'pointer' : null);
}
if (!config[__tooltip_grouped]) {
$$.hideXGridFocus();
$$.hideTooltip();
if (!config[__data_selection_grouped]) {
$$.unexpandCircles(index);
$$.unexpandBars();
}
}
})
.filter(function (d) {
if (this.nodeName === 'circle') {
return $$.isWithinCircle(this, $$.pointSelectR(d));
}
else if (this.nodeName === 'path') {
return $$.isWithinBar(this);
}
})
.each(function (d) {
if (config[__data_selection_enabled] && (config[__data_selection_grouped] || config[__data_selection_isselectable](d))) {
eventRect.style('cursor', 'pointer');
}
if (!config[__tooltip_grouped]) {
$$.showTooltip([d], d3.mouse(this));
$$.showXGridFocus([d]);
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index, d.id); }
$$.expandBars(index, d.id);
}
});
})
.on('click', function (d) {
var index = d.index;
if ($$.hasArcType() || !$$.toggleShape) { return; }
if ($$.cancelClick) {
$$.cancelClick = false;
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
$$.toggleShape(this, d, index);
});
})
.call(
d3.behavior.drag().origin(Object)
.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;
eventRectEnter.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height)
.attr('class', CLASS[_eventRect])
.on('mouseout', function () {
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
})
.on('mousemove', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest, sameXData, selectedData;
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
if (! closest) { return; }
if ($$.isScatterType(closest)) {
sameXData = [closest];
} else {
sameXData = $$.filterSameX(targetsToShow, closest.x);
}
// show tooltip when cursor is close to some point
selectedData = sameXData.map(function (d) {
return $$.addName(d);
});
$$.showTooltip(selectedData, mouse);
// expand points
if (config[__point_focus_expand_enabled]) {
$$.unexpandCircles();
$$.expandCircles(closest.index, closest.id);
}
// Show xgrid focus line
$$.showXGridFocus(selectedData);
// Show cursor as pointer if point is close to mouse position
if ($$.dist(closest, mouse) < 100) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', 'pointer');
if (!$$.mouseover) {
config[__data_onmouseover].call($$, closest);
$$.mouseover = true;
}
} else if ($$.mouseover) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', null);
config[__data_onmouseout].call($$, closest);
$$.mouseover = false;
}
})
.on('click', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest;
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
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 () {
$$.toggleShape(this, closest, closest.index);
});
}
})
.call(
d3.behavior.drag().origin(Object)
.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.isTimeSeries = function () {
return this.config[__axis_x_type] === 'timeseries';
};
@ -1958,8 +1654,12 @@
$$.config[__data_xs][id] = xs[id];
});
};
c3_chart_internal_fn.isSingleX = function (xs) {
return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() === 1;
c3_chart_internal_fn.hasMultipleX = function (xs) {
return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1;
};
c3_chart_internal_fn.isMultipleX = function () {
var $$ = this, config = $$.config;
return notEmpty(config[__data_xs]) && $$.hasMultipleX(config[__data_xs]);
};
c3_chart_internal_fn.addName = function (data) {
var $$ = this, name;
@ -2517,6 +2217,308 @@
return i < config[__axis_x_categories].length ? config[__axis_x_categories][i] : i;
};
c3_chart_internal_fn.initEventRect = function () {
var $$ = this, CLASS = $$.CLASS;
$$.main.select('.' + CLASS[_chart]).append("g")
.attr("class", CLASS[_eventRects])
.style('fill-opacity', 0);
};
c3_chart_internal_fn.redrawEventRect = function () {
var $$ = this, config = $$.config, CLASS = $$.CLASS,
eventRectUpdate, maxDataCountTarget,
isMultipleX = $$.isMultipleX();
// rects for mouseover
var eventRects = $$.main.select('.' + CLASS[_eventRects])
.style('cursor', config[__zoom_enabled] ? config[__axis_rotated] ? 'ns-resize' : 'ew-resize' : null)
.classed(CLASS[_eventRectsMultiple], isMultipleX)
.classed(CLASS[_eventRectsSingle], !isMultipleX);
// clear old rects
eventRects.selectAll('.' + CLASS[_eventRect]).remove();
// open as public variable
$$.eventRect = eventRects.selectAll('.' + CLASS[_eventRect]);
if (isMultipleX) {
eventRectUpdate = $$.eventRect.data([0]);
// enter : only one rect will be added
$$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
// update
$$.updateEventRect(eventRectUpdate);
// exit : not needed because always only one rect exists
}
else {
// Set data and update $$.eventRect
maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
$$.eventRect = eventRects.selectAll('.' + CLASS[_eventRect]);
eventRectUpdate = $$.eventRect.data(function (d) { return d; });
// enter
$$.generateEventRectsForSingleX(eventRectUpdate.enter());
// update
$$.updateEventRect(eventRectUpdate);
// exit
eventRectUpdate.exit().remove();
}
};
c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
var $$ = this, config = $$.config,
x, y, w, h, rectW, rectX;
// set update selection if null
eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; });
if ($$.isMultipleX()) {
// TODO: rotated not supported yet
x = 0;
y = 0;
w = $$.width;
h = $$.height;
}
else {
if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
rectW = function (d) {
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index],
w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2;
return w < 0 ? 0 : w;
};
rectX = function (d) {
var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index];
return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2;
};
} else {
rectW = $$.getEventRectWidth();
rectX = function (d) {
return $$.x(d.x) - (rectW / 2);
};
}
x = config[__axis_rotated] ? 0 : rectX;
y = config[__axis_rotated] ? rectX : 0;
w = config[__axis_rotated] ? $$.width : rectW;
h = config[__axis_rotated] ? rectW : $$.height;
}
eventRectUpdate
.attr('class', $$.classEvent.bind($$))
.attr("x", x)
.attr("y", y)
.attr("width", w)
.attr("height", h);
};
c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
var $$ = this, d3 = $$.d3, config = $$.config;
eventRectEnter.append("rect")
.attr("class", generateCall($$.classEvent, $$))
.style("cursor", config[__data_selection_enabled] && config[__data_selection_grouped] ? "pointer" : null)
.on('mouseover', function (d) {
var index = d.index, selectedData, newData;
if ($$.dragging) { return; } // do nothing if dragging
if ($$.hasArcType()) { return; }
selectedData = $$.data.targets.map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
// Sort selectedData as names order
newData = [];
Object.keys(config[__data_names]).forEach(function (id) {
for (var j = 0; j < selectedData.length; j++) {
if (selectedData[j] && selectedData[j].id === id) {
newData.push(selectedData[j]);
selectedData.shift(j);
break;
}
}
});
selectedData = newData.concat(selectedData); // Add remained
// Expand shapes for selection
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index); }
$$.expandBars(index);
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseover].call(c3, d);
});
})
.on('mouseout', function (d) {
var index = d.index;
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
// Undo expanded shapes
$$.unexpandCircles(index);
$$.unexpandBars();
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseout].call($$, d);
});
})
.on('mousemove', function (d) {
var selectedData, index = d.index,
eventRect = $$.svg.select('.' + CLASS[_eventRect] + '-' + index);
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType()) { return; }
// Show tooltip
selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
if (config[__tooltip_grouped]) {
$$.showTooltip(selectedData, d3.mouse(this));
$$.showXGridFocus(selectedData);
}
if (config[__tooltip_grouped] && (!config[__data_selection_enabled] || config[__data_selection_grouped])) {
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index)
.each(function () {
d3.select(this).classed(CLASS[_EXPANDED], true);
if (config[__data_selection_enabled]) {
eventRect.style('cursor', config[__data_selection_grouped] ? 'pointer' : null);
}
if (!config[__tooltip_grouped]) {
$$.hideXGridFocus();
$$.hideTooltip();
if (!config[__data_selection_grouped]) {
$$.unexpandCircles(index);
$$.unexpandBars();
}
}
})
.filter(function (d) {
if (this.nodeName === 'circle') {
return $$.isWithinCircle(this, $$.pointSelectR(d));
}
else if (this.nodeName === 'path') {
return $$.isWithinBar(this);
}
})
.each(function (d) {
if (config[__data_selection_enabled] && (config[__data_selection_grouped] || config[__data_selection_isselectable](d))) {
eventRect.style('cursor', 'pointer');
}
if (!config[__tooltip_grouped]) {
$$.showTooltip([d], d3.mouse(this));
$$.showXGridFocus([d]);
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index, d.id); }
$$.expandBars(index, d.id);
}
});
})
.on('click', function (d) {
var index = d.index;
if ($$.hasArcType() || !$$.toggleShape) { return; }
if ($$.cancelClick) {
$$.cancelClick = false;
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
$$.toggleShape(this, d, index);
});
})
.call(
d3.behavior.drag().origin(Object)
.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;
eventRectEnter.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height)
.attr('class', CLASS[_eventRect])
.on('mouseout', function () {
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
})
.on('mousemove', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest, sameXData, selectedData;
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
if (! closest) { return; }
if ($$.isScatterType(closest)) {
sameXData = [closest];
} else {
sameXData = $$.filterSameX(targetsToShow, closest.x);
}
// show tooltip when cursor is close to some point
selectedData = sameXData.map(function (d) {
return $$.addName(d);
});
$$.showTooltip(selectedData, mouse);
// expand points
if (config[__point_focus_expand_enabled]) {
$$.unexpandCircles();
$$.expandCircles(closest.index, closest.id);
}
// Show xgrid focus line
$$.showXGridFocus(selectedData);
// Show cursor as pointer if point is close to mouse position
if ($$.dist(closest, mouse) < 100) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', 'pointer');
if (!$$.mouseover) {
config[__data_onmouseover].call($$, closest);
$$.mouseover = true;
}
} else if ($$.mouseover) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', null);
config[__data_onmouseout].call($$, closest);
$$.mouseover = false;
}
})
.on('click', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest;
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
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 () {
$$.toggleShape(this, closest, closest.index);
});
}
})
.call(
d3.behavior.drag().origin(Object)
.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.getCurrentWidth = function () {
var $$ = this, config = $$.config;
return config[__size_width] ? config[__size_width] : $$.getParentWidth();

6
c3.min.js vendored

File diff suppressed because one or more lines are too long

316
src/core.js

@ -127,7 +127,7 @@ c3_chart_internal_fn.initParams = function () {
c3_chart_internal_fn.initWithData = function (data) {
var $$ = this, d3 = $$.d3, config = $$.config;
var main, eventRect, binding = true;
var main, binding = true;
if ($$.initPie) { $$.initPie(); }
if ($$.initBrush) { $$.initBrush(); }
@ -220,9 +220,7 @@ c3_chart_internal_fn.initWithData = function (data) {
.attr('class', CLASS[_chart]);
// Cover whole with rects for events
eventRect = main.select('.' + CLASS[_chart]).append("g")
.attr("class", CLASS[_eventRects])
.style('fill-opacity', 0);
$$.initEventRect();
// Define g for bar chart area
if ($$.initBar) { $$.initBar(); }
@ -400,9 +398,7 @@ c3_chart_internal_fn.updateTargets = function (targets) {
c3_chart_internal_fn.redraw = function (options, transitions) {
var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
var eventRect, eventRectUpdate;
var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType), maxDataCountTarget;
var rectX, rectW;
var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withLegend;
var hideAxis = $$.hasArcType();
var drawArea, drawBar, drawLine, xForText, yForText;
@ -544,70 +540,9 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
.selectAll('circle')
.remove();
// event rect
if (config[__interaction_enabled]) {
// rect for mouseover
eventRect = main.select('.' + CLASS[_eventRects])
.style('cursor', config[__zoom_enabled] ? config[__axis_rotated] ? 'ns-resize' : 'ew-resize' : null);
if (notEmpty(config[__data_xs]) && !$$.isSingleX(config[__data_xs])) {
if (!eventRect.classed(CLASS[_eventRectsMultiple])) {
eventRect.classed(CLASS[_eventRectsMultiple], true).classed(CLASS[_eventRectsSingle], false)
.selectAll('.' + CLASS[_eventRect]).remove();
}
eventRectUpdate = main.select('.' + CLASS[_eventRects]).selectAll('.' + CLASS[_eventRect])
.data([0]);
// enter : only one rect will be added
$$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
// update
eventRectUpdate
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height);
// exit : not needed because always only one rect exists
} else {
if (!eventRect.classed(CLASS[_eventRectsSingle])) {
eventRect.classed(CLASS[_eventRectsMultiple], false).classed(CLASS[_eventRectsSingle], true)
.selectAll('.' + CLASS[_eventRect]).remove();
}
if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
rectW = function (d) {
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index],
w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2;
return w < 0 ? 0 : w;
};
rectX = function (d) {
var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index];
return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2;
};
} else {
rectW = $$.getEventRectWidth();
rectX = function (d) {
return $$.x(d.x) - (rectW / 2);
};
}
// Set data
maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
main.select('.' + CLASS[_eventRects])
.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
// Update rects
eventRectUpdate = main.select('.' + CLASS[_eventRects]).selectAll('.' + CLASS[_eventRect])
.data(function (d) { return d; });
// enter
$$.generateEventRectsForSingleX(eventRectUpdate.enter());
// update
eventRectUpdate
.attr('class', generateCall($$.classEvent, $$))
.attr("x", config[__axis_rotated] ? 0 : rectX)
.attr("y", config[__axis_rotated] ? rectX : 0)
.attr("width", config[__axis_rotated] ? $$.width : rectW)
.attr("height", config[__axis_rotated] ? rectW : $$.height);
// exit
eventRectUpdate.exit().remove();
}
$$.redrawEventRect();
}
// transition should be derived from one transition
@ -616,30 +551,8 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
$$.addTransitionForBar(transitions, drawBar);
$$.addTransitionForLine(transitions, drawLine);
/*
transitions.push(mainLine.transition()
.attr("d", drawLine)
.style("stroke", $$.color)
.style("opacity", 1));
*/
$$.addTransitionForArea(transitions, drawArea);
/*
transitions.push(mainArea.transition()
.attr("d", drawArea)
.style("fill", $$.color)
.style("opacity", $$.orgAreaOpacity));
*/
$$.addTransitionForCircle(transitions, cx, cy);
/*
transitions.push(mainCircle.transition()
.style('opacity', generateCall($$.opacityForCircle, $$))
.style("fill", $$.color)
.attr("cx", cx)
.attr("cy", cy));
transitions.push(main.selectAll('.' + CLASS[_selectedCircle]).transition()
.attr("cx", cx)
.attr("cy", cy));
*/
$$.addTransitionForText(transitions, xForText, yForText, options.flow);
$$.addTransitionForRegion(transitions);
$$.addTransitionForGrid(transitions);
@ -769,11 +682,7 @@ c3_chart_internal_fn.redraw = function (options, transitions) {
mainRegion.select('rect').filter($$.isRegionOnX)
.attr("x", generateCall($$.regionX, $$))
.attr("width", generateCall($$.regionWidth, $$));
eventRectUpdate
.attr("x", config[__axis_rotated] ? 0 : rectX)
.attr("y", config[__axis_rotated] ? rectX : 0)
.attr("width", config[__axis_rotated] ? $$.width : rectW)
.attr("height", config[__axis_rotated] ? rectW : $$.height);
$$.updateEventRect();
// callback for end of flow
done();
@ -815,219 +724,6 @@ c3_chart_internal_fn.updateAndRedraw = function (options) {
$$.redraw(options, transitions);
};
c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
var $$ = this, d3 = $$.d3, config = $$.config;
eventRectEnter.append("rect")
.attr("class", generateCall($$.classEvent, $$))
.style("cursor", config[__data_selection_enabled] && config[__data_selection_grouped] ? "pointer" : null)
.on('mouseover', function (d) {
var index = d.index, selectedData, newData;
if ($$.dragging) { return; } // do nothing if dragging
if ($$.hasArcType()) { return; }
selectedData = $$.data.targets.map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
// Sort selectedData as names order
newData = [];
Object.keys(config[__data_names]).forEach(function (id) {
for (var j = 0; j < selectedData.length; j++) {
if (selectedData[j] && selectedData[j].id === id) {
newData.push(selectedData[j]);
selectedData.shift(j);
break;
}
}
});
selectedData = newData.concat(selectedData); // Add remained
// Expand shapes for selection
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index); }
$$.expandBars(index);
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseover].call(c3, d);
});
})
.on('mouseout', function (d) {
var index = d.index;
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
// Undo expanded shapes
$$.unexpandCircles(index);
$$.unexpandBars();
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseout].call($$, d);
});
})
.on('mousemove', function (d) {
var selectedData, index = d.index,
eventRect = $$.svg.select('.' + CLASS[_eventRect] + '-' + index);
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType()) { return; }
// Show tooltip
selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
if (config[__tooltip_grouped]) {
$$.showTooltip(selectedData, d3.mouse(this));
$$.showXGridFocus(selectedData);
}
if (config[__tooltip_grouped] && (!config[__data_selection_enabled] || config[__data_selection_grouped])) {
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index)
.each(function () {
d3.select(this).classed(CLASS[_EXPANDED], true);
if (config[__data_selection_enabled]) {
eventRect.style('cursor', config[__data_selection_grouped] ? 'pointer' : null);
}
if (!config[__tooltip_grouped]) {
$$.hideXGridFocus();
$$.hideTooltip();
if (!config[__data_selection_grouped]) {
$$.unexpandCircles(index);
$$.unexpandBars();
}
}
})
.filter(function (d) {
if (this.nodeName === 'circle') {
return $$.isWithinCircle(this, $$.pointSelectR(d));
}
else if (this.nodeName === 'path') {
return $$.isWithinBar(this);
}
})
.each(function (d) {
if (config[__data_selection_enabled] && (config[__data_selection_grouped] || config[__data_selection_isselectable](d))) {
eventRect.style('cursor', 'pointer');
}
if (!config[__tooltip_grouped]) {
$$.showTooltip([d], d3.mouse(this));
$$.showXGridFocus([d]);
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index, d.id); }
$$.expandBars(index, d.id);
}
});
})
.on('click', function (d) {
var index = d.index;
if ($$.hasArcType() || !$$.toggleShape) { return; }
if ($$.cancelClick) {
$$.cancelClick = false;
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
$$.toggleShape(this, d, index);
});
})
.call(
d3.behavior.drag().origin(Object)
.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;
eventRectEnter.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height)
.attr('class', CLASS[_eventRect])
.on('mouseout', function () {
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
})
.on('mousemove', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest, sameXData, selectedData;
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
if (! closest) { return; }
if ($$.isScatterType(closest)) {
sameXData = [closest];
} else {
sameXData = $$.filterSameX(targetsToShow, closest.x);
}
// show tooltip when cursor is close to some point
selectedData = sameXData.map(function (d) {
return $$.addName(d);
});
$$.showTooltip(selectedData, mouse);
// expand points
if (config[__point_focus_expand_enabled]) {
$$.unexpandCircles();
$$.expandCircles(closest.index, closest.id);
}
// Show xgrid focus line
$$.showXGridFocus(selectedData);
// Show cursor as pointer if point is close to mouse position
if ($$.dist(closest, mouse) < 100) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', 'pointer');
if (!$$.mouseover) {
config[__data_onmouseover].call($$, closest);
$$.mouseover = true;
}
} else if ($$.mouseover) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', null);
config[__data_onmouseout].call($$, closest);
$$.mouseover = false;
}
})
.on('click', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest;
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
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 () {
$$.toggleShape(this, closest, closest.index);
});
}
})
.call(
d3.behavior.drag().origin(Object)
.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.isTimeSeries = function () {
return this.config[__axis_x_type] === 'timeseries';
};

8
src/data.js

@ -38,8 +38,12 @@ c3_chart_internal_fn.addXs = function (xs) {
$$.config[__data_xs][id] = xs[id];
});
};
c3_chart_internal_fn.isSingleX = function (xs) {
return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() === 1;
c3_chart_internal_fn.hasMultipleX = function (xs) {
return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1;
};
c3_chart_internal_fn.isMultipleX = function () {
var $$ = this, config = $$.config;
return notEmpty(config[__data_xs]) && $$.hasMultipleX(config[__data_xs]);
};
c3_chart_internal_fn.addName = function (data) {
var $$ = this, name;

301
src/interaction.js

@ -0,0 +1,301 @@
c3_chart_internal_fn.initEventRect = function () {
var $$ = this, CLASS = $$.CLASS;
$$.main.select('.' + CLASS[_chart]).append("g")
.attr("class", CLASS[_eventRects])
.style('fill-opacity', 0);
};
c3_chart_internal_fn.redrawEventRect = function () {
var $$ = this, config = $$.config, CLASS = $$.CLASS,
eventRectUpdate, maxDataCountTarget,
isMultipleX = $$.isMultipleX();
// rects for mouseover
var eventRects = $$.main.select('.' + CLASS[_eventRects])
.style('cursor', config[__zoom_enabled] ? config[__axis_rotated] ? 'ns-resize' : 'ew-resize' : null)
.classed(CLASS[_eventRectsMultiple], isMultipleX)
.classed(CLASS[_eventRectsSingle], !isMultipleX);
// clear old rects
eventRects.selectAll('.' + CLASS[_eventRect]).remove();
// open as public variable
$$.eventRect = eventRects.selectAll('.' + CLASS[_eventRect]);
if (isMultipleX) {
eventRectUpdate = $$.eventRect.data([0]);
// enter : only one rect will be added
$$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
// update
$$.updateEventRect(eventRectUpdate);
// exit : not needed because always only one rect exists
}
else {
// Set data and update $$.eventRect
maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
$$.eventRect = eventRects.selectAll('.' + CLASS[_eventRect]);
eventRectUpdate = $$.eventRect.data(function (d) { return d; });
// enter
$$.generateEventRectsForSingleX(eventRectUpdate.enter());
// update
$$.updateEventRect(eventRectUpdate);
// exit
eventRectUpdate.exit().remove();
}
};
c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
var $$ = this, config = $$.config,
x, y, w, h, rectW, rectX;
// set update selection if null
eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; });
if ($$.isMultipleX()) {
// TODO: rotated not supported yet
x = 0;
y = 0;
w = $$.width;
h = $$.height;
}
else {
if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
rectW = function (d) {
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), dx = $$.data.xs[d.id][d.index],
w = ($$.x(nextX ? nextX : dx) - $$.x(prevX ? prevX : dx)) / 2;
return w < 0 ? 0 : w;
};
rectX = function (d) {
var prevX = $$.getPrevX(d.index), dx = $$.data.xs[d.id][d.index];
return ($$.x(dx) + $$.x(prevX ? prevX : dx)) / 2;
};
} else {
rectW = $$.getEventRectWidth();
rectX = function (d) {
return $$.x(d.x) - (rectW / 2);
};
}
x = config[__axis_rotated] ? 0 : rectX;
y = config[__axis_rotated] ? rectX : 0;
w = config[__axis_rotated] ? $$.width : rectW;
h = config[__axis_rotated] ? rectW : $$.height;
}
eventRectUpdate
.attr('class', $$.classEvent.bind($$))
.attr("x", x)
.attr("y", y)
.attr("width", w)
.attr("height", h);
};
c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
var $$ = this, d3 = $$.d3, config = $$.config;
eventRectEnter.append("rect")
.attr("class", generateCall($$.classEvent, $$))
.style("cursor", config[__data_selection_enabled] && config[__data_selection_grouped] ? "pointer" : null)
.on('mouseover', function (d) {
var index = d.index, selectedData, newData;
if ($$.dragging) { return; } // do nothing if dragging
if ($$.hasArcType()) { return; }
selectedData = $$.data.targets.map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
// Sort selectedData as names order
newData = [];
Object.keys(config[__data_names]).forEach(function (id) {
for (var j = 0; j < selectedData.length; j++) {
if (selectedData[j] && selectedData[j].id === id) {
newData.push(selectedData[j]);
selectedData.shift(j);
break;
}
}
});
selectedData = newData.concat(selectedData); // Add remained
// Expand shapes for selection
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index); }
$$.expandBars(index);
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseover].call(c3, d);
});
})
.on('mouseout', function (d) {
var index = d.index;
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
// Undo expanded shapes
$$.unexpandCircles(index);
$$.unexpandBars();
// Call event handler
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
config[__data_onmouseout].call($$, d);
});
})
.on('mousemove', function (d) {
var selectedData, index = d.index,
eventRect = $$.svg.select('.' + CLASS[_eventRect] + '-' + index);
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType()) { return; }
// Show tooltip
selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
return $$.addName($$.getValueOnIndex(t.values, index));
});
if (config[__tooltip_grouped]) {
$$.showTooltip(selectedData, d3.mouse(this));
$$.showXGridFocus(selectedData);
}
if (config[__tooltip_grouped] && (!config[__data_selection_enabled] || config[__data_selection_grouped])) {
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index)
.each(function () {
d3.select(this).classed(CLASS[_EXPANDED], true);
if (config[__data_selection_enabled]) {
eventRect.style('cursor', config[__data_selection_grouped] ? 'pointer' : null);
}
if (!config[__tooltip_grouped]) {
$$.hideXGridFocus();
$$.hideTooltip();
if (!config[__data_selection_grouped]) {
$$.unexpandCircles(index);
$$.unexpandBars();
}
}
})
.filter(function (d) {
if (this.nodeName === 'circle') {
return $$.isWithinCircle(this, $$.pointSelectR(d));
}
else if (this.nodeName === 'path') {
return $$.isWithinBar(this);
}
})
.each(function (d) {
if (config[__data_selection_enabled] && (config[__data_selection_grouped] || config[__data_selection_isselectable](d))) {
eventRect.style('cursor', 'pointer');
}
if (!config[__tooltip_grouped]) {
$$.showTooltip([d], d3.mouse(this));
$$.showXGridFocus([d]);
if (config[__point_focus_expand_enabled]) { $$.expandCircles(index, d.id); }
$$.expandBars(index, d.id);
}
});
})
.on('click', function (d) {
var index = d.index;
if ($$.hasArcType() || !$$.toggleShape) { return; }
if ($$.cancelClick) {
$$.cancelClick = false;
return;
}
$$.main.selectAll('.' + CLASS[_shape] + '-' + index).each(function (d) {
$$.toggleShape(this, d, index);
});
})
.call(
d3.behavior.drag().origin(Object)
.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;
eventRectEnter.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', $$.width)
.attr('height', $$.height)
.attr('class', CLASS[_eventRect])
.on('mouseout', function () {
if ($$.hasArcType()) { return; }
$$.hideXGridFocus();
$$.hideTooltip();
$$.unexpandCircles();
})
.on('mousemove', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest, sameXData, selectedData;
if ($$.dragging) { return; } // do nothing when dragging
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
if (! closest) { return; }
if ($$.isScatterType(closest)) {
sameXData = [closest];
} else {
sameXData = $$.filterSameX(targetsToShow, closest.x);
}
// show tooltip when cursor is close to some point
selectedData = sameXData.map(function (d) {
return $$.addName(d);
});
$$.showTooltip(selectedData, mouse);
// expand points
if (config[__point_focus_expand_enabled]) {
$$.unexpandCircles();
$$.expandCircles(closest.index, closest.id);
}
// Show xgrid focus line
$$.showXGridFocus(selectedData);
// Show cursor as pointer if point is close to mouse position
if ($$.dist(closest, mouse) < 100) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', 'pointer');
if (!$$.mouseover) {
config[__data_onmouseover].call($$, closest);
$$.mouseover = true;
}
} else if ($$.mouseover) {
$$.svg.select('.' + CLASS[_eventRect]).style('cursor', null);
config[__data_onmouseout].call($$, closest);
$$.mouseover = false;
}
})
.on('click', function () {
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
var mouse, closest;
if ($$.hasArcType(targetsToShow)) { return; }
mouse = d3.mouse(this);
closest = $$.findClosestFromTargets(targetsToShow, mouse);
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 () {
$$.toggleShape(this, closest, closest.index);
});
}
})
.call(
d3.behavior.drag().origin(Object)
.on('drag', function () { $$.drag(d3.mouse(this)); })
.on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
.on('dragend', function () { $$.dragend(); })
)
.on("dblclick.zoom", null);
};
Loading…
Cancel
Save