1 |
38675
|
sandro.lab
|
(function (window) {
|
2 |
|
|
'use strict';
|
3 |
|
|
|
4 |
|
|
/*global define, module, exports, require */
|
5 |
|
|
|
6 |
|
|
var c3 = { version: "0.4.10" };
|
7 |
|
|
|
8 |
|
|
var c3_chart_fn,
|
9 |
|
|
c3_chart_internal_fn,
|
10 |
|
|
c3_chart_internal_axis_fn;
|
11 |
|
|
|
12 |
|
|
function API(owner) {
|
13 |
|
|
this.owner = owner;
|
14 |
|
|
}
|
15 |
|
|
|
16 |
|
|
function inherit(base, derived) {
|
17 |
|
|
|
18 |
|
|
if (Object.create) {
|
19 |
|
|
derived.prototype = Object.create(base.prototype);
|
20 |
|
|
} else {
|
21 |
|
|
var f = function f() {};
|
22 |
|
|
f.prototype = base.prototype;
|
23 |
|
|
derived.prototype = new f();
|
24 |
|
|
}
|
25 |
|
|
|
26 |
|
|
derived.prototype.constructor = derived;
|
27 |
|
|
|
28 |
|
|
return derived;
|
29 |
|
|
}
|
30 |
|
|
|
31 |
|
|
function Chart(config) {
|
32 |
|
|
var $$ = this.internal = new ChartInternal(this);
|
33 |
|
|
$$.loadConfig(config);
|
34 |
|
|
$$.init();
|
35 |
|
|
|
36 |
|
|
// bind "this" to nested API
|
37 |
|
|
(function bindThis(fn, target, argThis) {
|
38 |
|
|
Object.keys(fn).forEach(function (key) {
|
39 |
|
|
target[key] = fn[key].bind(argThis);
|
40 |
|
|
if (Object.keys(fn[key]).length > 0) {
|
41 |
|
|
bindThis(fn[key], target[key], argThis);
|
42 |
|
|
}
|
43 |
|
|
});
|
44 |
|
|
})(c3_chart_fn, this, this);
|
45 |
|
|
}
|
46 |
|
|
|
47 |
|
|
function ChartInternal(api) {
|
48 |
|
|
var $$ = this;
|
49 |
|
|
$$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
|
50 |
|
|
$$.api = api;
|
51 |
|
|
$$.config = $$.getDefaultConfig();
|
52 |
|
|
$$.data = {};
|
53 |
|
|
$$.cache = {};
|
54 |
|
|
$$.axes = {};
|
55 |
|
|
}
|
56 |
|
|
|
57 |
|
|
c3.generate = function (config) {
|
58 |
|
|
return new Chart(config);
|
59 |
|
|
};
|
60 |
|
|
|
61 |
|
|
c3.chart = {
|
62 |
|
|
fn: Chart.prototype,
|
63 |
|
|
internal: {
|
64 |
|
|
fn: ChartInternal.prototype,
|
65 |
|
|
axis: {
|
66 |
|
|
fn: Axis.prototype
|
67 |
|
|
}
|
68 |
|
|
}
|
69 |
|
|
};
|
70 |
|
|
c3_chart_fn = c3.chart.fn;
|
71 |
|
|
c3_chart_internal_fn = c3.chart.internal.fn;
|
72 |
|
|
c3_chart_internal_axis_fn = c3.chart.internal.axis.fn;
|
73 |
|
|
|
74 |
|
|
c3_chart_internal_fn.init = function () {
|
75 |
|
|
var $$ = this, config = $$.config;
|
76 |
|
|
|
77 |
|
|
$$.initParams();
|
78 |
|
|
|
79 |
|
|
if (config.data_url) {
|
80 |
|
|
$$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData);
|
81 |
|
|
}
|
82 |
|
|
else if (config.data_json) {
|
83 |
|
|
$$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
|
84 |
|
|
}
|
85 |
|
|
else if (config.data_rows) {
|
86 |
|
|
$$.initWithData($$.convertRowsToData(config.data_rows));
|
87 |
|
|
}
|
88 |
|
|
else if (config.data_columns) {
|
89 |
|
|
$$.initWithData($$.convertColumnsToData(config.data_columns));
|
90 |
|
|
}
|
91 |
|
|
else {
|
92 |
|
|
throw Error('url or json or rows or columns is required.');
|
93 |
|
|
}
|
94 |
|
|
};
|
95 |
|
|
|
96 |
|
|
c3_chart_internal_fn.initParams = function () {
|
97 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config;
|
98 |
|
|
|
99 |
|
|
// MEMO: clipId needs to be unique because it conflicts when multiple charts exist
|
100 |
|
|
$$.clipId = "c3-" + (+new Date()) + '-clip',
|
101 |
|
|
$$.clipIdForXAxis = $$.clipId + '-xaxis',
|
102 |
|
|
$$.clipIdForYAxis = $$.clipId + '-yaxis',
|
103 |
|
|
$$.clipIdForGrid = $$.clipId + '-grid',
|
104 |
|
|
$$.clipIdForSubchart = $$.clipId + '-subchart',
|
105 |
|
|
$$.clipPath = $$.getClipPath($$.clipId),
|
106 |
|
|
$$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis),
|
107 |
|
|
$$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
|
108 |
|
|
$$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid),
|
109 |
|
|
$$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart),
|
110 |
|
|
|
111 |
|
|
$$.dragStart = null;
|
112 |
|
|
$$.dragging = false;
|
113 |
|
|
$$.flowing = false;
|
114 |
|
|
$$.cancelClick = false;
|
115 |
|
|
$$.mouseover = false;
|
116 |
|
|
$$.transiting = false;
|
117 |
|
|
|
118 |
|
|
$$.color = $$.generateColor();
|
119 |
|
|
$$.levelColor = $$.generateLevelColor();
|
120 |
|
|
|
121 |
|
|
$$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc;
|
122 |
|
|
$$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc;
|
123 |
|
|
$$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([
|
124 |
|
|
[".%L", function (d) { return d.getMilliseconds(); }],
|
125 |
|
|
[":%S", function (d) { return d.getSeconds(); }],
|
126 |
|
|
["%I:%M", function (d) { return d.getMinutes(); }],
|
127 |
|
|
["%I %p", function (d) { return d.getHours(); }],
|
128 |
|
|
["%-m/%-d", function (d) { return d.getDay() && d.getDate() !== 1; }],
|
129 |
|
|
["%-m/%-d", function (d) { return d.getDate() !== 1; }],
|
130 |
|
|
["%-m/%-d", function (d) { return d.getMonth(); }],
|
131 |
|
|
["%Y/%-m/%-d", function () { return true; }]
|
132 |
|
|
]);
|
133 |
|
|
|
134 |
|
|
$$.hiddenTargetIds = [];
|
135 |
|
|
$$.hiddenLegendIds = [];
|
136 |
|
|
$$.focusedTargetIds = [];
|
137 |
|
|
$$.defocusedTargetIds = [];
|
138 |
|
|
|
139 |
|
|
$$.xOrient = config.axis_rotated ? "left" : "bottom";
|
140 |
|
|
$$.yOrient = config.axis_rotated ? (config.axis_y_inner ? "top" : "bottom") : (config.axis_y_inner ? "right" : "left");
|
141 |
|
|
$$.y2Orient = config.axis_rotated ? (config.axis_y2_inner ? "bottom" : "top") : (config.axis_y2_inner ? "left" : "right");
|
142 |
|
|
$$.subXOrient = config.axis_rotated ? "left" : "bottom";
|
143 |
|
|
|
144 |
|
|
$$.isLegendRight = config.legend_position === 'right';
|
145 |
|
|
$$.isLegendInset = config.legend_position === 'inset';
|
146 |
|
|
$$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right';
|
147 |
|
|
$$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left';
|
148 |
|
|
$$.legendStep = 0;
|
149 |
|
|
$$.legendItemWidth = 0;
|
150 |
|
|
$$.legendItemHeight = 0;
|
151 |
|
|
|
152 |
|
|
$$.currentMaxTickWidths = {
|
153 |
|
|
x: 0,
|
154 |
|
|
y: 0,
|
155 |
|
|
y2: 0
|
156 |
|
|
};
|
157 |
|
|
|
158 |
|
|
$$.rotated_padding_left = 30;
|
159 |
|
|
$$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
|
160 |
|
|
$$.rotated_padding_top = 5;
|
161 |
|
|
|
162 |
|
|
$$.withoutFadeIn = {};
|
163 |
|
|
|
164 |
|
|
$$.intervalForObserveInserted = undefined;
|
165 |
|
|
|
166 |
|
|
$$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
|
167 |
|
|
};
|
168 |
|
|
|
169 |
|
|
c3_chart_internal_fn.initChartElements = function () {
|
170 |
|
|
if (this.initBar) { this.initBar(); }
|
171 |
|
|
if (this.initLine) { this.initLine(); }
|
172 |
|
|
if (this.initArc) { this.initArc(); }
|
173 |
|
|
if (this.initGauge) { this.initGauge(); }
|
174 |
|
|
if (this.initText) { this.initText(); }
|
175 |
|
|
};
|
176 |
|
|
|
177 |
|
|
c3_chart_internal_fn.initWithData = function (data) {
|
178 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config;
|
179 |
|
|
var defs, main, binding = true;
|
180 |
|
|
|
181 |
|
|
$$.axis = new Axis($$);
|
182 |
|
|
|
183 |
|
|
if ($$.initPie) { $$.initPie(); }
|
184 |
|
|
if ($$.initBrush) { $$.initBrush(); }
|
185 |
|
|
if ($$.initZoom) { $$.initZoom(); }
|
186 |
|
|
|
187 |
|
|
if (!config.bindto) {
|
188 |
|
|
$$.selectChart = d3.selectAll([]);
|
189 |
|
|
}
|
190 |
|
|
else if (typeof config.bindto.node === 'function') {
|
191 |
|
|
$$.selectChart = config.bindto;
|
192 |
|
|
}
|
193 |
|
|
else {
|
194 |
|
|
$$.selectChart = d3.select(config.bindto);
|
195 |
|
|
}
|
196 |
|
|
if ($$.selectChart.empty()) {
|
197 |
|
|
$$.selectChart = d3.select(document.createElement('div')).style('opacity', 0);
|
198 |
|
|
$$.observeInserted($$.selectChart);
|
199 |
|
|
binding = false;
|
200 |
|
|
}
|
201 |
|
|
$$.selectChart.html("").classed("c3", true);
|
202 |
|
|
|
203 |
|
|
// Init data as targets
|
204 |
|
|
$$.data.xs = {};
|
205 |
|
|
$$.data.targets = $$.convertDataToTargets(data);
|
206 |
|
|
|
207 |
|
|
if (config.data_filter) {
|
208 |
|
|
$$.data.targets = $$.data.targets.filter(config.data_filter);
|
209 |
|
|
}
|
210 |
|
|
|
211 |
|
|
// Set targets to hide if needed
|
212 |
|
|
if (config.data_hide) {
|
213 |
|
|
$$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide);
|
214 |
|
|
}
|
215 |
|
|
if (config.legend_hide) {
|
216 |
|
|
$$.addHiddenLegendIds(config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide);
|
217 |
|
|
}
|
218 |
|
|
|
219 |
|
|
// when gauge, hide legend // TODO: fix
|
220 |
|
|
if ($$.hasType('gauge')) {
|
221 |
|
|
config.legend_show = false;
|
222 |
|
|
}
|
223 |
|
|
|
224 |
|
|
// Init sizes and scales
|
225 |
|
|
$$.updateSizes();
|
226 |
|
|
$$.updateScales();
|
227 |
|
|
|
228 |
|
|
// Set domains for each scale
|
229 |
|
|
$$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
|
230 |
|
|
$$.y.domain($$.getYDomain($$.data.targets, 'y'));
|
231 |
|
|
$$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
|
232 |
|
|
$$.subX.domain($$.x.domain());
|
233 |
|
|
$$.subY.domain($$.y.domain());
|
234 |
|
|
$$.subY2.domain($$.y2.domain());
|
235 |
|
|
|
236 |
|
|
// Save original x domain for zoom update
|
237 |
|
|
$$.orgXDomain = $$.x.domain();
|
238 |
|
|
|
239 |
|
|
// Set initialized scales to brush and zoom
|
240 |
|
|
if ($$.brush) { $$.brush.scale($$.subX); }
|
241 |
|
|
if (config.zoom_enabled) { $$.zoom.scale($$.x); }
|
242 |
|
|
|
243 |
|
|
/*-- Basic Elements --*/
|
244 |
|
|
|
245 |
|
|
// Define svgs
|
246 |
|
|
$$.svg = $$.selectChart.append("svg")
|
247 |
|
|
.style("overflow", "hidden")
|
248 |
|
|
.on('mouseenter', function () { return config.onmouseover.call($$); })
|
249 |
|
|
.on('mouseleave', function () { return config.onmouseout.call($$); });
|
250 |
|
|
|
251 |
|
|
// Define defs
|
252 |
|
|
defs = $$.svg.append("defs");
|
253 |
|
|
$$.clipChart = $$.appendClip(defs, $$.clipId);
|
254 |
|
|
$$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
|
255 |
|
|
$$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
|
256 |
|
|
$$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
|
257 |
|
|
$$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
|
258 |
|
|
$$.updateSvgSize();
|
259 |
|
|
|
260 |
|
|
// Define regions
|
261 |
|
|
main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main'));
|
262 |
|
|
|
263 |
|
|
if ($$.initSubchart) { $$.initSubchart(); }
|
264 |
|
|
if ($$.initTooltip) { $$.initTooltip(); }
|
265 |
|
|
if ($$.initLegend) { $$.initLegend(); }
|
266 |
|
|
|
267 |
|
|
/*-- Main Region --*/
|
268 |
|
|
|
269 |
|
|
// text when empty
|
270 |
|
|
main.append("text")
|
271 |
|
|
.attr("class", CLASS.text + ' ' + CLASS.empty)
|
272 |
|
|
.attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers.
|
273 |
|
|
.attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE.
|
274 |
|
|
|
275 |
|
|
// Regions
|
276 |
|
|
$$.initRegion();
|
277 |
|
|
|
278 |
|
|
// Grids
|
279 |
|
|
$$.initGrid();
|
280 |
|
|
|
281 |
|
|
// Define g for chart area
|
282 |
|
|
main.append('g')
|
283 |
|
|
.attr("clip-path", $$.clipPath)
|
284 |
|
|
.attr('class', CLASS.chart);
|
285 |
|
|
|
286 |
|
|
// Grid lines
|
287 |
|
|
if (config.grid_lines_front) { $$.initGridLines(); }
|
288 |
|
|
|
289 |
|
|
// Cover whole with rects for events
|
290 |
|
|
$$.initEventRect();
|
291 |
|
|
|
292 |
|
|
// Define g for chart
|
293 |
|
|
$$.initChartElements();
|
294 |
|
|
|
295 |
|
|
// if zoom privileged, insert rect to forefront
|
296 |
|
|
// TODO: is this needed?
|
297 |
|
|
main.insert('rect', config.zoom_privileged ? null : 'g.' + CLASS.regions)
|
298 |
|
|
.attr('class', CLASS.zoomRect)
|
299 |
|
|
.attr('width', $$.width)
|
300 |
|
|
.attr('height', $$.height)
|
301 |
|
|
.style('opacity', 0)
|
302 |
|
|
.on("dblclick.zoom", null);
|
303 |
|
|
|
304 |
|
|
// Set default extent if defined
|
305 |
|
|
if (config.axis_x_extent) { $$.brush.extent($$.getDefaultExtent()); }
|
306 |
|
|
|
307 |
|
|
// Add Axis
|
308 |
|
|
$$.axis.init();
|
309 |
|
|
|
310 |
|
|
// Set targets
|
311 |
|
|
$$.updateTargets($$.data.targets);
|
312 |
|
|
|
313 |
|
|
// Draw with targets
|
314 |
|
|
if (binding) {
|
315 |
|
|
$$.updateDimension();
|
316 |
|
|
$$.config.oninit.call($$);
|
317 |
|
|
$$.redraw({
|
318 |
|
|
withTransition: false,
|
319 |
|
|
withTransform: true,
|
320 |
|
|
withUpdateXDomain: true,
|
321 |
|
|
withUpdateOrgXDomain: true,
|
322 |
|
|
withTransitionForAxis: false
|
323 |
|
|
});
|
324 |
|
|
}
|
325 |
|
|
|
326 |
|
|
// Bind resize event
|
327 |
|
|
if (window.onresize == null) {
|
328 |
|
|
window.onresize = $$.generateResize();
|
329 |
|
|
}
|
330 |
|
|
if (window.onresize.add) {
|
331 |
|
|
window.onresize.add(function () {
|
332 |
|
|
config.onresize.call($$);
|
333 |
|
|
});
|
334 |
|
|
window.onresize.add(function () {
|
335 |
|
|
$$.api.flush();
|
336 |
|
|
});
|
337 |
|
|
window.onresize.add(function () {
|
338 |
|
|
config.onresized.call($$);
|
339 |
|
|
});
|
340 |
|
|
}
|
341 |
|
|
|
342 |
|
|
// export element of the chart
|
343 |
|
|
$$.api.element = $$.selectChart.node();
|
344 |
|
|
};
|
345 |
|
|
|
346 |
|
|
c3_chart_internal_fn.smoothLines = function (el, type) {
|
347 |
|
|
var $$ = this;
|
348 |
|
|
if (type === 'grid') {
|
349 |
|
|
el.each(function () {
|
350 |
|
|
var g = $$.d3.select(this),
|
351 |
|
|
x1 = g.attr('x1'),
|
352 |
|
|
x2 = g.attr('x2'),
|
353 |
|
|
y1 = g.attr('y1'),
|
354 |
|
|
y2 = g.attr('y2');
|
355 |
|
|
g.attr({
|
356 |
|
|
'x1': Math.ceil(x1),
|
357 |
|
|
'x2': Math.ceil(x2),
|
358 |
|
|
'y1': Math.ceil(y1),
|
359 |
|
|
'y2': Math.ceil(y2)
|
360 |
|
|
});
|
361 |
|
|
});
|
362 |
|
|
}
|
363 |
|
|
};
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
c3_chart_internal_fn.updateSizes = function () {
|
367 |
|
|
var $$ = this, config = $$.config;
|
368 |
|
|
var legendHeight = $$.legend ? $$.getLegendHeight() : 0,
|
369 |
|
|
legendWidth = $$.legend ? $$.getLegendWidth() : 0,
|
370 |
|
|
legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight,
|
371 |
|
|
hasArc = $$.hasArcType(),
|
372 |
|
|
xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
|
373 |
|
|
subchartHeight = config.subchart_show && !hasArc ? (config.subchart_size_height + xAxisHeight) : 0;
|
374 |
|
|
|
375 |
|
|
$$.currentWidth = $$.getCurrentWidth();
|
376 |
|
|
$$.currentHeight = $$.getCurrentHeight();
|
377 |
|
|
|
378 |
|
|
// for main
|
379 |
|
|
$$.margin = config.axis_rotated ? {
|
380 |
|
|
top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
|
381 |
|
|
right: hasArc ? 0 : $$.getCurrentPaddingRight(),
|
382 |
|
|
bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(),
|
383 |
|
|
left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
|
384 |
|
|
} : {
|
385 |
|
|
top: 4 + $$.getCurrentPaddingTop(), // for top tick text
|
386 |
|
|
right: hasArc ? 0 : $$.getCurrentPaddingRight(),
|
387 |
|
|
bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),
|
388 |
|
|
left: hasArc ? 0 : $$.getCurrentPaddingLeft()
|
389 |
|
|
};
|
390 |
|
|
|
391 |
|
|
// for subchart
|
392 |
|
|
$$.margin2 = config.axis_rotated ? {
|
393 |
|
|
top: $$.margin.top,
|
394 |
|
|
right: NaN,
|
395 |
|
|
bottom: 20 + legendHeightForBottom,
|
396 |
|
|
left: $$.rotated_padding_left
|
397 |
|
|
} : {
|
398 |
|
|
top: $$.currentHeight - subchartHeight - legendHeightForBottom,
|
399 |
|
|
right: NaN,
|
400 |
|
|
bottom: xAxisHeight + legendHeightForBottom,
|
401 |
|
|
left: $$.margin.left
|
402 |
|
|
};
|
403 |
|
|
|
404 |
|
|
// for legend
|
405 |
|
|
$$.margin3 = {
|
406 |
|
|
top: 0,
|
407 |
|
|
right: NaN,
|
408 |
|
|
bottom: 0,
|
409 |
|
|
left: 0
|
410 |
|
|
};
|
411 |
|
|
if ($$.updateSizeForLegend) { $$.updateSizeForLegend(legendHeight, legendWidth); }
|
412 |
|
|
|
413 |
|
|
$$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
|
414 |
|
|
$$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
|
415 |
|
|
if ($$.width < 0) { $$.width = 0; }
|
416 |
|
|
if ($$.height < 0) { $$.height = 0; }
|
417 |
|
|
|
418 |
|
|
$$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;
|
419 |
|
|
$$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
|
420 |
|
|
if ($$.width2 < 0) { $$.width2 = 0; }
|
421 |
|
|
if ($$.height2 < 0) { $$.height2 = 0; }
|
422 |
|
|
|
423 |
|
|
// for arc
|
424 |
|
|
$$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
|
425 |
|
|
$$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
|
426 |
|
|
if ($$.hasType('gauge')) {
|
427 |
|
|
$$.arcHeight += $$.height - $$.getGaugeLabelHeight();
|
428 |
|
|
}
|
429 |
|
|
if ($$.updateRadius) { $$.updateRadius(); }
|
430 |
|
|
|
431 |
|
|
if ($$.isLegendRight && hasArc) {
|
432 |
|
|
$$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
|
433 |
|
|
}
|
434 |
|
|
};
|
435 |
|
|
|
436 |
|
|
c3_chart_internal_fn.updateTargets = function (targets) {
|
437 |
|
|
var $$ = this;
|
438 |
|
|
|
439 |
|
|
/*-- Main --*/
|
440 |
|
|
|
441 |
|
|
//-- Text --//
|
442 |
|
|
$$.updateTargetsForText(targets);
|
443 |
|
|
|
444 |
|
|
//-- Bar --//
|
445 |
|
|
$$.updateTargetsForBar(targets);
|
446 |
|
|
|
447 |
|
|
//-- Line --//
|
448 |
|
|
$$.updateTargetsForLine(targets);
|
449 |
|
|
|
450 |
|
|
//-- Arc --//
|
451 |
|
|
if ($$.hasArcType() && $$.updateTargetsForArc) { $$.updateTargetsForArc(targets); }
|
452 |
|
|
|
453 |
|
|
/*-- Sub --*/
|
454 |
|
|
|
455 |
|
|
if ($$.updateTargetsForSubchart) { $$.updateTargetsForSubchart(targets); }
|
456 |
|
|
|
457 |
|
|
// Fade-in each chart
|
458 |
|
|
$$.showTargets();
|
459 |
|
|
};
|
460 |
|
|
c3_chart_internal_fn.showTargets = function () {
|
461 |
|
|
var $$ = this;
|
462 |
|
|
$$.svg.selectAll('.' + CLASS.target).filter(function (d) { return $$.isTargetToShow(d.id); })
|
463 |
|
|
.transition().duration($$.config.transition_duration)
|
464 |
|
|
.style("opacity", 1);
|
465 |
|
|
};
|
466 |
|
|
|
467 |
|
|
c3_chart_internal_fn.redraw = function (options, transitions) {
|
468 |
|
|
var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
|
469 |
|
|
var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
|
470 |
|
|
var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis,
|
471 |
|
|
withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend,
|
472 |
|
|
withEventRect, withDimension, withUpdateXAxis;
|
473 |
|
|
var hideAxis = $$.hasArcType();
|
474 |
|
|
var drawArea, drawBar, drawLine, xForText, yForText;
|
475 |
|
|
var duration, durationForExit, durationForAxis;
|
476 |
|
|
var waitForDraw, flow;
|
477 |
|
|
var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling, xDomainForZoom;
|
478 |
|
|
var xv = $$.xv.bind($$), cx, cy;
|
479 |
|
|
|
480 |
|
|
options = options || {};
|
481 |
|
|
withY = getOption(options, "withY", true);
|
482 |
|
|
withSubchart = getOption(options, "withSubchart", true);
|
483 |
|
|
withTransition = getOption(options, "withTransition", true);
|
484 |
|
|
withTransform = getOption(options, "withTransform", false);
|
485 |
|
|
withUpdateXDomain = getOption(options, "withUpdateXDomain", false);
|
486 |
|
|
withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false);
|
487 |
|
|
withTrimXDomain = getOption(options, "withTrimXDomain", true);
|
488 |
|
|
withUpdateXAxis = getOption(options, "withUpdateXAxis", withUpdateXDomain);
|
489 |
|
|
withLegend = getOption(options, "withLegend", false);
|
490 |
|
|
withEventRect = getOption(options, "withEventRect", true);
|
491 |
|
|
withDimension = getOption(options, "withDimension", true);
|
492 |
|
|
withTransitionForExit = getOption(options, "withTransitionForExit", withTransition);
|
493 |
|
|
withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition);
|
494 |
|
|
|
495 |
|
|
duration = withTransition ? config.transition_duration : 0;
|
496 |
|
|
durationForExit = withTransitionForExit ? duration : 0;
|
497 |
|
|
durationForAxis = withTransitionForAxis ? duration : 0;
|
498 |
|
|
|
499 |
|
|
transitions = transitions || $$.axis.generateTransitions(durationForAxis);
|
500 |
|
|
|
501 |
|
|
// update legend and transform each g
|
502 |
|
|
if (withLegend && config.legend_show) {
|
503 |
|
|
$$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
|
504 |
|
|
} else if (withDimension) {
|
505 |
|
|
// need to update dimension (e.g. axis.y.tick.values) because y tick values should change
|
506 |
|
|
// no need to update axis in it because they will be updated in redraw()
|
507 |
|
|
$$.updateDimension(true);
|
508 |
|
|
}
|
509 |
|
|
|
510 |
|
|
// MEMO: needed for grids calculation
|
511 |
|
|
if ($$.isCategorized() && targetsToShow.length === 0) {
|
512 |
|
|
$$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
|
513 |
|
|
}
|
514 |
|
|
|
515 |
|
|
if (targetsToShow.length) {
|
516 |
|
|
$$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
|
517 |
|
|
if (!config.axis_x_tick_values) {
|
518 |
|
|
tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
|
519 |
|
|
}
|
520 |
|
|
} else {
|
521 |
|
|
$$.xAxis.tickValues([]);
|
522 |
|
|
$$.subXAxis.tickValues([]);
|
523 |
|
|
}
|
524 |
|
|
|
525 |
|
|
if (config.zoom_rescale && !options.flow) {
|
526 |
|
|
xDomainForZoom = $$.x.orgDomain();
|
527 |
|
|
}
|
528 |
|
|
|
529 |
|
|
$$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
|
530 |
|
|
$$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
|
531 |
|
|
|
532 |
|
|
if (!config.axis_y_tick_values && config.axis_y_tick_count) {
|
533 |
|
|
$$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
|
534 |
|
|
}
|
535 |
|
|
if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
|
536 |
|
|
$$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
|
537 |
|
|
}
|
538 |
|
|
|
539 |
|
|
// axes
|
540 |
|
|
$$.axis.redraw(transitions, hideAxis);
|
541 |
|
|
|
542 |
|
|
// Update axis label
|
543 |
|
|
$$.axis.updateLabels(withTransition);
|
544 |
|
|
|
545 |
|
|
// show/hide if manual culling needed
|
546 |
|
|
if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
|
547 |
|
|
if (config.axis_x_tick_culling && tickValues) {
|
548 |
|
|
for (i = 1; i < tickValues.length; i++) {
|
549 |
|
|
if (tickValues.length / i < config.axis_x_tick_culling_max) {
|
550 |
|
|
intervalForCulling = i;
|
551 |
|
|
break;
|
552 |
|
|
}
|
553 |
|
|
}
|
554 |
|
|
$$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
|
555 |
|
|
var index = tickValues.indexOf(e);
|
556 |
|
|
if (index >= 0) {
|
557 |
|
|
d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
|
558 |
|
|
}
|
559 |
|
|
});
|
560 |
|
|
} else {
|
561 |
|
|
$$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block');
|
562 |
|
|
}
|
563 |
|
|
}
|
564 |
|
|
|
565 |
|
|
// setup drawer - MEMO: these must be called after axis updated
|
566 |
|
|
drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
|
567 |
|
|
drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
|
568 |
|
|
drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
|
569 |
|
|
xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
|
570 |
|
|
yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
|
571 |
|
|
|
572 |
|
|
// Update sub domain
|
573 |
|
|
if (withY) {
|
574 |
|
|
$$.subY.domain($$.getYDomain(targetsToShow, 'y'));
|
575 |
|
|
$$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
|
576 |
|
|
}
|
577 |
|
|
|
578 |
|
|
// tooltip
|
579 |
|
|
$$.tooltip.style("display", "none");
|
580 |
|
|
|
581 |
|
|
// xgrid focus
|
582 |
|
|
$$.updateXgridFocus();
|
583 |
|
|
|
584 |
|
|
// Data empty label positioning and text.
|
585 |
|
|
main.select("text." + CLASS.text + '.' + CLASS.empty)
|
586 |
|
|
.attr("x", $$.width / 2)
|
587 |
|
|
.attr("y", $$.height / 2)
|
588 |
|
|
.text(config.data_empty_label_text)
|
589 |
|
|
.transition()
|
590 |
|
|
.style('opacity', targetsToShow.length ? 0 : 1);
|
591 |
|
|
|
592 |
|
|
// grid
|
593 |
|
|
$$.updateGrid(duration);
|
594 |
|
|
|
595 |
|
|
// rect for regions
|
596 |
|
|
$$.updateRegion(duration);
|
597 |
|
|
|
598 |
|
|
// bars
|
599 |
|
|
$$.updateBar(durationForExit);
|
600 |
|
|
|
601 |
|
|
// lines, areas and cricles
|
602 |
|
|
$$.updateLine(durationForExit);
|
603 |
|
|
$$.updateArea(durationForExit);
|
604 |
|
|
$$.updateCircle();
|
605 |
|
|
|
606 |
|
|
// text
|
607 |
|
|
if ($$.hasDataLabel()) {
|
608 |
|
|
$$.updateText(durationForExit);
|
609 |
|
|
}
|
610 |
|
|
|
611 |
|
|
// arc
|
612 |
|
|
if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); }
|
613 |
|
|
|
614 |
|
|
// subchart
|
615 |
|
|
if ($$.redrawSubchart) {
|
616 |
|
|
$$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
|
617 |
|
|
}
|
618 |
|
|
|
619 |
|
|
// circles for select
|
620 |
|
|
main.selectAll('.' + CLASS.selectedCircles)
|
621 |
|
|
.filter($$.isBarType.bind($$))
|
622 |
|
|
.selectAll('circle')
|
623 |
|
|
.remove();
|
624 |
|
|
|
625 |
|
|
// event rects will redrawn when flow called
|
626 |
|
|
if (config.interaction_enabled && !options.flow && withEventRect) {
|
627 |
|
|
$$.redrawEventRect();
|
628 |
|
|
if ($$.updateZoom) { $$.updateZoom(); }
|
629 |
|
|
}
|
630 |
|
|
|
631 |
|
|
// update circleY based on updated parameters
|
632 |
|
|
$$.updateCircleY();
|
633 |
|
|
|
634 |
|
|
// generate circle x/y functions depending on updated params
|
635 |
|
|
cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
|
636 |
|
|
cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
|
637 |
|
|
|
638 |
|
|
if (options.flow) {
|
639 |
|
|
flow = $$.generateFlow({
|
640 |
|
|
targets: targetsToShow,
|
641 |
|
|
flow: options.flow,
|
642 |
|
|
duration: options.flow.duration,
|
643 |
|
|
drawBar: drawBar,
|
644 |
|
|
drawLine: drawLine,
|
645 |
|
|
drawArea: drawArea,
|
646 |
|
|
cx: cx,
|
647 |
|
|
cy: cy,
|
648 |
|
|
xv: xv,
|
649 |
|
|
xForText: xForText,
|
650 |
|
|
yForText: yForText
|
651 |
|
|
});
|
652 |
|
|
}
|
653 |
|
|
|
654 |
|
|
if ((duration || flow) && $$.isTabVisible()) { // Only use transition if tab visible. See #938.
|
655 |
|
|
// transition should be derived from one transition
|
656 |
|
|
d3.transition().duration(duration).each(function () {
|
657 |
|
|
var transitionsToWait = [];
|
658 |
|
|
|
659 |
|
|
// redraw and gather transitions
|
660 |
|
|
[
|
661 |
|
|
$$.redrawBar(drawBar, true),
|
662 |
|
|
$$.redrawLine(drawLine, true),
|
663 |
|
|
$$.redrawArea(drawArea, true),
|
664 |
|
|
$$.redrawCircle(cx, cy, true),
|
665 |
|
|
$$.redrawText(xForText, yForText, options.flow, true),
|
666 |
|
|
$$.redrawRegion(true),
|
667 |
|
|
$$.redrawGrid(true),
|
668 |
|
|
].forEach(function (transitions) {
|
669 |
|
|
transitions.forEach(function (transition) {
|
670 |
|
|
transitionsToWait.push(transition);
|
671 |
|
|
});
|
672 |
|
|
});
|
673 |
|
|
|
674 |
|
|
// Wait for end of transitions to call flow and onrendered callback
|
675 |
|
|
waitForDraw = $$.generateWait();
|
676 |
|
|
transitionsToWait.forEach(function (t) {
|
677 |
|
|
waitForDraw.add(t);
|
678 |
|
|
});
|
679 |
|
|
})
|
680 |
|
|
.call(waitForDraw, function () {
|
681 |
|
|
if (flow) {
|
682 |
|
|
flow();
|
683 |
|
|
}
|
684 |
|
|
if (config.onrendered) {
|
685 |
|
|
config.onrendered.call($$);
|
686 |
|
|
}
|
687 |
|
|
});
|
688 |
|
|
}
|
689 |
|
|
else {
|
690 |
|
|
$$.redrawBar(drawBar);
|
691 |
|
|
$$.redrawLine(drawLine);
|
692 |
|
|
$$.redrawArea(drawArea);
|
693 |
|
|
$$.redrawCircle(cx, cy);
|
694 |
|
|
$$.redrawText(xForText, yForText, options.flow);
|
695 |
|
|
$$.redrawRegion();
|
696 |
|
|
$$.redrawGrid();
|
697 |
|
|
if (config.onrendered) {
|
698 |
|
|
config.onrendered.call($$);
|
699 |
|
|
}
|
700 |
|
|
}
|
701 |
|
|
|
702 |
|
|
// update fadein condition
|
703 |
|
|
$$.mapToIds($$.data.targets).forEach(function (id) {
|
704 |
|
|
$$.withoutFadeIn[id] = true;
|
705 |
|
|
});
|
706 |
|
|
};
|
707 |
|
|
|
708 |
|
|
c3_chart_internal_fn.updateAndRedraw = function (options) {
|
709 |
|
|
var $$ = this, config = $$.config, transitions;
|
710 |
|
|
options = options || {};
|
711 |
|
|
// same with redraw
|
712 |
|
|
options.withTransition = getOption(options, "withTransition", true);
|
713 |
|
|
options.withTransform = getOption(options, "withTransform", false);
|
714 |
|
|
options.withLegend = getOption(options, "withLegend", false);
|
715 |
|
|
// NOT same with redraw
|
716 |
|
|
options.withUpdateXDomain = true;
|
717 |
|
|
options.withUpdateOrgXDomain = true;
|
718 |
|
|
options.withTransitionForExit = false;
|
719 |
|
|
options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition);
|
720 |
|
|
// MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
|
721 |
|
|
$$.updateSizes();
|
722 |
|
|
// MEMO: called in updateLegend in redraw if withLegend
|
723 |
|
|
if (!(options.withLegend && config.legend_show)) {
|
724 |
|
|
transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
|
725 |
|
|
// Update scales
|
726 |
|
|
$$.updateScales();
|
727 |
|
|
$$.updateSvgSize();
|
728 |
|
|
// Update g positions
|
729 |
|
|
$$.transformAll(options.withTransitionForTransform, transitions);
|
730 |
|
|
}
|
731 |
|
|
// Draw with new sizes & scales
|
732 |
|
|
$$.redraw(options, transitions);
|
733 |
|
|
};
|
734 |
|
|
c3_chart_internal_fn.redrawWithoutRescale = function () {
|
735 |
|
|
this.redraw({
|
736 |
|
|
withY: false,
|
737 |
|
|
withSubchart: false,
|
738 |
|
|
withEventRect: false,
|
739 |
|
|
withTransitionForAxis: false
|
740 |
|
|
});
|
741 |
|
|
};
|
742 |
|
|
|
743 |
|
|
c3_chart_internal_fn.isTimeSeries = function () {
|
744 |
|
|
return this.config.axis_x_type === 'timeseries';
|
745 |
|
|
};
|
746 |
|
|
c3_chart_internal_fn.isCategorized = function () {
|
747 |
|
|
return this.config.axis_x_type.indexOf('categor') >= 0;
|
748 |
|
|
};
|
749 |
|
|
c3_chart_internal_fn.isCustomX = function () {
|
750 |
|
|
var $$ = this, config = $$.config;
|
751 |
|
|
return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
|
752 |
|
|
};
|
753 |
|
|
|
754 |
|
|
c3_chart_internal_fn.isTimeSeriesY = function () {
|
755 |
|
|
return this.config.axis_y_type === 'timeseries';
|
756 |
|
|
};
|
757 |
|
|
|
758 |
|
|
c3_chart_internal_fn.getTranslate = function (target) {
|
759 |
|
|
var $$ = this, config = $$.config, x, y;
|
760 |
|
|
if (target === 'main') {
|
761 |
|
|
x = asHalfPixel($$.margin.left);
|
762 |
|
|
y = asHalfPixel($$.margin.top);
|
763 |
|
|
} else if (target === 'context') {
|
764 |
|
|
x = asHalfPixel($$.margin2.left);
|
765 |
|
|
y = asHalfPixel($$.margin2.top);
|
766 |
|
|
} else if (target === 'legend') {
|
767 |
|
|
x = $$.margin3.left;
|
768 |
|
|
y = $$.margin3.top;
|
769 |
|
|
} else if (target === 'x') {
|
770 |
|
|
x = 0;
|
771 |
|
|
y = config.axis_rotated ? 0 : $$.height;
|
772 |
|
|
} else if (target === 'y') {
|
773 |
|
|
x = 0;
|
774 |
|
|
y = config.axis_rotated ? $$.height : 0;
|
775 |
|
|
} else if (target === 'y2') {
|
776 |
|
|
x = config.axis_rotated ? 0 : $$.width;
|
777 |
|
|
y = config.axis_rotated ? 1 : 0;
|
778 |
|
|
} else if (target === 'subx') {
|
779 |
|
|
x = 0;
|
780 |
|
|
y = config.axis_rotated ? 0 : $$.height2;
|
781 |
|
|
} else if (target === 'arc') {
|
782 |
|
|
x = $$.arcWidth / 2;
|
783 |
|
|
y = $$.arcHeight / 2;
|
784 |
|
|
}
|
785 |
|
|
return "translate(" + x + "," + y + ")";
|
786 |
|
|
};
|
787 |
|
|
c3_chart_internal_fn.initialOpacity = function (d) {
|
788 |
|
|
return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
|
789 |
|
|
};
|
790 |
|
|
c3_chart_internal_fn.initialOpacityForCircle = function (d) {
|
791 |
|
|
return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
|
792 |
|
|
};
|
793 |
|
|
c3_chart_internal_fn.opacityForCircle = function (d) {
|
794 |
|
|
var opacity = this.config.point_show ? 1 : 0;
|
795 |
|
|
return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0;
|
796 |
|
|
};
|
797 |
|
|
c3_chart_internal_fn.opacityForText = function () {
|
798 |
|
|
return this.hasDataLabel() ? 1 : 0;
|
799 |
|
|
};
|
800 |
|
|
c3_chart_internal_fn.xx = function (d) {
|
801 |
|
|
return d ? this.x(d.x) : null;
|
802 |
|
|
};
|
803 |
|
|
c3_chart_internal_fn.xv = function (d) {
|
804 |
|
|
var $$ = this, value = d.value;
|
805 |
|
|
if ($$.isTimeSeries()) {
|
806 |
|
|
value = $$.parseDate(d.value);
|
807 |
|
|
}
|
808 |
|
|
else if ($$.isCategorized() && typeof d.value === 'string') {
|
809 |
|
|
value = $$.config.axis_x_categories.indexOf(d.value);
|
810 |
|
|
}
|
811 |
|
|
return Math.ceil($$.x(value));
|
812 |
|
|
};
|
813 |
|
|
c3_chart_internal_fn.yv = function (d) {
|
814 |
|
|
var $$ = this,
|
815 |
|
|
yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
|
816 |
|
|
return Math.ceil(yScale(d.value));
|
817 |
|
|
};
|
818 |
|
|
c3_chart_internal_fn.subxx = function (d) {
|
819 |
|
|
return d ? this.subX(d.x) : null;
|
820 |
|
|
};
|
821 |
|
|
|
822 |
|
|
c3_chart_internal_fn.transformMain = function (withTransition, transitions) {
|
823 |
|
|
var $$ = this,
|
824 |
|
|
xAxis, yAxis, y2Axis;
|
825 |
|
|
if (transitions && transitions.axisX) {
|
826 |
|
|
xAxis = transitions.axisX;
|
827 |
|
|
} else {
|
828 |
|
|
xAxis = $$.main.select('.' + CLASS.axisX);
|
829 |
|
|
if (withTransition) { xAxis = xAxis.transition(); }
|
830 |
|
|
}
|
831 |
|
|
if (transitions && transitions.axisY) {
|
832 |
|
|
yAxis = transitions.axisY;
|
833 |
|
|
} else {
|
834 |
|
|
yAxis = $$.main.select('.' + CLASS.axisY);
|
835 |
|
|
if (withTransition) { yAxis = yAxis.transition(); }
|
836 |
|
|
}
|
837 |
|
|
if (transitions && transitions.axisY2) {
|
838 |
|
|
y2Axis = transitions.axisY2;
|
839 |
|
|
} else {
|
840 |
|
|
y2Axis = $$.main.select('.' + CLASS.axisY2);
|
841 |
|
|
if (withTransition) { y2Axis = y2Axis.transition(); }
|
842 |
|
|
}
|
843 |
|
|
(withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main'));
|
844 |
|
|
xAxis.attr("transform", $$.getTranslate('x'));
|
845 |
|
|
yAxis.attr("transform", $$.getTranslate('y'));
|
846 |
|
|
y2Axis.attr("transform", $$.getTranslate('y2'));
|
847 |
|
|
$$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc'));
|
848 |
|
|
};
|
849 |
|
|
c3_chart_internal_fn.transformAll = function (withTransition, transitions) {
|
850 |
|
|
var $$ = this;
|
851 |
|
|
$$.transformMain(withTransition, transitions);
|
852 |
|
|
if ($$.config.subchart_show) { $$.transformContext(withTransition, transitions); }
|
853 |
|
|
if ($$.legend) { $$.transformLegend(withTransition); }
|
854 |
|
|
};
|
855 |
|
|
|
856 |
|
|
c3_chart_internal_fn.updateSvgSize = function () {
|
857 |
|
|
var $$ = this,
|
858 |
|
|
brush = $$.svg.select(".c3-brush .background");
|
859 |
|
|
$$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
|
860 |
|
|
$$.svg.selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid]).select('rect')
|
861 |
|
|
.attr('width', $$.width)
|
862 |
|
|
.attr('height', $$.height);
|
863 |
|
|
$$.svg.select('#' + $$.clipIdForXAxis).select('rect')
|
864 |
|
|
.attr('x', $$.getXAxisClipX.bind($$))
|
865 |
|
|
.attr('y', $$.getXAxisClipY.bind($$))
|
866 |
|
|
.attr('width', $$.getXAxisClipWidth.bind($$))
|
867 |
|
|
.attr('height', $$.getXAxisClipHeight.bind($$));
|
868 |
|
|
$$.svg.select('#' + $$.clipIdForYAxis).select('rect')
|
869 |
|
|
.attr('x', $$.getYAxisClipX.bind($$))
|
870 |
|
|
.attr('y', $$.getYAxisClipY.bind($$))
|
871 |
|
|
.attr('width', $$.getYAxisClipWidth.bind($$))
|
872 |
|
|
.attr('height', $$.getYAxisClipHeight.bind($$));
|
873 |
|
|
$$.svg.select('#' + $$.clipIdForSubchart).select('rect')
|
874 |
|
|
.attr('width', $$.width)
|
875 |
|
|
.attr('height', brush.size() ? brush.attr('height') : 0);
|
876 |
|
|
$$.svg.select('.' + CLASS.zoomRect)
|
877 |
|
|
.attr('width', $$.width)
|
878 |
|
|
.attr('height', $$.height);
|
879 |
|
|
// MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
|
880 |
|
|
$$.selectChart.style('max-height', $$.currentHeight + "px");
|
881 |
|
|
};
|
882 |
|
|
|
883 |
|
|
|
884 |
|
|
c3_chart_internal_fn.updateDimension = function (withoutAxis) {
|
885 |
|
|
var $$ = this;
|
886 |
|
|
if (!withoutAxis) {
|
887 |
|
|
if ($$.config.axis_rotated) {
|
888 |
|
|
$$.axes.x.call($$.xAxis);
|
889 |
|
|
$$.axes.subx.call($$.subXAxis);
|
890 |
|
|
} else {
|
891 |
|
|
$$.axes.y.call($$.yAxis);
|
892 |
|
|
$$.axes.y2.call($$.y2Axis);
|
893 |
|
|
}
|
894 |
|
|
}
|
895 |
|
|
$$.updateSizes();
|
896 |
|
|
$$.updateScales();
|
897 |
|
|
$$.updateSvgSize();
|
898 |
|
|
$$.transformAll(false);
|
899 |
|
|
};
|
900 |
|
|
|
901 |
|
|
c3_chart_internal_fn.observeInserted = function (selection) {
|
902 |
|
|
var $$ = this, observer;
|
903 |
|
|
if (typeof MutationObserver === 'undefined') {
|
904 |
|
|
window.console.error("MutationObserver not defined.");
|
905 |
|
|
return;
|
906 |
|
|
}
|
907 |
|
|
observer= new MutationObserver(function (mutations) {
|
908 |
|
|
mutations.forEach(function (mutation) {
|
909 |
|
|
if (mutation.type === 'childList' && mutation.previousSibling) {
|
910 |
|
|
observer.disconnect();
|
911 |
|
|
// need to wait for completion of load because size calculation requires the actual sizes determined after that completion
|
912 |
|
|
$$.intervalForObserveInserted = window.setInterval(function () {
|
913 |
|
|
// parentNode will NOT be null when completed
|
914 |
|
|
if (selection.node().parentNode) {
|
915 |
|
|
window.clearInterval($$.intervalForObserveInserted);
|
916 |
|
|
$$.updateDimension();
|
917 |
|
|
$$.config.oninit.call($$);
|
918 |
|
|
$$.redraw({
|
919 |
|
|
withTransform: true,
|
920 |
|
|
withUpdateXDomain: true,
|
921 |
|
|
withUpdateOrgXDomain: true,
|
922 |
|
|
withTransition: false,
|
923 |
|
|
withTransitionForTransform: false,
|
924 |
|
|
withLegend: true
|
925 |
|
|
});
|
926 |
|
|
selection.transition().style('opacity', 1);
|
927 |
|
|
}
|
928 |
|
|
}, 10);
|
929 |
|
|
}
|
930 |
|
|
});
|
931 |
|
|
});
|
932 |
|
|
observer.observe(selection.node(), {attributes: true, childList: true, characterData: true});
|
933 |
|
|
};
|
934 |
|
|
|
935 |
|
|
|
936 |
|
|
c3_chart_internal_fn.generateResize = function () {
|
937 |
|
|
var resizeFunctions = [];
|
938 |
|
|
function callResizeFunctions() {
|
939 |
|
|
resizeFunctions.forEach(function (f) {
|
940 |
|
|
f();
|
941 |
|
|
});
|
942 |
|
|
}
|
943 |
|
|
callResizeFunctions.add = function (f) {
|
944 |
|
|
resizeFunctions.push(f);
|
945 |
|
|
};
|
946 |
|
|
return callResizeFunctions;
|
947 |
|
|
};
|
948 |
|
|
|
949 |
|
|
c3_chart_internal_fn.endall = function (transition, callback) {
|
950 |
|
|
var n = 0;
|
951 |
|
|
transition
|
952 |
|
|
.each(function () { ++n; })
|
953 |
|
|
.each("end", function () {
|
954 |
|
|
if (!--n) { callback.apply(this, arguments); }
|
955 |
|
|
});
|
956 |
|
|
};
|
957 |
|
|
c3_chart_internal_fn.generateWait = function () {
|
958 |
|
|
var transitionsToWait = [],
|
959 |
|
|
f = function (transition, callback) {
|
960 |
|
|
var timer = setInterval(function () {
|
961 |
|
|
var done = 0;
|
962 |
|
|
transitionsToWait.forEach(function (t) {
|
963 |
|
|
if (t.empty()) {
|
964 |
|
|
done += 1;
|
965 |
|
|
return;
|
966 |
|
|
}
|
967 |
|
|
try {
|
968 |
|
|
t.transition();
|
969 |
|
|
} catch (e) {
|
970 |
|
|
done += 1;
|
971 |
|
|
}
|
972 |
|
|
});
|
973 |
|
|
if (done === transitionsToWait.length) {
|
974 |
|
|
clearInterval(timer);
|
975 |
|
|
if (callback) { callback(); }
|
976 |
|
|
}
|
977 |
|
|
}, 10);
|
978 |
|
|
};
|
979 |
|
|
f.add = function (transition) {
|
980 |
|
|
transitionsToWait.push(transition);
|
981 |
|
|
};
|
982 |
|
|
return f;
|
983 |
|
|
};
|
984 |
|
|
|
985 |
|
|
c3_chart_internal_fn.parseDate = function (date) {
|
986 |
|
|
var $$ = this, parsedDate;
|
987 |
|
|
if (date instanceof Date) {
|
988 |
|
|
parsedDate = date;
|
989 |
|
|
} else if (typeof date === 'string') {
|
990 |
|
|
parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
|
991 |
|
|
} else if (typeof date === 'number' || !isNaN(date)) {
|
992 |
|
|
parsedDate = new Date(+date);
|
993 |
|
|
}
|
994 |
|
|
if (!parsedDate || isNaN(+parsedDate)) {
|
995 |
|
|
window.console.error("Failed to parse x '" + date + "' to Date object");
|
996 |
|
|
}
|
997 |
|
|
return parsedDate;
|
998 |
|
|
};
|
999 |
|
|
|
1000 |
|
|
c3_chart_internal_fn.isTabVisible = function () {
|
1001 |
|
|
var hidden;
|
1002 |
|
|
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
|
1003 |
|
|
hidden = "hidden";
|
1004 |
|
|
} else if (typeof document.mozHidden !== "undefined") {
|
1005 |
|
|
hidden = "mozHidden";
|
1006 |
|
|
} else if (typeof document.msHidden !== "undefined") {
|
1007 |
|
|
hidden = "msHidden";
|
1008 |
|
|
} else if (typeof document.webkitHidden !== "undefined") {
|
1009 |
|
|
hidden = "webkitHidden";
|
1010 |
|
|
}
|
1011 |
|
|
|
1012 |
|
|
return document[hidden] ? false : true;
|
1013 |
|
|
};
|
1014 |
|
|
|
1015 |
|
|
c3_chart_internal_fn.getDefaultConfig = function () {
|
1016 |
|
|
var config = {
|
1017 |
|
|
bindto: '#chart',
|
1018 |
|
|
size_width: undefined,
|
1019 |
|
|
size_height: undefined,
|
1020 |
|
|
padding_left: undefined,
|
1021 |
|
|
padding_right: undefined,
|
1022 |
|
|
padding_top: undefined,
|
1023 |
|
|
padding_bottom: undefined,
|
1024 |
|
|
zoom_enabled: false,
|
1025 |
|
|
zoom_extent: undefined,
|
1026 |
|
|
zoom_privileged: false,
|
1027 |
|
|
zoom_rescale: false,
|
1028 |
|
|
zoom_onzoom: function () {},
|
1029 |
|
|
zoom_onzoomstart: function () {},
|
1030 |
|
|
zoom_onzoomend: function () {},
|
1031 |
|
|
interaction_enabled: true,
|
1032 |
|
|
onmouseover: function () {},
|
1033 |
|
|
onmouseout: function () {},
|
1034 |
|
|
onresize: function () {},
|
1035 |
|
|
onresized: function () {},
|
1036 |
|
|
oninit: function () {},
|
1037 |
|
|
onrendered: function () {},
|
1038 |
|
|
transition_duration: 350,
|
1039 |
|
|
data_x: undefined,
|
1040 |
|
|
data_xs: {},
|
1041 |
|
|
data_xFormat: '%Y-%m-%d',
|
1042 |
|
|
data_xLocaltime: true,
|
1043 |
|
|
data_xSort: true,
|
1044 |
|
|
data_idConverter: function (id) { return id; },
|
1045 |
|
|
data_names: {},
|
1046 |
|
|
data_classes: {},
|
1047 |
|
|
data_groups: [],
|
1048 |
|
|
data_axes: {},
|
1049 |
|
|
data_type: undefined,
|
1050 |
|
|
data_types: {},
|
1051 |
|
|
data_labels: {},
|
1052 |
|
|
data_order: 'desc',
|
1053 |
|
|
data_regions: {},
|
1054 |
|
|
data_color: undefined,
|
1055 |
|
|
data_colors: {},
|
1056 |
|
|
data_hide: false,
|
1057 |
|
|
data_filter: undefined,
|
1058 |
|
|
data_selection_enabled: false,
|
1059 |
|
|
data_selection_grouped: false,
|
1060 |
|
|
data_selection_isselectable: function () { return true; },
|
1061 |
|
|
data_selection_multiple: true,
|
1062 |
|
|
data_selection_draggable: false,
|
1063 |
|
|
data_onclick: function () {},
|
1064 |
|
|
data_onmouseover: function () {},
|
1065 |
|
|
data_onmouseout: function () {},
|
1066 |
|
|
data_onselected: function () {},
|
1067 |
|
|
data_onunselected: function () {},
|
1068 |
|
|
data_url: undefined,
|
1069 |
|
|
data_json: undefined,
|
1070 |
|
|
data_rows: undefined,
|
1071 |
|
|
data_columns: undefined,
|
1072 |
|
|
data_mimeType: undefined,
|
1073 |
|
|
data_keys: undefined,
|
1074 |
|
|
// configuration for no plot-able data supplied.
|
1075 |
|
|
data_empty_label_text: "",
|
1076 |
|
|
// subchart
|
1077 |
|
|
subchart_show: false,
|
1078 |
|
|
subchart_size_height: 60,
|
1079 |
|
|
subchart_onbrush: function () {},
|
1080 |
|
|
// color
|
1081 |
|
|
color_pattern: [],
|
1082 |
|
|
color_threshold: {},
|
1083 |
|
|
// legend
|
1084 |
|
|
legend_show: true,
|
1085 |
|
|
legend_hide: false,
|
1086 |
|
|
legend_position: 'bottom',
|
1087 |
|
|
legend_inset_anchor: 'top-left',
|
1088 |
|
|
legend_inset_x: 10,
|
1089 |
|
|
legend_inset_y: 0,
|
1090 |
|
|
legend_inset_step: undefined,
|
1091 |
|
|
legend_item_onclick: undefined,
|
1092 |
|
|
legend_item_onmouseover: undefined,
|
1093 |
|
|
legend_item_onmouseout: undefined,
|
1094 |
|
|
legend_equally: false,
|
1095 |
|
|
// axis
|
1096 |
|
|
axis_rotated: false,
|
1097 |
|
|
axis_x_show: true,
|
1098 |
|
|
axis_x_type: 'indexed',
|
1099 |
|
|
axis_x_localtime: true,
|
1100 |
|
|
axis_x_categories: [],
|
1101 |
|
|
axis_x_tick_centered: false,
|
1102 |
|
|
axis_x_tick_format: undefined,
|
1103 |
|
|
axis_x_tick_culling: {},
|
1104 |
|
|
axis_x_tick_culling_max: 10,
|
1105 |
|
|
axis_x_tick_count: undefined,
|
1106 |
|
|
axis_x_tick_fit: true,
|
1107 |
|
|
axis_x_tick_values: null,
|
1108 |
|
|
axis_x_tick_rotate: 0,
|
1109 |
|
|
axis_x_tick_outer: true,
|
1110 |
|
|
axis_x_tick_multiline: true,
|
1111 |
|
|
axis_x_tick_width: null,
|
1112 |
|
|
axis_x_max: undefined,
|
1113 |
|
|
axis_x_min: undefined,
|
1114 |
|
|
axis_x_padding: {},
|
1115 |
|
|
axis_x_height: undefined,
|
1116 |
|
|
axis_x_extent: undefined,
|
1117 |
|
|
axis_x_label: {},
|
1118 |
|
|
axis_y_show: true,
|
1119 |
|
|
axis_y_type: undefined,
|
1120 |
|
|
axis_y_max: undefined,
|
1121 |
|
|
axis_y_min: undefined,
|
1122 |
|
|
axis_y_inverted: false,
|
1123 |
|
|
axis_y_center: undefined,
|
1124 |
|
|
axis_y_inner: undefined,
|
1125 |
|
|
axis_y_label: {},
|
1126 |
|
|
axis_y_tick_format: undefined,
|
1127 |
|
|
axis_y_tick_outer: true,
|
1128 |
|
|
axis_y_tick_values: null,
|
1129 |
|
|
axis_y_tick_count: undefined,
|
1130 |
|
|
axis_y_tick_time_value: undefined,
|
1131 |
|
|
axis_y_tick_time_interval: undefined,
|
1132 |
|
|
axis_y_padding: {},
|
1133 |
|
|
axis_y_default: undefined,
|
1134 |
|
|
axis_y2_show: false,
|
1135 |
|
|
axis_y2_max: undefined,
|
1136 |
|
|
axis_y2_min: undefined,
|
1137 |
|
|
axis_y2_inverted: false,
|
1138 |
|
|
axis_y2_center: undefined,
|
1139 |
|
|
axis_y2_inner: undefined,
|
1140 |
|
|
axis_y2_label: {},
|
1141 |
|
|
axis_y2_tick_format: undefined,
|
1142 |
|
|
axis_y2_tick_outer: true,
|
1143 |
|
|
axis_y2_tick_values: null,
|
1144 |
|
|
axis_y2_tick_count: undefined,
|
1145 |
|
|
axis_y2_padding: {},
|
1146 |
|
|
axis_y2_default: undefined,
|
1147 |
|
|
// grid
|
1148 |
|
|
grid_x_show: false,
|
1149 |
|
|
grid_x_type: 'tick',
|
1150 |
|
|
grid_x_lines: [],
|
1151 |
|
|
grid_y_show: false,
|
1152 |
|
|
// not used
|
1153 |
|
|
// grid_y_type: 'tick',
|
1154 |
|
|
grid_y_lines: [],
|
1155 |
|
|
grid_y_ticks: 10,
|
1156 |
|
|
grid_focus_show: true,
|
1157 |
|
|
grid_lines_front: true,
|
1158 |
|
|
// point - point of each data
|
1159 |
|
|
point_show: true,
|
1160 |
|
|
point_r: 2.5,
|
1161 |
|
|
point_focus_expand_enabled: true,
|
1162 |
|
|
point_focus_expand_r: undefined,
|
1163 |
|
|
point_select_r: undefined,
|
1164 |
|
|
// line
|
1165 |
|
|
line_connectNull: false,
|
1166 |
|
|
line_step_type: 'step',
|
1167 |
|
|
// bar
|
1168 |
|
|
bar_width: undefined,
|
1169 |
|
|
bar_width_ratio: 0.6,
|
1170 |
|
|
bar_width_max: undefined,
|
1171 |
|
|
bar_zerobased: true,
|
1172 |
|
|
// area
|
1173 |
|
|
area_zerobased: true,
|
1174 |
|
|
// pie
|
1175 |
|
|
pie_label_show: true,
|
1176 |
|
|
pie_label_format: undefined,
|
1177 |
|
|
pie_label_threshold: 0.05,
|
1178 |
|
|
pie_expand: true,
|
1179 |
|
|
// gauge
|
1180 |
|
|
gauge_label_show: true,
|
1181 |
|
|
gauge_label_format: undefined,
|
1182 |
|
|
gauge_expand: true,
|
1183 |
|
|
gauge_min: 0,
|
1184 |
|
|
gauge_max: 100,
|
1185 |
|
|
gauge_units: undefined,
|
1186 |
|
|
gauge_width: undefined,
|
1187 |
|
|
// donut
|
1188 |
|
|
donut_label_show: true,
|
1189 |
|
|
donut_label_format: undefined,
|
1190 |
|
|
donut_label_threshold: 0.05,
|
1191 |
|
|
donut_width: undefined,
|
1192 |
|
|
donut_expand: true,
|
1193 |
|
|
donut_title: "",
|
1194 |
|
|
// region - region to change style
|
1195 |
|
|
regions: [],
|
1196 |
|
|
// tooltip - show when mouseover on each data
|
1197 |
|
|
tooltip_show: true,
|
1198 |
|
|
tooltip_grouped: true,
|
1199 |
|
|
tooltip_format_title: undefined,
|
1200 |
|
|
tooltip_format_name: undefined,
|
1201 |
|
|
tooltip_format_value: undefined,
|
1202 |
|
|
tooltip_position: undefined,
|
1203 |
|
|
tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
|
1204 |
|
|
return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : '';
|
1205 |
|
|
},
|
1206 |
|
|
tooltip_init_show: false,
|
1207 |
|
|
tooltip_init_x: 0,
|
1208 |
|
|
tooltip_init_position: {top: '0px', left: '50px'}
|
1209 |
|
|
};
|
1210 |
|
|
|
1211 |
|
|
Object.keys(this.additionalConfig).forEach(function (key) {
|
1212 |
|
|
config[key] = this.additionalConfig[key];
|
1213 |
|
|
}, this);
|
1214 |
|
|
|
1215 |
|
|
return config;
|
1216 |
|
|
};
|
1217 |
|
|
c3_chart_internal_fn.additionalConfig = {};
|
1218 |
|
|
|
1219 |
|
|
c3_chart_internal_fn.loadConfig = function (config) {
|
1220 |
|
|
var this_config = this.config, target, keys, read;
|
1221 |
|
|
function find() {
|
1222 |
|
|
var key = keys.shift();
|
1223 |
|
|
// console.log("key =>", key, ", target =>", target);
|
1224 |
|
|
if (key && target && typeof target === 'object' && key in target) {
|
1225 |
|
|
target = target[key];
|
1226 |
|
|
return find();
|
1227 |
|
|
}
|
1228 |
|
|
else if (!key) {
|
1229 |
|
|
return target;
|
1230 |
|
|
}
|
1231 |
|
|
else {
|
1232 |
|
|
return undefined;
|
1233 |
|
|
}
|
1234 |
|
|
}
|
1235 |
|
|
Object.keys(this_config).forEach(function (key) {
|
1236 |
|
|
target = config;
|
1237 |
|
|
keys = key.split('_');
|
1238 |
|
|
read = find();
|
1239 |
|
|
// console.log("CONFIG : ", key, read);
|
1240 |
|
|
if (isDefined(read)) {
|
1241 |
|
|
this_config[key] = read;
|
1242 |
|
|
}
|
1243 |
|
|
});
|
1244 |
|
|
};
|
1245 |
|
|
|
1246 |
|
|
c3_chart_internal_fn.getScale = function (min, max, forTimeseries) {
|
1247 |
|
|
return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]);
|
1248 |
|
|
};
|
1249 |
|
|
c3_chart_internal_fn.getX = function (min, max, domain, offset) {
|
1250 |
|
|
var $$ = this,
|
1251 |
|
|
scale = $$.getScale(min, max, $$.isTimeSeries()),
|
1252 |
|
|
_scale = domain ? scale.domain(domain) : scale, key;
|
1253 |
|
|
// Define customized scale if categorized axis
|
1254 |
|
|
if ($$.isCategorized()) {
|
1255 |
|
|
offset = offset || function () { return 0; };
|
1256 |
|
|
scale = function (d, raw) {
|
1257 |
|
|
var v = _scale(d) + offset(d);
|
1258 |
|
|
return raw ? v : Math.ceil(v);
|
1259 |
|
|
};
|
1260 |
|
|
} else {
|
1261 |
|
|
scale = function (d, raw) {
|
1262 |
|
|
var v = _scale(d);
|
1263 |
|
|
return raw ? v : Math.ceil(v);
|
1264 |
|
|
};
|
1265 |
|
|
}
|
1266 |
|
|
// define functions
|
1267 |
|
|
for (key in _scale) {
|
1268 |
|
|
scale[key] = _scale[key];
|
1269 |
|
|
}
|
1270 |
|
|
scale.orgDomain = function () {
|
1271 |
|
|
return _scale.domain();
|
1272 |
|
|
};
|
1273 |
|
|
// define custom domain() for categorized axis
|
1274 |
|
|
if ($$.isCategorized()) {
|
1275 |
|
|
scale.domain = function (domain) {
|
1276 |
|
|
if (!arguments.length) {
|
1277 |
|
|
domain = this.orgDomain();
|
1278 |
|
|
return [domain[0], domain[1] + 1];
|
1279 |
|
|
}
|
1280 |
|
|
_scale.domain(domain);
|
1281 |
|
|
return scale;
|
1282 |
|
|
};
|
1283 |
|
|
}
|
1284 |
|
|
return scale;
|
1285 |
|
|
};
|
1286 |
|
|
c3_chart_internal_fn.getY = function (min, max, domain) {
|
1287 |
|
|
var scale = this.getScale(min, max, this.isTimeSeriesY());
|
1288 |
|
|
if (domain) { scale.domain(domain); }
|
1289 |
|
|
return scale;
|
1290 |
|
|
};
|
1291 |
|
|
c3_chart_internal_fn.getYScale = function (id) {
|
1292 |
|
|
return this.axis.getId(id) === 'y2' ? this.y2 : this.y;
|
1293 |
|
|
};
|
1294 |
|
|
c3_chart_internal_fn.getSubYScale = function (id) {
|
1295 |
|
|
return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;
|
1296 |
|
|
};
|
1297 |
|
|
c3_chart_internal_fn.updateScales = function () {
|
1298 |
|
|
var $$ = this, config = $$.config,
|
1299 |
|
|
forInit = !$$.x;
|
1300 |
|
|
// update edges
|
1301 |
|
|
$$.xMin = config.axis_rotated ? 1 : 0;
|
1302 |
|
|
$$.xMax = config.axis_rotated ? $$.height : $$.width;
|
1303 |
|
|
$$.yMin = config.axis_rotated ? 0 : $$.height;
|
1304 |
|
|
$$.yMax = config.axis_rotated ? $$.width : 1;
|
1305 |
|
|
$$.subXMin = $$.xMin;
|
1306 |
|
|
$$.subXMax = $$.xMax;
|
1307 |
|
|
$$.subYMin = config.axis_rotated ? 0 : $$.height2;
|
1308 |
|
|
$$.subYMax = config.axis_rotated ? $$.width2 : 1;
|
1309 |
|
|
// update scales
|
1310 |
|
|
$$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () { return $$.xAxis.tickOffset(); });
|
1311 |
|
|
$$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain());
|
1312 |
|
|
$$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain());
|
1313 |
|
|
$$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) { return d % 1 ? 0 : $$.subXAxis.tickOffset(); });
|
1314 |
|
|
$$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain());
|
1315 |
|
|
$$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain());
|
1316 |
|
|
// update axes
|
1317 |
|
|
$$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
|
1318 |
|
|
$$.xAxisTickValues = $$.axis.getXAxisTickValues();
|
1319 |
|
|
$$.yAxisTickValues = $$.axis.getYAxisTickValues();
|
1320 |
|
|
$$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
|
1321 |
|
|
|
1322 |
|
|
$$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
|
1323 |
|
|
$$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
|
1324 |
|
|
$$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer);
|
1325 |
|
|
$$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer);
|
1326 |
|
|
|
1327 |
|
|
// Set initialized scales to brush and zoom
|
1328 |
|
|
if (!forInit) {
|
1329 |
|
|
if ($$.brush) { $$.brush.scale($$.subX); }
|
1330 |
|
|
if (config.zoom_enabled) { $$.zoom.scale($$.x); }
|
1331 |
|
|
}
|
1332 |
|
|
// update for arc
|
1333 |
|
|
if ($$.updateArc) { $$.updateArc(); }
|
1334 |
|
|
};
|
1335 |
|
|
|
1336 |
|
|
c3_chart_internal_fn.getYDomainMin = function (targets) {
|
1337 |
|
|
var $$ = this, config = $$.config,
|
1338 |
|
|
ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
|
1339 |
|
|
j, k, baseId, idsInGroup, id, hasNegativeValue;
|
1340 |
|
|
if (config.data_groups.length > 0) {
|
1341 |
|
|
hasNegativeValue = $$.hasNegativeValueInTargets(targets);
|
1342 |
|
|
for (j = 0; j < config.data_groups.length; j++) {
|
1343 |
|
|
// Determine baseId
|
1344 |
|
|
idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
|
1345 |
|
|
if (idsInGroup.length === 0) { continue; }
|
1346 |
|
|
baseId = idsInGroup[0];
|
1347 |
|
|
// Consider negative values
|
1348 |
|
|
if (hasNegativeValue && ys[baseId]) {
|
1349 |
|
|
ys[baseId].forEach(function (v, i) {
|
1350 |
|
|
ys[baseId][i] = v < 0 ? v : 0;
|
1351 |
|
|
});
|
1352 |
|
|
}
|
1353 |
|
|
// Compute min
|
1354 |
|
|
for (k = 1; k < idsInGroup.length; k++) {
|
1355 |
|
|
id = idsInGroup[k];
|
1356 |
|
|
if (! ys[id]) { continue; }
|
1357 |
|
|
ys[id].forEach(function (v, i) {
|
1358 |
|
|
if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {
|
1359 |
|
|
ys[baseId][i] += +v;
|
1360 |
|
|
}
|
1361 |
|
|
});
|
1362 |
|
|
}
|
1363 |
|
|
}
|
1364 |
|
|
}
|
1365 |
|
|
return $$.d3.min(Object.keys(ys).map(function (key) { return $$.d3.min(ys[key]); }));
|
1366 |
|
|
};
|
1367 |
|
|
c3_chart_internal_fn.getYDomainMax = function (targets) {
|
1368 |
|
|
var $$ = this, config = $$.config,
|
1369 |
|
|
ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),
|
1370 |
|
|
j, k, baseId, idsInGroup, id, hasPositiveValue;
|
1371 |
|
|
if (config.data_groups.length > 0) {
|
1372 |
|
|
hasPositiveValue = $$.hasPositiveValueInTargets(targets);
|
1373 |
|
|
for (j = 0; j < config.data_groups.length; j++) {
|
1374 |
|
|
// Determine baseId
|
1375 |
|
|
idsInGroup = config.data_groups[j].filter(function (id) { return ids.indexOf(id) >= 0; });
|
1376 |
|
|
if (idsInGroup.length === 0) { continue; }
|
1377 |
|
|
baseId = idsInGroup[0];
|
1378 |
|
|
// Consider positive values
|
1379 |
|
|
if (hasPositiveValue && ys[baseId]) {
|
1380 |
|
|
ys[baseId].forEach(function (v, i) {
|
1381 |
|
|
ys[baseId][i] = v > 0 ? v : 0;
|
1382 |
|
|
});
|
1383 |
|
|
}
|
1384 |
|
|
// Compute max
|
1385 |
|
|
for (k = 1; k < idsInGroup.length; k++) {
|
1386 |
|
|
id = idsInGroup[k];
|
1387 |
|
|
if (! ys[id]) { continue; }
|
1388 |
|
|
ys[id].forEach(function (v, i) {
|
1389 |
|
|
if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {
|
1390 |
|
|
ys[baseId][i] += +v;
|
1391 |
|
|
}
|
1392 |
|
|
});
|
1393 |
|
|
}
|
1394 |
|
|
}
|
1395 |
|
|
}
|
1396 |
|
|
return $$.d3.max(Object.keys(ys).map(function (key) { return $$.d3.max(ys[key]); }));
|
1397 |
|
|
};
|
1398 |
|
|
c3_chart_internal_fn.getYDomain = function (targets, axisId, xDomain) {
|
1399 |
|
|
var $$ = this, config = $$.config,
|
1400 |
|
|
targetsByAxisId = targets.filter(function (t) { return $$.axis.getId(t.id) === axisId; }),
|
1401 |
|
|
yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId,
|
1402 |
|
|
yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,
|
1403 |
|
|
yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,
|
1404 |
|
|
yDomainMin = $$.getYDomainMin(yTargets),
|
1405 |
|
|
yDomainMax = $$.getYDomainMax(yTargets),
|
1406 |
|
|
domain, domainLength, padding, padding_top, padding_bottom,
|
1407 |
|
|
center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,
|
1408 |
|
|
yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative,
|
1409 |
|
|
isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased),
|
1410 |
|
|
isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted,
|
1411 |
|
|
showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,
|
1412 |
|
|
showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
|
1413 |
|
|
|
1414 |
|
|
// MEMO: avoid inverting domain unexpectedly
|
1415 |
|
|
yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? (yDomainMin < yMax ? yDomainMin : yMax - 10) : yDomainMin;
|
1416 |
|
|
yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? (yMin < yDomainMax ? yDomainMax : yMin + 10) : yDomainMax;
|
1417 |
|
|
|
1418 |
|
|
if (yTargets.length === 0) { // use current domain if target of axisId is none
|
1419 |
|
|
return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
|
1420 |
|
|
}
|
1421 |
|
|
if (isNaN(yDomainMin)) { // set minimum to zero when not number
|
1422 |
|
|
yDomainMin = 0;
|
1423 |
|
|
}
|
1424 |
|
|
if (isNaN(yDomainMax)) { // set maximum to have same value as yDomainMin
|
1425 |
|
|
yDomainMax = yDomainMin;
|
1426 |
|
|
}
|
1427 |
|
|
if (yDomainMin === yDomainMax) {
|
1428 |
|
|
yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
|
1429 |
|
|
}
|
1430 |
|
|
isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
|
1431 |
|
|
isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
|
1432 |
|
|
|
1433 |
|
|
// Cancel zerobased if axis_*_min / axis_*_max specified
|
1434 |
|
|
if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {
|
1435 |
|
|
isZeroBased = false;
|
1436 |
|
|
}
|
1437 |
|
|
|
1438 |
|
|
// Bar/Area chart should be 0-based if all positive|negative
|
1439 |
|
|
if (isZeroBased) {
|
1440 |
|
|
if (isAllPositive) { yDomainMin = 0; }
|
1441 |
|
|
if (isAllNegative) { yDomainMax = 0; }
|
1442 |
|
|
}
|
1443 |
|
|
|
1444 |
|
|
domainLength = Math.abs(yDomainMax - yDomainMin);
|
1445 |
|
|
padding = padding_top = padding_bottom = domainLength * 0.1;
|
1446 |
|
|
|
1447 |
|
|
if (typeof center !== 'undefined') {
|
1448 |
|
|
yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
|
1449 |
|
|
yDomainMax = center + yDomainAbs;
|
1450 |
|
|
yDomainMin = center - yDomainAbs;
|
1451 |
|
|
}
|
1452 |
|
|
// add padding for data label
|
1453 |
|
|
if (showHorizontalDataLabel) {
|
1454 |
|
|
lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
|
1455 |
|
|
diff = diffDomain($$.y.range());
|
1456 |
|
|
ratio = [lengths[0] / diff, lengths[1] / diff];
|
1457 |
|
|
padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
|
1458 |
|
|
padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
|
1459 |
|
|
} else if (showVerticalDataLabel) {
|
1460 |
|
|
lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
|
1461 |
|
|
padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength);
|
1462 |
|
|
padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength);
|
1463 |
|
|
}
|
1464 |
|
|
if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
|
1465 |
|
|
padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);
|
1466 |
|
|
padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);
|
1467 |
|
|
}
|
1468 |
|
|
if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
|
1469 |
|
|
padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);
|
1470 |
|
|
padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);
|
1471 |
|
|
}
|
1472 |
|
|
// Bar/Area chart should be 0-based if all positive|negative
|
1473 |
|
|
if (isZeroBased) {
|
1474 |
|
|
if (isAllPositive) { padding_bottom = yDomainMin; }
|
1475 |
|
|
if (isAllNegative) { padding_top = -yDomainMax; }
|
1476 |
|
|
}
|
1477 |
|
|
domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
|
1478 |
|
|
return isInverted ? domain.reverse() : domain;
|
1479 |
|
|
};
|
1480 |
|
|
c3_chart_internal_fn.getXDomainMin = function (targets) {
|
1481 |
|
|
var $$ = this, config = $$.config;
|
1482 |
|
|
return isDefined(config.axis_x_min) ?
|
1483 |
|
|
($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) :
|
1484 |
|
|
$$.d3.min(targets, function (t) { return $$.d3.min(t.values, function (v) { return v.x; }); });
|
1485 |
|
|
};
|
1486 |
|
|
c3_chart_internal_fn.getXDomainMax = function (targets) {
|
1487 |
|
|
var $$ = this, config = $$.config;
|
1488 |
|
|
return isDefined(config.axis_x_max) ?
|
1489 |
|
|
($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) :
|
1490 |
|
|
$$.d3.max(targets, function (t) { return $$.d3.max(t.values, function (v) { return v.x; }); });
|
1491 |
|
|
};
|
1492 |
|
|
c3_chart_internal_fn.getXDomainPadding = function (domain) {
|
1493 |
|
|
var $$ = this, config = $$.config,
|
1494 |
|
|
diff = domain[1] - domain[0],
|
1495 |
|
|
maxDataCount, padding, paddingLeft, paddingRight;
|
1496 |
|
|
if ($$.isCategorized()) {
|
1497 |
|
|
padding = 0;
|
1498 |
|
|
} else if ($$.hasType('bar')) {
|
1499 |
|
|
maxDataCount = $$.getMaxDataCount();
|
1500 |
|
|
padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5;
|
1501 |
|
|
} else {
|
1502 |
|
|
padding = diff * 0.01;
|
1503 |
|
|
}
|
1504 |
|
|
if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) {
|
1505 |
|
|
paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;
|
1506 |
|
|
paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;
|
1507 |
|
|
} else if (typeof config.axis_x_padding === 'number') {
|
1508 |
|
|
paddingLeft = paddingRight = config.axis_x_padding;
|
1509 |
|
|
} else {
|
1510 |
|
|
paddingLeft = paddingRight = padding;
|
1511 |
|
|
}
|
1512 |
|
|
return {left: paddingLeft, right: paddingRight};
|
1513 |
|
|
};
|
1514 |
|
|
c3_chart_internal_fn.getXDomain = function (targets) {
|
1515 |
|
|
var $$ = this,
|
1516 |
|
|
xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],
|
1517 |
|
|
firstX = xDomain[0], lastX = xDomain[1],
|
1518 |
|
|
padding = $$.getXDomainPadding(xDomain),
|
1519 |
|
|
min = 0, max = 0;
|
1520 |
|
|
// show center of x domain if min and max are the same
|
1521 |
|
|
if ((firstX - lastX) === 0 && !$$.isCategorized()) {
|
1522 |
|
|
if ($$.isTimeSeries()) {
|
1523 |
|
|
firstX = new Date(firstX.getTime() * 0.5);
|
1524 |
|
|
lastX = new Date(lastX.getTime() * 1.5);
|
1525 |
|
|
} else {
|
1526 |
|
|
firstX = firstX === 0 ? 1 : (firstX * 0.5);
|
1527 |
|
|
lastX = lastX === 0 ? -1 : (lastX * 1.5);
|
1528 |
|
|
}
|
1529 |
|
|
}
|
1530 |
|
|
if (firstX || firstX === 0) {
|
1531 |
|
|
min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
|
1532 |
|
|
}
|
1533 |
|
|
if (lastX || lastX === 0) {
|
1534 |
|
|
max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
|
1535 |
|
|
}
|
1536 |
|
|
return [min, max];
|
1537 |
|
|
};
|
1538 |
|
|
c3_chart_internal_fn.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
|
1539 |
|
|
var $$ = this, config = $$.config;
|
1540 |
|
|
|
1541 |
|
|
if (withUpdateOrgXDomain) {
|
1542 |
|
|
$$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
|
1543 |
|
|
$$.orgXDomain = $$.x.domain();
|
1544 |
|
|
if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
|
1545 |
|
|
$$.subX.domain($$.x.domain());
|
1546 |
|
|
if ($$.brush) { $$.brush.scale($$.subX); }
|
1547 |
|
|
}
|
1548 |
|
|
if (withUpdateXDomain) {
|
1549 |
|
|
$$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent());
|
1550 |
|
|
if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }
|
1551 |
|
|
}
|
1552 |
|
|
|
1553 |
|
|
// Trim domain when too big by zoom mousemove event
|
1554 |
|
|
if (withTrim) { $$.x.domain($$.trimXDomain($$.x.orgDomain())); }
|
1555 |
|
|
|
1556 |
|
|
return $$.x.domain();
|
1557 |
|
|
};
|
1558 |
|
|
c3_chart_internal_fn.trimXDomain = function (domain) {
|
1559 |
|
|
var $$ = this;
|
1560 |
|
|
if (domain[0] <= $$.orgXDomain[0]) {
|
1561 |
|
|
domain[1] = +domain[1] + ($$.orgXDomain[0] - domain[0]);
|
1562 |
|
|
domain[0] = $$.orgXDomain[0];
|
1563 |
|
|
}
|
1564 |
|
|
if ($$.orgXDomain[1] <= domain[1]) {
|
1565 |
|
|
domain[0] = +domain[0] - (domain[1] - $$.orgXDomain[1]);
|
1566 |
|
|
domain[1] = $$.orgXDomain[1];
|
1567 |
|
|
}
|
1568 |
|
|
return domain;
|
1569 |
|
|
};
|
1570 |
|
|
|
1571 |
|
|
c3_chart_internal_fn.isX = function (key) {
|
1572 |
|
|
var $$ = this, config = $$.config;
|
1573 |
|
|
return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));
|
1574 |
|
|
};
|
1575 |
|
|
c3_chart_internal_fn.isNotX = function (key) {
|
1576 |
|
|
return !this.isX(key);
|
1577 |
|
|
};
|
1578 |
|
|
c3_chart_internal_fn.getXKey = function (id) {
|
1579 |
|
|
var $$ = this, config = $$.config;
|
1580 |
|
|
return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
|
1581 |
|
|
};
|
1582 |
|
|
c3_chart_internal_fn.getXValuesOfXKey = function (key, targets) {
|
1583 |
|
|
var $$ = this,
|
1584 |
|
|
xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
|
1585 |
|
|
ids.forEach(function (id) {
|
1586 |
|
|
if ($$.getXKey(id) === key) {
|
1587 |
|
|
xValues = $$.data.xs[id];
|
1588 |
|
|
}
|
1589 |
|
|
});
|
1590 |
|
|
return xValues;
|
1591 |
|
|
};
|
1592 |
|
|
c3_chart_internal_fn.getIndexByX = function (x) {
|
1593 |
|
|
var $$ = this,
|
1594 |
|
|
data = $$.filterByX($$.data.targets, x);
|
1595 |
|
|
return data.length ? data[0].index : null;
|
1596 |
|
|
};
|
1597 |
|
|
c3_chart_internal_fn.getXValue = function (id, i) {
|
1598 |
|
|
var $$ = this;
|
1599 |
|
|
return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
|
1600 |
|
|
};
|
1601 |
|
|
c3_chart_internal_fn.getOtherTargetXs = function () {
|
1602 |
|
|
var $$ = this,
|
1603 |
|
|
idsForX = Object.keys($$.data.xs);
|
1604 |
|
|
return idsForX.length ? $$.data.xs[idsForX[0]] : null;
|
1605 |
|
|
};
|
1606 |
|
|
c3_chart_internal_fn.getOtherTargetX = function (index) {
|
1607 |
|
|
var xs = this.getOtherTargetXs();
|
1608 |
|
|
return xs && index < xs.length ? xs[index] : null;
|
1609 |
|
|
};
|
1610 |
|
|
c3_chart_internal_fn.addXs = function (xs) {
|
1611 |
|
|
var $$ = this;
|
1612 |
|
|
Object.keys(xs).forEach(function (id) {
|
1613 |
|
|
$$.config.data_xs[id] = xs[id];
|
1614 |
|
|
});
|
1615 |
|
|
};
|
1616 |
|
|
c3_chart_internal_fn.hasMultipleX = function (xs) {
|
1617 |
|
|
return this.d3.set(Object.keys(xs).map(function (id) { return xs[id]; })).size() > 1;
|
1618 |
|
|
};
|
1619 |
|
|
c3_chart_internal_fn.isMultipleX = function () {
|
1620 |
|
|
return notEmpty(this.config.data_xs) || !this.config.data_xSort || this.hasType('scatter');
|
1621 |
|
|
};
|
1622 |
|
|
c3_chart_internal_fn.addName = function (data) {
|
1623 |
|
|
var $$ = this, name;
|
1624 |
|
|
if (data) {
|
1625 |
|
|
name = $$.config.data_names[data.id];
|
1626 |
|
|
data.name = name ? name : data.id;
|
1627 |
|
|
}
|
1628 |
|
|
return data;
|
1629 |
|
|
};
|
1630 |
|
|
c3_chart_internal_fn.getValueOnIndex = function (values, index) {
|
1631 |
|
|
var valueOnIndex = values.filter(function (v) { return v.index === index; });
|
1632 |
|
|
return valueOnIndex.length ? valueOnIndex[0] : null;
|
1633 |
|
|
};
|
1634 |
|
|
c3_chart_internal_fn.updateTargetX = function (targets, x) {
|
1635 |
|
|
var $$ = this;
|
1636 |
|
|
targets.forEach(function (t) {
|
1637 |
|
|
t.values.forEach(function (v, i) {
|
1638 |
|
|
v.x = $$.generateTargetX(x[i], t.id, i);
|
1639 |
|
|
});
|
1640 |
|
|
$$.data.xs[t.id] = x;
|
1641 |
|
|
});
|
1642 |
|
|
};
|
1643 |
|
|
c3_chart_internal_fn.updateTargetXs = function (targets, xs) {
|
1644 |
|
|
var $$ = this;
|
1645 |
|
|
targets.forEach(function (t) {
|
1646 |
|
|
if (xs[t.id]) {
|
1647 |
|
|
$$.updateTargetX([t], xs[t.id]);
|
1648 |
|
|
}
|
1649 |
|
|
});
|
1650 |
|
|
};
|
1651 |
|
|
c3_chart_internal_fn.generateTargetX = function (rawX, id, index) {
|
1652 |
|
|
var $$ = this, x;
|
1653 |
|
|
if ($$.isTimeSeries()) {
|
1654 |
|
|
x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
|
1655 |
|
|
}
|
1656 |
|
|
else if ($$.isCustomX() && !$$.isCategorized()) {
|
1657 |
|
|
x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
|
1658 |
|
|
}
|
1659 |
|
|
else {
|
1660 |
|
|
x = index;
|
1661 |
|
|
}
|
1662 |
|
|
return x;
|
1663 |
|
|
};
|
1664 |
|
|
c3_chart_internal_fn.cloneTarget = function (target) {
|
1665 |
|
|
return {
|
1666 |
|
|
id : target.id,
|
1667 |
|
|
id_org : target.id_org,
|
1668 |
|
|
values : target.values.map(function (d) {
|
1669 |
|
|
return {x: d.x, value: d.value, id: d.id};
|
1670 |
|
|
})
|
1671 |
|
|
};
|
1672 |
|
|
};
|
1673 |
|
|
c3_chart_internal_fn.updateXs = function () {
|
1674 |
|
|
var $$ = this;
|
1675 |
|
|
if ($$.data.targets.length) {
|
1676 |
|
|
$$.xs = [];
|
1677 |
|
|
$$.data.targets[0].values.forEach(function (v) {
|
1678 |
|
|
$$.xs[v.index] = v.x;
|
1679 |
|
|
});
|
1680 |
|
|
}
|
1681 |
|
|
};
|
1682 |
|
|
c3_chart_internal_fn.getPrevX = function (i) {
|
1683 |
|
|
var x = this.xs[i - 1];
|
1684 |
|
|
return typeof x !== 'undefined' ? x : null;
|
1685 |
|
|
};
|
1686 |
|
|
c3_chart_internal_fn.getNextX = function (i) {
|
1687 |
|
|
var x = this.xs[i + 1];
|
1688 |
|
|
return typeof x !== 'undefined' ? x : null;
|
1689 |
|
|
};
|
1690 |
|
|
c3_chart_internal_fn.getMaxDataCount = function () {
|
1691 |
|
|
var $$ = this;
|
1692 |
|
|
return $$.d3.max($$.data.targets, function (t) { return t.values.length; });
|
1693 |
|
|
};
|
1694 |
|
|
c3_chart_internal_fn.getMaxDataCountTarget = function (targets) {
|
1695 |
|
|
var length = targets.length, max = 0, maxTarget;
|
1696 |
|
|
if (length > 1) {
|
1697 |
|
|
targets.forEach(function (t) {
|
1698 |
|
|
if (t.values.length > max) {
|
1699 |
|
|
maxTarget = t;
|
1700 |
|
|
max = t.values.length;
|
1701 |
|
|
}
|
1702 |
|
|
});
|
1703 |
|
|
} else {
|
1704 |
|
|
maxTarget = length ? targets[0] : null;
|
1705 |
|
|
}
|
1706 |
|
|
return maxTarget;
|
1707 |
|
|
};
|
1708 |
|
|
c3_chart_internal_fn.getEdgeX = function (targets) {
|
1709 |
|
|
var $$ = this;
|
1710 |
|
|
return !targets.length ? [0, 0] : [
|
1711 |
|
|
$$.d3.min(targets, function (t) { return t.values[0].x; }),
|
1712 |
|
|
$$.d3.max(targets, function (t) { return t.values[t.values.length - 1].x; })
|
1713 |
|
|
];
|
1714 |
|
|
};
|
1715 |
|
|
c3_chart_internal_fn.mapToIds = function (targets) {
|
1716 |
|
|
return targets.map(function (d) { return d.id; });
|
1717 |
|
|
};
|
1718 |
|
|
c3_chart_internal_fn.mapToTargetIds = function (ids) {
|
1719 |
|
|
var $$ = this;
|
1720 |
|
|
return ids ? (isString(ids) ? [ids] : ids) : $$.mapToIds($$.data.targets);
|
1721 |
|
|
};
|
1722 |
|
|
c3_chart_internal_fn.hasTarget = function (targets, id) {
|
1723 |
|
|
var ids = this.mapToIds(targets), i;
|
1724 |
|
|
for (i = 0; i < ids.length; i++) {
|
1725 |
|
|
if (ids[i] === id) {
|
1726 |
|
|
return true;
|
1727 |
|
|
}
|
1728 |
|
|
}
|
1729 |
|
|
return false;
|
1730 |
|
|
};
|
1731 |
|
|
c3_chart_internal_fn.isTargetToShow = function (targetId) {
|
1732 |
|
|
return this.hiddenTargetIds.indexOf(targetId) < 0;
|
1733 |
|
|
};
|
1734 |
|
|
c3_chart_internal_fn.isLegendToShow = function (targetId) {
|
1735 |
|
|
return this.hiddenLegendIds.indexOf(targetId) < 0;
|
1736 |
|
|
};
|
1737 |
|
|
c3_chart_internal_fn.filterTargetsToShow = function (targets) {
|
1738 |
|
|
var $$ = this;
|
1739 |
|
|
return targets.filter(function (t) { return $$.isTargetToShow(t.id); });
|
1740 |
|
|
};
|
1741 |
|
|
c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
|
1742 |
|
|
var $$ = this;
|
1743 |
|
|
var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values();
|
1744 |
|
|
return $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; });
|
1745 |
|
|
};
|
1746 |
|
|
c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
|
1747 |
|
|
this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);
|
1748 |
|
|
};
|
1749 |
|
|
c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) {
|
1750 |
|
|
this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
|
1751 |
|
|
};
|
1752 |
|
|
c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) {
|
1753 |
|
|
this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);
|
1754 |
|
|
};
|
1755 |
|
|
c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) {
|
1756 |
|
|
this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
|
1757 |
|
|
};
|
1758 |
|
|
c3_chart_internal_fn.getValuesAsIdKeyed = function (targets) {
|
1759 |
|
|
var ys = {};
|
1760 |
|
|
targets.forEach(function (t) {
|
1761 |
|
|
ys[t.id] = [];
|
1762 |
|
|
t.values.forEach(function (v) {
|
1763 |
|
|
ys[t.id].push(v.value);
|
1764 |
|
|
});
|
1765 |
|
|
});
|
1766 |
|
|
return ys;
|
1767 |
|
|
};
|
1768 |
|
|
c3_chart_internal_fn.checkValueInTargets = function (targets, checker) {
|
1769 |
|
|
var ids = Object.keys(targets), i, j, values;
|
1770 |
|
|
for (i = 0; i < ids.length; i++) {
|
1771 |
|
|
values = targets[ids[i]].values;
|
1772 |
|
|
for (j = 0; j < values.length; j++) {
|
1773 |
|
|
if (checker(values[j].value)) {
|
1774 |
|
|
return true;
|
1775 |
|
|
}
|
1776 |
|
|
}
|
1777 |
|
|
}
|
1778 |
|
|
return false;
|
1779 |
|
|
};
|
1780 |
|
|
c3_chart_internal_fn.hasNegativeValueInTargets = function (targets) {
|
1781 |
|
|
return this.checkValueInTargets(targets, function (v) { return v < 0; });
|
1782 |
|
|
};
|
1783 |
|
|
c3_chart_internal_fn.hasPositiveValueInTargets = function (targets) {
|
1784 |
|
|
return this.checkValueInTargets(targets, function (v) { return v > 0; });
|
1785 |
|
|
};
|
1786 |
|
|
c3_chart_internal_fn.isOrderDesc = function () {
|
1787 |
|
|
var config = this.config;
|
1788 |
|
|
return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc';
|
1789 |
|
|
};
|
1790 |
|
|
c3_chart_internal_fn.isOrderAsc = function () {
|
1791 |
|
|
var config = this.config;
|
1792 |
|
|
return typeof(config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc';
|
1793 |
|
|
};
|
1794 |
|
|
c3_chart_internal_fn.orderTargets = function (targets) {
|
1795 |
|
|
var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
|
1796 |
|
|
if (orderAsc || orderDesc) {
|
1797 |
|
|
targets.sort(function (t1, t2) {
|
1798 |
|
|
var reducer = function (p, c) { return p + Math.abs(c.value); };
|
1799 |
|
|
var t1Sum = t1.values.reduce(reducer, 0),
|
1800 |
|
|
t2Sum = t2.values.reduce(reducer, 0);
|
1801 |
|
|
return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
|
1802 |
|
|
});
|
1803 |
|
|
} else if (isFunction(config.data_order)) {
|
1804 |
|
|
targets.sort(config.data_order);
|
1805 |
|
|
} // TODO: accept name array for order
|
1806 |
|
|
return targets;
|
1807 |
|
|
};
|
1808 |
|
|
c3_chart_internal_fn.filterByX = function (targets, x) {
|
1809 |
|
|
return this.d3.merge(targets.map(function (t) { return t.values; })).filter(function (v) { return v.x - x === 0; });
|
1810 |
|
|
};
|
1811 |
|
|
c3_chart_internal_fn.filterRemoveNull = function (data) {
|
1812 |
|
|
return data.filter(function (d) { return isValue(d.value); });
|
1813 |
|
|
};
|
1814 |
|
|
c3_chart_internal_fn.filterByXDomain = function (targets, xDomain) {
|
1815 |
|
|
return targets.map(function (t) {
|
1816 |
|
|
return {
|
1817 |
|
|
id: t.id,
|
1818 |
|
|
id_org: t.id_org,
|
1819 |
|
|
values: t.values.filter(function (v) {
|
1820 |
|
|
return xDomain[0] <= v.x && v.x <= xDomain[1];
|
1821 |
|
|
})
|
1822 |
|
|
};
|
1823 |
|
|
});
|
1824 |
|
|
};
|
1825 |
|
|
c3_chart_internal_fn.hasDataLabel = function () {
|
1826 |
|
|
var config = this.config;
|
1827 |
|
|
if (typeof config.data_labels === 'boolean' && config.data_labels) {
|
1828 |
|
|
return true;
|
1829 |
|
|
} else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) {
|
1830 |
|
|
return true;
|
1831 |
|
|
}
|
1832 |
|
|
return false;
|
1833 |
|
|
};
|
1834 |
|
|
c3_chart_internal_fn.getDataLabelLength = function (min, max, key) {
|
1835 |
|
|
var $$ = this,
|
1836 |
|
|
lengths = [0, 0], paddingCoef = 1.3;
|
1837 |
|
|
$$.selectChart.select('svg').selectAll('.dummy')
|
1838 |
|
|
.data([min, max])
|
1839 |
|
|
.enter().append('text')
|
1840 |
|
|
.text(function (d) { return $$.dataLabelFormat(d.id)(d); })
|
1841 |
|
|
.each(function (d, i) {
|
1842 |
|
|
lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
|
1843 |
|
|
})
|
1844 |
|
|
.remove();
|
1845 |
|
|
return lengths;
|
1846 |
|
|
};
|
1847 |
|
|
c3_chart_internal_fn.isNoneArc = function (d) {
|
1848 |
|
|
return this.hasTarget(this.data.targets, d.id);
|
1849 |
|
|
},
|
1850 |
|
|
c3_chart_internal_fn.isArc = function (d) {
|
1851 |
|
|
return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
|
1852 |
|
|
};
|
1853 |
|
|
c3_chart_internal_fn.findSameXOfValues = function (values, index) {
|
1854 |
|
|
var i, targetX = values[index].x, sames = [];
|
1855 |
|
|
for (i = index - 1; i >= 0; i--) {
|
1856 |
|
|
if (targetX !== values[i].x) { break; }
|
1857 |
|
|
sames.push(values[i]);
|
1858 |
|
|
}
|
1859 |
|
|
for (i = index; i < values.length; i++) {
|
1860 |
|
|
if (targetX !== values[i].x) { break; }
|
1861 |
|
|
sames.push(values[i]);
|
1862 |
|
|
}
|
1863 |
|
|
return sames;
|
1864 |
|
|
};
|
1865 |
|
|
|
1866 |
|
|
c3_chart_internal_fn.findClosestFromTargets = function (targets, pos) {
|
1867 |
|
|
var $$ = this, candidates;
|
1868 |
|
|
|
1869 |
|
|
// map to array of closest points of each target
|
1870 |
|
|
candidates = targets.map(function (target) {
|
1871 |
|
|
return $$.findClosest(target.values, pos);
|
1872 |
|
|
});
|
1873 |
|
|
|
1874 |
|
|
// decide closest point and return
|
1875 |
|
|
return $$.findClosest(candidates, pos);
|
1876 |
|
|
};
|
1877 |
|
|
c3_chart_internal_fn.findClosest = function (values, pos) {
|
1878 |
|
|
var $$ = this, minDist = 100, closest;
|
1879 |
|
|
|
1880 |
|
|
// find mouseovering bar
|
1881 |
|
|
values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) {
|
1882 |
|
|
var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();
|
1883 |
|
|
if (!closest && $$.isWithinBar(shape)) {
|
1884 |
|
|
closest = v;
|
1885 |
|
|
}
|
1886 |
|
|
});
|
1887 |
|
|
|
1888 |
|
|
// find closest point from non-bar
|
1889 |
|
|
values.filter(function (v) { return v && !$$.isBarType(v.id); }).forEach(function (v) {
|
1890 |
|
|
var d = $$.dist(v, pos);
|
1891 |
|
|
if (d < minDist) {
|
1892 |
|
|
minDist = d;
|
1893 |
|
|
closest = v;
|
1894 |
|
|
}
|
1895 |
|
|
});
|
1896 |
|
|
|
1897 |
|
|
return closest;
|
1898 |
|
|
};
|
1899 |
|
|
c3_chart_internal_fn.dist = function (data, pos) {
|
1900 |
|
|
var $$ = this, config = $$.config,
|
1901 |
|
|
xIndex = config.axis_rotated ? 1 : 0,
|
1902 |
|
|
yIndex = config.axis_rotated ? 0 : 1,
|
1903 |
|
|
y = $$.circleY(data, data.index),
|
1904 |
|
|
x = $$.x(data.x);
|
1905 |
|
|
return Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2);
|
1906 |
|
|
};
|
1907 |
|
|
c3_chart_internal_fn.convertValuesToStep = function (values) {
|
1908 |
|
|
var converted = [].concat(values), i;
|
1909 |
|
|
|
1910 |
|
|
if (!this.isCategorized()) {
|
1911 |
|
|
return values;
|
1912 |
|
|
}
|
1913 |
|
|
|
1914 |
|
|
for (i = values.length + 1; 0 < i; i--) {
|
1915 |
|
|
converted[i] = converted[i - 1];
|
1916 |
|
|
}
|
1917 |
|
|
|
1918 |
|
|
converted[0] = {
|
1919 |
|
|
x: converted[0].x - 1,
|
1920 |
|
|
value: converted[0].value,
|
1921 |
|
|
id: converted[0].id
|
1922 |
|
|
};
|
1923 |
|
|
converted[values.length + 1] = {
|
1924 |
|
|
x: converted[values.length].x + 1,
|
1925 |
|
|
value: converted[values.length].value,
|
1926 |
|
|
id: converted[values.length].id
|
1927 |
|
|
};
|
1928 |
|
|
|
1929 |
|
|
return converted;
|
1930 |
|
|
};
|
1931 |
|
|
c3_chart_internal_fn.updateDataAttributes = function (name, attrs) {
|
1932 |
|
|
var $$ = this, config = $$.config, current = config['data_' + name];
|
1933 |
|
|
if (typeof attrs === 'undefined') { return current; }
|
1934 |
|
|
Object.keys(attrs).forEach(function (id) {
|
1935 |
|
|
current[id] = attrs[id];
|
1936 |
|
|
});
|
1937 |
|
|
$$.redraw({withLegend: true});
|
1938 |
|
|
return current;
|
1939 |
|
|
};
|
1940 |
|
|
|
1941 |
|
|
c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) {
|
1942 |
|
|
var $$ = this, type = mimeType ? mimeType : 'csv';
|
1943 |
|
|
$$.d3.xhr(url, function (error, data) {
|
1944 |
|
|
var d;
|
1945 |
|
|
if (!data) {
|
1946 |
|
|
throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');
|
1947 |
|
|
}
|
1948 |
|
|
if (type === 'json') {
|
1949 |
|
|
d = $$.convertJsonToData(JSON.parse(data.response), keys);
|
1950 |
|
|
} else if (type === 'tsv') {
|
1951 |
|
|
d = $$.convertTsvToData(data.response);
|
1952 |
|
|
} else {
|
1953 |
|
|
d = $$.convertCsvToData(data.response);
|
1954 |
|
|
}
|
1955 |
|
|
done.call($$, d);
|
1956 |
|
|
});
|
1957 |
|
|
};
|
1958 |
|
|
c3_chart_internal_fn.convertXsvToData = function (xsv, parser) {
|
1959 |
|
|
var rows = parser.parseRows(xsv), d;
|
1960 |
|
|
if (rows.length === 1) {
|
1961 |
|
|
d = [{}];
|
1962 |
|
|
rows[0].forEach(function (id) {
|
1963 |
|
|
d[0][id] = null;
|
1964 |
|
|
});
|
1965 |
|
|
} else {
|
1966 |
|
|
d = parser.parse(xsv);
|
1967 |
|
|
}
|
1968 |
|
|
return d;
|
1969 |
|
|
};
|
1970 |
|
|
c3_chart_internal_fn.convertCsvToData = function (csv) {
|
1971 |
|
|
return this.convertXsvToData(csv, this.d3.csv);
|
1972 |
|
|
};
|
1973 |
|
|
c3_chart_internal_fn.convertTsvToData = function (tsv) {
|
1974 |
|
|
return this.convertXsvToData(tsv, this.d3.tsv);
|
1975 |
|
|
};
|
1976 |
|
|
c3_chart_internal_fn.convertJsonToData = function (json, keys) {
|
1977 |
|
|
var $$ = this,
|
1978 |
|
|
new_rows = [], targetKeys, data;
|
1979 |
|
|
if (keys) { // when keys specified, json would be an array that includes objects
|
1980 |
|
|
if (keys.x) {
|
1981 |
|
|
targetKeys = keys.value.concat(keys.x);
|
1982 |
|
|
$$.config.data_x = keys.x;
|
1983 |
|
|
} else {
|
1984 |
|
|
targetKeys = keys.value;
|
1985 |
|
|
}
|
1986 |
|
|
new_rows.push(targetKeys);
|
1987 |
|
|
json.forEach(function (o) {
|
1988 |
|
|
var new_row = [];
|
1989 |
|
|
targetKeys.forEach(function (key) {
|
1990 |
|
|
// convert undefined to null because undefined data will be removed in convertDataToTargets()
|
1991 |
|
|
var v = isUndefined(o[key]) ? null : o[key];
|
1992 |
|
|
new_row.push(v);
|
1993 |
|
|
});
|
1994 |
|
|
new_rows.push(new_row);
|
1995 |
|
|
});
|
1996 |
|
|
data = $$.convertRowsToData(new_rows);
|
1997 |
|
|
} else {
|
1998 |
|
|
Object.keys(json).forEach(function (key) {
|
1999 |
|
|
new_rows.push([key].concat(json[key]));
|
2000 |
|
|
});
|
2001 |
|
|
data = $$.convertColumnsToData(new_rows);
|
2002 |
|
|
}
|
2003 |
|
|
return data;
|
2004 |
|
|
};
|
2005 |
|
|
c3_chart_internal_fn.convertRowsToData = function (rows) {
|
2006 |
|
|
var keys = rows[0], new_row = {}, new_rows = [], i, j;
|
2007 |
|
|
for (i = 1; i < rows.length; i++) {
|
2008 |
|
|
new_row = {};
|
2009 |
|
|
for (j = 0; j < rows[i].length; j++) {
|
2010 |
|
|
if (isUndefined(rows[i][j])) {
|
2011 |
|
|
throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
|
2012 |
|
|
}
|
2013 |
|
|
new_row[keys[j]] = rows[i][j];
|
2014 |
|
|
}
|
2015 |
|
|
new_rows.push(new_row);
|
2016 |
|
|
}
|
2017 |
|
|
return new_rows;
|
2018 |
|
|
};
|
2019 |
|
|
c3_chart_internal_fn.convertColumnsToData = function (columns) {
|
2020 |
|
|
var new_rows = [], i, j, key;
|
2021 |
|
|
for (i = 0; i < columns.length; i++) {
|
2022 |
|
|
key = columns[i][0];
|
2023 |
|
|
for (j = 1; j < columns[i].length; j++) {
|
2024 |
|
|
if (isUndefined(new_rows[j - 1])) {
|
2025 |
|
|
new_rows[j - 1] = {};
|
2026 |
|
|
}
|
2027 |
|
|
if (isUndefined(columns[i][j])) {
|
2028 |
|
|
throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
|
2029 |
|
|
}
|
2030 |
|
|
new_rows[j - 1][key] = columns[i][j];
|
2031 |
|
|
}
|
2032 |
|
|
}
|
2033 |
|
|
return new_rows;
|
2034 |
|
|
};
|
2035 |
|
|
c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) {
|
2036 |
|
|
var $$ = this, config = $$.config,
|
2037 |
|
|
ids = $$.d3.keys(data[0]).filter($$.isNotX, $$),
|
2038 |
|
|
xs = $$.d3.keys(data[0]).filter($$.isX, $$),
|
2039 |
|
|
targets;
|
2040 |
|
|
|
2041 |
|
|
// save x for update data by load when custom x and c3.x API
|
2042 |
|
|
ids.forEach(function (id) {
|
2043 |
|
|
var xKey = $$.getXKey(id);
|
2044 |
|
|
|
2045 |
|
|
if ($$.isCustomX() || $$.isTimeSeries()) {
|
2046 |
|
|
// if included in input data
|
2047 |
|
|
if (xs.indexOf(xKey) >= 0) {
|
2048 |
|
|
$$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat(
|
2049 |
|
|
data.map(function (d) { return d[xKey]; })
|
2050 |
|
|
.filter(isValue)
|
2051 |
|
|
.map(function (rawX, i) { return $$.generateTargetX(rawX, id, i); })
|
2052 |
|
|
);
|
2053 |
|
|
}
|
2054 |
|
|
// if not included in input data, find from preloaded data of other id's x
|
2055 |
|
|
else if (config.data_x) {
|
2056 |
|
|
$$.data.xs[id] = $$.getOtherTargetXs();
|
2057 |
|
|
}
|
2058 |
|
|
// if not included in input data, find from preloaded data
|
2059 |
|
|
else if (notEmpty(config.data_xs)) {
|
2060 |
|
|
$$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
|
2061 |
|
|
}
|
2062 |
|
|
// MEMO: if no x included, use same x of current will be used
|
2063 |
|
|
} else {
|
2064 |
|
|
$$.data.xs[id] = data.map(function (d, i) { return i; });
|
2065 |
|
|
}
|
2066 |
|
|
});
|
2067 |
|
|
|
2068 |
|
|
|
2069 |
|
|
// check x is defined
|
2070 |
|
|
ids.forEach(function (id) {
|
2071 |
|
|
if (!$$.data.xs[id]) {
|
2072 |
|
|
throw new Error('x is not defined for id = "' + id + '".');
|
2073 |
|
|
}
|
2074 |
|
|
});
|
2075 |
|
|
|
2076 |
|
|
// convert to target
|
2077 |
|
|
targets = ids.map(function (id, index) {
|
2078 |
|
|
var convertedId = config.data_idConverter(id);
|
2079 |
|
|
return {
|
2080 |
|
|
id: convertedId,
|
2081 |
|
|
id_org: id,
|
2082 |
|
|
values: data.map(function (d, i) {
|
2083 |
|
|
var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i);
|
2084 |
|
|
// use x as categories if custom x and categorized
|
2085 |
|
|
if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) {
|
2086 |
|
|
if (i === 0) { config.axis_x_categories = []; }
|
2087 |
|
|
config.axis_x_categories.push(rawX);
|
2088 |
|
|
}
|
2089 |
|
|
// mark as x = undefined if value is undefined and filter to remove after mapped
|
2090 |
|
|
if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
|
2091 |
|
|
x = undefined;
|
2092 |
|
|
}
|
2093 |
|
|
return {x: x, value: d[id] !== null && !isNaN(d[id]) ? +d[id] : null, id: convertedId};
|
2094 |
|
|
}).filter(function (v) { return isDefined(v.x); })
|
2095 |
|
|
};
|
2096 |
|
|
});
|
2097 |
|
|
|
2098 |
|
|
// finish targets
|
2099 |
|
|
targets.forEach(function (t) {
|
2100 |
|
|
var i;
|
2101 |
|
|
// sort values by its x
|
2102 |
|
|
if (config.data_xSort) {
|
2103 |
|
|
t.values = t.values.sort(function (v1, v2) {
|
2104 |
|
|
var x1 = v1.x || v1.x === 0 ? v1.x : Infinity,
|
2105 |
|
|
x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
|
2106 |
|
|
return x1 - x2;
|
2107 |
|
|
});
|
2108 |
|
|
}
|
2109 |
|
|
// indexing each value
|
2110 |
|
|
i = 0;
|
2111 |
|
|
t.values.forEach(function (v) {
|
2112 |
|
|
v.index = i++;
|
2113 |
|
|
});
|
2114 |
|
|
// this needs to be sorted because its index and value.index is identical
|
2115 |
|
|
$$.data.xs[t.id].sort(function (v1, v2) {
|
2116 |
|
|
return v1 - v2;
|
2117 |
|
|
});
|
2118 |
|
|
});
|
2119 |
|
|
|
2120 |
|
|
// set target types
|
2121 |
|
|
if (config.data_type) {
|
2122 |
|
|
$$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type);
|
2123 |
|
|
}
|
2124 |
|
|
|
2125 |
|
|
// cache as original id keyed
|
2126 |
|
|
targets.forEach(function (d) {
|
2127 |
|
|
$$.addCache(d.id_org, d);
|
2128 |
|
|
});
|
2129 |
|
|
|
2130 |
|
|
return targets;
|
2131 |
|
|
};
|
2132 |
|
|
|
2133 |
|
|
c3_chart_internal_fn.load = function (targets, args) {
|
2134 |
|
|
var $$ = this;
|
2135 |
|
|
if (targets) {
|
2136 |
|
|
// filter loading targets if needed
|
2137 |
|
|
if (args.filter) {
|
2138 |
|
|
targets = targets.filter(args.filter);
|
2139 |
|
|
}
|
2140 |
|
|
// set type if args.types || args.type specified
|
2141 |
|
|
if (args.type || args.types) {
|
2142 |
|
|
targets.forEach(function (t) {
|
2143 |
|
|
var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
|
2144 |
|
|
$$.setTargetType(t.id, type);
|
2145 |
|
|
});
|
2146 |
|
|
}
|
2147 |
|
|
// Update/Add data
|
2148 |
|
|
$$.data.targets.forEach(function (d) {
|
2149 |
|
|
for (var i = 0; i < targets.length; i++) {
|
2150 |
|
|
if (d.id === targets[i].id) {
|
2151 |
|
|
d.values = targets[i].values;
|
2152 |
|
|
targets.splice(i, 1);
|
2153 |
|
|
break;
|
2154 |
|
|
}
|
2155 |
|
|
}
|
2156 |
|
|
});
|
2157 |
|
|
$$.data.targets = $$.data.targets.concat(targets); // add remained
|
2158 |
|
|
}
|
2159 |
|
|
|
2160 |
|
|
// Set targets
|
2161 |
|
|
$$.updateTargets($$.data.targets);
|
2162 |
|
|
|
2163 |
|
|
// Redraw with new targets
|
2164 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
|
2165 |
|
|
|
2166 |
|
|
if (args.done) { args.done(); }
|
2167 |
|
|
};
|
2168 |
|
|
c3_chart_internal_fn.loadFromArgs = function (args) {
|
2169 |
|
|
var $$ = this;
|
2170 |
|
|
if (args.data) {
|
2171 |
|
|
$$.load($$.convertDataToTargets(args.data), args);
|
2172 |
|
|
}
|
2173 |
|
|
else if (args.url) {
|
2174 |
|
|
$$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) {
|
2175 |
|
|
$$.load($$.convertDataToTargets(data), args);
|
2176 |
|
|
});
|
2177 |
|
|
}
|
2178 |
|
|
else if (args.json) {
|
2179 |
|
|
$$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
|
2180 |
|
|
}
|
2181 |
|
|
else if (args.rows) {
|
2182 |
|
|
$$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
|
2183 |
|
|
}
|
2184 |
|
|
else if (args.columns) {
|
2185 |
|
|
$$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
|
2186 |
|
|
}
|
2187 |
|
|
else {
|
2188 |
|
|
$$.load(null, args);
|
2189 |
|
|
}
|
2190 |
|
|
};
|
2191 |
|
|
c3_chart_internal_fn.unload = function (targetIds, done) {
|
2192 |
|
|
var $$ = this;
|
2193 |
|
|
if (!done) {
|
2194 |
|
|
done = function () {};
|
2195 |
|
|
}
|
2196 |
|
|
// filter existing target
|
2197 |
|
|
targetIds = targetIds.filter(function (id) { return $$.hasTarget($$.data.targets, id); });
|
2198 |
|
|
// If no target, call done and return
|
2199 |
|
|
if (!targetIds || targetIds.length === 0) {
|
2200 |
|
|
done();
|
2201 |
|
|
return;
|
2202 |
|
|
}
|
2203 |
|
|
$$.svg.selectAll(targetIds.map(function (id) { return $$.selectorTarget(id); }))
|
2204 |
|
|
.transition()
|
2205 |
|
|
.style('opacity', 0)
|
2206 |
|
|
.remove()
|
2207 |
|
|
.call($$.endall, done);
|
2208 |
|
|
targetIds.forEach(function (id) {
|
2209 |
|
|
// Reset fadein for future load
|
2210 |
|
|
$$.withoutFadeIn[id] = false;
|
2211 |
|
|
// Remove target's elements
|
2212 |
|
|
if ($$.legend) {
|
2213 |
|
|
$$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();
|
2214 |
|
|
}
|
2215 |
|
|
// Remove target
|
2216 |
|
|
$$.data.targets = $$.data.targets.filter(function (t) {
|
2217 |
|
|
return t.id !== id;
|
2218 |
|
|
});
|
2219 |
|
|
});
|
2220 |
|
|
};
|
2221 |
|
|
|
2222 |
|
|
c3_chart_internal_fn.categoryName = function (i) {
|
2223 |
|
|
var config = this.config;
|
2224 |
|
|
return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
|
2225 |
|
|
};
|
2226 |
|
|
|
2227 |
|
|
c3_chart_internal_fn.initEventRect = function () {
|
2228 |
|
|
var $$ = this;
|
2229 |
|
|
$$.main.select('.' + CLASS.chart).append("g")
|
2230 |
|
|
.attr("class", CLASS.eventRects)
|
2231 |
|
|
.style('fill-opacity', 0);
|
2232 |
|
|
};
|
2233 |
|
|
c3_chart_internal_fn.redrawEventRect = function () {
|
2234 |
|
|
var $$ = this, config = $$.config,
|
2235 |
|
|
eventRectUpdate, maxDataCountTarget,
|
2236 |
|
|
isMultipleX = $$.isMultipleX();
|
2237 |
|
|
|
2238 |
|
|
// rects for mouseover
|
2239 |
|
|
var eventRects = $$.main.select('.' + CLASS.eventRects)
|
2240 |
|
|
.style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null)
|
2241 |
|
|
.classed(CLASS.eventRectsMultiple, isMultipleX)
|
2242 |
|
|
.classed(CLASS.eventRectsSingle, !isMultipleX);
|
2243 |
|
|
|
2244 |
|
|
// clear old rects
|
2245 |
|
|
eventRects.selectAll('.' + CLASS.eventRect).remove();
|
2246 |
|
|
|
2247 |
|
|
// open as public variable
|
2248 |
|
|
$$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
|
2249 |
|
|
|
2250 |
|
|
if (isMultipleX) {
|
2251 |
|
|
eventRectUpdate = $$.eventRect.data([0]);
|
2252 |
|
|
// enter : only one rect will be added
|
2253 |
|
|
$$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
|
2254 |
|
|
// update
|
2255 |
|
|
$$.updateEventRect(eventRectUpdate);
|
2256 |
|
|
// exit : not needed because always only one rect exists
|
2257 |
|
|
}
|
2258 |
|
|
else {
|
2259 |
|
|
// Set data and update $$.eventRect
|
2260 |
|
|
maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
|
2261 |
|
|
eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
|
2262 |
|
|
$$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);
|
2263 |
|
|
eventRectUpdate = $$.eventRect.data(function (d) { return d; });
|
2264 |
|
|
// enter
|
2265 |
|
|
$$.generateEventRectsForSingleX(eventRectUpdate.enter());
|
2266 |
|
|
// update
|
2267 |
|
|
$$.updateEventRect(eventRectUpdate);
|
2268 |
|
|
// exit
|
2269 |
|
|
eventRectUpdate.exit().remove();
|
2270 |
|
|
}
|
2271 |
|
|
};
|
2272 |
|
|
c3_chart_internal_fn.updateEventRect = function (eventRectUpdate) {
|
2273 |
|
|
var $$ = this, config = $$.config,
|
2274 |
|
|
x, y, w, h, rectW, rectX;
|
2275 |
|
|
|
2276 |
|
|
// set update selection if null
|
2277 |
|
|
eventRectUpdate = eventRectUpdate || $$.eventRect.data(function (d) { return d; });
|
2278 |
|
|
|
2279 |
|
|
if ($$.isMultipleX()) {
|
2280 |
|
|
// TODO: rotated not supported yet
|
2281 |
|
|
x = 0;
|
2282 |
|
|
y = 0;
|
2283 |
|
|
w = $$.width;
|
2284 |
|
|
h = $$.height;
|
2285 |
|
|
}
|
2286 |
|
|
else {
|
2287 |
|
|
if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
|
2288 |
|
|
|
2289 |
|
|
// update index for x that is used by prevX and nextX
|
2290 |
|
|
$$.updateXs();
|
2291 |
|
|
|
2292 |
|
|
rectW = function (d) {
|
2293 |
|
|
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index);
|
2294 |
|
|
|
2295 |
|
|
// if there this is a single data point make the eventRect full width (or height)
|
2296 |
|
|
if (prevX === null && nextX === null) {
|
2297 |
|
|
return config.axis_rotated ? $$.height : $$.width;
|
2298 |
|
|
}
|
2299 |
|
|
|
2300 |
|
|
if (prevX === null) { prevX = $$.x.domain()[0]; }
|
2301 |
|
|
if (nextX === null) { nextX = $$.x.domain()[1]; }
|
2302 |
|
|
|
2303 |
|
|
return Math.max(0, ($$.x(nextX) - $$.x(prevX)) / 2);
|
2304 |
|
|
};
|
2305 |
|
|
rectX = function (d) {
|
2306 |
|
|
var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index),
|
2307 |
|
|
thisX = $$.data.xs[d.id][d.index];
|
2308 |
|
|
|
2309 |
|
|
// if there this is a single data point position the eventRect at 0
|
2310 |
|
|
if (prevX === null && nextX === null) {
|
2311 |
|
|
return 0;
|
2312 |
|
|
}
|
2313 |
|
|
|
2314 |
|
|
if (prevX === null) { prevX = $$.x.domain()[0]; }
|
2315 |
|
|
|
2316 |
|
|
return ($$.x(thisX) + $$.x(prevX)) / 2;
|
2317 |
|
|
};
|
2318 |
|
|
} else {
|
2319 |
|
|
rectW = $$.getEventRectWidth();
|
2320 |
|
|
rectX = function (d) {
|
2321 |
|
|
return $$.x(d.x) - (rectW / 2);
|
2322 |
|
|
};
|
2323 |
|
|
}
|
2324 |
|
|
x = config.axis_rotated ? 0 : rectX;
|
2325 |
|
|
y = config.axis_rotated ? rectX : 0;
|
2326 |
|
|
w = config.axis_rotated ? $$.width : rectW;
|
2327 |
|
|
h = config.axis_rotated ? rectW : $$.height;
|
2328 |
|
|
}
|
2329 |
|
|
|
2330 |
|
|
eventRectUpdate
|
2331 |
|
|
.attr('class', $$.classEvent.bind($$))
|
2332 |
|
|
.attr("x", x)
|
2333 |
|
|
.attr("y", y)
|
2334 |
|
|
.attr("width", w)
|
2335 |
|
|
.attr("height", h);
|
2336 |
|
|
};
|
2337 |
|
|
c3_chart_internal_fn.generateEventRectsForSingleX = function (eventRectEnter) {
|
2338 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config;
|
2339 |
|
|
eventRectEnter.append("rect")
|
2340 |
|
|
.attr("class", $$.classEvent.bind($$))
|
2341 |
|
|
.style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null)
|
2342 |
|
|
.on('mouseover', function (d) {
|
2343 |
|
|
var index = d.index;
|
2344 |
|
|
|
2345 |
|
|
if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing
|
2346 |
|
|
if ($$.hasArcType()) { return; }
|
2347 |
|
|
|
2348 |
|
|
// Expand shapes for selection
|
2349 |
|
|
if (config.point_focus_expand_enabled) { $$.expandCircles(index, null, true); }
|
2350 |
|
|
$$.expandBars(index, null, true);
|
2351 |
|
|
|
2352 |
|
|
// Call event handler
|
2353 |
|
|
$$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
|
2354 |
|
|
config.data_onmouseover.call($$.api, d);
|
2355 |
|
|
});
|
2356 |
|
|
})
|
2357 |
|
|
.on('mouseout', function (d) {
|
2358 |
|
|
var index = d.index;
|
2359 |
|
|
if (!$$.config) { return; } // chart is destroyed
|
2360 |
|
|
if ($$.hasArcType()) { return; }
|
2361 |
|
|
$$.hideXGridFocus();
|
2362 |
|
|
$$.hideTooltip();
|
2363 |
|
|
// Undo expanded shapes
|
2364 |
|
|
$$.unexpandCircles();
|
2365 |
|
|
$$.unexpandBars();
|
2366 |
|
|
// Call event handler
|
2367 |
|
|
$$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
|
2368 |
|
|
config.data_onmouseout.call($$.api, d);
|
2369 |
|
|
});
|
2370 |
|
|
})
|
2371 |
|
|
.on('mousemove', function (d) {
|
2372 |
|
|
var selectedData, index = d.index,
|
2373 |
|
|
eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index);
|
2374 |
|
|
|
2375 |
|
|
if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing
|
2376 |
|
|
if ($$.hasArcType()) { return; }
|
2377 |
|
|
|
2378 |
|
|
if ($$.isStepType(d) && $$.config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
|
2379 |
|
|
index -= 1;
|
2380 |
|
|
}
|
2381 |
|
|
|
2382 |
|
|
// Show tooltip
|
2383 |
|
|
selectedData = $$.filterTargetsToShow($$.data.targets).map(function (t) {
|
2384 |
|
|
return $$.addName($$.getValueOnIndex(t.values, index));
|
2385 |
|
|
});
|
2386 |
|
|
|
2387 |
|
|
if (config.tooltip_grouped) {
|
2388 |
|
|
$$.showTooltip(selectedData, this);
|
2389 |
|
|
$$.showXGridFocus(selectedData);
|
2390 |
|
|
}
|
2391 |
|
|
|
2392 |
|
|
if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) {
|
2393 |
|
|
return;
|
2394 |
|
|
}
|
2395 |
|
|
|
2396 |
|
|
$$.main.selectAll('.' + CLASS.shape + '-' + index)
|
2397 |
|
|
.each(function () {
|
2398 |
|
|
d3.select(this).classed(CLASS.EXPANDED, true);
|
2399 |
|
|
if (config.data_selection_enabled) {
|
2400 |
|
|
eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null);
|
2401 |
|
|
}
|
2402 |
|
|
if (!config.tooltip_grouped) {
|
2403 |
|
|
$$.hideXGridFocus();
|
2404 |
|
|
$$.hideTooltip();
|
2405 |
|
|
if (!config.data_selection_grouped) {
|
2406 |
|
|
$$.unexpandCircles(index);
|
2407 |
|
|
$$.unexpandBars(index);
|
2408 |
|
|
}
|
2409 |
|
|
}
|
2410 |
|
|
})
|
2411 |
|
|
.filter(function (d) {
|
2412 |
|
|
return $$.isWithinShape(this, d);
|
2413 |
|
|
})
|
2414 |
|
|
.each(function (d) {
|
2415 |
|
|
if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) {
|
2416 |
|
|
eventRect.style('cursor', 'pointer');
|
2417 |
|
|
}
|
2418 |
|
|
if (!config.tooltip_grouped) {
|
2419 |
|
|
$$.showTooltip([d], this);
|
2420 |
|
|
$$.showXGridFocus([d]);
|
2421 |
|
|
if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id, true); }
|
2422 |
|
|
$$.expandBars(index, d.id, true);
|
2423 |
|
|
}
|
2424 |
|
|
});
|
2425 |
|
|
})
|
2426 |
|
|
.on('click', function (d) {
|
2427 |
|
|
var index = d.index;
|
2428 |
|
|
if ($$.hasArcType() || !$$.toggleShape) { return; }
|
2429 |
|
|
if ($$.cancelClick) {
|
2430 |
|
|
$$.cancelClick = false;
|
2431 |
|
|
return;
|
2432 |
|
|
}
|
2433 |
|
|
if ($$.isStepType(d) && config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
|
2434 |
|
|
index -= 1;
|
2435 |
|
|
}
|
2436 |
|
|
$$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {
|
2437 |
|
|
if (config.data_selection_grouped || $$.isWithinShape(this, d)) {
|
2438 |
|
|
$$.toggleShape(this, d, index);
|
2439 |
|
|
$$.config.data_onclick.call($$.api, d, this);
|
2440 |
|
|
}
|
2441 |
|
|
});
|
2442 |
|
|
})
|
2443 |
|
|
.call(
|
2444 |
|
|
config.data_selection_draggable && $$.drag ? (
|
2445 |
|
|
d3.behavior.drag().origin(Object)
|
2446 |
|
|
.on('drag', function () { $$.drag(d3.mouse(this)); })
|
2447 |
|
|
.on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
|
2448 |
|
|
.on('dragend', function () { $$.dragend(); })
|
2449 |
|
|
) : function () {}
|
2450 |
|
|
);
|
2451 |
|
|
};
|
2452 |
|
|
|
2453 |
|
|
c3_chart_internal_fn.generateEventRectsForMultipleXs = function (eventRectEnter) {
|
2454 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config;
|
2455 |
|
|
|
2456 |
|
|
function mouseout() {
|
2457 |
|
|
$$.svg.select('.' + CLASS.eventRect).style('cursor', null);
|
2458 |
|
|
$$.hideXGridFocus();
|
2459 |
|
|
$$.hideTooltip();
|
2460 |
|
|
$$.unexpandCircles();
|
2461 |
|
|
$$.unexpandBars();
|
2462 |
|
|
}
|
2463 |
|
|
|
2464 |
|
|
eventRectEnter.append('rect')
|
2465 |
|
|
.attr('x', 0)
|
2466 |
|
|
.attr('y', 0)
|
2467 |
|
|
.attr('width', $$.width)
|
2468 |
|
|
.attr('height', $$.height)
|
2469 |
|
|
.attr('class', CLASS.eventRect)
|
2470 |
|
|
.on('mouseout', function () {
|
2471 |
|
|
if (!$$.config) { return; } // chart is destroyed
|
2472 |
|
|
if ($$.hasArcType()) { return; }
|
2473 |
|
|
mouseout();
|
2474 |
|
|
})
|
2475 |
|
|
.on('mousemove', function () {
|
2476 |
|
|
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
|
2477 |
|
|
var mouse, closest, sameXData, selectedData;
|
2478 |
|
|
|
2479 |
|
|
if ($$.dragging) { return; } // do nothing when dragging
|
2480 |
|
|
if ($$.hasArcType(targetsToShow)) { return; }
|
2481 |
|
|
|
2482 |
|
|
mouse = d3.mouse(this);
|
2483 |
|
|
closest = $$.findClosestFromTargets(targetsToShow, mouse);
|
2484 |
|
|
|
2485 |
|
|
if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {
|
2486 |
|
|
config.data_onmouseout.call($$.api, $$.mouseover);
|
2487 |
|
|
$$.mouseover = undefined;
|
2488 |
|
|
}
|
2489 |
|
|
|
2490 |
|
|
if (! closest) {
|
2491 |
|
|
mouseout();
|
2492 |
|
|
return;
|
2493 |
|
|
}
|
2494 |
|
|
|
2495 |
|
|
if ($$.isScatterType(closest) || !config.tooltip_grouped) {
|
2496 |
|
|
sameXData = [closest];
|
2497 |
|
|
} else {
|
2498 |
|
|
sameXData = $$.filterByX(targetsToShow, closest.x);
|
2499 |
|
|
}
|
2500 |
|
|
|
2501 |
|
|
// show tooltip when cursor is close to some point
|
2502 |
|
|
selectedData = sameXData.map(function (d) {
|
2503 |
|
|
return $$.addName(d);
|
2504 |
|
|
});
|
2505 |
|
|
$$.showTooltip(selectedData, this);
|
2506 |
|
|
|
2507 |
|
|
// expand points
|
2508 |
|
|
if (config.point_focus_expand_enabled) {
|
2509 |
|
|
$$.expandCircles(closest.index, closest.id, true);
|
2510 |
|
|
}
|
2511 |
|
|
$$.expandBars(closest.index, closest.id, true);
|
2512 |
|
|
|
2513 |
|
|
// Show xgrid focus line
|
2514 |
|
|
$$.showXGridFocus(selectedData);
|
2515 |
|
|
|
2516 |
|
|
// Show cursor as pointer if point is close to mouse position
|
2517 |
|
|
if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
|
2518 |
|
|
$$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
|
2519 |
|
|
if (!$$.mouseover) {
|
2520 |
|
|
config.data_onmouseover.call($$.api, closest);
|
2521 |
|
|
$$.mouseover = closest;
|
2522 |
|
|
}
|
2523 |
|
|
}
|
2524 |
|
|
})
|
2525 |
|
|
.on('click', function () {
|
2526 |
|
|
var targetsToShow = $$.filterTargetsToShow($$.data.targets);
|
2527 |
|
|
var mouse, closest;
|
2528 |
|
|
|
2529 |
|
|
if ($$.hasArcType(targetsToShow)) { return; }
|
2530 |
|
|
|
2531 |
|
|
mouse = d3.mouse(this);
|
2532 |
|
|
closest = $$.findClosestFromTargets(targetsToShow, mouse);
|
2533 |
|
|
|
2534 |
|
|
if (! closest) { return; }
|
2535 |
|
|
|
2536 |
|
|
// select if selection enabled
|
2537 |
|
|
if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
|
2538 |
|
|
$$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll('.' + CLASS.shape + '-' + closest.index).each(function () {
|
2539 |
|
|
if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
|
2540 |
|
|
$$.toggleShape(this, closest, closest.index);
|
2541 |
|
|
$$.config.data_onclick.call($$.api, closest, this);
|
2542 |
|
|
}
|
2543 |
|
|
});
|
2544 |
|
|
}
|
2545 |
|
|
})
|
2546 |
|
|
.call(
|
2547 |
|
|
config.data_selection_draggable && $$.drag ? (
|
2548 |
|
|
d3.behavior.drag().origin(Object)
|
2549 |
|
|
.on('drag', function () { $$.drag(d3.mouse(this)); })
|
2550 |
|
|
.on('dragstart', function () { $$.dragstart(d3.mouse(this)); })
|
2551 |
|
|
.on('dragend', function () { $$.dragend(); })
|
2552 |
|
|
) : function () {}
|
2553 |
|
|
);
|
2554 |
|
|
};
|
2555 |
|
|
c3_chart_internal_fn.dispatchEvent = function (type, index, mouse) {
|
2556 |
|
|
var $$ = this,
|
2557 |
|
|
selector = '.' + CLASS.eventRect + (!$$.isMultipleX() ? '-' + index : ''),
|
2558 |
|
|
eventRect = $$.main.select(selector).node(),
|
2559 |
|
|
box = eventRect.getBoundingClientRect(),
|
2560 |
|
|
x = box.left + (mouse ? mouse[0] : 0),
|
2561 |
|
|
y = box.top + (mouse ? mouse[1] : 0),
|
2562 |
|
|
event = document.createEvent("MouseEvents");
|
2563 |
|
|
|
2564 |
|
|
event.initMouseEvent(type, true, true, window, 0, x, y, x, y,
|
2565 |
|
|
false, false, false, false, 0, null);
|
2566 |
|
|
eventRect.dispatchEvent(event);
|
2567 |
|
|
};
|
2568 |
|
|
|
2569 |
|
|
c3_chart_internal_fn.getCurrentWidth = function () {
|
2570 |
|
|
var $$ = this, config = $$.config;
|
2571 |
|
|
return config.size_width ? config.size_width : $$.getParentWidth();
|
2572 |
|
|
};
|
2573 |
|
|
c3_chart_internal_fn.getCurrentHeight = function () {
|
2574 |
|
|
var $$ = this, config = $$.config,
|
2575 |
|
|
h = config.size_height ? config.size_height : $$.getParentHeight();
|
2576 |
|
|
return h > 0 ? h : 320 / ($$.hasType('gauge') ? 2 : 1);
|
2577 |
|
|
};
|
2578 |
|
|
c3_chart_internal_fn.getCurrentPaddingTop = function () {
|
2579 |
|
|
var config = this.config;
|
2580 |
|
|
return isValue(config.padding_top) ? config.padding_top : 0;
|
2581 |
|
|
};
|
2582 |
|
|
c3_chart_internal_fn.getCurrentPaddingBottom = function () {
|
2583 |
|
|
var config = this.config;
|
2584 |
|
|
return isValue(config.padding_bottom) ? config.padding_bottom : 0;
|
2585 |
|
|
};
|
2586 |
|
|
c3_chart_internal_fn.getCurrentPaddingLeft = function (withoutRecompute) {
|
2587 |
|
|
var $$ = this, config = $$.config;
|
2588 |
|
|
if (isValue(config.padding_left)) {
|
2589 |
|
|
return config.padding_left;
|
2590 |
|
|
} else if (config.axis_rotated) {
|
2591 |
|
|
return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
|
2592 |
|
|
} else if (!config.axis_y_show || config.axis_y_inner) { // && !config.axis_rotated
|
2593 |
|
|
return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
|
2594 |
|
|
} else {
|
2595 |
|
|
return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
|
2596 |
|
|
}
|
2597 |
|
|
};
|
2598 |
|
|
c3_chart_internal_fn.getCurrentPaddingRight = function () {
|
2599 |
|
|
var $$ = this, config = $$.config,
|
2600 |
|
|
defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
|
2601 |
|
|
if (isValue(config.padding_right)) {
|
2602 |
|
|
return config.padding_right + 1; // 1 is needed not to hide tick line
|
2603 |
|
|
} else if (config.axis_rotated) {
|
2604 |
|
|
return defaultPadding + legendWidthOnRight;
|
2605 |
|
|
} else if (!config.axis_y2_show || config.axis_y2_inner) { // && !config.axis_rotated
|
2606 |
|
|
return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
|
2607 |
|
|
} else {
|
2608 |
|
|
return ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
|
2609 |
|
|
}
|
2610 |
|
|
};
|
2611 |
|
|
|
2612 |
|
|
c3_chart_internal_fn.getParentRectValue = function (key) {
|
2613 |
|
|
var parent = this.selectChart.node(), v;
|
2614 |
|
|
while (parent && parent.tagName !== 'BODY') {
|
2615 |
|
|
try {
|
2616 |
|
|
v = parent.getBoundingClientRect()[key];
|
2617 |
|
|
} catch(e) {
|
2618 |
|
|
if (key === 'width') {
|
2619 |
|
|
// In IE in certain cases getBoundingClientRect
|
2620 |
|
|
// will cause an "unspecified error"
|
2621 |
|
|
v = parent.offsetWidth;
|
2622 |
|
|
}
|
2623 |
|
|
}
|
2624 |
|
|
if (v) {
|
2625 |
|
|
break;
|
2626 |
|
|
}
|
2627 |
|
|
parent = parent.parentNode;
|
2628 |
|
|
}
|
2629 |
|
|
return v;
|
2630 |
|
|
};
|
2631 |
|
|
c3_chart_internal_fn.getParentWidth = function () {
|
2632 |
|
|
return this.getParentRectValue('width');
|
2633 |
|
|
};
|
2634 |
|
|
c3_chart_internal_fn.getParentHeight = function () {
|
2635 |
|
|
var h = this.selectChart.style('height');
|
2636 |
|
|
return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;
|
2637 |
|
|
};
|
2638 |
|
|
|
2639 |
|
|
|
2640 |
|
|
c3_chart_internal_fn.getSvgLeft = function (withoutRecompute) {
|
2641 |
|
|
var $$ = this, config = $$.config,
|
2642 |
|
|
hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner),
|
2643 |
|
|
leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
|
2644 |
|
|
leftAxis = $$.main.select('.' + leftAxisClass).node(),
|
2645 |
|
|
svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {right: 0},
|
2646 |
|
|
chartRect = $$.selectChart.node().getBoundingClientRect(),
|
2647 |
|
|
hasArc = $$.hasArcType(),
|
2648 |
|
|
svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
|
2649 |
|
|
return svgLeft > 0 ? svgLeft : 0;
|
2650 |
|
|
};
|
2651 |
|
|
|
2652 |
|
|
|
2653 |
|
|
c3_chart_internal_fn.getAxisWidthByAxisId = function (id, withoutRecompute) {
|
2654 |
|
|
var $$ = this, position = $$.axis.getLabelPositionById(id);
|
2655 |
|
|
return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40);
|
2656 |
|
|
};
|
2657 |
|
|
c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) {
|
2658 |
|
|
var $$ = this, config = $$.config, h = 30;
|
2659 |
|
|
if (axisId === 'x' && !config.axis_x_show) { return 8; }
|
2660 |
|
|
if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
|
2661 |
|
|
if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; }
|
2662 |
|
|
if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
|
2663 |
|
|
// Calculate x axis height when tick rotated
|
2664 |
|
|
if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
|
2665 |
|
|
h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
|
2666 |
|
|
}
|
2667 |
|
|
return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
|
2668 |
|
|
};
|
2669 |
|
|
|
2670 |
|
|
c3_chart_internal_fn.getEventRectWidth = function () {
|
2671 |
|
|
return Math.max(0, this.xAxis.tickInterval());
|
2672 |
|
|
};
|
2673 |
|
|
|
2674 |
|
|
c3_chart_internal_fn.getShapeIndices = function (typeFilter) {
|
2675 |
|
|
var $$ = this, config = $$.config,
|
2676 |
|
|
indices = {}, i = 0, j, k;
|
2677 |
|
|
$$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
|
2678 |
|
|
for (j = 0; j < config.data_groups.length; j++) {
|
2679 |
|
|
if (config.data_groups[j].indexOf(d.id) < 0) { continue; }
|
2680 |
|
|
for (k = 0; k < config.data_groups[j].length; k++) {
|
2681 |
|
|
if (config.data_groups[j][k] in indices) {
|
2682 |
|
|
indices[d.id] = indices[config.data_groups[j][k]];
|
2683 |
|
|
break;
|
2684 |
|
|
}
|
2685 |
|
|
}
|
2686 |
|
|
}
|
2687 |
|
|
if (isUndefined(indices[d.id])) { indices[d.id] = i++; }
|
2688 |
|
|
});
|
2689 |
|
|
indices.__max__ = i - 1;
|
2690 |
|
|
return indices;
|
2691 |
|
|
};
|
2692 |
|
|
c3_chart_internal_fn.getShapeX = function (offset, targetsNum, indices, isSub) {
|
2693 |
|
|
var $$ = this, scale = isSub ? $$.subX : $$.x;
|
2694 |
|
|
return function (d) {
|
2695 |
|
|
var index = d.id in indices ? indices[d.id] : 0;
|
2696 |
|
|
return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
|
2697 |
|
|
};
|
2698 |
|
|
};
|
2699 |
|
|
c3_chart_internal_fn.getShapeY = function (isSub) {
|
2700 |
|
|
var $$ = this;
|
2701 |
|
|
return function (d) {
|
2702 |
|
|
var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
|
2703 |
|
|
return scale(d.value);
|
2704 |
|
|
};
|
2705 |
|
|
};
|
2706 |
|
|
c3_chart_internal_fn.getShapeOffset = function (typeFilter, indices, isSub) {
|
2707 |
|
|
var $$ = this,
|
2708 |
|
|
targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))),
|
2709 |
|
|
targetIds = targets.map(function (t) { return t.id; });
|
2710 |
|
|
return function (d, i) {
|
2711 |
|
|
var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),
|
2712 |
|
|
y0 = scale(0), offset = y0;
|
2713 |
|
|
targets.forEach(function (t) {
|
2714 |
|
|
var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;
|
2715 |
|
|
if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; }
|
2716 |
|
|
if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
|
2717 |
|
|
if (values[i].value * d.value >= 0) {
|
2718 |
|
|
offset += scale(values[i].value) - y0;
|
2719 |
|
|
}
|
2720 |
|
|
}
|
2721 |
|
|
});
|
2722 |
|
|
return offset;
|
2723 |
|
|
};
|
2724 |
|
|
};
|
2725 |
|
|
c3_chart_internal_fn.isWithinShape = function (that, d) {
|
2726 |
|
|
var $$ = this,
|
2727 |
|
|
shape = $$.d3.select(that), isWithin;
|
2728 |
|
|
if (!$$.isTargetToShow(d.id)) {
|
2729 |
|
|
isWithin = false;
|
2730 |
|
|
}
|
2731 |
|
|
else if (that.nodeName === 'circle') {
|
2732 |
|
|
isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
|
2733 |
|
|
}
|
2734 |
|
|
else if (that.nodeName === 'path') {
|
2735 |
|
|
isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true;
|
2736 |
|
|
}
|
2737 |
|
|
return isWithin;
|
2738 |
|
|
};
|
2739 |
|
|
|
2740 |
|
|
|
2741 |
|
|
c3_chart_internal_fn.getInterpolate = function (d) {
|
2742 |
|
|
var $$ = this;
|
2743 |
|
|
return $$.isSplineType(d) ? "cardinal" : $$.isStepType(d) ? $$.config.line_step_type : "linear";
|
2744 |
|
|
};
|
2745 |
|
|
|
2746 |
|
|
c3_chart_internal_fn.initLine = function () {
|
2747 |
|
|
var $$ = this;
|
2748 |
|
|
$$.main.select('.' + CLASS.chart).append("g")
|
2749 |
|
|
.attr("class", CLASS.chartLines);
|
2750 |
|
|
};
|
2751 |
|
|
c3_chart_internal_fn.updateTargetsForLine = function (targets) {
|
2752 |
|
|
var $$ = this, config = $$.config,
|
2753 |
|
|
mainLineUpdate, mainLineEnter,
|
2754 |
|
|
classChartLine = $$.classChartLine.bind($$),
|
2755 |
|
|
classLines = $$.classLines.bind($$),
|
2756 |
|
|
classAreas = $$.classAreas.bind($$),
|
2757 |
|
|
classCircles = $$.classCircles.bind($$),
|
2758 |
|
|
classFocus = $$.classFocus.bind($$);
|
2759 |
|
|
mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
|
2760 |
|
|
.data(targets)
|
2761 |
|
|
.attr('class', function (d) { return classChartLine(d) + classFocus(d); });
|
2762 |
|
|
mainLineEnter = mainLineUpdate.enter().append('g')
|
2763 |
|
|
.attr('class', classChartLine)
|
2764 |
|
|
.style('opacity', 0)
|
2765 |
|
|
.style("pointer-events", "none");
|
2766 |
|
|
// Lines for each data
|
2767 |
|
|
mainLineEnter.append('g')
|
2768 |
|
|
.attr("class", classLines);
|
2769 |
|
|
// Areas
|
2770 |
|
|
mainLineEnter.append('g')
|
2771 |
|
|
.attr('class', classAreas);
|
2772 |
|
|
// Circles for each data point on lines
|
2773 |
|
|
mainLineEnter.append('g')
|
2774 |
|
|
.attr("class", function (d) { return $$.generateClass(CLASS.selectedCircles, d.id); });
|
2775 |
|
|
mainLineEnter.append('g')
|
2776 |
|
|
.attr("class", classCircles)
|
2777 |
|
|
.style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
|
2778 |
|
|
// Update date for selected circles
|
2779 |
|
|
targets.forEach(function (t) {
|
2780 |
|
|
$$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) {
|
2781 |
|
|
d.value = t.values[d.index].value;
|
2782 |
|
|
});
|
2783 |
|
|
});
|
2784 |
|
|
// MEMO: can not keep same color...
|
2785 |
|
|
//mainLineUpdate.exit().remove();
|
2786 |
|
|
};
|
2787 |
|
|
c3_chart_internal_fn.updateLine = function (durationForExit) {
|
2788 |
|
|
var $$ = this;
|
2789 |
|
|
$$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
|
2790 |
|
|
.data($$.lineData.bind($$));
|
2791 |
|
|
$$.mainLine.enter().append('path')
|
2792 |
|
|
.attr('class', $$.classLine.bind($$))
|
2793 |
|
|
.style("stroke", $$.color);
|
2794 |
|
|
$$.mainLine
|
2795 |
|
|
.style("opacity", $$.initialOpacity.bind($$))
|
2796 |
|
|
.style('shape-rendering', function (d) { return $$.isStepType(d) ? 'crispEdges' : ''; })
|
2797 |
|
|
.attr('transform', null);
|
2798 |
|
|
$$.mainLine.exit().transition().duration(durationForExit)
|
2799 |
|
|
.style('opacity', 0)
|
2800 |
|
|
.remove();
|
2801 |
|
|
};
|
2802 |
|
|
c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) {
|
2803 |
|
|
return [
|
2804 |
|
|
(withTransition ? this.mainLine.transition() : this.mainLine)
|
2805 |
|
|
.attr("d", drawLine)
|
2806 |
|
|
.style("stroke", this.color)
|
2807 |
|
|
.style("opacity", 1)
|
2808 |
|
|
];
|
2809 |
|
|
};
|
2810 |
|
|
c3_chart_internal_fn.generateDrawLine = function (lineIndices, isSub) {
|
2811 |
|
|
var $$ = this, config = $$.config,
|
2812 |
|
|
line = $$.d3.svg.line(),
|
2813 |
|
|
getPoints = $$.generateGetLinePoints(lineIndices, isSub),
|
2814 |
|
|
yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
|
2815 |
|
|
xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
|
2816 |
|
|
yValue = function (d, i) {
|
2817 |
|
|
return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);
|
2818 |
|
|
};
|
2819 |
|
|
|
2820 |
|
|
line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
|
2821 |
|
|
if (!config.line_connectNull) { line = line.defined(function (d) { return d.value != null; }); }
|
2822 |
|
|
return function (d) {
|
2823 |
|
|
var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
|
2824 |
|
|
x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
|
2825 |
|
|
if ($$.isLineType(d)) {
|
2826 |
|
|
if (config.data_regions[d.id]) {
|
2827 |
|
|
path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
|
2828 |
|
|
} else {
|
2829 |
|
|
if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }
|
2830 |
|
|
path = line.interpolate($$.getInterpolate(d))(values);
|
2831 |
|
|
}
|
2832 |
|
|
} else {
|
2833 |
|
|
if (values[0]) {
|
2834 |
|
|
x0 = x(values[0].x);
|
2835 |
|
|
y0 = y(values[0].value);
|
2836 |
|
|
}
|
2837 |
|
|
path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
|
2838 |
|
|
}
|
2839 |
|
|
return path ? path : "M 0 0";
|
2840 |
|
|
};
|
2841 |
|
|
};
|
2842 |
|
|
c3_chart_internal_fn.generateGetLinePoints = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints
|
2843 |
|
|
var $$ = this, config = $$.config,
|
2844 |
|
|
lineTargetsNum = lineIndices.__max__ + 1,
|
2845 |
|
|
x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),
|
2846 |
|
|
y = $$.getShapeY(!!isSub),
|
2847 |
|
|
lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),
|
2848 |
|
|
yScale = isSub ? $$.getSubYScale : $$.getYScale;
|
2849 |
|
|
return function (d, i) {
|
2850 |
|
|
var y0 = yScale.call($$, d.id)(0),
|
2851 |
|
|
offset = lineOffset(d, i) || y0, // offset is for stacked area chart
|
2852 |
|
|
posX = x(d), posY = y(d);
|
2853 |
|
|
// fix posY not to overflow opposite quadrant
|
2854 |
|
|
if (config.axis_rotated) {
|
2855 |
|
|
if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
|
2856 |
|
|
}
|
2857 |
|
|
// 1 point that marks the line position
|
2858 |
|
|
return [
|
2859 |
|
|
[posX, posY - (y0 - offset)],
|
2860 |
|
|
[posX, posY - (y0 - offset)], // needed for compatibility
|
2861 |
|
|
[posX, posY - (y0 - offset)], // needed for compatibility
|
2862 |
|
|
[posX, posY - (y0 - offset)] // needed for compatibility
|
2863 |
|
|
];
|
2864 |
|
|
};
|
2865 |
|
|
};
|
2866 |
|
|
|
2867 |
|
|
|
2868 |
|
|
c3_chart_internal_fn.lineWithRegions = function (d, x, y, _regions) {
|
2869 |
|
|
var $$ = this, config = $$.config,
|
2870 |
|
|
prev = -1, i, j,
|
2871 |
|
|
s = "M", sWithRegion,
|
2872 |
|
|
xp, yp, dx, dy, dd, diff, diffx2,
|
2873 |
|
|
xOffset = $$.isCategorized() ? 0.5 : 0,
|
2874 |
|
|
xValue, yValue,
|
2875 |
|
|
regions = [];
|
2876 |
|
|
|
2877 |
|
|
function isWithinRegions(x, regions) {
|
2878 |
|
|
var i;
|
2879 |
|
|
for (i = 0; i < regions.length; i++) {
|
2880 |
|
|
if (regions[i].start < x && x <= regions[i].end) { return true; }
|
2881 |
|
|
}
|
2882 |
|
|
return false;
|
2883 |
|
|
}
|
2884 |
|
|
|
2885 |
|
|
// Check start/end of regions
|
2886 |
|
|
if (isDefined(_regions)) {
|
2887 |
|
|
for (i = 0; i < _regions.length; i++) {
|
2888 |
|
|
regions[i] = {};
|
2889 |
|
|
if (isUndefined(_regions[i].start)) {
|
2890 |
|
|
regions[i].start = d[0].x;
|
2891 |
|
|
} else {
|
2892 |
|
|
regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;
|
2893 |
|
|
}
|
2894 |
|
|
if (isUndefined(_regions[i].end)) {
|
2895 |
|
|
regions[i].end = d[d.length - 1].x;
|
2896 |
|
|
} else {
|
2897 |
|
|
regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;
|
2898 |
|
|
}
|
2899 |
|
|
}
|
2900 |
|
|
}
|
2901 |
|
|
|
2902 |
|
|
// Set scales
|
2903 |
|
|
xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); };
|
2904 |
|
|
yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); };
|
2905 |
|
|
|
2906 |
|
|
// Define svg generator function for region
|
2907 |
|
|
function generateM(points) {
|
2908 |
|
|
return 'M' + points[0][0] + ' ' + points[0][1] + ' ' + points[1][0] + ' ' + points[1][1];
|
2909 |
|
|
}
|
2910 |
|
|
if ($$.isTimeSeries()) {
|
2911 |
|
|
sWithRegion = function (d0, d1, j, diff) {
|
2912 |
|
|
var x0 = d0.x.getTime(), x_diff = d1.x - d0.x,
|
2913 |
|
|
xv0 = new Date(x0 + x_diff * j),
|
2914 |
|
|
xv1 = new Date(x0 + x_diff * (j + diff)),
|
2915 |
|
|
points;
|
2916 |
|
|
if (config.axis_rotated) {
|
2917 |
|
|
points = [[y(yp(j)), x(xv0)], [y(yp(j + diff)), x(xv1)]];
|
2918 |
|
|
} else {
|
2919 |
|
|
points = [[x(xv0), y(yp(j))], [x(xv1), y(yp(j + diff))]];
|
2920 |
|
|
}
|
2921 |
|
|
return generateM(points);
|
2922 |
|
|
};
|
2923 |
|
|
} else {
|
2924 |
|
|
sWithRegion = function (d0, d1, j, diff) {
|
2925 |
|
|
var points;
|
2926 |
|
|
if (config.axis_rotated) {
|
2927 |
|
|
points = [[y(yp(j), true), x(xp(j))], [y(yp(j + diff), true), x(xp(j + diff))]];
|
2928 |
|
|
} else {
|
2929 |
|
|
points = [[x(xp(j), true), y(yp(j))], [x(xp(j + diff), true), y(yp(j + diff))]];
|
2930 |
|
|
}
|
2931 |
|
|
return generateM(points);
|
2932 |
|
|
};
|
2933 |
|
|
}
|
2934 |
|
|
|
2935 |
|
|
// Generate
|
2936 |
|
|
for (i = 0; i < d.length; i++) {
|
2937 |
|
|
|
2938 |
|
|
// Draw as normal
|
2939 |
|
|
if (isUndefined(regions) || ! isWithinRegions(d[i].x, regions)) {
|
2940 |
|
|
s += " " + xValue(d[i]) + " " + yValue(d[i]);
|
2941 |
|
|
}
|
2942 |
|
|
// Draw with region // TODO: Fix for horizotal charts
|
2943 |
|
|
else {
|
2944 |
|
|
xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
|
2945 |
|
|
yp = $$.getScale(d[i - 1].value, d[i].value);
|
2946 |
|
|
|
2947 |
|
|
dx = x(d[i].x) - x(d[i - 1].x);
|
2948 |
|
|
dy = y(d[i].value) - y(d[i - 1].value);
|
2949 |
|
|
dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
|
2950 |
|
|
diff = 2 / dd;
|
2951 |
|
|
diffx2 = diff * 2;
|
2952 |
|
|
|
2953 |
|
|
for (j = diff; j <= 1; j += diffx2) {
|
2954 |
|
|
s += sWithRegion(d[i - 1], d[i], j, diff);
|
2955 |
|
|
}
|
2956 |
|
|
}
|
2957 |
|
|
prev = d[i].x;
|
2958 |
|
|
}
|
2959 |
|
|
|
2960 |
|
|
return s;
|
2961 |
|
|
};
|
2962 |
|
|
|
2963 |
|
|
|
2964 |
|
|
c3_chart_internal_fn.updateArea = function (durationForExit) {
|
2965 |
|
|
var $$ = this, d3 = $$.d3;
|
2966 |
|
|
$$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
|
2967 |
|
|
.data($$.lineData.bind($$));
|
2968 |
|
|
$$.mainArea.enter().append('path')
|
2969 |
|
|
.attr("class", $$.classArea.bind($$))
|
2970 |
|
|
.style("fill", $$.color)
|
2971 |
|
|
.style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
|
2972 |
|
|
$$.mainArea
|
2973 |
|
|
.style("opacity", $$.orgAreaOpacity);
|
2974 |
|
|
$$.mainArea.exit().transition().duration(durationForExit)
|
2975 |
|
|
.style('opacity', 0)
|
2976 |
|
|
.remove();
|
2977 |
|
|
};
|
2978 |
|
|
c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) {
|
2979 |
|
|
return [
|
2980 |
|
|
(withTransition ? this.mainArea.transition() : this.mainArea)
|
2981 |
|
|
.attr("d", drawArea)
|
2982 |
|
|
.style("fill", this.color)
|
2983 |
|
|
.style("opacity", this.orgAreaOpacity)
|
2984 |
|
|
];
|
2985 |
|
|
};
|
2986 |
|
|
c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) {
|
2987 |
|
|
var $$ = this, config = $$.config, area = $$.d3.svg.area(),
|
2988 |
|
|
getPoints = $$.generateGetAreaPoints(areaIndices, isSub),
|
2989 |
|
|
yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
|
2990 |
|
|
xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },
|
2991 |
|
|
value0 = function (d, i) {
|
2992 |
|
|
return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
|
2993 |
|
|
},
|
2994 |
|
|
value1 = function (d, i) {
|
2995 |
|
|
return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
|
2996 |
|
|
};
|
2997 |
|
|
|
2998 |
|
|
area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1);
|
2999 |
|
|
if (!config.line_connectNull) {
|
3000 |
|
|
area = area.defined(function (d) { return d.value !== null; });
|
3001 |
|
|
}
|
3002 |
|
|
|
3003 |
|
|
return function (d) {
|
3004 |
|
|
var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
|
3005 |
|
|
x0 = 0, y0 = 0, path;
|
3006 |
|
|
if ($$.isAreaType(d)) {
|
3007 |
|
|
if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }
|
3008 |
|
|
path = area.interpolate($$.getInterpolate(d))(values);
|
3009 |
|
|
} else {
|
3010 |
|
|
if (values[0]) {
|
3011 |
|
|
x0 = $$.x(values[0].x);
|
3012 |
|
|
y0 = $$.getYScale(d.id)(values[0].value);
|
3013 |
|
|
}
|
3014 |
|
|
path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
|
3015 |
|
|
}
|
3016 |
|
|
return path ? path : "M 0 0";
|
3017 |
|
|
};
|
3018 |
|
|
};
|
3019 |
|
|
c3_chart_internal_fn.getAreaBaseValue = function () {
|
3020 |
|
|
return 0;
|
3021 |
|
|
};
|
3022 |
|
|
c3_chart_internal_fn.generateGetAreaPoints = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints
|
3023 |
|
|
var $$ = this, config = $$.config,
|
3024 |
|
|
areaTargetsNum = areaIndices.__max__ + 1,
|
3025 |
|
|
x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),
|
3026 |
|
|
y = $$.getShapeY(!!isSub),
|
3027 |
|
|
areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),
|
3028 |
|
|
yScale = isSub ? $$.getSubYScale : $$.getYScale;
|
3029 |
|
|
return function (d, i) {
|
3030 |
|
|
var y0 = yScale.call($$, d.id)(0),
|
3031 |
|
|
offset = areaOffset(d, i) || y0, // offset is for stacked area chart
|
3032 |
|
|
posX = x(d), posY = y(d);
|
3033 |
|
|
// fix posY not to overflow opposite quadrant
|
3034 |
|
|
if (config.axis_rotated) {
|
3035 |
|
|
if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
|
3036 |
|
|
}
|
3037 |
|
|
// 1 point that marks the area position
|
3038 |
|
|
return [
|
3039 |
|
|
[posX, offset],
|
3040 |
|
|
[posX, posY - (y0 - offset)],
|
3041 |
|
|
[posX, posY - (y0 - offset)], // needed for compatibility
|
3042 |
|
|
[posX, offset] // needed for compatibility
|
3043 |
|
|
];
|
3044 |
|
|
};
|
3045 |
|
|
};
|
3046 |
|
|
|
3047 |
|
|
|
3048 |
|
|
c3_chart_internal_fn.updateCircle = function () {
|
3049 |
|
|
var $$ = this;
|
3050 |
|
|
$$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle)
|
3051 |
|
|
.data($$.lineOrScatterData.bind($$));
|
3052 |
|
|
$$.mainCircle.enter().append("circle")
|
3053 |
|
|
.attr("class", $$.classCircle.bind($$))
|
3054 |
|
|
.attr("r", $$.pointR.bind($$))
|
3055 |
|
|
.style("fill", $$.color);
|
3056 |
|
|
$$.mainCircle
|
3057 |
|
|
.style("opacity", $$.initialOpacityForCircle.bind($$));
|
3058 |
|
|
$$.mainCircle.exit().remove();
|
3059 |
|
|
};
|
3060 |
|
|
c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) {
|
3061 |
|
|
var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle);
|
3062 |
|
|
return [
|
3063 |
|
|
(withTransition ? this.mainCircle.transition() : this.mainCircle)
|
3064 |
|
|
.style('opacity', this.opacityForCircle.bind(this))
|
3065 |
|
|
.style("fill", this.color)
|
3066 |
|
|
.attr("cx", cx)
|
3067 |
|
|
.attr("cy", cy),
|
3068 |
|
|
(withTransition ? selectedCircles.transition() : selectedCircles)
|
3069 |
|
|
.attr("cx", cx)
|
3070 |
|
|
.attr("cy", cy)
|
3071 |
|
|
];
|
3072 |
|
|
};
|
3073 |
|
|
c3_chart_internal_fn.circleX = function (d) {
|
3074 |
|
|
return d.x || d.x === 0 ? this.x(d.x) : null;
|
3075 |
|
|
};
|
3076 |
|
|
c3_chart_internal_fn.updateCircleY = function () {
|
3077 |
|
|
var $$ = this, lineIndices, getPoints;
|
3078 |
|
|
if ($$.config.data_groups.length > 0) {
|
3079 |
|
|
lineIndices = $$.getShapeIndices($$.isLineType),
|
3080 |
|
|
getPoints = $$.generateGetLinePoints(lineIndices);
|
3081 |
|
|
$$.circleY = function (d, i) {
|
3082 |
|
|
return getPoints(d, i)[0][1];
|
3083 |
|
|
};
|
3084 |
|
|
} else {
|
3085 |
|
|
$$.circleY = function (d) {
|
3086 |
|
|
return $$.getYScale(d.id)(d.value);
|
3087 |
|
|
};
|
3088 |
|
|
}
|
3089 |
|
|
};
|
3090 |
|
|
c3_chart_internal_fn.getCircles = function (i, id) {
|
3091 |
|
|
var $$ = this;
|
3092 |
|
|
return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
|
3093 |
|
|
};
|
3094 |
|
|
c3_chart_internal_fn.expandCircles = function (i, id, reset) {
|
3095 |
|
|
var $$ = this,
|
3096 |
|
|
r = $$.pointExpandedR.bind($$);
|
3097 |
|
|
if (reset) { $$.unexpandCircles(); }
|
3098 |
|
|
$$.getCircles(i, id)
|
3099 |
|
|
.classed(CLASS.EXPANDED, true)
|
3100 |
|
|
.attr('r', r);
|
3101 |
|
|
};
|
3102 |
|
|
c3_chart_internal_fn.unexpandCircles = function (i) {
|
3103 |
|
|
var $$ = this,
|
3104 |
|
|
r = $$.pointR.bind($$);
|
3105 |
|
|
$$.getCircles(i)
|
3106 |
|
|
.filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); })
|
3107 |
|
|
.classed(CLASS.EXPANDED, false)
|
3108 |
|
|
.attr('r', r);
|
3109 |
|
|
};
|
3110 |
|
|
c3_chart_internal_fn.pointR = function (d) {
|
3111 |
|
|
var $$ = this, config = $$.config;
|
3112 |
|
|
return $$.isStepType(d) ? 0 : (isFunction(config.point_r) ? config.point_r(d) : config.point_r);
|
3113 |
|
|
};
|
3114 |
|
|
c3_chart_internal_fn.pointExpandedR = function (d) {
|
3115 |
|
|
var $$ = this, config = $$.config;
|
3116 |
|
|
return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d);
|
3117 |
|
|
};
|
3118 |
|
|
c3_chart_internal_fn.pointSelectR = function (d) {
|
3119 |
|
|
var $$ = this, config = $$.config;
|
3120 |
|
|
return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
|
3121 |
|
|
};
|
3122 |
|
|
c3_chart_internal_fn.isWithinCircle = function (that, r) {
|
3123 |
|
|
var d3 = this.d3,
|
3124 |
|
|
mouse = d3.mouse(that), d3_this = d3.select(that),
|
3125 |
|
|
cx = +d3_this.attr("cx"), cy = +d3_this.attr("cy");
|
3126 |
|
|
return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
|
3127 |
|
|
};
|
3128 |
|
|
c3_chart_internal_fn.isWithinStep = function (that, y) {
|
3129 |
|
|
return Math.abs(y - this.d3.mouse(that)[1]) < 30;
|
3130 |
|
|
};
|
3131 |
|
|
|
3132 |
|
|
c3_chart_internal_fn.initBar = function () {
|
3133 |
|
|
var $$ = this;
|
3134 |
|
|
$$.main.select('.' + CLASS.chart).append("g")
|
3135 |
|
|
.attr("class", CLASS.chartBars);
|
3136 |
|
|
};
|
3137 |
|
|
c3_chart_internal_fn.updateTargetsForBar = function (targets) {
|
3138 |
|
|
var $$ = this, config = $$.config,
|
3139 |
|
|
mainBarUpdate, mainBarEnter,
|
3140 |
|
|
classChartBar = $$.classChartBar.bind($$),
|
3141 |
|
|
classBars = $$.classBars.bind($$),
|
3142 |
|
|
classFocus = $$.classFocus.bind($$);
|
3143 |
|
|
mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
|
3144 |
|
|
.data(targets)
|
3145 |
|
|
.attr('class', function (d) { return classChartBar(d) + classFocus(d); });
|
3146 |
|
|
mainBarEnter = mainBarUpdate.enter().append('g')
|
3147 |
|
|
.attr('class', classChartBar)
|
3148 |
|
|
.style('opacity', 0)
|
3149 |
|
|
.style("pointer-events", "none");
|
3150 |
|
|
// Bars for each data
|
3151 |
|
|
mainBarEnter.append('g')
|
3152 |
|
|
.attr("class", classBars)
|
3153 |
|
|
.style("cursor", function (d) { return config.data_selection_isselectable(d) ? "pointer" : null; });
|
3154 |
|
|
|
3155 |
|
|
};
|
3156 |
|
|
c3_chart_internal_fn.updateBar = function (durationForExit) {
|
3157 |
|
|
var $$ = this,
|
3158 |
|
|
barData = $$.barData.bind($$),
|
3159 |
|
|
classBar = $$.classBar.bind($$),
|
3160 |
|
|
initialOpacity = $$.initialOpacity.bind($$),
|
3161 |
|
|
color = function (d) { return $$.color(d.id); };
|
3162 |
|
|
$$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
|
3163 |
|
|
.data(barData);
|
3164 |
|
|
$$.mainBar.enter().append('path')
|
3165 |
|
|
.attr("class", classBar)
|
3166 |
|
|
.style("stroke", color)
|
3167 |
|
|
.style("fill", color);
|
3168 |
|
|
$$.mainBar
|
3169 |
|
|
.style("opacity", initialOpacity);
|
3170 |
|
|
$$.mainBar.exit().transition().duration(durationForExit)
|
3171 |
|
|
.style('opacity', 0)
|
3172 |
|
|
.remove();
|
3173 |
|
|
};
|
3174 |
|
|
c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) {
|
3175 |
|
|
return [
|
3176 |
|
|
(withTransition ? this.mainBar.transition() : this.mainBar)
|
3177 |
|
|
.attr('d', drawBar)
|
3178 |
|
|
.style("fill", this.color)
|
3179 |
|
|
.style("opacity", 1)
|
3180 |
|
|
];
|
3181 |
|
|
};
|
3182 |
|
|
c3_chart_internal_fn.getBarW = function (axis, barTargetsNum) {
|
3183 |
|
|
var $$ = this, config = $$.config,
|
3184 |
|
|
w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum : 0;
|
3185 |
|
|
return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
|
3186 |
|
|
};
|
3187 |
|
|
c3_chart_internal_fn.getBars = function (i, id) {
|
3188 |
|
|
var $$ = this;
|
3189 |
|
|
return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
|
3190 |
|
|
};
|
3191 |
|
|
c3_chart_internal_fn.expandBars = function (i, id, reset) {
|
3192 |
|
|
var $$ = this;
|
3193 |
|
|
if (reset) { $$.unexpandBars(); }
|
3194 |
|
|
$$.getBars(i, id).classed(CLASS.EXPANDED, true);
|
3195 |
|
|
};
|
3196 |
|
|
c3_chart_internal_fn.unexpandBars = function (i) {
|
3197 |
|
|
var $$ = this;
|
3198 |
|
|
$$.getBars(i).classed(CLASS.EXPANDED, false);
|
3199 |
|
|
};
|
3200 |
|
|
c3_chart_internal_fn.generateDrawBar = function (barIndices, isSub) {
|
3201 |
|
|
var $$ = this, config = $$.config,
|
3202 |
|
|
getPoints = $$.generateGetBarPoints(barIndices, isSub);
|
3203 |
|
|
return function (d, i) {
|
3204 |
|
|
// 4 points that make a bar
|
3205 |
|
|
var points = getPoints(d, i);
|
3206 |
|
|
|
3207 |
|
|
// switch points if axis is rotated, not applicable for sub chart
|
3208 |
|
|
var indexX = config.axis_rotated ? 1 : 0;
|
3209 |
|
|
var indexY = config.axis_rotated ? 0 : 1;
|
3210 |
|
|
|
3211 |
|
|
var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +
|
3212 |
|
|
'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' +
|
3213 |
|
|
'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' +
|
3214 |
|
|
'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' +
|
3215 |
|
|
'z';
|
3216 |
|
|
|
3217 |
|
|
return path;
|
3218 |
|
|
};
|
3219 |
|
|
};
|
3220 |
|
|
c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
|
3221 |
|
|
var $$ = this,
|
3222 |
|
|
axis = isSub ? $$.subXAxis : $$.xAxis,
|
3223 |
|
|
barTargetsNum = barIndices.__max__ + 1,
|
3224 |
|
|
barW = $$.getBarW(axis, barTargetsNum),
|
3225 |
|
|
barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
|
3226 |
|
|
barY = $$.getShapeY(!!isSub),
|
3227 |
|
|
barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
|
3228 |
|
|
yScale = isSub ? $$.getSubYScale : $$.getYScale;
|
3229 |
|
|
return function (d, i) {
|
3230 |
|
|
var y0 = yScale.call($$, d.id)(0),
|
3231 |
|
|
offset = barOffset(d, i) || y0, // offset is for stacked bar chart
|
3232 |
|
|
posX = barX(d), posY = barY(d);
|
3233 |
|
|
// fix posY not to overflow opposite quadrant
|
3234 |
|
|
if ($$.config.axis_rotated) {
|
3235 |
|
|
if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }
|
3236 |
|
|
}
|
3237 |
|
|
// 4 points that make a bar
|
3238 |
|
|
return [
|
3239 |
|
|
[posX, offset],
|
3240 |
|
|
[posX, posY - (y0 - offset)],
|
3241 |
|
|
[posX + barW, posY - (y0 - offset)],
|
3242 |
|
|
[posX + barW, offset]
|
3243 |
|
|
];
|
3244 |
|
|
};
|
3245 |
|
|
};
|
3246 |
|
|
c3_chart_internal_fn.isWithinBar = function (that) {
|
3247 |
|
|
var mouse = this.d3.mouse(that), box = that.getBoundingClientRect(),
|
3248 |
|
|
seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1),
|
3249 |
|
|
x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y),
|
3250 |
|
|
w = box.width, h = box.height, offset = 2,
|
3251 |
|
|
sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset;
|
3252 |
|
|
return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
|
3253 |
|
|
};
|
3254 |
|
|
|
3255 |
|
|
c3_chart_internal_fn.initText = function () {
|
3256 |
|
|
var $$ = this;
|
3257 |
|
|
$$.main.select('.' + CLASS.chart).append("g")
|
3258 |
|
|
.attr("class", CLASS.chartTexts);
|
3259 |
|
|
$$.mainText = $$.d3.selectAll([]);
|
3260 |
|
|
};
|
3261 |
|
|
c3_chart_internal_fn.updateTargetsForText = function (targets) {
|
3262 |
|
|
var $$ = this, mainTextUpdate, mainTextEnter,
|
3263 |
|
|
classChartText = $$.classChartText.bind($$),
|
3264 |
|
|
classTexts = $$.classTexts.bind($$),
|
3265 |
|
|
classFocus = $$.classFocus.bind($$);
|
3266 |
|
|
mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText)
|
3267 |
|
|
.data(targets)
|
3268 |
|
|
.attr('class', function (d) { return classChartText(d) + classFocus(d); });
|
3269 |
|
|
mainTextEnter = mainTextUpdate.enter().append('g')
|
3270 |
|
|
.attr('class', classChartText)
|
3271 |
|
|
.style('opacity', 0)
|
3272 |
|
|
.style("pointer-events", "none");
|
3273 |
|
|
mainTextEnter.append('g')
|
3274 |
|
|
.attr('class', classTexts);
|
3275 |
|
|
};
|
3276 |
|
|
c3_chart_internal_fn.updateText = function (durationForExit) {
|
3277 |
|
|
var $$ = this, config = $$.config,
|
3278 |
|
|
barOrLineData = $$.barOrLineData.bind($$),
|
3279 |
|
|
classText = $$.classText.bind($$);
|
3280 |
|
|
$$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text)
|
3281 |
|
|
.data(barOrLineData);
|
3282 |
|
|
$$.mainText.enter().append('text')
|
3283 |
|
|
.attr("class", classText)
|
3284 |
|
|
.attr('text-anchor', function (d) { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })
|
3285 |
|
|
.style("stroke", 'none')
|
3286 |
|
|
.style("fill", function (d) { return $$.color(d); })
|
3287 |
|
|
.style("fill-opacity", 0);
|
3288 |
|
|
$$.mainText
|
3289 |
|
|
.text(function (d, i, j) { return $$.dataLabelFormat(d.id)(d.value, d.id, i, j); });
|
3290 |
|
|
$$.mainText.exit()
|
3291 |
|
|
.transition().duration(durationForExit)
|
3292 |
|
|
.style('fill-opacity', 0)
|
3293 |
|
|
.remove();
|
3294 |
|
|
};
|
3295 |
|
|
c3_chart_internal_fn.redrawText = function (xForText, yForText, forFlow, withTransition) {
|
3296 |
|
|
return [
|
3297 |
|
|
(withTransition ? this.mainText.transition() : this.mainText)
|
3298 |
|
|
.attr('x', xForText)
|
3299 |
|
|
.attr('y', yForText)
|
3300 |
|
|
.style("fill", this.color)
|
3301 |
|
|
.style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
|
3302 |
|
|
];
|
3303 |
|
|
};
|
3304 |
|
|
c3_chart_internal_fn.getTextRect = function (text, cls) {
|
3305 |
|
|
var dummy = this.d3.select('body').append('div').classed('c3', true),
|
3306 |
|
|
svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
|
3307 |
|
|
rect;
|
3308 |
|
|
svg.selectAll('.dummy')
|
3309 |
|
|
.data([text])
|
3310 |
|
|
.enter().append('text')
|
3311 |
|
|
.classed(cls ? cls : "", true)
|
3312 |
|
|
.text(text)
|
3313 |
|
|
.each(function () { rect = this.getBoundingClientRect(); });
|
3314 |
|
|
dummy.remove();
|
3315 |
|
|
return rect;
|
3316 |
|
|
};
|
3317 |
|
|
c3_chart_internal_fn.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {
|
3318 |
|
|
var $$ = this,
|
3319 |
|
|
getAreaPoints = $$.generateGetAreaPoints(areaIndices, false),
|
3320 |
|
|
getBarPoints = $$.generateGetBarPoints(barIndices, false),
|
3321 |
|
|
getLinePoints = $$.generateGetLinePoints(lineIndices, false),
|
3322 |
|
|
getter = forX ? $$.getXForText : $$.getYForText;
|
3323 |
|
|
return function (d, i) {
|
3324 |
|
|
var getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints;
|
3325 |
|
|
return getter.call($$, getPoints(d, i), d, this);
|
3326 |
|
|
};
|
3327 |
|
|
};
|
3328 |
|
|
c3_chart_internal_fn.getXForText = function (points, d, textElement) {
|
3329 |
|
|
var $$ = this,
|
3330 |
|
|
box = textElement.getBoundingClientRect(), xPos, padding;
|
3331 |
|
|
if ($$.config.axis_rotated) {
|
3332 |
|
|
padding = $$.isBarType(d) ? 4 : 6;
|
3333 |
|
|
xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
|
3334 |
|
|
} else {
|
3335 |
|
|
xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
|
3336 |
|
|
}
|
3337 |
|
|
// show labels regardless of the domain if value is null
|
3338 |
|
|
if (d.value === null) {
|
3339 |
|
|
if (xPos > $$.width) {
|
3340 |
|
|
xPos = $$.width - box.width;
|
3341 |
|
|
} else if (xPos < 0) {
|
3342 |
|
|
xPos = 4;
|
3343 |
|
|
}
|
3344 |
|
|
}
|
3345 |
|
|
return xPos;
|
3346 |
|
|
};
|
3347 |
|
|
c3_chart_internal_fn.getYForText = function (points, d, textElement) {
|
3348 |
|
|
var $$ = this,
|
3349 |
|
|
box = textElement.getBoundingClientRect(),
|
3350 |
|
|
yPos;
|
3351 |
|
|
if ($$.config.axis_rotated) {
|
3352 |
|
|
yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
|
3353 |
|
|
} else {
|
3354 |
|
|
yPos = points[2][1];
|
3355 |
|
|
if (d.value < 0) {
|
3356 |
|
|
yPos += box.height;
|
3357 |
|
|
if ($$.isBarType(d) && $$.isSafari()) {
|
3358 |
|
|
yPos -= 3;
|
3359 |
|
|
}
|
3360 |
|
|
else if (!$$.isBarType(d) && $$.isChrome()) {
|
3361 |
|
|
yPos += 3;
|
3362 |
|
|
}
|
3363 |
|
|
} else {
|
3364 |
|
|
yPos += $$.isBarType(d) ? -3 : -6;
|
3365 |
|
|
}
|
3366 |
|
|
}
|
3367 |
|
|
// show labels regardless of the domain if value is null
|
3368 |
|
|
if (d.value === null && !$$.config.axis_rotated) {
|
3369 |
|
|
if (yPos < box.height) {
|
3370 |
|
|
yPos = box.height;
|
3371 |
|
|
} else if (yPos > this.height) {
|
3372 |
|
|
yPos = this.height - 4;
|
3373 |
|
|
}
|
3374 |
|
|
}
|
3375 |
|
|
return yPos;
|
3376 |
|
|
};
|
3377 |
|
|
|
3378 |
|
|
c3_chart_internal_fn.setTargetType = function (targetIds, type) {
|
3379 |
|
|
var $$ = this, config = $$.config;
|
3380 |
|
|
$$.mapToTargetIds(targetIds).forEach(function (id) {
|
3381 |
|
|
$$.withoutFadeIn[id] = (type === config.data_types[id]);
|
3382 |
|
|
config.data_types[id] = type;
|
3383 |
|
|
});
|
3384 |
|
|
if (!targetIds) {
|
3385 |
|
|
config.data_type = type;
|
3386 |
|
|
}
|
3387 |
|
|
};
|
3388 |
|
|
c3_chart_internal_fn.hasType = function (type, targets) {
|
3389 |
|
|
var $$ = this, types = $$.config.data_types, has = false;
|
3390 |
|
|
targets = targets || $$.data.targets;
|
3391 |
|
|
if (targets && targets.length) {
|
3392 |
|
|
targets.forEach(function (target) {
|
3393 |
|
|
var t = types[target.id];
|
3394 |
|
|
if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) {
|
3395 |
|
|
has = true;
|
3396 |
|
|
}
|
3397 |
|
|
});
|
3398 |
|
|
} else if (Object.keys(types).length) {
|
3399 |
|
|
Object.keys(types).forEach(function (id) {
|
3400 |
|
|
if (types[id] === type) { has = true; }
|
3401 |
|
|
});
|
3402 |
|
|
} else {
|
3403 |
|
|
has = $$.config.data_type === type;
|
3404 |
|
|
}
|
3405 |
|
|
return has;
|
3406 |
|
|
};
|
3407 |
|
|
c3_chart_internal_fn.hasArcType = function (targets) {
|
3408 |
|
|
return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets);
|
3409 |
|
|
};
|
3410 |
|
|
c3_chart_internal_fn.isLineType = function (d) {
|
3411 |
|
|
var config = this.config, id = isString(d) ? d : d.id;
|
3412 |
|
|
return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0;
|
3413 |
|
|
};
|
3414 |
|
|
c3_chart_internal_fn.isStepType = function (d) {
|
3415 |
|
|
var id = isString(d) ? d : d.id;
|
3416 |
|
|
return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
|
3417 |
|
|
};
|
3418 |
|
|
c3_chart_internal_fn.isSplineType = function (d) {
|
3419 |
|
|
var id = isString(d) ? d : d.id;
|
3420 |
|
|
return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
|
3421 |
|
|
};
|
3422 |
|
|
c3_chart_internal_fn.isAreaType = function (d) {
|
3423 |
|
|
var id = isString(d) ? d : d.id;
|
3424 |
|
|
return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
|
3425 |
|
|
};
|
3426 |
|
|
c3_chart_internal_fn.isBarType = function (d) {
|
3427 |
|
|
var id = isString(d) ? d : d.id;
|
3428 |
|
|
return this.config.data_types[id] === 'bar';
|
3429 |
|
|
};
|
3430 |
|
|
c3_chart_internal_fn.isScatterType = function (d) {
|
3431 |
|
|
var id = isString(d) ? d : d.id;
|
3432 |
|
|
return this.config.data_types[id] === 'scatter';
|
3433 |
|
|
};
|
3434 |
|
|
c3_chart_internal_fn.isPieType = function (d) {
|
3435 |
|
|
var id = isString(d) ? d : d.id;
|
3436 |
|
|
return this.config.data_types[id] === 'pie';
|
3437 |
|
|
};
|
3438 |
|
|
c3_chart_internal_fn.isGaugeType = function (d) {
|
3439 |
|
|
var id = isString(d) ? d : d.id;
|
3440 |
|
|
return this.config.data_types[id] === 'gauge';
|
3441 |
|
|
};
|
3442 |
|
|
c3_chart_internal_fn.isDonutType = function (d) {
|
3443 |
|
|
var id = isString(d) ? d : d.id;
|
3444 |
|
|
return this.config.data_types[id] === 'donut';
|
3445 |
|
|
};
|
3446 |
|
|
c3_chart_internal_fn.isArcType = function (d) {
|
3447 |
|
|
return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
|
3448 |
|
|
};
|
3449 |
|
|
c3_chart_internal_fn.lineData = function (d) {
|
3450 |
|
|
return this.isLineType(d) ? [d] : [];
|
3451 |
|
|
};
|
3452 |
|
|
c3_chart_internal_fn.arcData = function (d) {
|
3453 |
|
|
return this.isArcType(d.data) ? [d] : [];
|
3454 |
|
|
};
|
3455 |
|
|
/* not used
|
3456 |
|
|
function scatterData(d) {
|
3457 |
|
|
return isScatterType(d) ? d.values : [];
|
3458 |
|
|
}
|
3459 |
|
|
*/
|
3460 |
|
|
c3_chart_internal_fn.barData = function (d) {
|
3461 |
|
|
return this.isBarType(d) ? d.values : [];
|
3462 |
|
|
};
|
3463 |
|
|
c3_chart_internal_fn.lineOrScatterData = function (d) {
|
3464 |
|
|
return this.isLineType(d) || this.isScatterType(d) ? d.values : [];
|
3465 |
|
|
};
|
3466 |
|
|
c3_chart_internal_fn.barOrLineData = function (d) {
|
3467 |
|
|
return this.isBarType(d) || this.isLineType(d) ? d.values : [];
|
3468 |
|
|
};
|
3469 |
|
|
|
3470 |
|
|
c3_chart_internal_fn.initGrid = function () {
|
3471 |
|
|
var $$ = this, config = $$.config, d3 = $$.d3;
|
3472 |
|
|
$$.grid = $$.main.append('g')
|
3473 |
|
|
.attr("clip-path", $$.clipPathForGrid)
|
3474 |
|
|
.attr('class', CLASS.grid);
|
3475 |
|
|
if (config.grid_x_show) {
|
3476 |
|
|
$$.grid.append("g").attr("class", CLASS.xgrids);
|
3477 |
|
|
}
|
3478 |
|
|
if (config.grid_y_show) {
|
3479 |
|
|
$$.grid.append('g').attr('class', CLASS.ygrids);
|
3480 |
|
|
}
|
3481 |
|
|
if (config.grid_focus_show) {
|
3482 |
|
|
$$.grid.append('g')
|
3483 |
|
|
.attr("class", CLASS.xgridFocus)
|
3484 |
|
|
.append('line')
|
3485 |
|
|
.attr('class', CLASS.xgridFocus);
|
3486 |
|
|
}
|
3487 |
|
|
$$.xgrid = d3.selectAll([]);
|
3488 |
|
|
if (!config.grid_lines_front) { $$.initGridLines(); }
|
3489 |
|
|
};
|
3490 |
|
|
c3_chart_internal_fn.initGridLines = function () {
|
3491 |
|
|
var $$ = this, d3 = $$.d3;
|
3492 |
|
|
$$.gridLines = $$.main.append('g')
|
3493 |
|
|
.attr("clip-path", $$.clipPathForGrid)
|
3494 |
|
|
.attr('class', CLASS.grid + ' ' + CLASS.gridLines);
|
3495 |
|
|
$$.gridLines.append('g').attr("class", CLASS.xgridLines);
|
3496 |
|
|
$$.gridLines.append('g').attr('class', CLASS.ygridLines);
|
3497 |
|
|
$$.xgridLines = d3.selectAll([]);
|
3498 |
|
|
};
|
3499 |
|
|
c3_chart_internal_fn.updateXGrid = function (withoutUpdate) {
|
3500 |
|
|
var $$ = this, config = $$.config, d3 = $$.d3,
|
3501 |
|
|
xgridData = $$.generateGridData(config.grid_x_type, $$.x),
|
3502 |
|
|
tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
|
3503 |
|
|
|
3504 |
|
|
$$.xgridAttr = config.axis_rotated ? {
|
3505 |
|
|
'x1': 0,
|
3506 |
|
|
'x2': $$.width,
|
3507 |
|
|
'y1': function (d) { return $$.x(d) - tickOffset; },
|
3508 |
|
|
'y2': function (d) { return $$.x(d) - tickOffset; }
|
3509 |
|
|
} : {
|
3510 |
|
|
'x1': function (d) { return $$.x(d) + tickOffset; },
|
3511 |
|
|
'x2': function (d) { return $$.x(d) + tickOffset; },
|
3512 |
|
|
'y1': 0,
|
3513 |
|
|
'y2': $$.height
|
3514 |
|
|
};
|
3515 |
|
|
|
3516 |
|
|
$$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid)
|
3517 |
|
|
.data(xgridData);
|
3518 |
|
|
$$.xgrid.enter().append('line').attr("class", CLASS.xgrid);
|
3519 |
|
|
if (!withoutUpdate) {
|
3520 |
|
|
$$.xgrid.attr($$.xgridAttr)
|
3521 |
|
|
.style("opacity", function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; });
|
3522 |
|
|
}
|
3523 |
|
|
$$.xgrid.exit().remove();
|
3524 |
|
|
};
|
3525 |
|
|
|
3526 |
|
|
c3_chart_internal_fn.updateYGrid = function () {
|
3527 |
|
|
var $$ = this, config = $$.config,
|
3528 |
|
|
gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
|
3529 |
|
|
$$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid)
|
3530 |
|
|
.data(gridValues);
|
3531 |
|
|
$$.ygrid.enter().append('line')
|
3532 |
|
|
.attr('class', CLASS.ygrid);
|
3533 |
|
|
$$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0)
|
3534 |
|
|
.attr("x2", config.axis_rotated ? $$.y : $$.width)
|
3535 |
|
|
.attr("y1", config.axis_rotated ? 0 : $$.y)
|
3536 |
|
|
.attr("y2", config.axis_rotated ? $$.height : $$.y);
|
3537 |
|
|
$$.ygrid.exit().remove();
|
3538 |
|
|
$$.smoothLines($$.ygrid, 'grid');
|
3539 |
|
|
};
|
3540 |
|
|
|
3541 |
|
|
c3_chart_internal_fn.gridTextAnchor = function (d) {
|
3542 |
|
|
return d.position ? d.position : "end";
|
3543 |
|
|
};
|
3544 |
|
|
c3_chart_internal_fn.gridTextDx = function (d) {
|
3545 |
|
|
return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;
|
3546 |
|
|
};
|
3547 |
|
|
c3_chart_internal_fn.xGridTextX = function (d) {
|
3548 |
|
|
return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0;
|
3549 |
|
|
};
|
3550 |
|
|
c3_chart_internal_fn.yGridTextX = function (d) {
|
3551 |
|
|
return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width;
|
3552 |
|
|
};
|
3553 |
|
|
c3_chart_internal_fn.updateGrid = function (duration) {
|
3554 |
|
|
var $$ = this, main = $$.main, config = $$.config,
|
3555 |
|
|
xgridLine, ygridLine, yv;
|
3556 |
|
|
|
3557 |
|
|
// hide if arc type
|
3558 |
|
|
$$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
|
3559 |
|
|
|
3560 |
|
|
main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
|
3561 |
|
|
if (config.grid_x_show) {
|
3562 |
|
|
$$.updateXGrid();
|
3563 |
|
|
}
|
3564 |
|
|
$$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine)
|
3565 |
|
|
.data(config.grid_x_lines);
|
3566 |
|
|
// enter
|
3567 |
|
|
xgridLine = $$.xgridLines.enter().append('g')
|
3568 |
|
|
.attr("class", function (d) { return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : ''); });
|
3569 |
|
|
xgridLine.append('line')
|
3570 |
|
|
.style("opacity", 0);
|
3571 |
|
|
xgridLine.append('text')
|
3572 |
|
|
.attr("text-anchor", $$.gridTextAnchor)
|
3573 |
|
|
.attr("transform", config.axis_rotated ? "" : "rotate(-90)")
|
3574 |
|
|
.attr('dx', $$.gridTextDx)
|
3575 |
|
|
.attr('dy', -5)
|
3576 |
|
|
.style("opacity", 0);
|
3577 |
|
|
// udpate
|
3578 |
|
|
// done in d3.transition() of the end of this function
|
3579 |
|
|
// exit
|
3580 |
|
|
$$.xgridLines.exit().transition().duration(duration)
|
3581 |
|
|
.style("opacity", 0)
|
3582 |
|
|
.remove();
|
3583 |
|
|
|
3584 |
|
|
// Y-Grid
|
3585 |
|
|
if (config.grid_y_show) {
|
3586 |
|
|
$$.updateYGrid();
|
3587 |
|
|
}
|
3588 |
|
|
$$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine)
|
3589 |
|
|
.data(config.grid_y_lines);
|
3590 |
|
|
// enter
|
3591 |
|
|
ygridLine = $$.ygridLines.enter().append('g')
|
3592 |
|
|
.attr("class", function (d) { return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : ''); });
|
3593 |
|
|
ygridLine.append('line')
|
3594 |
|
|
.style("opacity", 0);
|
3595 |
|
|
ygridLine.append('text')
|
3596 |
|
|
.attr("text-anchor", $$.gridTextAnchor)
|
3597 |
|
|
.attr("transform", config.axis_rotated ? "rotate(-90)" : "")
|
3598 |
|
|
.attr('dx', $$.gridTextDx)
|
3599 |
|
|
.attr('dy', -5)
|
3600 |
|
|
.style("opacity", 0);
|
3601 |
|
|
// update
|
3602 |
|
|
yv = $$.yv.bind($$);
|
3603 |
|
|
$$.ygridLines.select('line')
|
3604 |
|
|
.transition().duration(duration)
|
3605 |
|
|
.attr("x1", config.axis_rotated ? yv : 0)
|
3606 |
|
|
.attr("x2", config.axis_rotated ? yv : $$.width)
|
3607 |
|
|
.attr("y1", config.axis_rotated ? 0 : yv)
|
3608 |
|
|
.attr("y2", config.axis_rotated ? $$.height : yv)
|
3609 |
|
|
.style("opacity", 1);
|
3610 |
|
|
$$.ygridLines.select('text')
|
3611 |
|
|
.transition().duration(duration)
|
3612 |
|
|
.attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$))
|
3613 |
|
|
.attr("y", yv)
|
3614 |
|
|
.text(function (d) { return d.text; })
|
3615 |
|
|
.style("opacity", 1);
|
3616 |
|
|
// exit
|
3617 |
|
|
$$.ygridLines.exit().transition().duration(duration)
|
3618 |
|
|
.style("opacity", 0)
|
3619 |
|
|
.remove();
|
3620 |
|
|
};
|
3621 |
|
|
c3_chart_internal_fn.redrawGrid = function (withTransition) {
|
3622 |
|
|
var $$ = this, config = $$.config, xv = $$.xv.bind($$),
|
3623 |
|
|
lines = $$.xgridLines.select('line'),
|
3624 |
|
|
texts = $$.xgridLines.select('text');
|
3625 |
|
|
return [
|
3626 |
|
|
(withTransition ? lines.transition() : lines)
|
3627 |
|
|
.attr("x1", config.axis_rotated ? 0 : xv)
|
3628 |
|
|
.attr("x2", config.axis_rotated ? $$.width : xv)
|
3629 |
|
|
.attr("y1", config.axis_rotated ? xv : 0)
|
3630 |
|
|
.attr("y2", config.axis_rotated ? xv : $$.height)
|
3631 |
|
|
.style("opacity", 1),
|
3632 |
|
|
(withTransition ? texts.transition() : texts)
|
3633 |
|
|
.attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$))
|
3634 |
|
|
.attr("y", xv)
|
3635 |
|
|
.text(function (d) { return d.text; })
|
3636 |
|
|
.style("opacity", 1)
|
3637 |
|
|
];
|
3638 |
|
|
};
|
3639 |
|
|
c3_chart_internal_fn.showXGridFocus = function (selectedData) {
|
3640 |
|
|
var $$ = this, config = $$.config,
|
3641 |
|
|
dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }),
|
3642 |
|
|
focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),
|
3643 |
|
|
xx = $$.xx.bind($$);
|
3644 |
|
|
if (! config.tooltip_show) { return; }
|
3645 |
|
|
// Hide when scatter plot exists
|
3646 |
|
|
if ($$.hasType('scatter') || $$.hasArcType()) { return; }
|
3647 |
|
|
focusEl
|
3648 |
|
|
.style("visibility", "visible")
|
3649 |
|
|
.data([dataToShow[0]])
|
3650 |
|
|
.attr(config.axis_rotated ? 'y1' : 'x1', xx)
|
3651 |
|
|
.attr(config.axis_rotated ? 'y2' : 'x2', xx);
|
3652 |
|
|
$$.smoothLines(focusEl, 'grid');
|
3653 |
|
|
};
|
3654 |
|
|
c3_chart_internal_fn.hideXGridFocus = function () {
|
3655 |
|
|
this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
|
3656 |
|
|
};
|
3657 |
|
|
c3_chart_internal_fn.updateXgridFocus = function () {
|
3658 |
|
|
var $$ = this, config = $$.config;
|
3659 |
|
|
$$.main.select('line.' + CLASS.xgridFocus)
|
3660 |
|
|
.attr("x1", config.axis_rotated ? 0 : -10)
|
3661 |
|
|
.attr("x2", config.axis_rotated ? $$.width : -10)
|
3662 |
|
|
.attr("y1", config.axis_rotated ? -10 : 0)
|
3663 |
|
|
.attr("y2", config.axis_rotated ? -10 : $$.height);
|
3664 |
|
|
};
|
3665 |
|
|
c3_chart_internal_fn.generateGridData = function (type, scale) {
|
3666 |
|
|
var $$ = this,
|
3667 |
|
|
gridData = [], xDomain, firstYear, lastYear, i,
|
3668 |
|
|
tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size();
|
3669 |
|
|
if (type === 'year') {
|
3670 |
|
|
xDomain = $$.getXDomain();
|
3671 |
|
|
firstYear = xDomain[0].getFullYear();
|
3672 |
|
|
lastYear = xDomain[1].getFullYear();
|
3673 |
|
|
for (i = firstYear; i <= lastYear; i++) {
|
3674 |
|
|
gridData.push(new Date(i + '-01-01 00:00:00'));
|
3675 |
|
|
}
|
3676 |
|
|
} else {
|
3677 |
|
|
gridData = scale.ticks(10);
|
3678 |
|
|
if (gridData.length > tickNum) { // use only int
|
3679 |
|
|
gridData = gridData.filter(function (d) { return ("" + d).indexOf('.') < 0; });
|
3680 |
|
|
}
|
3681 |
|
|
}
|
3682 |
|
|
return gridData;
|
3683 |
|
|
};
|
3684 |
|
|
c3_chart_internal_fn.getGridFilterToRemove = function (params) {
|
3685 |
|
|
return params ? function (line) {
|
3686 |
|
|
var found = false;
|
3687 |
|
|
[].concat(params).forEach(function (param) {
|
3688 |
|
|
if ((('value' in param && line.value === param.value) || ('class' in param && line['class'] === param['class']))) {
|
3689 |
|
|
found = true;
|
3690 |
|
|
}
|
3691 |
|
|
});
|
3692 |
|
|
return found;
|
3693 |
|
|
} : function () { return true; };
|
3694 |
|
|
};
|
3695 |
|
|
c3_chart_internal_fn.removeGridLines = function (params, forX) {
|
3696 |
|
|
var $$ = this, config = $$.config,
|
3697 |
|
|
toRemove = $$.getGridFilterToRemove(params),
|
3698 |
|
|
toShow = function (line) { return !toRemove(line); },
|
3699 |
|
|
classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,
|
3700 |
|
|
classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
|
3701 |
|
|
$$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove)
|
3702 |
|
|
.transition().duration(config.transition_duration)
|
3703 |
|
|
.style('opacity', 0).remove();
|
3704 |
|
|
if (forX) {
|
3705 |
|
|
config.grid_x_lines = config.grid_x_lines.filter(toShow);
|
3706 |
|
|
} else {
|
3707 |
|
|
config.grid_y_lines = config.grid_y_lines.filter(toShow);
|
3708 |
|
|
}
|
3709 |
|
|
};
|
3710 |
|
|
|
3711 |
|
|
c3_chart_internal_fn.initTooltip = function () {
|
3712 |
|
|
var $$ = this, config = $$.config, i;
|
3713 |
|
|
$$.tooltip = $$.selectChart
|
3714 |
|
|
.style("position", "relative")
|
3715 |
|
|
.append("div")
|
3716 |
|
|
.attr('class', CLASS.tooltipContainer)
|
3717 |
|
|
.style("position", "absolute")
|
3718 |
|
|
.style("pointer-events", "none")
|
3719 |
|
|
.style("display", "none");
|
3720 |
|
|
// Show tooltip if needed
|
3721 |
|
|
if (config.tooltip_init_show) {
|
3722 |
|
|
if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
|
3723 |
|
|
config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
|
3724 |
|
|
for (i = 0; i < $$.data.targets[0].values.length; i++) {
|
3725 |
|
|
if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; }
|
3726 |
|
|
}
|
3727 |
|
|
config.tooltip_init_x = i;
|
3728 |
|
|
}
|
3729 |
|
|
$$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
|
3730 |
|
|
return $$.addName(d.values[config.tooltip_init_x]);
|
3731 |
|
|
}), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
|
3732 |
|
|
$$.tooltip.style("top", config.tooltip_init_position.top)
|
3733 |
|
|
.style("left", config.tooltip_init_position.left)
|
3734 |
|
|
.style("display", "block");
|
3735 |
|
|
}
|
3736 |
|
|
};
|
3737 |
|
|
c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
|
3738 |
|
|
var $$ = this, config = $$.config,
|
3739 |
|
|
titleFormat = config.tooltip_format_title || defaultTitleFormat,
|
3740 |
|
|
nameFormat = config.tooltip_format_name || function (name) { return name; },
|
3741 |
|
|
valueFormat = config.tooltip_format_value || defaultValueFormat,
|
3742 |
|
|
text, i, title, value, name, bgcolor;
|
3743 |
|
|
for (i = 0; i < d.length; i++) {
|
3744 |
|
|
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
|
3745 |
|
|
|
3746 |
|
|
if (! text) {
|
3747 |
|
|
title = titleFormat ? titleFormat(d[i].x) : d[i].x;
|
3748 |
|
|
text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
|
3749 |
|
|
}
|
3750 |
|
|
|
3751 |
|
|
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
|
3752 |
|
|
if (value !== undefined) {
|
3753 |
|
|
name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
|
3754 |
|
|
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
|
3755 |
|
|
|
3756 |
|
|
text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
|
3757 |
|
|
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
|
3758 |
|
|
text += "<td class='value'>" + value + "</td>";
|
3759 |
|
|
text += "</tr>";
|
3760 |
|
|
}
|
3761 |
|
|
}
|
3762 |
|
|
return text + "</table>";
|
3763 |
|
|
};
|
3764 |
|
|
c3_chart_internal_fn.tooltipPosition = function (dataToShow, tWidth, tHeight, element) {
|
3765 |
|
|
var $$ = this, config = $$.config, d3 = $$.d3;
|
3766 |
|
|
var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
|
3767 |
|
|
var forArc = $$.hasArcType(),
|
3768 |
|
|
mouse = d3.mouse(element);
|
3769 |
|
|
// Determin tooltip position
|
3770 |
|
|
if (forArc) {
|
3771 |
|
|
tooltipLeft = (($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2) + mouse[0];
|
3772 |
|
|
tooltipTop = ($$.height / 2) + mouse[1] + 20;
|
3773 |
|
|
} else {
|
3774 |
|
|
svgLeft = $$.getSvgLeft(true);
|
3775 |
|
|
if (config.axis_rotated) {
|
3776 |
|
|
tooltipLeft = svgLeft + mouse[0] + 100;
|
3777 |
|
|
tooltipRight = tooltipLeft + tWidth;
|
3778 |
|
|
chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
|
3779 |
|
|
tooltipTop = $$.x(dataToShow[0].x) + 20;
|
3780 |
|
|
} else {
|
3781 |
|
|
tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
|
3782 |
|
|
tooltipRight = tooltipLeft + tWidth;
|
3783 |
|
|
chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
|
3784 |
|
|
tooltipTop = mouse[1] + 15;
|
3785 |
|
|
}
|
3786 |
|
|
|
3787 |
|
|
if (tooltipRight > chartRight) {
|
3788 |
|
|
// 20 is needed for Firefox to keep tooletip width
|
3789 |
|
|
tooltipLeft -= tooltipRight - chartRight + 20;
|
3790 |
|
|
}
|
3791 |
|
|
if (tooltipTop + tHeight > $$.currentHeight) {
|
3792 |
|
|
tooltipTop -= tHeight + 30;
|
3793 |
|
|
}
|
3794 |
|
|
}
|
3795 |
|
|
if (tooltipTop < 0) {
|
3796 |
|
|
tooltipTop = 0;
|
3797 |
|
|
}
|
3798 |
|
|
return {top: tooltipTop, left: tooltipLeft};
|
3799 |
|
|
};
|
3800 |
|
|
c3_chart_internal_fn.showTooltip = function (selectedData, element) {
|
3801 |
|
|
var $$ = this, config = $$.config;
|
3802 |
|
|
var tWidth, tHeight, position;
|
3803 |
|
|
var forArc = $$.hasArcType(),
|
3804 |
|
|
dataToShow = selectedData.filter(function (d) { return d && isValue(d.value); }),
|
3805 |
|
|
positionFunction = config.tooltip_position || c3_chart_internal_fn.tooltipPosition;
|
3806 |
|
|
if (dataToShow.length === 0 || !config.tooltip_show) {
|
3807 |
|
|
return;
|
3808 |
|
|
}
|
3809 |
|
|
$$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block");
|
3810 |
|
|
|
3811 |
|
|
// Get tooltip dimensions
|
3812 |
|
|
tWidth = $$.tooltip.property('offsetWidth');
|
3813 |
|
|
tHeight = $$.tooltip.property('offsetHeight');
|
3814 |
|
|
|
3815 |
|
|
position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
|
3816 |
|
|
// Set tooltip
|
3817 |
|
|
$$.tooltip
|
3818 |
|
|
.style("top", position.top + "px")
|
3819 |
|
|
.style("left", position.left + 'px');
|
3820 |
|
|
};
|
3821 |
|
|
c3_chart_internal_fn.hideTooltip = function () {
|
3822 |
|
|
this.tooltip.style("display", "none");
|
3823 |
|
|
};
|
3824 |
|
|
|
3825 |
|
|
c3_chart_internal_fn.initLegend = function () {
|
3826 |
|
|
var $$ = this;
|
3827 |
|
|
$$.legendItemTextBox = {};
|
3828 |
|
|
$$.legendHasRendered = false;
|
3829 |
|
|
$$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend'));
|
3830 |
|
|
if (!$$.config.legend_show) {
|
3831 |
|
|
$$.legend.style('visibility', 'hidden');
|
3832 |
|
|
$$.hiddenLegendIds = $$.mapToIds($$.data.targets);
|
3833 |
|
|
return;
|
3834 |
|
|
}
|
3835 |
|
|
// MEMO: call here to update legend box and tranlate for all
|
3836 |
|
|
// MEMO: translate will be upated by this, so transform not needed in updateLegend()
|
3837 |
|
|
$$.updateLegendWithDefaults();
|
3838 |
|
|
};
|
3839 |
|
|
c3_chart_internal_fn.updateLegendWithDefaults = function () {
|
3840 |
|
|
var $$ = this;
|
3841 |
|
|
$$.updateLegend($$.mapToIds($$.data.targets), {withTransform: false, withTransitionForTransform: false, withTransition: false});
|
3842 |
|
|
};
|
3843 |
|
|
c3_chart_internal_fn.updateSizeForLegend = function (legendHeight, legendWidth) {
|
3844 |
|
|
var $$ = this, config = $$.config, insetLegendPosition = {
|
3845 |
|
|
top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,
|
3846 |
|
|
left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5
|
3847 |
|
|
};
|
3848 |
|
|
|
3849 |
|
|
$$.margin3 = {
|
3850 |
|
|
top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,
|
3851 |
|
|
right: NaN,
|
3852 |
|
|
bottom: 0,
|
3853 |
|
|
left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0
|
3854 |
|
|
};
|
3855 |
|
|
};
|
3856 |
|
|
c3_chart_internal_fn.transformLegend = function (withTransition) {
|
3857 |
|
|
var $$ = this;
|
3858 |
|
|
(withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend'));
|
3859 |
|
|
};
|
3860 |
|
|
c3_chart_internal_fn.updateLegendStep = function (step) {
|
3861 |
|
|
this.legendStep = step;
|
3862 |
|
|
};
|
3863 |
|
|
c3_chart_internal_fn.updateLegendItemWidth = function (w) {
|
3864 |
|
|
this.legendItemWidth = w;
|
3865 |
|
|
};
|
3866 |
|
|
c3_chart_internal_fn.updateLegendItemHeight = function (h) {
|
3867 |
|
|
this.legendItemHeight = h;
|
3868 |
|
|
};
|
3869 |
|
|
c3_chart_internal_fn.getLegendWidth = function () {
|
3870 |
|
|
var $$ = this;
|
3871 |
|
|
return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;
|
3872 |
|
|
};
|
3873 |
|
|
c3_chart_internal_fn.getLegendHeight = function () {
|
3874 |
|
|
var $$ = this, h = 0;
|
3875 |
|
|
if ($$.config.legend_show) {
|
3876 |
|
|
if ($$.isLegendRight) {
|
3877 |
|
|
h = $$.currentHeight;
|
3878 |
|
|
} else {
|
3879 |
|
|
h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
|
3880 |
|
|
}
|
3881 |
|
|
}
|
3882 |
|
|
return h;
|
3883 |
|
|
};
|
3884 |
|
|
c3_chart_internal_fn.opacityForLegend = function (legendItem) {
|
3885 |
|
|
return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
|
3886 |
|
|
};
|
3887 |
|
|
c3_chart_internal_fn.opacityForUnfocusedLegend = function (legendItem) {
|
3888 |
|
|
return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;
|
3889 |
|
|
};
|
3890 |
|
|
c3_chart_internal_fn.toggleFocusLegend = function (targetIds, focus) {
|
3891 |
|
|
var $$ = this;
|
3892 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
3893 |
|
|
$$.legend.selectAll('.' + CLASS.legendItem)
|
3894 |
|
|
.filter(function (id) { return targetIds.indexOf(id) >= 0; })
|
3895 |
|
|
.classed(CLASS.legendItemFocused, focus)
|
3896 |
|
|
.transition().duration(100)
|
3897 |
|
|
.style('opacity', function () {
|
3898 |
|
|
var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
|
3899 |
|
|
return opacity.call($$, $$.d3.select(this));
|
3900 |
|
|
});
|
3901 |
|
|
};
|
3902 |
|
|
c3_chart_internal_fn.revertLegend = function () {
|
3903 |
|
|
var $$ = this, d3 = $$.d3;
|
3904 |
|
|
$$.legend.selectAll('.' + CLASS.legendItem)
|
3905 |
|
|
.classed(CLASS.legendItemFocused, false)
|
3906 |
|
|
.transition().duration(100)
|
3907 |
|
|
.style('opacity', function () { return $$.opacityForLegend(d3.select(this)); });
|
3908 |
|
|
};
|
3909 |
|
|
c3_chart_internal_fn.showLegend = function (targetIds) {
|
3910 |
|
|
var $$ = this, config = $$.config;
|
3911 |
|
|
if (!config.legend_show) {
|
3912 |
|
|
config.legend_show = true;
|
3913 |
|
|
$$.legend.style('visibility', 'visible');
|
3914 |
|
|
if (!$$.legendHasRendered) {
|
3915 |
|
|
$$.updateLegendWithDefaults();
|
3916 |
|
|
}
|
3917 |
|
|
}
|
3918 |
|
|
$$.removeHiddenLegendIds(targetIds);
|
3919 |
|
|
$$.legend.selectAll($$.selectorLegends(targetIds))
|
3920 |
|
|
.style('visibility', 'visible')
|
3921 |
|
|
.transition()
|
3922 |
|
|
.style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); });
|
3923 |
|
|
};
|
3924 |
|
|
c3_chart_internal_fn.hideLegend = function (targetIds) {
|
3925 |
|
|
var $$ = this, config = $$.config;
|
3926 |
|
|
if (config.legend_show && isEmpty(targetIds)) {
|
3927 |
|
|
config.legend_show = false;
|
3928 |
|
|
$$.legend.style('visibility', 'hidden');
|
3929 |
|
|
}
|
3930 |
|
|
$$.addHiddenLegendIds(targetIds);
|
3931 |
|
|
$$.legend.selectAll($$.selectorLegends(targetIds))
|
3932 |
|
|
.style('opacity', 0)
|
3933 |
|
|
.style('visibility', 'hidden');
|
3934 |
|
|
};
|
3935 |
|
|
c3_chart_internal_fn.clearLegendItemTextBoxCache = function () {
|
3936 |
|
|
this.legendItemTextBox = {};
|
3937 |
|
|
};
|
3938 |
|
|
c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
|
3939 |
|
|
var $$ = this, config = $$.config;
|
3940 |
|
|
var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
|
3941 |
|
|
var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = 15;
|
3942 |
|
|
var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
|
3943 |
|
|
var withTransition, withTransitionForTransform;
|
3944 |
|
|
var texts, rects, tiles, background;
|
3945 |
|
|
|
3946 |
|
|
options = options || {};
|
3947 |
|
|
withTransition = getOption(options, "withTransition", true);
|
3948 |
|
|
withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
|
3949 |
|
|
|
3950 |
|
|
function getTextBox(textElement, id) {
|
3951 |
|
|
if (!$$.legendItemTextBox[id]) {
|
3952 |
|
|
$$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem);
|
3953 |
|
|
}
|
3954 |
|
|
return $$.legendItemTextBox[id];
|
3955 |
|
|
}
|
3956 |
|
|
|
3957 |
|
|
function updatePositions(textElement, id, index) {
|
3958 |
|
|
var reset = index === 0, isLast = index === targetIds.length - 1,
|
3959 |
|
|
box = getTextBox(textElement, id),
|
3960 |
|
|
itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight),
|
3961 |
|
|
itemHeight = box.height + paddingTop,
|
3962 |
|
|
itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
|
3963 |
|
|
areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),
|
3964 |
|
|
margin, maxLength;
|
3965 |
|
|
|
3966 |
|
|
// MEMO: care about condifion of step, totalLength
|
3967 |
|
|
function updateValues(id, withoutStep) {
|
3968 |
|
|
if (!withoutStep) {
|
3969 |
|
|
margin = (areaLength - totalLength - itemLength) / 2;
|
3970 |
|
|
if (margin < posMin) {
|
3971 |
|
|
margin = (areaLength - itemLength) / 2;
|
3972 |
|
|
totalLength = 0;
|
3973 |
|
|
step++;
|
3974 |
|
|
}
|
3975 |
|
|
}
|
3976 |
|
|
steps[id] = step;
|
3977 |
|
|
margins[step] = $$.isLegendInset ? 10 : margin;
|
3978 |
|
|
offsets[id] = totalLength;
|
3979 |
|
|
totalLength += itemLength;
|
3980 |
|
|
}
|
3981 |
|
|
|
3982 |
|
|
if (reset) {
|
3983 |
|
|
totalLength = 0;
|
3984 |
|
|
step = 0;
|
3985 |
|
|
maxWidth = 0;
|
3986 |
|
|
maxHeight = 0;
|
3987 |
|
|
}
|
3988 |
|
|
|
3989 |
|
|
if (config.legend_show && !$$.isLegendToShow(id)) {
|
3990 |
|
|
widths[id] = heights[id] = steps[id] = offsets[id] = 0;
|
3991 |
|
|
return;
|
3992 |
|
|
}
|
3993 |
|
|
|
3994 |
|
|
widths[id] = itemWidth;
|
3995 |
|
|
heights[id] = itemHeight;
|
3996 |
|
|
|
3997 |
|
|
if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; }
|
3998 |
|
|
if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; }
|
3999 |
|
|
maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
|
4000 |
|
|
|
4001 |
|
|
if (config.legend_equally) {
|
4002 |
|
|
Object.keys(widths).forEach(function (id) { widths[id] = maxWidth; });
|
4003 |
|
|
Object.keys(heights).forEach(function (id) { heights[id] = maxHeight; });
|
4004 |
|
|
margin = (areaLength - maxLength * targetIds.length) / 2;
|
4005 |
|
|
if (margin < posMin) {
|
4006 |
|
|
totalLength = 0;
|
4007 |
|
|
step = 0;
|
4008 |
|
|
targetIds.forEach(function (id) { updateValues(id); });
|
4009 |
|
|
}
|
4010 |
|
|
else {
|
4011 |
|
|
updateValues(id, true);
|
4012 |
|
|
}
|
4013 |
|
|
} else {
|
4014 |
|
|
updateValues(id);
|
4015 |
|
|
}
|
4016 |
|
|
}
|
4017 |
|
|
|
4018 |
|
|
if ($$.isLegendInset) {
|
4019 |
|
|
step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;
|
4020 |
|
|
$$.updateLegendStep(step);
|
4021 |
|
|
}
|
4022 |
|
|
|
4023 |
|
|
if ($$.isLegendRight) {
|
4024 |
|
|
xForLegend = function (id) { return maxWidth * steps[id]; };
|
4025 |
|
|
yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
|
4026 |
|
|
} else if ($$.isLegendInset) {
|
4027 |
|
|
xForLegend = function (id) { return maxWidth * steps[id] + 10; };
|
4028 |
|
|
yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
|
4029 |
|
|
} else {
|
4030 |
|
|
xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
|
4031 |
|
|
yForLegend = function (id) { return maxHeight * steps[id]; };
|
4032 |
|
|
}
|
4033 |
|
|
xForLegendText = function (id, i) { return xForLegend(id, i) + 14; };
|
4034 |
|
|
yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };
|
4035 |
|
|
xForLegendRect = function (id, i) { return xForLegend(id, i); };
|
4036 |
|
|
yForLegendRect = function (id, i) { return yForLegend(id, i) - 5; };
|
4037 |
|
|
|
4038 |
|
|
// Define g for legend area
|
4039 |
|
|
l = $$.legend.selectAll('.' + CLASS.legendItem)
|
4040 |
|
|
.data(targetIds)
|
4041 |
|
|
.enter().append('g')
|
4042 |
|
|
.attr('class', function (id) { return $$.generateClass(CLASS.legendItem, id); })
|
4043 |
|
|
.style('visibility', function (id) { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; })
|
4044 |
|
|
.style('cursor', 'pointer')
|
4045 |
|
|
.on('click', function (id) {
|
4046 |
|
|
if (config.legend_item_onclick) {
|
4047 |
|
|
config.legend_item_onclick.call($$, id);
|
4048 |
|
|
} else {
|
4049 |
|
|
if ($$.d3.event.altKey) {
|
4050 |
|
|
$$.api.hide();
|
4051 |
|
|
$$.api.show(id);
|
4052 |
|
|
} else {
|
4053 |
|
|
$$.api.toggle(id);
|
4054 |
|
|
$$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
|
4055 |
|
|
}
|
4056 |
|
|
}
|
4057 |
|
|
})
|
4058 |
|
|
.on('mouseover', function (id) {
|
4059 |
|
|
$$.d3.select(this).classed(CLASS.legendItemFocused, true);
|
4060 |
|
|
if (!$$.transiting && $$.isTargetToShow(id)) {
|
4061 |
|
|
$$.api.focus(id);
|
4062 |
|
|
}
|
4063 |
|
|
if (config.legend_item_onmouseover) {
|
4064 |
|
|
config.legend_item_onmouseover.call($$, id);
|
4065 |
|
|
}
|
4066 |
|
|
})
|
4067 |
|
|
.on('mouseout', function (id) {
|
4068 |
|
|
$$.d3.select(this).classed(CLASS.legendItemFocused, false);
|
4069 |
|
|
$$.api.revert();
|
4070 |
|
|
if (config.legend_item_onmouseout) {
|
4071 |
|
|
config.legend_item_onmouseout.call($$, id);
|
4072 |
|
|
}
|
4073 |
|
|
});
|
4074 |
|
|
l.append('text')
|
4075 |
|
|
.text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; })
|
4076 |
|
|
.each(function (id, i) { updatePositions(this, id, i); })
|
4077 |
|
|
.style("pointer-events", "none")
|
4078 |
|
|
.attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
|
4079 |
|
|
.attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
|
4080 |
|
|
l.append('rect')
|
4081 |
|
|
.attr("class", CLASS.legendItemEvent)
|
4082 |
|
|
.style('fill-opacity', 0)
|
4083 |
|
|
.attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
|
4084 |
|
|
.attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
|
4085 |
|
|
l.append('rect')
|
4086 |
|
|
.attr("class", CLASS.legendItemTile)
|
4087 |
|
|
.style("pointer-events", "none")
|
4088 |
|
|
.style('fill', $$.color)
|
4089 |
|
|
.attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
|
4090 |
|
|
.attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend)
|
4091 |
|
|
.attr('width', 10)
|
4092 |
|
|
.attr('height', 10);
|
4093 |
|
|
|
4094 |
|
|
// Set background for inset legend
|
4095 |
|
|
background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
|
4096 |
|
|
if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
|
4097 |
|
|
background = $$.legend.insert('g', '.' + CLASS.legendItem)
|
4098 |
|
|
.attr("class", CLASS.legendBackground)
|
4099 |
|
|
.append('rect');
|
4100 |
|
|
}
|
4101 |
|
|
|
4102 |
|
|
texts = $$.legend.selectAll('text')
|
4103 |
|
|
.data(targetIds)
|
4104 |
|
|
.text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update
|
4105 |
|
|
.each(function (id, i) { updatePositions(this, id, i); });
|
4106 |
|
|
(withTransition ? texts.transition() : texts)
|
4107 |
|
|
.attr('x', xForLegendText)
|
4108 |
|
|
.attr('y', yForLegendText);
|
4109 |
|
|
|
4110 |
|
|
rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent)
|
4111 |
|
|
.data(targetIds);
|
4112 |
|
|
(withTransition ? rects.transition() : rects)
|
4113 |
|
|
.attr('width', function (id) { return widths[id]; })
|
4114 |
|
|
.attr('height', function (id) { return heights[id]; })
|
4115 |
|
|
.attr('x', xForLegendRect)
|
4116 |
|
|
.attr('y', yForLegendRect);
|
4117 |
|
|
|
4118 |
|
|
tiles = $$.legend.selectAll('rect.' + CLASS.legendItemTile)
|
4119 |
|
|
.data(targetIds);
|
4120 |
|
|
(withTransition ? tiles.transition() : tiles)
|
4121 |
|
|
.style('fill', $$.color)
|
4122 |
|
|
.attr('x', xForLegend)
|
4123 |
|
|
.attr('y', yForLegend);
|
4124 |
|
|
|
4125 |
|
|
if (background) {
|
4126 |
|
|
(withTransition ? background.transition() : background)
|
4127 |
|
|
.attr('height', $$.getLegendHeight() - 12)
|
4128 |
|
|
.attr('width', maxWidth * (step + 1) + 10);
|
4129 |
|
|
}
|
4130 |
|
|
|
4131 |
|
|
// toggle legend state
|
4132 |
|
|
$$.legend.selectAll('.' + CLASS.legendItem)
|
4133 |
|
|
.classed(CLASS.legendItemHidden, function (id) { return !$$.isTargetToShow(id); });
|
4134 |
|
|
|
4135 |
|
|
// Update all to reflect change of legend
|
4136 |
|
|
$$.updateLegendItemWidth(maxWidth);
|
4137 |
|
|
$$.updateLegendItemHeight(maxHeight);
|
4138 |
|
|
$$.updateLegendStep(step);
|
4139 |
|
|
// Update size and scale
|
4140 |
|
|
$$.updateSizes();
|
4141 |
|
|
$$.updateScales();
|
4142 |
|
|
$$.updateSvgSize();
|
4143 |
|
|
// Update g positions
|
4144 |
|
|
$$.transformAll(withTransitionForTransform, transitions);
|
4145 |
|
|
$$.legendHasRendered = true;
|
4146 |
|
|
};
|
4147 |
|
|
|
4148 |
|
|
function Axis(owner) {
|
4149 |
|
|
API.call(this, owner);
|
4150 |
|
|
}
|
4151 |
|
|
|
4152 |
|
|
inherit(API, Axis);
|
4153 |
|
|
|
4154 |
|
|
Axis.prototype.init = function init() {
|
4155 |
|
|
|
4156 |
|
|
var $$ = this.owner, config = $$.config, main = $$.main;
|
4157 |
|
|
$$.axes.x = main.append("g")
|
4158 |
|
|
.attr("class", CLASS.axis + ' ' + CLASS.axisX)
|
4159 |
|
|
.attr("clip-path", $$.clipPathForXAxis)
|
4160 |
|
|
.attr("transform", $$.getTranslate('x'))
|
4161 |
|
|
.style("visibility", config.axis_x_show ? 'visible' : 'hidden');
|
4162 |
|
|
$$.axes.x.append("text")
|
4163 |
|
|
.attr("class", CLASS.axisXLabel)
|
4164 |
|
|
.attr("transform", config.axis_rotated ? "rotate(-90)" : "")
|
4165 |
|
|
.style("text-anchor", this.textAnchorForXAxisLabel.bind(this));
|
4166 |
|
|
$$.axes.y = main.append("g")
|
4167 |
|
|
.attr("class", CLASS.axis + ' ' + CLASS.axisY)
|
4168 |
|
|
.attr("clip-path", config.axis_y_inner ? "" : $$.clipPathForYAxis)
|
4169 |
|
|
.attr("transform", $$.getTranslate('y'))
|
4170 |
|
|
.style("visibility", config.axis_y_show ? 'visible' : 'hidden');
|
4171 |
|
|
$$.axes.y.append("text")
|
4172 |
|
|
.attr("class", CLASS.axisYLabel)
|
4173 |
|
|
.attr("transform", config.axis_rotated ? "" : "rotate(-90)")
|
4174 |
|
|
.style("text-anchor", this.textAnchorForYAxisLabel.bind(this));
|
4175 |
|
|
|
4176 |
|
|
$$.axes.y2 = main.append("g")
|
4177 |
|
|
.attr("class", CLASS.axis + ' ' + CLASS.axisY2)
|
4178 |
|
|
// clip-path?
|
4179 |
|
|
.attr("transform", $$.getTranslate('y2'))
|
4180 |
|
|
.style("visibility", config.axis_y2_show ? 'visible' : 'hidden');
|
4181 |
|
|
$$.axes.y2.append("text")
|
4182 |
|
|
.attr("class", CLASS.axisY2Label)
|
4183 |
|
|
.attr("transform", config.axis_rotated ? "" : "rotate(-90)")
|
4184 |
|
|
.style("text-anchor", this.textAnchorForY2AxisLabel.bind(this));
|
4185 |
|
|
};
|
4186 |
|
|
Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
|
4187 |
|
|
var $$ = this.owner, config = $$.config,
|
4188 |
|
|
axisParams = {
|
4189 |
|
|
isCategory: $$.isCategorized(),
|
4190 |
|
|
withOuterTick: withOuterTick,
|
4191 |
|
|
tickMultiline: config.axis_x_tick_multiline,
|
4192 |
|
|
tickWidth: config.axis_x_tick_width,
|
4193 |
|
|
tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
|
4194 |
|
|
withoutTransition: withoutTransition,
|
4195 |
|
|
},
|
4196 |
|
|
axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient);
|
4197 |
|
|
|
4198 |
|
|
if ($$.isTimeSeries() && tickValues) {
|
4199 |
|
|
tickValues = tickValues.map(function (v) { return $$.parseDate(v); });
|
4200 |
|
|
}
|
4201 |
|
|
|
4202 |
|
|
// Set tick
|
4203 |
|
|
axis.tickFormat(tickFormat).tickValues(tickValues);
|
4204 |
|
|
if ($$.isCategorized()) {
|
4205 |
|
|
axis.tickCentered(config.axis_x_tick_centered);
|
4206 |
|
|
if (isEmpty(config.axis_x_tick_culling)) {
|
4207 |
|
|
config.axis_x_tick_culling = false;
|
4208 |
|
|
}
|
4209 |
|
|
}
|
4210 |
|
|
|
4211 |
|
|
return axis;
|
4212 |
|
|
};
|
4213 |
|
|
Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
|
4214 |
|
|
var $$ = this.owner, config = $$.config, tickValues;
|
4215 |
|
|
if (config.axis_x_tick_fit || config.axis_x_tick_count) {
|
4216 |
|
|
tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
|
4217 |
|
|
}
|
4218 |
|
|
if (axis) {
|
4219 |
|
|
axis.tickValues(tickValues);
|
4220 |
|
|
} else {
|
4221 |
|
|
$$.xAxis.tickValues(tickValues);
|
4222 |
|
|
$$.subXAxis.tickValues(tickValues);
|
4223 |
|
|
}
|
4224 |
|
|
return tickValues;
|
4225 |
|
|
};
|
4226 |
|
|
Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition) {
|
4227 |
|
|
var axisParams = {
|
4228 |
|
|
withOuterTick: withOuterTick,
|
4229 |
|
|
withoutTransition: withoutTransition,
|
4230 |
|
|
},
|
4231 |
|
|
$$ = this.owner,
|
4232 |
|
|
d3 = $$.d3,
|
4233 |
|
|
config = $$.config,
|
4234 |
|
|
axis = c3_axis(d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
|
4235 |
|
|
if ($$.isTimeSeriesY()) {
|
4236 |
|
|
axis.ticks(d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
|
4237 |
|
|
} else {
|
4238 |
|
|
axis.tickValues(tickValues);
|
4239 |
|
|
}
|
4240 |
|
|
return axis;
|
4241 |
|
|
};
|
4242 |
|
|
Axis.prototype.getId = function getId(id) {
|
4243 |
|
|
var config = this.owner.config;
|
4244 |
|
|
return id in config.data_axes ? config.data_axes[id] : 'y';
|
4245 |
|
|
};
|
4246 |
|
|
Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
|
4247 |
|
|
var $$ = this.owner, config = $$.config,
|
4248 |
|
|
format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) { return v < 0 ? v.toFixed(0) : v; };
|
4249 |
|
|
if (config.axis_x_tick_format) {
|
4250 |
|
|
if (isFunction(config.axis_x_tick_format)) {
|
4251 |
|
|
format = config.axis_x_tick_format;
|
4252 |
|
|
} else if ($$.isTimeSeries()) {
|
4253 |
|
|
format = function (date) {
|
4254 |
|
|
return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : "";
|
4255 |
|
|
};
|
4256 |
|
|
}
|
4257 |
|
|
}
|
4258 |
|
|
return isFunction(format) ? function (v) { return format.call($$, v); } : format;
|
4259 |
|
|
};
|
4260 |
|
|
Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
|
4261 |
|
|
return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
|
4262 |
|
|
};
|
4263 |
|
|
Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
|
4264 |
|
|
return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
|
4265 |
|
|
};
|
4266 |
|
|
Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
|
4267 |
|
|
return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
|
4268 |
|
|
};
|
4269 |
|
|
Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
|
4270 |
|
|
return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
|
4271 |
|
|
};
|
4272 |
|
|
Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
|
4273 |
|
|
var $$ = this.owner, config = $$.config, option;
|
4274 |
|
|
if (axisId === 'y') {
|
4275 |
|
|
option = config.axis_y_label;
|
4276 |
|
|
} else if (axisId === 'y2') {
|
4277 |
|
|
option = config.axis_y2_label;
|
4278 |
|
|
} else if (axisId === 'x') {
|
4279 |
|
|
option = config.axis_x_label;
|
4280 |
|
|
}
|
4281 |
|
|
return option;
|
4282 |
|
|
};
|
4283 |
|
|
Axis.prototype.getLabelText = function getLabelText(axisId) {
|
4284 |
|
|
var option = this.getLabelOptionByAxisId(axisId);
|
4285 |
|
|
return isString(option) ? option : option ? option.text : null;
|
4286 |
|
|
};
|
4287 |
|
|
Axis.prototype.setLabelText = function setLabelText(axisId, text) {
|
4288 |
|
|
var $$ = this.owner, config = $$.config,
|
4289 |
|
|
option = this.getLabelOptionByAxisId(axisId);
|
4290 |
|
|
if (isString(option)) {
|
4291 |
|
|
if (axisId === 'y') {
|
4292 |
|
|
config.axis_y_label = text;
|
4293 |
|
|
} else if (axisId === 'y2') {
|
4294 |
|
|
config.axis_y2_label = text;
|
4295 |
|
|
} else if (axisId === 'x') {
|
4296 |
|
|
config.axis_x_label = text;
|
4297 |
|
|
}
|
4298 |
|
|
} else if (option) {
|
4299 |
|
|
option.text = text;
|
4300 |
|
|
}
|
4301 |
|
|
};
|
4302 |
|
|
Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
|
4303 |
|
|
var option = this.getLabelOptionByAxisId(axisId),
|
4304 |
|
|
position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition;
|
4305 |
|
|
return {
|
4306 |
|
|
isInner: position.indexOf('inner') >= 0,
|
4307 |
|
|
isOuter: position.indexOf('outer') >= 0,
|
4308 |
|
|
isLeft: position.indexOf('left') >= 0,
|
4309 |
|
|
isCenter: position.indexOf('center') >= 0,
|
4310 |
|
|
isRight: position.indexOf('right') >= 0,
|
4311 |
|
|
isTop: position.indexOf('top') >= 0,
|
4312 |
|
|
isMiddle: position.indexOf('middle') >= 0,
|
4313 |
|
|
isBottom: position.indexOf('bottom') >= 0
|
4314 |
|
|
};
|
4315 |
|
|
};
|
4316 |
|
|
Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
|
4317 |
|
|
return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');
|
4318 |
|
|
};
|
4319 |
|
|
Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
|
4320 |
|
|
return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
|
4321 |
|
|
};
|
4322 |
|
|
Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
|
4323 |
|
|
return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
|
4324 |
|
|
};
|
4325 |
|
|
Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
|
4326 |
|
|
return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();
|
4327 |
|
|
};
|
4328 |
|
|
Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
|
4329 |
|
|
return this.getLabelText('x');
|
4330 |
|
|
};
|
4331 |
|
|
Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
|
4332 |
|
|
return this.getLabelText('y');
|
4333 |
|
|
};
|
4334 |
|
|
Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
|
4335 |
|
|
return this.getLabelText('y2');
|
4336 |
|
|
};
|
4337 |
|
|
Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
|
4338 |
|
|
var $$ = this.owner;
|
4339 |
|
|
if (forHorizontal) {
|
4340 |
|
|
return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
|
4341 |
|
|
} else {
|
4342 |
|
|
return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;
|
4343 |
|
|
}
|
4344 |
|
|
};
|
4345 |
|
|
Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
|
4346 |
|
|
if (forHorizontal) {
|
4347 |
|
|
return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
|
4348 |
|
|
} else {
|
4349 |
|
|
return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0";
|
4350 |
|
|
}
|
4351 |
|
|
};
|
4352 |
|
|
Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
|
4353 |
|
|
if (forHorizontal) {
|
4354 |
|
|
return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
|
4355 |
|
|
} else {
|
4356 |
|
|
return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
|
4357 |
|
|
}
|
4358 |
|
|
};
|
4359 |
|
|
Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
|
4360 |
|
|
return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
|
4361 |
|
|
};
|
4362 |
|
|
Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
|
4363 |
|
|
return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
|
4364 |
|
|
};
|
4365 |
|
|
Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
|
4366 |
|
|
return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
|
4367 |
|
|
};
|
4368 |
|
|
Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
|
4369 |
|
|
return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
|
4370 |
|
|
};
|
4371 |
|
|
Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
|
4372 |
|
|
return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
|
4373 |
|
|
};
|
4374 |
|
|
Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
|
4375 |
|
|
return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
|
4376 |
|
|
};
|
4377 |
|
|
Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
|
4378 |
|
|
var $$ = this.owner, config = $$.config,
|
4379 |
|
|
position = this.getXAxisLabelPosition();
|
4380 |
|
|
if (config.axis_rotated) {
|
4381 |
|
|
return position.isInner ? "1.2em" : -25 - this.getMaxTickWidth('x');
|
4382 |
|
|
} else {
|
4383 |
|
|
return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em";
|
4384 |
|
|
}
|
4385 |
|
|
};
|
4386 |
|
|
Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
|
4387 |
|
|
var $$ = this.owner,
|
4388 |
|
|
position = this.getYAxisLabelPosition();
|
4389 |
|
|
if ($$.config.axis_rotated) {
|
4390 |
|
|
return position.isInner ? "-0.5em" : "3em";
|
4391 |
|
|
} else {
|
4392 |
|
|
return position.isInner ? "1.2em" : -10 - ($$.config.axis_y_inner ? 0 : (this.getMaxTickWidth('y') + 10));
|
4393 |
|
|
}
|
4394 |
|
|
};
|
4395 |
|
|
Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
|
4396 |
|
|
var $$ = this.owner,
|
4397 |
|
|
position = this.getY2AxisLabelPosition();
|
4398 |
|
|
if ($$.config.axis_rotated) {
|
4399 |
|
|
return position.isInner ? "1.2em" : "-2.2em";
|
4400 |
|
|
} else {
|
4401 |
|
|
return position.isInner ? "-0.5em" : 15 + ($$.config.axis_y2_inner ? 0 : (this.getMaxTickWidth('y2') + 15));
|
4402 |
|
|
}
|
4403 |
|
|
};
|
4404 |
|
|
Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
|
4405 |
|
|
var $$ = this.owner;
|
4406 |
|
|
return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
|
4407 |
|
|
};
|
4408 |
|
|
Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
|
4409 |
|
|
var $$ = this.owner;
|
4410 |
|
|
return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
|
4411 |
|
|
};
|
4412 |
|
|
Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
|
4413 |
|
|
var $$ = this.owner;
|
4414 |
|
|
return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
|
4415 |
|
|
};
|
4416 |
|
|
Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
|
4417 |
|
|
var $$ = this.owner, config = $$.config,
|
4418 |
|
|
maxWidth = 0, targetsToShow, scale, axis, dummy, svg;
|
4419 |
|
|
if (withoutRecompute && $$.currentMaxTickWidths[id]) {
|
4420 |
|
|
return $$.currentMaxTickWidths[id];
|
4421 |
|
|
}
|
4422 |
|
|
if ($$.svg) {
|
4423 |
|
|
targetsToShow = $$.filterTargetsToShow($$.data.targets);
|
4424 |
|
|
if (id === 'y') {
|
4425 |
|
|
scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
|
4426 |
|
|
axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true);
|
4427 |
|
|
} else if (id === 'y2') {
|
4428 |
|
|
scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
|
4429 |
|
|
axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true);
|
4430 |
|
|
} else {
|
4431 |
|
|
scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
|
4432 |
|
|
axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
|
4433 |
|
|
this.updateXAxisTickValues(targetsToShow, axis);
|
4434 |
|
|
}
|
4435 |
|
|
dummy = $$.d3.select('body').append('div').classed('c3', true);
|
4436 |
|
|
svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
|
4437 |
|
|
svg.append('g').call(axis).each(function () {
|
4438 |
|
|
$$.d3.select(this).selectAll('text').each(function () {
|
4439 |
|
|
var box = this.getBoundingClientRect();
|
4440 |
|
|
if (maxWidth < box.width) { maxWidth = box.width; }
|
4441 |
|
|
});
|
4442 |
|
|
dummy.remove();
|
4443 |
|
|
});
|
4444 |
|
|
}
|
4445 |
|
|
$$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
|
4446 |
|
|
return $$.currentMaxTickWidths[id];
|
4447 |
|
|
};
|
4448 |
|
|
|
4449 |
|
|
Axis.prototype.updateLabels = function updateLabels(withTransition) {
|
4450 |
|
|
var $$ = this.owner;
|
4451 |
|
|
var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel),
|
4452 |
|
|
axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel),
|
4453 |
|
|
axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
|
4454 |
|
|
(withTransition ? axisXLabel.transition() : axisXLabel)
|
4455 |
|
|
.attr("x", this.xForXAxisLabel.bind(this))
|
4456 |
|
|
.attr("dx", this.dxForXAxisLabel.bind(this))
|
4457 |
|
|
.attr("dy", this.dyForXAxisLabel.bind(this))
|
4458 |
|
|
.text(this.textForXAxisLabel.bind(this));
|
4459 |
|
|
(withTransition ? axisYLabel.transition() : axisYLabel)
|
4460 |
|
|
.attr("x", this.xForYAxisLabel.bind(this))
|
4461 |
|
|
.attr("dx", this.dxForYAxisLabel.bind(this))
|
4462 |
|
|
.attr("dy", this.dyForYAxisLabel.bind(this))
|
4463 |
|
|
.text(this.textForYAxisLabel.bind(this));
|
4464 |
|
|
(withTransition ? axisY2Label.transition() : axisY2Label)
|
4465 |
|
|
.attr("x", this.xForY2AxisLabel.bind(this))
|
4466 |
|
|
.attr("dx", this.dxForY2AxisLabel.bind(this))
|
4467 |
|
|
.attr("dy", this.dyForY2AxisLabel.bind(this))
|
4468 |
|
|
.text(this.textForY2AxisLabel.bind(this));
|
4469 |
|
|
};
|
4470 |
|
|
Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
|
4471 |
|
|
if (!isValue(padding[key])) {
|
4472 |
|
|
return defaultValue;
|
4473 |
|
|
}
|
4474 |
|
|
if (padding.unit === 'ratio') {
|
4475 |
|
|
return padding[key] * domainLength;
|
4476 |
|
|
}
|
4477 |
|
|
// assume padding is pixels if unit is not specified
|
4478 |
|
|
return this.convertPixelsToAxisPadding(padding[key], domainLength);
|
4479 |
|
|
};
|
4480 |
|
|
Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
|
4481 |
|
|
var $$ = this.owner,
|
4482 |
|
|
length = $$.config.axis_rotated ? $$.width : $$.height;
|
4483 |
|
|
return domainLength * (pixels / length);
|
4484 |
|
|
};
|
4485 |
|
|
Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
|
4486 |
|
|
var tickValues = values, targetCount, start, end, count, interval, i, tickValue;
|
4487 |
|
|
if (tickCount) {
|
4488 |
|
|
targetCount = isFunction(tickCount) ? tickCount() : tickCount;
|
4489 |
|
|
// compute ticks according to tickCount
|
4490 |
|
|
if (targetCount === 1) {
|
4491 |
|
|
tickValues = [values[0]];
|
4492 |
|
|
} else if (targetCount === 2) {
|
4493 |
|
|
tickValues = [values[0], values[values.length - 1]];
|
4494 |
|
|
} else if (targetCount > 2) {
|
4495 |
|
|
count = targetCount - 2;
|
4496 |
|
|
start = values[0];
|
4497 |
|
|
end = values[values.length - 1];
|
4498 |
|
|
interval = (end - start) / (count + 1);
|
4499 |
|
|
// re-construct unique values
|
4500 |
|
|
tickValues = [start];
|
4501 |
|
|
for (i = 0; i < count; i++) {
|
4502 |
|
|
tickValue = +start + interval * (i + 1);
|
4503 |
|
|
tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
|
4504 |
|
|
}
|
4505 |
|
|
tickValues.push(end);
|
4506 |
|
|
}
|
4507 |
|
|
}
|
4508 |
|
|
if (!forTimeSeries) { tickValues = tickValues.sort(function (a, b) { return a - b; }); }
|
4509 |
|
|
return tickValues;
|
4510 |
|
|
};
|
4511 |
|
|
Axis.prototype.generateTransitions = function generateTransitions(duration) {
|
4512 |
|
|
var $$ = this.owner, axes = $$.axes;
|
4513 |
|
|
return {
|
4514 |
|
|
axisX: duration ? axes.x.transition().duration(duration) : axes.x,
|
4515 |
|
|
axisY: duration ? axes.y.transition().duration(duration) : axes.y,
|
4516 |
|
|
axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
|
4517 |
|
|
axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
|
4518 |
|
|
};
|
4519 |
|
|
};
|
4520 |
|
|
Axis.prototype.redraw = function redraw(transitions, isHidden) {
|
4521 |
|
|
var $$ = this.owner;
|
4522 |
|
|
$$.axes.x.style("opacity", isHidden ? 0 : 1);
|
4523 |
|
|
$$.axes.y.style("opacity", isHidden ? 0 : 1);
|
4524 |
|
|
$$.axes.y2.style("opacity", isHidden ? 0 : 1);
|
4525 |
|
|
$$.axes.subx.style("opacity", isHidden ? 0 : 1);
|
4526 |
|
|
transitions.axisX.call($$.xAxis);
|
4527 |
|
|
transitions.axisY.call($$.yAxis);
|
4528 |
|
|
transitions.axisY2.call($$.y2Axis);
|
4529 |
|
|
transitions.axisSubX.call($$.subXAxis);
|
4530 |
|
|
};
|
4531 |
|
|
|
4532 |
|
|
c3_chart_internal_fn.getClipPath = function (id) {
|
4533 |
|
|
var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
|
4534 |
|
|
return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")";
|
4535 |
|
|
};
|
4536 |
|
|
c3_chart_internal_fn.appendClip = function (parent, id) {
|
4537 |
|
|
return parent.append("clipPath").attr("id", id).append("rect");
|
4538 |
|
|
};
|
4539 |
|
|
c3_chart_internal_fn.getAxisClipX = function (forHorizontal) {
|
4540 |
|
|
// axis line width + padding for left
|
4541 |
|
|
var left = Math.max(30, this.margin.left);
|
4542 |
|
|
return forHorizontal ? -(1 + left) : -(left - 1);
|
4543 |
|
|
};
|
4544 |
|
|
c3_chart_internal_fn.getAxisClipY = function (forHorizontal) {
|
4545 |
|
|
return forHorizontal ? -20 : -this.margin.top;
|
4546 |
|
|
};
|
4547 |
|
|
c3_chart_internal_fn.getXAxisClipX = function () {
|
4548 |
|
|
var $$ = this;
|
4549 |
|
|
return $$.getAxisClipX(!$$.config.axis_rotated);
|
4550 |
|
|
};
|
4551 |
|
|
c3_chart_internal_fn.getXAxisClipY = function () {
|
4552 |
|
|
var $$ = this;
|
4553 |
|
|
return $$.getAxisClipY(!$$.config.axis_rotated);
|
4554 |
|
|
};
|
4555 |
|
|
c3_chart_internal_fn.getYAxisClipX = function () {
|
4556 |
|
|
var $$ = this;
|
4557 |
|
|
return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
|
4558 |
|
|
};
|
4559 |
|
|
c3_chart_internal_fn.getYAxisClipY = function () {
|
4560 |
|
|
var $$ = this;
|
4561 |
|
|
return $$.getAxisClipY($$.config.axis_rotated);
|
4562 |
|
|
};
|
4563 |
|
|
c3_chart_internal_fn.getAxisClipWidth = function (forHorizontal) {
|
4564 |
|
|
var $$ = this,
|
4565 |
|
|
left = Math.max(30, $$.margin.left),
|
4566 |
|
|
right = Math.max(30, $$.margin.right);
|
4567 |
|
|
// width + axis line width + padding for left/right
|
4568 |
|
|
return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
|
4569 |
|
|
};
|
4570 |
|
|
c3_chart_internal_fn.getAxisClipHeight = function (forHorizontal) {
|
4571 |
|
|
// less than 20 is not enough to show the axis label 'outer' without legend
|
4572 |
|
|
return (forHorizontal ? this.margin.bottom : (this.margin.top + this.height)) + 20;
|
4573 |
|
|
};
|
4574 |
|
|
c3_chart_internal_fn.getXAxisClipWidth = function () {
|
4575 |
|
|
var $$ = this;
|
4576 |
|
|
return $$.getAxisClipWidth(!$$.config.axis_rotated);
|
4577 |
|
|
};
|
4578 |
|
|
c3_chart_internal_fn.getXAxisClipHeight = function () {
|
4579 |
|
|
var $$ = this;
|
4580 |
|
|
return $$.getAxisClipHeight(!$$.config.axis_rotated);
|
4581 |
|
|
};
|
4582 |
|
|
c3_chart_internal_fn.getYAxisClipWidth = function () {
|
4583 |
|
|
var $$ = this;
|
4584 |
|
|
return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);
|
4585 |
|
|
};
|
4586 |
|
|
c3_chart_internal_fn.getYAxisClipHeight = function () {
|
4587 |
|
|
var $$ = this;
|
4588 |
|
|
return $$.getAxisClipHeight($$.config.axis_rotated);
|
4589 |
|
|
};
|
4590 |
|
|
|
4591 |
|
|
c3_chart_internal_fn.initPie = function () {
|
4592 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config;
|
4593 |
|
|
$$.pie = d3.layout.pie().value(function (d) {
|
4594 |
|
|
return d.values.reduce(function (a, b) { return a + b.value; }, 0);
|
4595 |
|
|
});
|
4596 |
|
|
if (!config.data_order) {
|
4597 |
|
|
$$.pie.sort(null);
|
4598 |
|
|
}
|
4599 |
|
|
};
|
4600 |
|
|
|
4601 |
|
|
c3_chart_internal_fn.updateRadius = function () {
|
4602 |
|
|
var $$ = this, config = $$.config,
|
4603 |
|
|
w = config.gauge_width || config.donut_width;
|
4604 |
|
|
$$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;
|
4605 |
|
|
$$.radius = $$.radiusExpanded * 0.95;
|
4606 |
|
|
$$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
|
4607 |
|
|
$$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;
|
4608 |
|
|
};
|
4609 |
|
|
|
4610 |
|
|
c3_chart_internal_fn.updateArc = function () {
|
4611 |
|
|
var $$ = this;
|
4612 |
|
|
$$.svgArc = $$.getSvgArc();
|
4613 |
|
|
$$.svgArcExpanded = $$.getSvgArcExpanded();
|
4614 |
|
|
$$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
|
4615 |
|
|
};
|
4616 |
|
|
|
4617 |
|
|
c3_chart_internal_fn.updateAngle = function (d) {
|
4618 |
|
|
var $$ = this, config = $$.config,
|
4619 |
|
|
found = false, index = 0,
|
4620 |
|
|
gMin = config.gauge_min, gMax = config.gauge_max, gTic, gValue;
|
4621 |
|
|
$$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
|
4622 |
|
|
if (! found && t.data.id === d.data.id) {
|
4623 |
|
|
found = true;
|
4624 |
|
|
d = t;
|
4625 |
|
|
d.index = index;
|
4626 |
|
|
}
|
4627 |
|
|
index++;
|
4628 |
|
|
});
|
4629 |
|
|
if (isNaN(d.startAngle)) {
|
4630 |
|
|
d.startAngle = 0;
|
4631 |
|
|
}
|
4632 |
|
|
if (isNaN(d.endAngle)) {
|
4633 |
|
|
d.endAngle = d.startAngle;
|
4634 |
|
|
}
|
4635 |
|
|
if ($$.isGaugeType(d.data)) {
|
4636 |
|
|
gTic = (Math.PI) / (gMax - gMin);
|
4637 |
|
|
gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);
|
4638 |
|
|
d.startAngle = -1 * (Math.PI / 2);
|
4639 |
|
|
d.endAngle = d.startAngle + gTic * gValue;
|
4640 |
|
|
}
|
4641 |
|
|
return found ? d : null;
|
4642 |
|
|
};
|
4643 |
|
|
|
4644 |
|
|
c3_chart_internal_fn.getSvgArc = function () {
|
4645 |
|
|
var $$ = this,
|
4646 |
|
|
arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius),
|
4647 |
|
|
newArc = function (d, withoutUpdate) {
|
4648 |
|
|
var updated;
|
4649 |
|
|
if (withoutUpdate) { return arc(d); } // for interpolate
|
4650 |
|
|
updated = $$.updateAngle(d);
|
4651 |
|
|
return updated ? arc(updated) : "M 0 0";
|
4652 |
|
|
};
|
4653 |
|
|
// TODO: extends all function
|
4654 |
|
|
newArc.centroid = arc.centroid;
|
4655 |
|
|
return newArc;
|
4656 |
|
|
};
|
4657 |
|
|
|
4658 |
|
|
c3_chart_internal_fn.getSvgArcExpanded = function (rate) {
|
4659 |
|
|
var $$ = this,
|
4660 |
|
|
arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius);
|
4661 |
|
|
return function (d) {
|
4662 |
|
|
var updated = $$.updateAngle(d);
|
4663 |
|
|
return updated ? arc(updated) : "M 0 0";
|
4664 |
|
|
};
|
4665 |
|
|
};
|
4666 |
|
|
|
4667 |
|
|
c3_chart_internal_fn.getArc = function (d, withoutUpdate, force) {
|
4668 |
|
|
return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
|
4669 |
|
|
};
|
4670 |
|
|
|
4671 |
|
|
|
4672 |
|
|
c3_chart_internal_fn.transformForArcLabel = function (d) {
|
4673 |
|
|
var $$ = this,
|
4674 |
|
|
updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
|
4675 |
|
|
if (updated && !$$.hasType('gauge')) {
|
4676 |
|
|
c = this.svgArc.centroid(updated);
|
4677 |
|
|
x = isNaN(c[0]) ? 0 : c[0];
|
4678 |
|
|
y = isNaN(c[1]) ? 0 : c[1];
|
4679 |
|
|
h = Math.sqrt(x * x + y * y);
|
4680 |
|
|
// TODO: ratio should be an option?
|
4681 |
|
|
ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
|
4682 |
|
|
translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")";
|
4683 |
|
|
}
|
4684 |
|
|
return translate;
|
4685 |
|
|
};
|
4686 |
|
|
|
4687 |
|
|
c3_chart_internal_fn.getArcRatio = function (d) {
|
4688 |
|
|
var $$ = this,
|
4689 |
|
|
whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2);
|
4690 |
|
|
return d ? (d.endAngle - d.startAngle) / whole : null;
|
4691 |
|
|
};
|
4692 |
|
|
|
4693 |
|
|
c3_chart_internal_fn.convertToArcData = function (d) {
|
4694 |
|
|
return this.addName({
|
4695 |
|
|
id: d.data.id,
|
4696 |
|
|
value: d.value,
|
4697 |
|
|
ratio: this.getArcRatio(d),
|
4698 |
|
|
index: d.index
|
4699 |
|
|
});
|
4700 |
|
|
};
|
4701 |
|
|
|
4702 |
|
|
c3_chart_internal_fn.textForArcLabel = function (d) {
|
4703 |
|
|
var $$ = this,
|
4704 |
|
|
updated, value, ratio, id, format;
|
4705 |
|
|
if (! $$.shouldShowArcLabel()) { return ""; }
|
4706 |
|
|
updated = $$.updateAngle(d);
|
4707 |
|
|
value = updated ? updated.value : null;
|
4708 |
|
|
ratio = $$.getArcRatio(updated);
|
4709 |
|
|
id = d.data.id;
|
4710 |
|
|
if (! $$.hasType('gauge') && ! $$.meetsArcLabelThreshold(ratio)) { return ""; }
|
4711 |
|
|
format = $$.getArcLabelFormat();
|
4712 |
|
|
return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);
|
4713 |
|
|
};
|
4714 |
|
|
|
4715 |
|
|
c3_chart_internal_fn.expandArc = function (targetIds) {
|
4716 |
|
|
var $$ = this, interval;
|
4717 |
|
|
|
4718 |
|
|
// MEMO: avoid to cancel transition
|
4719 |
|
|
if ($$.transiting) {
|
4720 |
|
|
interval = window.setInterval(function () {
|
4721 |
|
|
if (!$$.transiting) {
|
4722 |
|
|
window.clearInterval(interval);
|
4723 |
|
|
if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
|
4724 |
|
|
$$.expandArc(targetIds);
|
4725 |
|
|
}
|
4726 |
|
|
}
|
4727 |
|
|
}, 10);
|
4728 |
|
|
return;
|
4729 |
|
|
}
|
4730 |
|
|
|
4731 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
4732 |
|
|
|
4733 |
|
|
$$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) {
|
4734 |
|
|
if (! $$.shouldExpand(d.data.id)) { return; }
|
4735 |
|
|
$$.d3.select(this).selectAll('path')
|
4736 |
|
|
.transition().duration(50)
|
4737 |
|
|
.attr("d", $$.svgArcExpanded)
|
4738 |
|
|
.transition().duration(100)
|
4739 |
|
|
.attr("d", $$.svgArcExpandedSub)
|
4740 |
|
|
.each(function (d) {
|
4741 |
|
|
if ($$.isDonutType(d.data)) {
|
4742 |
|
|
// callback here
|
4743 |
|
|
}
|
4744 |
|
|
});
|
4745 |
|
|
});
|
4746 |
|
|
};
|
4747 |
|
|
|
4748 |
|
|
c3_chart_internal_fn.unexpandArc = function (targetIds) {
|
4749 |
|
|
var $$ = this;
|
4750 |
|
|
|
4751 |
|
|
if ($$.transiting) { return; }
|
4752 |
|
|
|
4753 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
4754 |
|
|
|
4755 |
|
|
$$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path')
|
4756 |
|
|
.transition().duration(50)
|
4757 |
|
|
.attr("d", $$.svgArc);
|
4758 |
|
|
$$.svg.selectAll('.' + CLASS.arc)
|
4759 |
|
|
.style("opacity", 1);
|
4760 |
|
|
};
|
4761 |
|
|
|
4762 |
|
|
c3_chart_internal_fn.shouldExpand = function (id) {
|
4763 |
|
|
var $$ = this, config = $$.config;
|
4764 |
|
|
return ($$.isDonutType(id) && config.donut_expand) || ($$.isGaugeType(id) && config.gauge_expand) || ($$.isPieType(id) && config.pie_expand);
|
4765 |
|
|
};
|
4766 |
|
|
|
4767 |
|
|
c3_chart_internal_fn.shouldShowArcLabel = function () {
|
4768 |
|
|
var $$ = this, config = $$.config, shouldShow = true;
|
4769 |
|
|
if ($$.hasType('donut')) {
|
4770 |
|
|
shouldShow = config.donut_label_show;
|
4771 |
|
|
} else if ($$.hasType('pie')) {
|
4772 |
|
|
shouldShow = config.pie_label_show;
|
4773 |
|
|
}
|
4774 |
|
|
// when gauge, always true
|
4775 |
|
|
return shouldShow;
|
4776 |
|
|
};
|
4777 |
|
|
|
4778 |
|
|
c3_chart_internal_fn.meetsArcLabelThreshold = function (ratio) {
|
4779 |
|
|
var $$ = this, config = $$.config,
|
4780 |
|
|
threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold;
|
4781 |
|
|
return ratio >= threshold;
|
4782 |
|
|
};
|
4783 |
|
|
|
4784 |
|
|
c3_chart_internal_fn.getArcLabelFormat = function () {
|
4785 |
|
|
var $$ = this, config = $$.config,
|
4786 |
|
|
format = config.pie_label_format;
|
4787 |
|
|
if ($$.hasType('gauge')) {
|
4788 |
|
|
format = config.gauge_label_format;
|
4789 |
|
|
} else if ($$.hasType('donut')) {
|
4790 |
|
|
format = config.donut_label_format;
|
4791 |
|
|
}
|
4792 |
|
|
return format;
|
4793 |
|
|
};
|
4794 |
|
|
|
4795 |
|
|
c3_chart_internal_fn.getArcTitle = function () {
|
4796 |
|
|
var $$ = this;
|
4797 |
|
|
return $$.hasType('donut') ? $$.config.donut_title : "";
|
4798 |
|
|
};
|
4799 |
|
|
|
4800 |
|
|
c3_chart_internal_fn.updateTargetsForArc = function (targets) {
|
4801 |
|
|
var $$ = this, main = $$.main,
|
4802 |
|
|
mainPieUpdate, mainPieEnter,
|
4803 |
|
|
classChartArc = $$.classChartArc.bind($$),
|
4804 |
|
|
classArcs = $$.classArcs.bind($$),
|
4805 |
|
|
classFocus = $$.classFocus.bind($$);
|
4806 |
|
|
mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc)
|
4807 |
|
|
.data($$.pie(targets))
|
4808 |
|
|
.attr("class", function (d) { return classChartArc(d) + classFocus(d.data); });
|
4809 |
|
|
mainPieEnter = mainPieUpdate.enter().append("g")
|
4810 |
|
|
.attr("class", classChartArc);
|
4811 |
|
|
mainPieEnter.append('g')
|
4812 |
|
|
.attr('class', classArcs);
|
4813 |
|
|
mainPieEnter.append("text")
|
4814 |
|
|
.attr("dy", $$.hasType('gauge') ? "-.1em" : ".35em")
|
4815 |
|
|
.style("opacity", 0)
|
4816 |
|
|
.style("text-anchor", "middle")
|
4817 |
|
|
.style("pointer-events", "none");
|
4818 |
|
|
// MEMO: can not keep same color..., but not bad to update color in redraw
|
4819 |
|
|
//mainPieUpdate.exit().remove();
|
4820 |
|
|
};
|
4821 |
|
|
|
4822 |
|
|
c3_chart_internal_fn.initArc = function () {
|
4823 |
|
|
var $$ = this;
|
4824 |
|
|
$$.arcs = $$.main.select('.' + CLASS.chart).append("g")
|
4825 |
|
|
.attr("class", CLASS.chartArcs)
|
4826 |
|
|
.attr("transform", $$.getTranslate('arc'));
|
4827 |
|
|
$$.arcs.append('text')
|
4828 |
|
|
.attr('class', CLASS.chartArcsTitle)
|
4829 |
|
|
.style("text-anchor", "middle")
|
4830 |
|
|
.text($$.getArcTitle());
|
4831 |
|
|
};
|
4832 |
|
|
|
4833 |
|
|
c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransform) {
|
4834 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main,
|
4835 |
|
|
mainArc;
|
4836 |
|
|
mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc)
|
4837 |
|
|
.data($$.arcData.bind($$));
|
4838 |
|
|
mainArc.enter().append('path')
|
4839 |
|
|
.attr("class", $$.classArc.bind($$))
|
4840 |
|
|
.style("fill", function (d) { return $$.color(d.data); })
|
4841 |
|
|
.style("cursor", function (d) { return config.interaction_enabled && config.data_selection_isselectable(d) ? "pointer" : null; })
|
4842 |
|
|
.style("opacity", 0)
|
4843 |
|
|
.each(function (d) {
|
4844 |
|
|
if ($$.isGaugeType(d.data)) {
|
4845 |
|
|
d.startAngle = d.endAngle = -1 * (Math.PI / 2);
|
4846 |
|
|
}
|
4847 |
|
|
this._current = d;
|
4848 |
|
|
});
|
4849 |
|
|
mainArc
|
4850 |
|
|
.attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; })
|
4851 |
|
|
.style("opacity", function (d) { return d === this._current ? 0 : 1; })
|
4852 |
|
|
.on('mouseover', config.interaction_enabled ? function (d) {
|
4853 |
|
|
var updated, arcData;
|
4854 |
|
|
if ($$.transiting) { // skip while transiting
|
4855 |
|
|
return;
|
4856 |
|
|
}
|
4857 |
|
|
updated = $$.updateAngle(d);
|
4858 |
|
|
arcData = $$.convertToArcData(updated);
|
4859 |
|
|
// transitions
|
4860 |
|
|
$$.expandArc(updated.data.id);
|
4861 |
|
|
$$.api.focus(updated.data.id);
|
4862 |
|
|
$$.toggleFocusLegend(updated.data.id, true);
|
4863 |
|
|
$$.config.data_onmouseover(arcData, this);
|
4864 |
|
|
} : null)
|
4865 |
|
|
.on('mousemove', config.interaction_enabled ? function (d) {
|
4866 |
|
|
var updated = $$.updateAngle(d),
|
4867 |
|
|
arcData = $$.convertToArcData(updated),
|
4868 |
|
|
selectedData = [arcData];
|
4869 |
|
|
$$.showTooltip(selectedData, this);
|
4870 |
|
|
} : null)
|
4871 |
|
|
.on('mouseout', config.interaction_enabled ? function (d) {
|
4872 |
|
|
var updated, arcData;
|
4873 |
|
|
if ($$.transiting) { // skip while transiting
|
4874 |
|
|
return;
|
4875 |
|
|
}
|
4876 |
|
|
updated = $$.updateAngle(d);
|
4877 |
|
|
arcData = $$.convertToArcData(updated);
|
4878 |
|
|
// transitions
|
4879 |
|
|
$$.unexpandArc(updated.data.id);
|
4880 |
|
|
$$.api.revert();
|
4881 |
|
|
$$.revertLegend();
|
4882 |
|
|
$$.hideTooltip();
|
4883 |
|
|
$$.config.data_onmouseout(arcData, this);
|
4884 |
|
|
} : null)
|
4885 |
|
|
.on('click', config.interaction_enabled ? function (d, i) {
|
4886 |
|
|
var updated = $$.updateAngle(d),
|
4887 |
|
|
arcData = $$.convertToArcData(updated);
|
4888 |
|
|
if ($$.toggleShape) { $$.toggleShape(this, arcData, i); }
|
4889 |
|
|
$$.config.data_onclick.call($$.api, arcData, this);
|
4890 |
|
|
} : null)
|
4891 |
|
|
.each(function () { $$.transiting = true; })
|
4892 |
|
|
.transition().duration(duration)
|
4893 |
|
|
.attrTween("d", function (d) {
|
4894 |
|
|
var updated = $$.updateAngle(d), interpolate;
|
4895 |
|
|
if (! updated) {
|
4896 |
|
|
return function () { return "M 0 0"; };
|
4897 |
|
|
}
|
4898 |
|
|
// if (this._current === d) {
|
4899 |
|
|
// this._current = {
|
4900 |
|
|
// startAngle: Math.PI*2,
|
4901 |
|
|
// endAngle: Math.PI*2,
|
4902 |
|
|
// };
|
4903 |
|
|
// }
|
4904 |
|
|
if (isNaN(this._current.startAngle)) {
|
4905 |
|
|
this._current.startAngle = 0;
|
4906 |
|
|
}
|
4907 |
|
|
if (isNaN(this._current.endAngle)) {
|
4908 |
|
|
this._current.endAngle = this._current.startAngle;
|
4909 |
|
|
}
|
4910 |
|
|
interpolate = d3.interpolate(this._current, updated);
|
4911 |
|
|
this._current = interpolate(0);
|
4912 |
|
|
return function (t) {
|
4913 |
|
|
var interpolated = interpolate(t);
|
4914 |
|
|
interpolated.data = d.data; // data.id will be updated by interporator
|
4915 |
|
|
return $$.getArc(interpolated, true);
|
4916 |
|
|
};
|
4917 |
|
|
})
|
4918 |
|
|
.attr("transform", withTransform ? "scale(1)" : "")
|
4919 |
|
|
.style("fill", function (d) {
|
4920 |
|
|
return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
|
4921 |
|
|
}) // Where gauge reading color would receive customization.
|
4922 |
|
|
.style("opacity", 1)
|
4923 |
|
|
.call($$.endall, function () {
|
4924 |
|
|
$$.transiting = false;
|
4925 |
|
|
});
|
4926 |
|
|
mainArc.exit().transition().duration(durationForExit)
|
4927 |
|
|
.style('opacity', 0)
|
4928 |
|
|
.remove();
|
4929 |
|
|
main.selectAll('.' + CLASS.chartArc).select('text')
|
4930 |
|
|
.style("opacity", 0)
|
4931 |
|
|
.attr('class', function (d) { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; })
|
4932 |
|
|
.text($$.textForArcLabel.bind($$))
|
4933 |
|
|
.attr("transform", $$.transformForArcLabel.bind($$))
|
4934 |
|
|
.style('font-size', function (d) { return $$.isGaugeType(d.data) ? Math.round($$.radius / 5) + 'px' : ''; })
|
4935 |
|
|
.transition().duration(duration)
|
4936 |
|
|
.style("opacity", function (d) { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; });
|
4937 |
|
|
main.select('.' + CLASS.chartArcsTitle)
|
4938 |
|
|
.style("opacity", $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0);
|
4939 |
|
|
|
4940 |
|
|
if ($$.hasType('gauge')) {
|
4941 |
|
|
$$.arcs.select('.' + CLASS.chartArcsBackground)
|
4942 |
|
|
.attr("d", function () {
|
4943 |
|
|
var d = {
|
4944 |
|
|
data: [{value: config.gauge_max}],
|
4945 |
|
|
startAngle: -1 * (Math.PI / 2),
|
4946 |
|
|
endAngle: Math.PI / 2
|
4947 |
|
|
};
|
4948 |
|
|
return $$.getArc(d, true, true);
|
4949 |
|
|
});
|
4950 |
|
|
$$.arcs.select('.' + CLASS.chartArcsGaugeUnit)
|
4951 |
|
|
.attr("dy", ".75em")
|
4952 |
|
|
.text(config.gauge_label_show ? config.gauge_units : '');
|
4953 |
|
|
$$.arcs.select('.' + CLASS.chartArcsGaugeMin)
|
4954 |
|
|
.attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px")
|
4955 |
|
|
.attr("dy", "1.2em")
|
4956 |
|
|
.text(config.gauge_label_show ? config.gauge_min : '');
|
4957 |
|
|
$$.arcs.select('.' + CLASS.chartArcsGaugeMax)
|
4958 |
|
|
.attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px")
|
4959 |
|
|
.attr("dy", "1.2em")
|
4960 |
|
|
.text(config.gauge_label_show ? config.gauge_max : '');
|
4961 |
|
|
}
|
4962 |
|
|
};
|
4963 |
|
|
c3_chart_internal_fn.initGauge = function () {
|
4964 |
|
|
var arcs = this.arcs;
|
4965 |
|
|
if (this.hasType('gauge')) {
|
4966 |
|
|
arcs.append('path')
|
4967 |
|
|
.attr("class", CLASS.chartArcsBackground);
|
4968 |
|
|
arcs.append("text")
|
4969 |
|
|
.attr("class", CLASS.chartArcsGaugeUnit)
|
4970 |
|
|
.style("text-anchor", "middle")
|
4971 |
|
|
.style("pointer-events", "none");
|
4972 |
|
|
arcs.append("text")
|
4973 |
|
|
.attr("class", CLASS.chartArcsGaugeMin)
|
4974 |
|
|
.style("text-anchor", "middle")
|
4975 |
|
|
.style("pointer-events", "none");
|
4976 |
|
|
arcs.append("text")
|
4977 |
|
|
.attr("class", CLASS.chartArcsGaugeMax)
|
4978 |
|
|
.style("text-anchor", "middle")
|
4979 |
|
|
.style("pointer-events", "none");
|
4980 |
|
|
}
|
4981 |
|
|
};
|
4982 |
|
|
c3_chart_internal_fn.getGaugeLabelHeight = function () {
|
4983 |
|
|
return this.config.gauge_label_show ? 20 : 0;
|
4984 |
|
|
};
|
4985 |
|
|
|
4986 |
|
|
c3_chart_internal_fn.initRegion = function () {
|
4987 |
|
|
var $$ = this;
|
4988 |
|
|
$$.region = $$.main.append('g')
|
4989 |
|
|
.attr("clip-path", $$.clipPath)
|
4990 |
|
|
.attr("class", CLASS.regions);
|
4991 |
|
|
};
|
4992 |
|
|
c3_chart_internal_fn.updateRegion = function (duration) {
|
4993 |
|
|
var $$ = this, config = $$.config;
|
4994 |
|
|
|
4995 |
|
|
// hide if arc type
|
4996 |
|
|
$$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
|
4997 |
|
|
|
4998 |
|
|
$$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
|
4999 |
|
|
.data(config.regions);
|
5000 |
|
|
$$.mainRegion.enter().append('g')
|
5001 |
|
|
.attr('class', $$.classRegion.bind($$))
|
5002 |
|
|
.append('rect')
|
5003 |
|
|
.style("fill-opacity", 0);
|
5004 |
|
|
$$.mainRegion.exit().transition().duration(duration)
|
5005 |
|
|
.style("opacity", 0)
|
5006 |
|
|
.remove();
|
5007 |
|
|
};
|
5008 |
|
|
c3_chart_internal_fn.redrawRegion = function (withTransition) {
|
5009 |
|
|
var $$ = this,
|
5010 |
|
|
regions = $$.mainRegion.selectAll('rect'),
|
5011 |
|
|
x = $$.regionX.bind($$),
|
5012 |
|
|
y = $$.regionY.bind($$),
|
5013 |
|
|
w = $$.regionWidth.bind($$),
|
5014 |
|
|
h = $$.regionHeight.bind($$);
|
5015 |
|
|
return [
|
5016 |
|
|
(withTransition ? regions.transition() : regions)
|
5017 |
|
|
.attr("x", x)
|
5018 |
|
|
.attr("y", y)
|
5019 |
|
|
.attr("width", w)
|
5020 |
|
|
.attr("height", h)
|
5021 |
|
|
.style("fill-opacity", function (d) { return isValue(d.opacity) ? d.opacity : 0.1; })
|
5022 |
|
|
];
|
5023 |
|
|
};
|
5024 |
|
|
c3_chart_internal_fn.regionX = function (d) {
|
5025 |
|
|
var $$ = this, config = $$.config,
|
5026 |
|
|
xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
|
5027 |
|
|
if (d.axis === 'y' || d.axis === 'y2') {
|
5028 |
|
|
xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
|
5029 |
|
|
} else {
|
5030 |
|
|
xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0);
|
5031 |
|
|
}
|
5032 |
|
|
return xPos;
|
5033 |
|
|
};
|
5034 |
|
|
c3_chart_internal_fn.regionY = function (d) {
|
5035 |
|
|
var $$ = this, config = $$.config,
|
5036 |
|
|
yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
|
5037 |
|
|
if (d.axis === 'y' || d.axis === 'y2') {
|
5038 |
|
|
yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0);
|
5039 |
|
|
} else {
|
5040 |
|
|
yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0;
|
5041 |
|
|
}
|
5042 |
|
|
return yPos;
|
5043 |
|
|
};
|
5044 |
|
|
c3_chart_internal_fn.regionWidth = function (d) {
|
5045 |
|
|
var $$ = this, config = $$.config,
|
5046 |
|
|
start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
|
5047 |
|
|
if (d.axis === 'y' || d.axis === 'y2') {
|
5048 |
|
|
end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width;
|
5049 |
|
|
} else {
|
5050 |
|
|
end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width);
|
5051 |
|
|
}
|
5052 |
|
|
return end < start ? 0 : end - start;
|
5053 |
|
|
};
|
5054 |
|
|
c3_chart_internal_fn.regionHeight = function (d) {
|
5055 |
|
|
var $$ = this, config = $$.config,
|
5056 |
|
|
start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
|
5057 |
|
|
if (d.axis === 'y' || d.axis === 'y2') {
|
5058 |
|
|
end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height);
|
5059 |
|
|
} else {
|
5060 |
|
|
end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height;
|
5061 |
|
|
}
|
5062 |
|
|
return end < start ? 0 : end - start;
|
5063 |
|
|
};
|
5064 |
|
|
c3_chart_internal_fn.isRegionOnX = function (d) {
|
5065 |
|
|
return !d.axis || d.axis === 'x';
|
5066 |
|
|
};
|
5067 |
|
|
|
5068 |
|
|
c3_chart_internal_fn.drag = function (mouse) {
|
5069 |
|
|
var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
|
5070 |
|
|
var sx, sy, mx, my, minX, maxX, minY, maxY;
|
5071 |
|
|
|
5072 |
|
|
if ($$.hasArcType()) { return; }
|
5073 |
|
|
if (! config.data_selection_enabled) { return; } // do nothing if not selectable
|
5074 |
|
|
if (config.zoom_enabled && ! $$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior
|
5075 |
|
|
if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection
|
5076 |
|
|
|
5077 |
|
|
sx = $$.dragStart[0];
|
5078 |
|
|
sy = $$.dragStart[1];
|
5079 |
|
|
mx = mouse[0];
|
5080 |
|
|
my = mouse[1];
|
5081 |
|
|
minX = Math.min(sx, mx);
|
5082 |
|
|
maxX = Math.max(sx, mx);
|
5083 |
|
|
minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my);
|
5084 |
|
|
maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my);
|
5085 |
|
|
|
5086 |
|
|
main.select('.' + CLASS.dragarea)
|
5087 |
|
|
.attr('x', minX)
|
5088 |
|
|
.attr('y', minY)
|
5089 |
|
|
.attr('width', maxX - minX)
|
5090 |
|
|
.attr('height', maxY - minY);
|
5091 |
|
|
// TODO: binary search when multiple xs
|
5092 |
|
|
main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape)
|
5093 |
|
|
.filter(function (d) { return config.data_selection_isselectable(d); })
|
5094 |
|
|
.each(function (d, i) {
|
5095 |
|
|
var shape = d3.select(this),
|
5096 |
|
|
isSelected = shape.classed(CLASS.SELECTED),
|
5097 |
|
|
isIncluded = shape.classed(CLASS.INCLUDED),
|
5098 |
|
|
_x, _y, _w, _h, toggle, isWithin = false, box;
|
5099 |
|
|
if (shape.classed(CLASS.circle)) {
|
5100 |
|
|
_x = shape.attr("cx") * 1;
|
5101 |
|
|
_y = shape.attr("cy") * 1;
|
5102 |
|
|
toggle = $$.togglePoint;
|
5103 |
|
|
isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
|
5104 |
|
|
}
|
5105 |
|
|
else if (shape.classed(CLASS.bar)) {
|
5106 |
|
|
box = getPathBox(this);
|
5107 |
|
|
_x = box.x;
|
5108 |
|
|
_y = box.y;
|
5109 |
|
|
_w = box.width;
|
5110 |
|
|
_h = box.height;
|
5111 |
|
|
toggle = $$.togglePath;
|
5112 |
|
|
isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
|
5113 |
|
|
} else {
|
5114 |
|
|
// line/area selection not supported yet
|
5115 |
|
|
return;
|
5116 |
|
|
}
|
5117 |
|
|
if (isWithin ^ isIncluded) {
|
5118 |
|
|
shape.classed(CLASS.INCLUDED, !isIncluded);
|
5119 |
|
|
// TODO: included/unincluded callback here
|
5120 |
|
|
shape.classed(CLASS.SELECTED, !isSelected);
|
5121 |
|
|
toggle.call($$, !isSelected, shape, d, i);
|
5122 |
|
|
}
|
5123 |
|
|
});
|
5124 |
|
|
};
|
5125 |
|
|
|
5126 |
|
|
c3_chart_internal_fn.dragstart = function (mouse) {
|
5127 |
|
|
var $$ = this, config = $$.config;
|
5128 |
|
|
if ($$.hasArcType()) { return; }
|
5129 |
|
|
if (! config.data_selection_enabled) { return; } // do nothing if not selectable
|
5130 |
|
|
$$.dragStart = mouse;
|
5131 |
|
|
$$.main.select('.' + CLASS.chart).append('rect')
|
5132 |
|
|
.attr('class', CLASS.dragarea)
|
5133 |
|
|
.style('opacity', 0.1);
|
5134 |
|
|
$$.dragging = true;
|
5135 |
|
|
};
|
5136 |
|
|
|
5137 |
|
|
c3_chart_internal_fn.dragend = function () {
|
5138 |
|
|
var $$ = this, config = $$.config;
|
5139 |
|
|
if ($$.hasArcType()) { return; }
|
5140 |
|
|
if (! config.data_selection_enabled) { return; } // do nothing if not selectable
|
5141 |
|
|
$$.main.select('.' + CLASS.dragarea)
|
5142 |
|
|
.transition().duration(100)
|
5143 |
|
|
.style('opacity', 0)
|
5144 |
|
|
.remove();
|
5145 |
|
|
$$.main.selectAll('.' + CLASS.shape)
|
5146 |
|
|
.classed(CLASS.INCLUDED, false);
|
5147 |
|
|
$$.dragging = false;
|
5148 |
|
|
};
|
5149 |
|
|
|
5150 |
|
|
c3_chart_internal_fn.selectPoint = function (target, d, i) {
|
5151 |
|
|
var $$ = this, config = $$.config,
|
5152 |
|
|
cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
|
5153 |
|
|
cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),
|
5154 |
|
|
r = $$.pointSelectR.bind($$);
|
5155 |
|
|
config.data_onselected.call($$.api, d, target.node());
|
5156 |
|
|
// add selected-circle on low layer g
|
5157 |
|
|
$$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
|
5158 |
|
|
.data([d])
|
5159 |
|
|
.enter().append('circle')
|
5160 |
|
|
.attr("class", function () { return $$.generateClass(CLASS.selectedCircle, i); })
|
5161 |
|
|
.attr("cx", cx)
|
5162 |
|
|
.attr("cy", cy)
|
5163 |
|
|
.attr("stroke", function () { return $$.color(d); })
|
5164 |
|
|
.attr("r", function (d) { return $$.pointSelectR(d) * 1.4; })
|
5165 |
|
|
.transition().duration(100)
|
5166 |
|
|
.attr("r", r);
|
5167 |
|
|
};
|
5168 |
|
|
c3_chart_internal_fn.unselectPoint = function (target, d, i) {
|
5169 |
|
|
var $$ = this;
|
5170 |
|
|
$$.config.data_onunselected(d, target.node());
|
5171 |
|
|
// remove selected-circle from low layer g
|
5172 |
|
|
$$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
|
5173 |
|
|
.transition().duration(100).attr('r', 0)
|
5174 |
|
|
.remove();
|
5175 |
|
|
};
|
5176 |
|
|
c3_chart_internal_fn.togglePoint = function (selected, target, d, i) {
|
5177 |
|
|
selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
|
5178 |
|
|
};
|
5179 |
|
|
c3_chart_internal_fn.selectPath = function (target, d) {
|
5180 |
|
|
var $$ = this;
|
5181 |
|
|
$$.config.data_onselected.call($$, d, target.node());
|
5182 |
|
|
target.transition().duration(100)
|
5183 |
|
|
.style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
|
5184 |
|
|
};
|
5185 |
|
|
c3_chart_internal_fn.unselectPath = function (target, d) {
|
5186 |
|
|
var $$ = this;
|
5187 |
|
|
$$.config.data_onunselected.call($$, d, target.node());
|
5188 |
|
|
target.transition().duration(100)
|
5189 |
|
|
.style("fill", function () { return $$.color(d); });
|
5190 |
|
|
};
|
5191 |
|
|
c3_chart_internal_fn.togglePath = function (selected, target, d, i) {
|
5192 |
|
|
selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
|
5193 |
|
|
};
|
5194 |
|
|
c3_chart_internal_fn.getToggle = function (that, d) {
|
5195 |
|
|
var $$ = this, toggle;
|
5196 |
|
|
if (that.nodeName === 'circle') {
|
5197 |
|
|
if ($$.isStepType(d)) {
|
5198 |
|
|
// circle is hidden in step chart, so treat as within the click area
|
5199 |
|
|
toggle = function () {}; // TODO: how to select step chart?
|
5200 |
|
|
} else {
|
5201 |
|
|
toggle = $$.togglePoint;
|
5202 |
|
|
}
|
5203 |
|
|
}
|
5204 |
|
|
else if (that.nodeName === 'path') {
|
5205 |
|
|
toggle = $$.togglePath;
|
5206 |
|
|
}
|
5207 |
|
|
return toggle;
|
5208 |
|
|
};
|
5209 |
|
|
c3_chart_internal_fn.toggleShape = function (that, d, i) {
|
5210 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config,
|
5211 |
|
|
shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED),
|
5212 |
|
|
toggle = $$.getToggle(that, d).bind($$);
|
5213 |
|
|
|
5214 |
|
|
if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
|
5215 |
|
|
if (!config.data_selection_multiple) {
|
5216 |
|
|
$$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) {
|
5217 |
|
|
var shape = d3.select(this);
|
5218 |
|
|
if (shape.classed(CLASS.SELECTED)) { toggle(false, shape.classed(CLASS.SELECTED, false), d, i); }
|
5219 |
|
|
});
|
5220 |
|
|
}
|
5221 |
|
|
shape.classed(CLASS.SELECTED, !isSelected);
|
5222 |
|
|
toggle(!isSelected, shape, d, i);
|
5223 |
|
|
}
|
5224 |
|
|
};
|
5225 |
|
|
|
5226 |
|
|
c3_chart_internal_fn.initBrush = function () {
|
5227 |
|
|
var $$ = this, d3 = $$.d3;
|
5228 |
|
|
$$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); });
|
5229 |
|
|
$$.brush.update = function () {
|
5230 |
|
|
if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); }
|
5231 |
|
|
return this;
|
5232 |
|
|
};
|
5233 |
|
|
$$.brush.scale = function (scale) {
|
5234 |
|
|
return $$.config.axis_rotated ? this.y(scale) : this.x(scale);
|
5235 |
|
|
};
|
5236 |
|
|
};
|
5237 |
|
|
c3_chart_internal_fn.initSubchart = function () {
|
5238 |
|
|
var $$ = this, config = $$.config,
|
5239 |
|
|
context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context'));
|
5240 |
|
|
|
5241 |
|
|
context.style('visibility', config.subchart_show ? 'visible' : 'hidden');
|
5242 |
|
|
|
5243 |
|
|
// Define g for chart area
|
5244 |
|
|
context.append('g')
|
5245 |
|
|
.attr("clip-path", $$.clipPathForSubchart)
|
5246 |
|
|
.attr('class', CLASS.chart);
|
5247 |
|
|
|
5248 |
|
|
// Define g for bar chart area
|
5249 |
|
|
context.select('.' + CLASS.chart).append("g")
|
5250 |
|
|
.attr("class", CLASS.chartBars);
|
5251 |
|
|
|
5252 |
|
|
// Define g for line chart area
|
5253 |
|
|
context.select('.' + CLASS.chart).append("g")
|
5254 |
|
|
.attr("class", CLASS.chartLines);
|
5255 |
|
|
|
5256 |
|
|
// Add extent rect for Brush
|
5257 |
|
|
context.append("g")
|
5258 |
|
|
.attr("clip-path", $$.clipPath)
|
5259 |
|
|
.attr("class", CLASS.brush)
|
5260 |
|
|
.call($$.brush);
|
5261 |
|
|
|
5262 |
|
|
// ATTENTION: This must be called AFTER chart added
|
5263 |
|
|
// Add Axis
|
5264 |
|
|
$$.axes.subx = context.append("g")
|
5265 |
|
|
.attr("class", CLASS.axisX)
|
5266 |
|
|
.attr("transform", $$.getTranslate('subx'))
|
5267 |
|
|
.attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis);
|
5268 |
|
|
};
|
5269 |
|
|
c3_chart_internal_fn.updateTargetsForSubchart = function (targets) {
|
5270 |
|
|
var $$ = this, context = $$.context, config = $$.config,
|
5271 |
|
|
contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate,
|
5272 |
|
|
classChartBar = $$.classChartBar.bind($$),
|
5273 |
|
|
classBars = $$.classBars.bind($$),
|
5274 |
|
|
classChartLine = $$.classChartLine.bind($$),
|
5275 |
|
|
classLines = $$.classLines.bind($$),
|
5276 |
|
|
classAreas = $$.classAreas.bind($$);
|
5277 |
|
|
|
5278 |
|
|
if (config.subchart_show) {
|
5279 |
|
|
//-- Bar --//
|
5280 |
|
|
contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)
|
5281 |
|
|
.data(targets)
|
5282 |
|
|
.attr('class', classChartBar);
|
5283 |
|
|
contextBarEnter = contextBarUpdate.enter().append('g')
|
5284 |
|
|
.style('opacity', 0)
|
5285 |
|
|
.attr('class', classChartBar);
|
5286 |
|
|
// Bars for each data
|
5287 |
|
|
contextBarEnter.append('g')
|
5288 |
|
|
.attr("class", classBars);
|
5289 |
|
|
|
5290 |
|
|
//-- Line --//
|
5291 |
|
|
contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)
|
5292 |
|
|
.data(targets)
|
5293 |
|
|
.attr('class', classChartLine);
|
5294 |
|
|
contextLineEnter = contextLineUpdate.enter().append('g')
|
5295 |
|
|
.style('opacity', 0)
|
5296 |
|
|
.attr('class', classChartLine);
|
5297 |
|
|
// Lines for each data
|
5298 |
|
|
contextLineEnter.append("g")
|
5299 |
|
|
.attr("class", classLines);
|
5300 |
|
|
// Area
|
5301 |
|
|
contextLineEnter.append("g")
|
5302 |
|
|
.attr("class", classAreas);
|
5303 |
|
|
|
5304 |
|
|
//-- Brush --//
|
5305 |
|
|
context.selectAll('.' + CLASS.brush + ' rect')
|
5306 |
|
|
.attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2);
|
5307 |
|
|
}
|
5308 |
|
|
};
|
5309 |
|
|
c3_chart_internal_fn.updateBarForSubchart = function (durationForExit) {
|
5310 |
|
|
var $$ = this;
|
5311 |
|
|
$$.contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)
|
5312 |
|
|
.data($$.barData.bind($$));
|
5313 |
|
|
$$.contextBar.enter().append('path')
|
5314 |
|
|
.attr("class", $$.classBar.bind($$))
|
5315 |
|
|
.style("stroke", 'none')
|
5316 |
|
|
.style("fill", $$.color);
|
5317 |
|
|
$$.contextBar
|
5318 |
|
|
.style("opacity", $$.initialOpacity.bind($$));
|
5319 |
|
|
$$.contextBar.exit().transition().duration(durationForExit)
|
5320 |
|
|
.style('opacity', 0)
|
5321 |
|
|
.remove();
|
5322 |
|
|
};
|
5323 |
|
|
c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
|
5324 |
|
|
(withTransition ? this.contextBar.transition().duration(duration) : this.contextBar)
|
5325 |
|
|
.attr('d', drawBarOnSub)
|
5326 |
|
|
.style('opacity', 1);
|
5327 |
|
|
};
|
5328 |
|
|
c3_chart_internal_fn.updateLineForSubchart = function (durationForExit) {
|
5329 |
|
|
var $$ = this;
|
5330 |
|
|
$$.contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)
|
5331 |
|
|
.data($$.lineData.bind($$));
|
5332 |
|
|
$$.contextLine.enter().append('path')
|
5333 |
|
|
.attr('class', $$.classLine.bind($$))
|
5334 |
|
|
.style('stroke', $$.color);
|
5335 |
|
|
$$.contextLine
|
5336 |
|
|
.style("opacity", $$.initialOpacity.bind($$));
|
5337 |
|
|
$$.contextLine.exit().transition().duration(durationForExit)
|
5338 |
|
|
.style('opacity', 0)
|
5339 |
|
|
.remove();
|
5340 |
|
|
};
|
5341 |
|
|
c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
|
5342 |
|
|
(withTransition ? this.contextLine.transition().duration(duration) : this.contextLine)
|
5343 |
|
|
.attr("d", drawLineOnSub)
|
5344 |
|
|
.style('opacity', 1);
|
5345 |
|
|
};
|
5346 |
|
|
c3_chart_internal_fn.updateAreaForSubchart = function (durationForExit) {
|
5347 |
|
|
var $$ = this, d3 = $$.d3;
|
5348 |
|
|
$$.contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)
|
5349 |
|
|
.data($$.lineData.bind($$));
|
5350 |
|
|
$$.contextArea.enter().append('path')
|
5351 |
|
|
.attr("class", $$.classArea.bind($$))
|
5352 |
|
|
.style("fill", $$.color)
|
5353 |
|
|
.style("opacity", function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });
|
5354 |
|
|
$$.contextArea
|
5355 |
|
|
.style("opacity", 0);
|
5356 |
|
|
$$.contextArea.exit().transition().duration(durationForExit)
|
5357 |
|
|
.style('opacity', 0)
|
5358 |
|
|
.remove();
|
5359 |
|
|
};
|
5360 |
|
|
c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
|
5361 |
|
|
(withTransition ? this.contextArea.transition().duration(duration) : this.contextArea)
|
5362 |
|
|
.attr("d", drawAreaOnSub)
|
5363 |
|
|
.style("fill", this.color)
|
5364 |
|
|
.style("opacity", this.orgAreaOpacity);
|
5365 |
|
|
};
|
5366 |
|
|
c3_chart_internal_fn.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
|
5367 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config,
|
5368 |
|
|
drawAreaOnSub, drawBarOnSub, drawLineOnSub;
|
5369 |
|
|
|
5370 |
|
|
$$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden');
|
5371 |
|
|
|
5372 |
|
|
// subchart
|
5373 |
|
|
if (config.subchart_show) {
|
5374 |
|
|
// reflect main chart to extent on subchart if zoomed
|
5375 |
|
|
if (d3.event && d3.event.type === 'zoom') {
|
5376 |
|
|
$$.brush.extent($$.x.orgDomain()).update();
|
5377 |
|
|
}
|
5378 |
|
|
// update subchart elements if needed
|
5379 |
|
|
if (withSubchart) {
|
5380 |
|
|
|
5381 |
|
|
// extent rect
|
5382 |
|
|
if (!$$.brush.empty()) {
|
5383 |
|
|
$$.brush.extent($$.x.orgDomain()).update();
|
5384 |
|
|
}
|
5385 |
|
|
// setup drawer - MEMO: this must be called after axis updated
|
5386 |
|
|
drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
|
5387 |
|
|
drawBarOnSub = $$.generateDrawBar(barIndices, true);
|
5388 |
|
|
drawLineOnSub = $$.generateDrawLine(lineIndices, true);
|
5389 |
|
|
|
5390 |
|
|
$$.updateBarForSubchart(duration);
|
5391 |
|
|
$$.updateLineForSubchart(duration);
|
5392 |
|
|
$$.updateAreaForSubchart(duration);
|
5393 |
|
|
|
5394 |
|
|
$$.redrawBarForSubchart(drawBarOnSub, duration, duration);
|
5395 |
|
|
$$.redrawLineForSubchart(drawLineOnSub, duration, duration);
|
5396 |
|
|
$$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
|
5397 |
|
|
}
|
5398 |
|
|
}
|
5399 |
|
|
};
|
5400 |
|
|
c3_chart_internal_fn.redrawForBrush = function () {
|
5401 |
|
|
var $$ = this, x = $$.x;
|
5402 |
|
|
$$.redraw({
|
5403 |
|
|
withTransition: false,
|
5404 |
|
|
withY: $$.config.zoom_rescale,
|
5405 |
|
|
withSubchart: false,
|
5406 |
|
|
withUpdateXDomain: true,
|
5407 |
|
|
withDimension: false
|
5408 |
|
|
});
|
5409 |
|
|
$$.config.subchart_onbrush.call($$.api, x.orgDomain());
|
5410 |
|
|
};
|
5411 |
|
|
c3_chart_internal_fn.transformContext = function (withTransition, transitions) {
|
5412 |
|
|
var $$ = this, subXAxis;
|
5413 |
|
|
if (transitions && transitions.axisSubX) {
|
5414 |
|
|
subXAxis = transitions.axisSubX;
|
5415 |
|
|
} else {
|
5416 |
|
|
subXAxis = $$.context.select('.' + CLASS.axisX);
|
5417 |
|
|
if (withTransition) { subXAxis = subXAxis.transition(); }
|
5418 |
|
|
}
|
5419 |
|
|
$$.context.attr("transform", $$.getTranslate('context'));
|
5420 |
|
|
subXAxis.attr("transform", $$.getTranslate('subx'));
|
5421 |
|
|
};
|
5422 |
|
|
c3_chart_internal_fn.getDefaultExtent = function () {
|
5423 |
|
|
var $$ = this, config = $$.config,
|
5424 |
|
|
extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent;
|
5425 |
|
|
if ($$.isTimeSeries()) {
|
5426 |
|
|
extent = [$$.parseDate(extent[0]), $$.parseDate(extent[1])];
|
5427 |
|
|
}
|
5428 |
|
|
return extent;
|
5429 |
|
|
};
|
5430 |
|
|
|
5431 |
|
|
c3_chart_internal_fn.initZoom = function () {
|
5432 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
|
5433 |
|
|
|
5434 |
|
|
$$.zoom = d3.behavior.zoom()
|
5435 |
|
|
.on("zoomstart", function () {
|
5436 |
|
|
startEvent = d3.event.sourceEvent;
|
5437 |
|
|
$$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null;
|
5438 |
|
|
config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
|
5439 |
|
|
})
|
5440 |
|
|
.on("zoom", function () {
|
5441 |
|
|
$$.redrawForZoom.call($$);
|
5442 |
|
|
})
|
5443 |
|
|
.on('zoomend', function () {
|
5444 |
|
|
var event = d3.event.sourceEvent;
|
5445 |
|
|
// if click, do nothing. otherwise, click interaction will be canceled.
|
5446 |
|
|
if (event && startEvent.clientX === event.clientX && startEvent.clientY === event.clientY) {
|
5447 |
|
|
return;
|
5448 |
|
|
}
|
5449 |
|
|
$$.redrawEventRect();
|
5450 |
|
|
$$.updateZoom();
|
5451 |
|
|
config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
|
5452 |
|
|
});
|
5453 |
|
|
$$.zoom.scale = function (scale) {
|
5454 |
|
|
return config.axis_rotated ? this.y(scale) : this.x(scale);
|
5455 |
|
|
};
|
5456 |
|
|
$$.zoom.orgScaleExtent = function () {
|
5457 |
|
|
var extent = config.zoom_extent ? config.zoom_extent : [1, 10];
|
5458 |
|
|
return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
|
5459 |
|
|
};
|
5460 |
|
|
$$.zoom.updateScaleExtent = function () {
|
5461 |
|
|
var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.orgXDomain),
|
5462 |
|
|
extent = this.orgScaleExtent();
|
5463 |
|
|
this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
|
5464 |
|
|
return this;
|
5465 |
|
|
};
|
5466 |
|
|
};
|
5467 |
|
|
c3_chart_internal_fn.updateZoom = function () {
|
5468 |
|
|
var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {};
|
5469 |
|
|
$$.main.select('.' + CLASS.zoomRect).call(z).on("dblclick.zoom", null);
|
5470 |
|
|
$$.main.selectAll('.' + CLASS.eventRect).call(z).on("dblclick.zoom", null);
|
5471 |
|
|
};
|
5472 |
|
|
c3_chart_internal_fn.redrawForZoom = function () {
|
5473 |
|
|
var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
|
5474 |
|
|
if (!config.zoom_enabled) {
|
5475 |
|
|
return;
|
5476 |
|
|
}
|
5477 |
|
|
if ($$.filterTargetsToShow($$.data.targets).length === 0) {
|
5478 |
|
|
return;
|
5479 |
|
|
}
|
5480 |
|
|
if (d3.event.sourceEvent.type === 'mousemove' && zoom.altDomain) {
|
5481 |
|
|
x.domain(zoom.altDomain);
|
5482 |
|
|
zoom.scale(x).updateScaleExtent();
|
5483 |
|
|
return;
|
5484 |
|
|
}
|
5485 |
|
|
if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
|
5486 |
|
|
x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
|
5487 |
|
|
}
|
5488 |
|
|
$$.redraw({
|
5489 |
|
|
withTransition: false,
|
5490 |
|
|
withY: config.zoom_rescale,
|
5491 |
|
|
withSubchart: false,
|
5492 |
|
|
withEventRect: false,
|
5493 |
|
|
withDimension: false
|
5494 |
|
|
});
|
5495 |
|
|
if (d3.event.sourceEvent.type === 'mousemove') {
|
5496 |
|
|
$$.cancelClick = true;
|
5497 |
|
|
}
|
5498 |
|
|
config.zoom_onzoom.call($$.api, x.orgDomain());
|
5499 |
|
|
};
|
5500 |
|
|
|
5501 |
|
|
c3_chart_internal_fn.generateColor = function () {
|
5502 |
|
|
var $$ = this, config = $$.config, d3 = $$.d3,
|
5503 |
|
|
colors = config.data_colors,
|
5504 |
|
|
pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(),
|
5505 |
|
|
callback = config.data_color,
|
5506 |
|
|
ids = [];
|
5507 |
|
|
|
5508 |
|
|
return function (d) {
|
5509 |
|
|
var id = d.id || (d.data && d.data.id) || d, color;
|
5510 |
|
|
|
5511 |
|
|
// if callback function is provided
|
5512 |
|
|
if (colors[id] instanceof Function) {
|
5513 |
|
|
color = colors[id](d);
|
5514 |
|
|
}
|
5515 |
|
|
// if specified, choose that color
|
5516 |
|
|
else if (colors[id]) {
|
5517 |
|
|
color = colors[id];
|
5518 |
|
|
}
|
5519 |
|
|
// if not specified, choose from pattern
|
5520 |
|
|
else {
|
5521 |
|
|
if (ids.indexOf(id) < 0) { ids.push(id); }
|
5522 |
|
|
color = pattern[ids.indexOf(id) % pattern.length];
|
5523 |
|
|
colors[id] = color;
|
5524 |
|
|
}
|
5525 |
|
|
return callback instanceof Function ? callback(color, d) : color;
|
5526 |
|
|
};
|
5527 |
|
|
};
|
5528 |
|
|
c3_chart_internal_fn.generateLevelColor = function () {
|
5529 |
|
|
var $$ = this, config = $$.config,
|
5530 |
|
|
colors = config.color_pattern,
|
5531 |
|
|
threshold = config.color_threshold,
|
5532 |
|
|
asValue = threshold.unit === 'value',
|
5533 |
|
|
values = threshold.values && threshold.values.length ? threshold.values : [],
|
5534 |
|
|
max = threshold.max || 100;
|
5535 |
|
|
return notEmpty(config.color_threshold) ? function (value) {
|
5536 |
|
|
var i, v, color = colors[colors.length - 1];
|
5537 |
|
|
for (i = 0; i < values.length; i++) {
|
5538 |
|
|
v = asValue ? value : (value * 100 / max);
|
5539 |
|
|
if (v < values[i]) {
|
5540 |
|
|
color = colors[i];
|
5541 |
|
|
break;
|
5542 |
|
|
}
|
5543 |
|
|
}
|
5544 |
|
|
return color;
|
5545 |
|
|
} : null;
|
5546 |
|
|
};
|
5547 |
|
|
|
5548 |
|
|
c3_chart_internal_fn.getYFormat = function (forArc) {
|
5549 |
|
|
var $$ = this,
|
5550 |
|
|
formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,
|
5551 |
|
|
formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
|
5552 |
|
|
return function (v, ratio, id) {
|
5553 |
|
|
var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
|
5554 |
|
|
return format.call($$, v, ratio);
|
5555 |
|
|
};
|
5556 |
|
|
};
|
5557 |
|
|
c3_chart_internal_fn.yFormat = function (v) {
|
5558 |
|
|
var $$ = this, config = $$.config,
|
5559 |
|
|
format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;
|
5560 |
|
|
return format(v);
|
5561 |
|
|
};
|
5562 |
|
|
c3_chart_internal_fn.y2Format = function (v) {
|
5563 |
|
|
var $$ = this, config = $$.config,
|
5564 |
|
|
format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;
|
5565 |
|
|
return format(v);
|
5566 |
|
|
};
|
5567 |
|
|
c3_chart_internal_fn.defaultValueFormat = function (v) {
|
5568 |
|
|
return isValue(v) ? +v : "";
|
5569 |
|
|
};
|
5570 |
|
|
c3_chart_internal_fn.defaultArcValueFormat = function (v, ratio) {
|
5571 |
|
|
return (ratio * 100).toFixed(1) + '%';
|
5572 |
|
|
};
|
5573 |
|
|
c3_chart_internal_fn.dataLabelFormat = function (targetId) {
|
5574 |
|
|
var $$ = this, data_labels = $$.config.data_labels,
|
5575 |
|
|
format, defaultFormat = function (v) { return isValue(v) ? +v : ""; };
|
5576 |
|
|
// find format according to axis id
|
5577 |
|
|
if (typeof data_labels.format === 'function') {
|
5578 |
|
|
format = data_labels.format;
|
5579 |
|
|
} else if (typeof data_labels.format === 'object') {
|
5580 |
|
|
if (data_labels.format[targetId]) {
|
5581 |
|
|
format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId];
|
5582 |
|
|
} else {
|
5583 |
|
|
format = function () { return ''; };
|
5584 |
|
|
}
|
5585 |
|
|
} else {
|
5586 |
|
|
format = defaultFormat;
|
5587 |
|
|
}
|
5588 |
|
|
return format;
|
5589 |
|
|
};
|
5590 |
|
|
|
5591 |
|
|
c3_chart_internal_fn.hasCaches = function (ids) {
|
5592 |
|
|
for (var i = 0; i < ids.length; i++) {
|
5593 |
|
|
if (! (ids[i] in this.cache)) { return false; }
|
5594 |
|
|
}
|
5595 |
|
|
return true;
|
5596 |
|
|
};
|
5597 |
|
|
c3_chart_internal_fn.addCache = function (id, target) {
|
5598 |
|
|
this.cache[id] = this.cloneTarget(target);
|
5599 |
|
|
};
|
5600 |
|
|
c3_chart_internal_fn.getCaches = function (ids) {
|
5601 |
|
|
var targets = [], i;
|
5602 |
|
|
for (i = 0; i < ids.length; i++) {
|
5603 |
|
|
if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); }
|
5604 |
|
|
}
|
5605 |
|
|
return targets;
|
5606 |
|
|
};
|
5607 |
|
|
|
5608 |
|
|
var CLASS = c3_chart_internal_fn.CLASS = {
|
5609 |
|
|
target: 'c3-target',
|
5610 |
|
|
chart: 'c3-chart',
|
5611 |
|
|
chartLine: 'c3-chart-line',
|
5612 |
|
|
chartLines: 'c3-chart-lines',
|
5613 |
|
|
chartBar: 'c3-chart-bar',
|
5614 |
|
|
chartBars: 'c3-chart-bars',
|
5615 |
|
|
chartText: 'c3-chart-text',
|
5616 |
|
|
chartTexts: 'c3-chart-texts',
|
5617 |
|
|
chartArc: 'c3-chart-arc',
|
5618 |
|
|
chartArcs: 'c3-chart-arcs',
|
5619 |
|
|
chartArcsTitle: 'c3-chart-arcs-title',
|
5620 |
|
|
chartArcsBackground: 'c3-chart-arcs-background',
|
5621 |
|
|
chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
|
5622 |
|
|
chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
|
5623 |
|
|
chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
|
5624 |
|
|
selectedCircle: 'c3-selected-circle',
|
5625 |
|
|
selectedCircles: 'c3-selected-circles',
|
5626 |
|
|
eventRect: 'c3-event-rect',
|
5627 |
|
|
eventRects: 'c3-event-rects',
|
5628 |
|
|
eventRectsSingle: 'c3-event-rects-single',
|
5629 |
|
|
eventRectsMultiple: 'c3-event-rects-multiple',
|
5630 |
|
|
zoomRect: 'c3-zoom-rect',
|
5631 |
|
|
brush: 'c3-brush',
|
5632 |
|
|
focused: 'c3-focused',
|
5633 |
|
|
defocused: 'c3-defocused',
|
5634 |
|
|
region: 'c3-region',
|
5635 |
|
|
regions: 'c3-regions',
|
5636 |
|
|
tooltipContainer: 'c3-tooltip-container',
|
5637 |
|
|
tooltip: 'c3-tooltip',
|
5638 |
|
|
tooltipName: 'c3-tooltip-name',
|
5639 |
|
|
shape: 'c3-shape',
|
5640 |
|
|
shapes: 'c3-shapes',
|
5641 |
|
|
line: 'c3-line',
|
5642 |
|
|
lines: 'c3-lines',
|
5643 |
|
|
bar: 'c3-bar',
|
5644 |
|
|
bars: 'c3-bars',
|
5645 |
|
|
circle: 'c3-circle',
|
5646 |
|
|
circles: 'c3-circles',
|
5647 |
|
|
arc: 'c3-arc',
|
5648 |
|
|
arcs: 'c3-arcs',
|
5649 |
|
|
area: 'c3-area',
|
5650 |
|
|
areas: 'c3-areas',
|
5651 |
|
|
empty: 'c3-empty',
|
5652 |
|
|
text: 'c3-text',
|
5653 |
|
|
texts: 'c3-texts',
|
5654 |
|
|
gaugeValue: 'c3-gauge-value',
|
5655 |
|
|
grid: 'c3-grid',
|
5656 |
|
|
gridLines: 'c3-grid-lines',
|
5657 |
|
|
xgrid: 'c3-xgrid',
|
5658 |
|
|
xgrids: 'c3-xgrids',
|
5659 |
|
|
xgridLine: 'c3-xgrid-line',
|
5660 |
|
|
xgridLines: 'c3-xgrid-lines',
|
5661 |
|
|
xgridFocus: 'c3-xgrid-focus',
|
5662 |
|
|
ygrid: 'c3-ygrid',
|
5663 |
|
|
ygrids: 'c3-ygrids',
|
5664 |
|
|
ygridLine: 'c3-ygrid-line',
|
5665 |
|
|
ygridLines: 'c3-ygrid-lines',
|
5666 |
|
|
axis: 'c3-axis',
|
5667 |
|
|
axisX: 'c3-axis-x',
|
5668 |
|
|
axisXLabel: 'c3-axis-x-label',
|
5669 |
|
|
axisY: 'c3-axis-y',
|
5670 |
|
|
axisYLabel: 'c3-axis-y-label',
|
5671 |
|
|
axisY2: 'c3-axis-y2',
|
5672 |
|
|
axisY2Label: 'c3-axis-y2-label',
|
5673 |
|
|
legendBackground: 'c3-legend-background',
|
5674 |
|
|
legendItem: 'c3-legend-item',
|
5675 |
|
|
legendItemEvent: 'c3-legend-item-event',
|
5676 |
|
|
legendItemTile: 'c3-legend-item-tile',
|
5677 |
|
|
legendItemHidden: 'c3-legend-item-hidden',
|
5678 |
|
|
legendItemFocused: 'c3-legend-item-focused',
|
5679 |
|
|
dragarea: 'c3-dragarea',
|
5680 |
|
|
EXPANDED: '_expanded_',
|
5681 |
|
|
SELECTED: '_selected_',
|
5682 |
|
|
INCLUDED: '_included_'
|
5683 |
|
|
};
|
5684 |
|
|
c3_chart_internal_fn.generateClass = function (prefix, targetId) {
|
5685 |
|
|
return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
|
5686 |
|
|
};
|
5687 |
|
|
c3_chart_internal_fn.classText = function (d) {
|
5688 |
|
|
return this.generateClass(CLASS.text, d.index);
|
5689 |
|
|
};
|
5690 |
|
|
c3_chart_internal_fn.classTexts = function (d) {
|
5691 |
|
|
return this.generateClass(CLASS.texts, d.id);
|
5692 |
|
|
};
|
5693 |
|
|
c3_chart_internal_fn.classShape = function (d) {
|
5694 |
|
|
return this.generateClass(CLASS.shape, d.index);
|
5695 |
|
|
};
|
5696 |
|
|
c3_chart_internal_fn.classShapes = function (d) {
|
5697 |
|
|
return this.generateClass(CLASS.shapes, d.id);
|
5698 |
|
|
};
|
5699 |
|
|
c3_chart_internal_fn.classLine = function (d) {
|
5700 |
|
|
return this.classShape(d) + this.generateClass(CLASS.line, d.id);
|
5701 |
|
|
};
|
5702 |
|
|
c3_chart_internal_fn.classLines = function (d) {
|
5703 |
|
|
return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
|
5704 |
|
|
};
|
5705 |
|
|
c3_chart_internal_fn.classCircle = function (d) {
|
5706 |
|
|
return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
|
5707 |
|
|
};
|
5708 |
|
|
c3_chart_internal_fn.classCircles = function (d) {
|
5709 |
|
|
return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
|
5710 |
|
|
};
|
5711 |
|
|
c3_chart_internal_fn.classBar = function (d) {
|
5712 |
|
|
return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
|
5713 |
|
|
};
|
5714 |
|
|
c3_chart_internal_fn.classBars = function (d) {
|
5715 |
|
|
return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
|
5716 |
|
|
};
|
5717 |
|
|
c3_chart_internal_fn.classArc = function (d) {
|
5718 |
|
|
return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
|
5719 |
|
|
};
|
5720 |
|
|
c3_chart_internal_fn.classArcs = function (d) {
|
5721 |
|
|
return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
|
5722 |
|
|
};
|
5723 |
|
|
c3_chart_internal_fn.classArea = function (d) {
|
5724 |
|
|
return this.classShape(d) + this.generateClass(CLASS.area, d.id);
|
5725 |
|
|
};
|
5726 |
|
|
c3_chart_internal_fn.classAreas = function (d) {
|
5727 |
|
|
return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
|
5728 |
|
|
};
|
5729 |
|
|
c3_chart_internal_fn.classRegion = function (d, i) {
|
5730 |
|
|
return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '');
|
5731 |
|
|
};
|
5732 |
|
|
c3_chart_internal_fn.classEvent = function (d) {
|
5733 |
|
|
return this.generateClass(CLASS.eventRect, d.index);
|
5734 |
|
|
};
|
5735 |
|
|
c3_chart_internal_fn.classTarget = function (id) {
|
5736 |
|
|
var $$ = this;
|
5737 |
|
|
var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
|
5738 |
|
|
if (additionalClassSuffix) {
|
5739 |
|
|
additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
|
5740 |
|
|
}
|
5741 |
|
|
return $$.generateClass(CLASS.target, id) + additionalClass;
|
5742 |
|
|
};
|
5743 |
|
|
c3_chart_internal_fn.classFocus = function (d) {
|
5744 |
|
|
return this.classFocused(d) + this.classDefocused(d);
|
5745 |
|
|
};
|
5746 |
|
|
c3_chart_internal_fn.classFocused = function (d) {
|
5747 |
|
|
return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
|
5748 |
|
|
};
|
5749 |
|
|
c3_chart_internal_fn.classDefocused = function (d) {
|
5750 |
|
|
return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');
|
5751 |
|
|
};
|
5752 |
|
|
c3_chart_internal_fn.classChartText = function (d) {
|
5753 |
|
|
return CLASS.chartText + this.classTarget(d.id);
|
5754 |
|
|
};
|
5755 |
|
|
c3_chart_internal_fn.classChartLine = function (d) {
|
5756 |
|
|
return CLASS.chartLine + this.classTarget(d.id);
|
5757 |
|
|
};
|
5758 |
|
|
c3_chart_internal_fn.classChartBar = function (d) {
|
5759 |
|
|
return CLASS.chartBar + this.classTarget(d.id);
|
5760 |
|
|
};
|
5761 |
|
|
c3_chart_internal_fn.classChartArc = function (d) {
|
5762 |
|
|
return CLASS.chartArc + this.classTarget(d.data.id);
|
5763 |
|
|
};
|
5764 |
|
|
c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
|
5765 |
|
|
return targetId || targetId === 0 ? ('-' + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, '-') : '';
|
5766 |
|
|
};
|
5767 |
|
|
c3_chart_internal_fn.selectorTarget = function (id, prefix) {
|
5768 |
|
|
return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
|
5769 |
|
|
};
|
5770 |
|
|
c3_chart_internal_fn.selectorTargets = function (ids, prefix) {
|
5771 |
|
|
var $$ = this;
|
5772 |
|
|
ids = ids || [];
|
5773 |
|
|
return ids.length ? ids.map(function (id) { return $$.selectorTarget(id, prefix); }) : null;
|
5774 |
|
|
};
|
5775 |
|
|
c3_chart_internal_fn.selectorLegend = function (id) {
|
5776 |
|
|
return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
|
5777 |
|
|
};
|
5778 |
|
|
c3_chart_internal_fn.selectorLegends = function (ids) {
|
5779 |
|
|
var $$ = this;
|
5780 |
|
|
return ids && ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null;
|
5781 |
|
|
};
|
5782 |
|
|
|
5783 |
|
|
var isValue = c3_chart_internal_fn.isValue = function (v) {
|
5784 |
|
|
return v || v === 0;
|
5785 |
|
|
},
|
5786 |
|
|
isFunction = c3_chart_internal_fn.isFunction = function (o) {
|
5787 |
|
|
return typeof o === 'function';
|
5788 |
|
|
},
|
5789 |
|
|
isString = c3_chart_internal_fn.isString = function (o) {
|
5790 |
|
|
return typeof o === 'string';
|
5791 |
|
|
},
|
5792 |
|
|
isUndefined = c3_chart_internal_fn.isUndefined = function (v) {
|
5793 |
|
|
return typeof v === 'undefined';
|
5794 |
|
|
},
|
5795 |
|
|
isDefined = c3_chart_internal_fn.isDefined = function (v) {
|
5796 |
|
|
return typeof v !== 'undefined';
|
5797 |
|
|
},
|
5798 |
|
|
ceil10 = c3_chart_internal_fn.ceil10 = function (v) {
|
5799 |
|
|
return Math.ceil(v / 10) * 10;
|
5800 |
|
|
},
|
5801 |
|
|
asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) {
|
5802 |
|
|
return Math.ceil(n) + 0.5;
|
5803 |
|
|
},
|
5804 |
|
|
diffDomain = c3_chart_internal_fn.diffDomain = function (d) {
|
5805 |
|
|
return d[1] - d[0];
|
5806 |
|
|
},
|
5807 |
|
|
isEmpty = c3_chart_internal_fn.isEmpty = function (o) {
|
5808 |
|
|
return !o || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
|
5809 |
|
|
},
|
5810 |
|
|
notEmpty = c3_chart_internal_fn.notEmpty = function (o) {
|
5811 |
|
|
return Object.keys(o).length > 0;
|
5812 |
|
|
},
|
5813 |
|
|
getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) {
|
5814 |
|
|
return isDefined(options[key]) ? options[key] : defaultValue;
|
5815 |
|
|
},
|
5816 |
|
|
hasValue = c3_chart_internal_fn.hasValue = function (dict, value) {
|
5817 |
|
|
var found = false;
|
5818 |
|
|
Object.keys(dict).forEach(function (key) {
|
5819 |
|
|
if (dict[key] === value) { found = true; }
|
5820 |
|
|
});
|
5821 |
|
|
return found;
|
5822 |
|
|
},
|
5823 |
|
|
getPathBox = c3_chart_internal_fn.getPathBox = function (path) {
|
5824 |
|
|
var box = path.getBoundingClientRect(),
|
5825 |
|
|
items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
|
5826 |
|
|
minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
|
5827 |
|
|
return {x: minX, y: minY, width: box.width, height: box.height};
|
5828 |
|
|
};
|
5829 |
|
|
|
5830 |
|
|
c3_chart_fn.focus = function (targetIds) {
|
5831 |
|
|
var $$ = this.internal, candidates;
|
5832 |
|
|
|
5833 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
5834 |
|
|
candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))),
|
5835 |
|
|
|
5836 |
|
|
this.revert();
|
5837 |
|
|
this.defocus();
|
5838 |
|
|
candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
|
5839 |
|
|
if ($$.hasArcType()) {
|
5840 |
|
|
$$.expandArc(targetIds);
|
5841 |
|
|
}
|
5842 |
|
|
$$.toggleFocusLegend(targetIds, true);
|
5843 |
|
|
|
5844 |
|
|
$$.focusedTargetIds = targetIds;
|
5845 |
|
|
$$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) {
|
5846 |
|
|
return targetIds.indexOf(id) < 0;
|
5847 |
|
|
});
|
5848 |
|
|
};
|
5849 |
|
|
|
5850 |
|
|
c3_chart_fn.defocus = function (targetIds) {
|
5851 |
|
|
var $$ = this.internal, candidates;
|
5852 |
|
|
|
5853 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
5854 |
|
|
candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))),
|
5855 |
|
|
|
5856 |
|
|
candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
|
5857 |
|
|
if ($$.hasArcType()) {
|
5858 |
|
|
$$.unexpandArc(targetIds);
|
5859 |
|
|
}
|
5860 |
|
|
$$.toggleFocusLegend(targetIds, false);
|
5861 |
|
|
|
5862 |
|
|
$$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) {
|
5863 |
|
|
return targetIds.indexOf(id) < 0;
|
5864 |
|
|
});
|
5865 |
|
|
$$.defocusedTargetIds = targetIds;
|
5866 |
|
|
};
|
5867 |
|
|
|
5868 |
|
|
c3_chart_fn.revert = function (targetIds) {
|
5869 |
|
|
var $$ = this.internal, candidates;
|
5870 |
|
|
|
5871 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
5872 |
|
|
candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
|
5873 |
|
|
|
5874 |
|
|
candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
|
5875 |
|
|
if ($$.hasArcType()) {
|
5876 |
|
|
$$.unexpandArc(targetIds);
|
5877 |
|
|
}
|
5878 |
|
|
if ($$.config.legend_show) {
|
5879 |
|
|
$$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
|
5880 |
|
|
$$.legend.selectAll($$.selectorLegends(targetIds))
|
5881 |
|
|
.filter(function () {
|
5882 |
|
|
return $$.d3.select(this).classed(CLASS.legendItemFocused);
|
5883 |
|
|
})
|
5884 |
|
|
.classed(CLASS.legendItemFocused, false);
|
5885 |
|
|
}
|
5886 |
|
|
|
5887 |
|
|
$$.focusedTargetIds = [];
|
5888 |
|
|
$$.defocusedTargetIds = [];
|
5889 |
|
|
};
|
5890 |
|
|
|
5891 |
|
|
c3_chart_fn.show = function (targetIds, options) {
|
5892 |
|
|
var $$ = this.internal, targets;
|
5893 |
|
|
|
5894 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
5895 |
|
|
options = options || {};
|
5896 |
|
|
|
5897 |
|
|
$$.removeHiddenTargetIds(targetIds);
|
5898 |
|
|
targets = $$.svg.selectAll($$.selectorTargets(targetIds));
|
5899 |
|
|
|
5900 |
|
|
targets.transition()
|
5901 |
|
|
.style('opacity', 1, 'important')
|
5902 |
|
|
.call($$.endall, function () {
|
5903 |
|
|
targets.style('opacity', null).style('opacity', 1);
|
5904 |
|
|
});
|
5905 |
|
|
|
5906 |
|
|
if (options.withLegend) {
|
5907 |
|
|
$$.showLegend(targetIds);
|
5908 |
|
|
}
|
5909 |
|
|
|
5910 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
|
5911 |
|
|
};
|
5912 |
|
|
|
5913 |
|
|
c3_chart_fn.hide = function (targetIds, options) {
|
5914 |
|
|
var $$ = this.internal, targets;
|
5915 |
|
|
|
5916 |
|
|
targetIds = $$.mapToTargetIds(targetIds);
|
5917 |
|
|
options = options || {};
|
5918 |
|
|
|
5919 |
|
|
$$.addHiddenTargetIds(targetIds);
|
5920 |
|
|
targets = $$.svg.selectAll($$.selectorTargets(targetIds));
|
5921 |
|
|
|
5922 |
|
|
targets.transition()
|
5923 |
|
|
.style('opacity', 0, 'important')
|
5924 |
|
|
.call($$.endall, function () {
|
5925 |
|
|
targets.style('opacity', null).style('opacity', 0);
|
5926 |
|
|
});
|
5927 |
|
|
|
5928 |
|
|
if (options.withLegend) {
|
5929 |
|
|
$$.hideLegend(targetIds);
|
5930 |
|
|
}
|
5931 |
|
|
|
5932 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
|
5933 |
|
|
};
|
5934 |
|
|
|
5935 |
|
|
c3_chart_fn.toggle = function (targetIds, options) {
|
5936 |
|
|
var that = this, $$ = this.internal;
|
5937 |
|
|
$$.mapToTargetIds(targetIds).forEach(function (targetId) {
|
5938 |
|
|
$$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options);
|
5939 |
|
|
});
|
5940 |
|
|
};
|
5941 |
|
|
|
5942 |
|
|
c3_chart_fn.zoom = function (domain) {
|
5943 |
|
|
var $$ = this.internal;
|
5944 |
|
|
if (domain) {
|
5945 |
|
|
if ($$.isTimeSeries()) {
|
5946 |
|
|
domain = domain.map(function (x) { return $$.parseDate(x); });
|
5947 |
|
|
}
|
5948 |
|
|
$$.brush.extent(domain);
|
5949 |
|
|
$$.redraw({withUpdateXDomain: true, withY: $$.config.zoom_rescale});
|
5950 |
|
|
$$.config.zoom_onzoom.call(this, $$.x.orgDomain());
|
5951 |
|
|
}
|
5952 |
|
|
return $$.brush.extent();
|
5953 |
|
|
};
|
5954 |
|
|
c3_chart_fn.zoom.enable = function (enabled) {
|
5955 |
|
|
var $$ = this.internal;
|
5956 |
|
|
$$.config.zoom_enabled = enabled;
|
5957 |
|
|
$$.updateAndRedraw();
|
5958 |
|
|
};
|
5959 |
|
|
c3_chart_fn.unzoom = function () {
|
5960 |
|
|
var $$ = this.internal;
|
5961 |
|
|
$$.brush.clear().update();
|
5962 |
|
|
$$.redraw({withUpdateXDomain: true});
|
5963 |
|
|
};
|
5964 |
|
|
|
5965 |
|
|
c3_chart_fn.load = function (args) {
|
5966 |
|
|
var $$ = this.internal, config = $$.config;
|
5967 |
|
|
// update xs if specified
|
5968 |
|
|
if (args.xs) {
|
5969 |
|
|
$$.addXs(args.xs);
|
5970 |
|
|
}
|
5971 |
|
|
// update classes if exists
|
5972 |
|
|
if ('classes' in args) {
|
5973 |
|
|
Object.keys(args.classes).forEach(function (id) {
|
5974 |
|
|
config.data_classes[id] = args.classes[id];
|
5975 |
|
|
});
|
5976 |
|
|
}
|
5977 |
|
|
// update categories if exists
|
5978 |
|
|
if ('categories' in args && $$.isCategorized()) {
|
5979 |
|
|
config.axis_x_categories = args.categories;
|
5980 |
|
|
}
|
5981 |
|
|
// update axes if exists
|
5982 |
|
|
if ('axes' in args) {
|
5983 |
|
|
Object.keys(args.axes).forEach(function (id) {
|
5984 |
|
|
config.data_axes[id] = args.axes[id];
|
5985 |
|
|
});
|
5986 |
|
|
}
|
5987 |
|
|
// update colors if exists
|
5988 |
|
|
if ('colors' in args) {
|
5989 |
|
|
Object.keys(args.colors).forEach(function (id) {
|
5990 |
|
|
config.data_colors[id] = args.colors[id];
|
5991 |
|
|
});
|
5992 |
|
|
}
|
5993 |
|
|
// use cache if exists
|
5994 |
|
|
if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
|
5995 |
|
|
$$.load($$.getCaches(args.cacheIds), args.done);
|
5996 |
|
|
return;
|
5997 |
|
|
}
|
5998 |
|
|
// unload if needed
|
5999 |
|
|
if ('unload' in args) {
|
6000 |
|
|
// TODO: do not unload if target will load (included in url/rows/columns)
|
6001 |
|
|
$$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), function () {
|
6002 |
|
|
$$.loadFromArgs(args);
|
6003 |
|
|
});
|
6004 |
|
|
} else {
|
6005 |
|
|
$$.loadFromArgs(args);
|
6006 |
|
|
}
|
6007 |
|
|
};
|
6008 |
|
|
|
6009 |
|
|
c3_chart_fn.unload = function (args) {
|
6010 |
|
|
var $$ = this.internal;
|
6011 |
|
|
args = args || {};
|
6012 |
|
|
if (args instanceof Array) {
|
6013 |
|
|
args = {ids: args};
|
6014 |
|
|
} else if (typeof args === 'string') {
|
6015 |
|
|
args = {ids: [args]};
|
6016 |
|
|
}
|
6017 |
|
|
$$.unload($$.mapToTargetIds(args.ids), function () {
|
6018 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true});
|
6019 |
|
|
if (args.done) { args.done(); }
|
6020 |
|
|
});
|
6021 |
|
|
};
|
6022 |
|
|
|
6023 |
|
|
c3_chart_fn.flow = function (args) {
|
6024 |
|
|
var $$ = this.internal,
|
6025 |
|
|
targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(),
|
6026 |
|
|
dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
|
6027 |
|
|
|
6028 |
|
|
if (args.json) {
|
6029 |
|
|
data = $$.convertJsonToData(args.json, args.keys);
|
6030 |
|
|
}
|
6031 |
|
|
else if (args.rows) {
|
6032 |
|
|
data = $$.convertRowsToData(args.rows);
|
6033 |
|
|
}
|
6034 |
|
|
else if (args.columns) {
|
6035 |
|
|
data = $$.convertColumnsToData(args.columns);
|
6036 |
|
|
}
|
6037 |
|
|
else {
|
6038 |
|
|
return;
|
6039 |
|
|
}
|
6040 |
|
|
targets = $$.convertDataToTargets(data, true);
|
6041 |
|
|
|
6042 |
|
|
// Update/Add data
|
6043 |
|
|
$$.data.targets.forEach(function (t) {
|
6044 |
|
|
var found = false, i, j;
|
6045 |
|
|
for (i = 0; i < targets.length; i++) {
|
6046 |
|
|
if (t.id === targets[i].id) {
|
6047 |
|
|
found = true;
|
6048 |
|
|
|
6049 |
|
|
if (t.values[t.values.length - 1]) {
|
6050 |
|
|
tail = t.values[t.values.length - 1].index + 1;
|
6051 |
|
|
}
|
6052 |
|
|
length = targets[i].values.length;
|
6053 |
|
|
|
6054 |
|
|
for (j = 0; j < length; j++) {
|
6055 |
|
|
targets[i].values[j].index = tail + j;
|
6056 |
|
|
if (!$$.isTimeSeries()) {
|
6057 |
|
|
targets[i].values[j].x = tail + j;
|
6058 |
|
|
}
|
6059 |
|
|
}
|
6060 |
|
|
t.values = t.values.concat(targets[i].values);
|
6061 |
|
|
|
6062 |
|
|
targets.splice(i, 1);
|
6063 |
|
|
break;
|
6064 |
|
|
}
|
6065 |
|
|
}
|
6066 |
|
|
if (!found) { notfoundIds.push(t.id); }
|
6067 |
|
|
});
|
6068 |
|
|
|
6069 |
|
|
// Append null for not found targets
|
6070 |
|
|
$$.data.targets.forEach(function (t) {
|
6071 |
|
|
var i, j;
|
6072 |
|
|
for (i = 0; i < notfoundIds.length; i++) {
|
6073 |
|
|
if (t.id === notfoundIds[i]) {
|
6074 |
|
|
tail = t.values[t.values.length - 1].index + 1;
|
6075 |
|
|
for (j = 0; j < length; j++) {
|
6076 |
|
|
t.values.push({
|
6077 |
|
|
id: t.id,
|
6078 |
|
|
index: tail + j,
|
6079 |
|
|
x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
|
6080 |
|
|
value: null
|
6081 |
|
|
});
|
6082 |
|
|
}
|
6083 |
|
|
}
|
6084 |
|
|
}
|
6085 |
|
|
});
|
6086 |
|
|
|
6087 |
|
|
// Generate null values for new target
|
6088 |
|
|
if ($$.data.targets.length) {
|
6089 |
|
|
targets.forEach(function (t) {
|
6090 |
|
|
var i, missing = [];
|
6091 |
|
|
for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
|
6092 |
|
|
missing.push({
|
6093 |
|
|
id: t.id,
|
6094 |
|
|
index: i,
|
6095 |
|
|
x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
|
6096 |
|
|
value: null
|
6097 |
|
|
});
|
6098 |
|
|
}
|
6099 |
|
|
t.values.forEach(function (v) {
|
6100 |
|
|
v.index += tail;
|
6101 |
|
|
if (!$$.isTimeSeries()) {
|
6102 |
|
|
v.x += tail;
|
6103 |
|
|
}
|
6104 |
|
|
});
|
6105 |
|
|
t.values = missing.concat(t.values);
|
6106 |
|
|
});
|
6107 |
|
|
}
|
6108 |
|
|
$$.data.targets = $$.data.targets.concat(targets); // add remained
|
6109 |
|
|
|
6110 |
|
|
// check data count because behavior needs to change when it's only one
|
6111 |
|
|
dataCount = $$.getMaxDataCount();
|
6112 |
|
|
baseTarget = $$.data.targets[0];
|
6113 |
|
|
baseValue = baseTarget.values[0];
|
6114 |
|
|
|
6115 |
|
|
// Update length to flow if needed
|
6116 |
|
|
if (isDefined(args.to)) {
|
6117 |
|
|
length = 0;
|
6118 |
|
|
to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
|
6119 |
|
|
baseTarget.values.forEach(function (v) {
|
6120 |
|
|
if (v.x < to) { length++; }
|
6121 |
|
|
});
|
6122 |
|
|
} else if (isDefined(args.length)) {
|
6123 |
|
|
length = args.length;
|
6124 |
|
|
}
|
6125 |
|
|
|
6126 |
|
|
// If only one data, update the domain to flow from left edge of the chart
|
6127 |
|
|
if (!orgDataCount) {
|
6128 |
|
|
if ($$.isTimeSeries()) {
|
6129 |
|
|
if (baseTarget.values.length > 1) {
|
6130 |
|
|
diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
|
6131 |
|
|
} else {
|
6132 |
|
|
diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
|
6133 |
|
|
}
|
6134 |
|
|
} else {
|
6135 |
|
|
diff = 1;
|
6136 |
|
|
}
|
6137 |
|
|
domain = [baseValue.x - diff, baseValue.x];
|
6138 |
|
|
$$.updateXDomain(null, true, true, false, domain);
|
6139 |
|
|
} else if (orgDataCount === 1) {
|
6140 |
|
|
if ($$.isTimeSeries()) {
|
6141 |
|
|
diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
|
6142 |
|
|
domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
|
6143 |
|
|
$$.updateXDomain(null, true, true, false, domain);
|
6144 |
|
|
}
|
6145 |
|
|
}
|
6146 |
|
|
|
6147 |
|
|
// Set targets
|
6148 |
|
|
$$.updateTargets($$.data.targets);
|
6149 |
|
|
|
6150 |
|
|
// Redraw with new targets
|
6151 |
|
|
$$.redraw({
|
6152 |
|
|
flow: {
|
6153 |
|
|
index: baseValue.index,
|
6154 |
|
|
length: length,
|
6155 |
|
|
duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
|
6156 |
|
|
done: args.done,
|
6157 |
|
|
orgDataCount: orgDataCount,
|
6158 |
|
|
},
|
6159 |
|
|
withLegend: true,
|
6160 |
|
|
withTransition: orgDataCount > 1,
|
6161 |
|
|
withTrimXDomain: false,
|
6162 |
|
|
withUpdateXAxis: true,
|
6163 |
|
|
});
|
6164 |
|
|
};
|
6165 |
|
|
|
6166 |
|
|
c3_chart_internal_fn.generateFlow = function (args) {
|
6167 |
|
|
var $$ = this, config = $$.config, d3 = $$.d3;
|
6168 |
|
|
|
6169 |
|
|
return function () {
|
6170 |
|
|
var targets = args.targets,
|
6171 |
|
|
flow = args.flow,
|
6172 |
|
|
drawBar = args.drawBar,
|
6173 |
|
|
drawLine = args.drawLine,
|
6174 |
|
|
drawArea = args.drawArea,
|
6175 |
|
|
cx = args.cx,
|
6176 |
|
|
cy = args.cy,
|
6177 |
|
|
xv = args.xv,
|
6178 |
|
|
xForText = args.xForText,
|
6179 |
|
|
yForText = args.yForText,
|
6180 |
|
|
duration = args.duration;
|
6181 |
|
|
|
6182 |
|
|
var translateX, scaleX = 1, transform,
|
6183 |
|
|
flowIndex = flow.index,
|
6184 |
|
|
flowLength = flow.length,
|
6185 |
|
|
flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),
|
6186 |
|
|
flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength),
|
6187 |
|
|
orgDomain = $$.x.domain(), domain,
|
6188 |
|
|
durationForFlow = flow.duration || duration,
|
6189 |
|
|
done = flow.done || function () {},
|
6190 |
|
|
wait = $$.generateWait();
|
6191 |
|
|
|
6192 |
|
|
var xgrid = $$.xgrid || d3.selectAll([]),
|
6193 |
|
|
xgridLines = $$.xgridLines || d3.selectAll([]),
|
6194 |
|
|
mainRegion = $$.mainRegion || d3.selectAll([]),
|
6195 |
|
|
mainText = $$.mainText || d3.selectAll([]),
|
6196 |
|
|
mainBar = $$.mainBar || d3.selectAll([]),
|
6197 |
|
|
mainLine = $$.mainLine || d3.selectAll([]),
|
6198 |
|
|
mainArea = $$.mainArea || d3.selectAll([]),
|
6199 |
|
|
mainCircle = $$.mainCircle || d3.selectAll([]);
|
6200 |
|
|
|
6201 |
|
|
// set flag
|
6202 |
|
|
$$.flowing = true;
|
6203 |
|
|
|
6204 |
|
|
// remove head data after rendered
|
6205 |
|
|
$$.data.targets.forEach(function (d) {
|
6206 |
|
|
d.values.splice(0, flowLength);
|
6207 |
|
|
});
|
6208 |
|
|
|
6209 |
|
|
// update x domain to generate axis elements for flow
|
6210 |
|
|
domain = $$.updateXDomain(targets, true, true);
|
6211 |
|
|
// update elements related to x scale
|
6212 |
|
|
if ($$.updateXGrid) { $$.updateXGrid(true); }
|
6213 |
|
|
|
6214 |
|
|
// generate transform to flow
|
6215 |
|
|
if (!flow.orgDataCount) { // if empty
|
6216 |
|
|
if ($$.data.targets[0].values.length !== 1) {
|
6217 |
|
|
translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
|
6218 |
|
|
} else {
|
6219 |
|
|
if ($$.isTimeSeries()) {
|
6220 |
|
|
flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
|
6221 |
|
|
flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
|
6222 |
|
|
translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
|
6223 |
|
|
} else {
|
6224 |
|
|
translateX = diffDomain(domain) / 2;
|
6225 |
|
|
}
|
6226 |
|
|
}
|
6227 |
|
|
} else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) {
|
6228 |
|
|
translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
|
6229 |
|
|
} else {
|
6230 |
|
|
if ($$.isTimeSeries()) {
|
6231 |
|
|
translateX = ($$.x(orgDomain[0]) - $$.x(domain[0]));
|
6232 |
|
|
} else {
|
6233 |
|
|
translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x));
|
6234 |
|
|
}
|
6235 |
|
|
}
|
6236 |
|
|
scaleX = (diffDomain(orgDomain) / diffDomain(domain));
|
6237 |
|
|
transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
|
6238 |
|
|
|
6239 |
|
|
// hide tooltip
|
6240 |
|
|
$$.hideXGridFocus();
|
6241 |
|
|
$$.hideTooltip();
|
6242 |
|
|
|
6243 |
|
|
d3.transition().ease('linear').duration(durationForFlow).each(function () {
|
6244 |
|
|
wait.add($$.axes.x.transition().call($$.xAxis));
|
6245 |
|
|
wait.add(mainBar.transition().attr('transform', transform));
|
6246 |
|
|
wait.add(mainLine.transition().attr('transform', transform));
|
6247 |
|
|
wait.add(mainArea.transition().attr('transform', transform));
|
6248 |
|
|
wait.add(mainCircle.transition().attr('transform', transform));
|
6249 |
|
|
wait.add(mainText.transition().attr('transform', transform));
|
6250 |
|
|
wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform));
|
6251 |
|
|
wait.add(xgrid.transition().attr('transform', transform));
|
6252 |
|
|
wait.add(xgridLines.transition().attr('transform', transform));
|
6253 |
|
|
})
|
6254 |
|
|
.call(wait, function () {
|
6255 |
|
|
var i, shapes = [], texts = [], eventRects = [];
|
6256 |
|
|
|
6257 |
|
|
// remove flowed elements
|
6258 |
|
|
if (flowLength) {
|
6259 |
|
|
for (i = 0; i < flowLength; i++) {
|
6260 |
|
|
shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
|
6261 |
|
|
texts.push('.' + CLASS.text + '-' + (flowIndex + i));
|
6262 |
|
|
eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i));
|
6263 |
|
|
}
|
6264 |
|
|
$$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove();
|
6265 |
|
|
$$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove();
|
6266 |
|
|
$$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove();
|
6267 |
|
|
$$.svg.select('.' + CLASS.xgrid).remove();
|
6268 |
|
|
}
|
6269 |
|
|
|
6270 |
|
|
// draw again for removing flowed elements and reverting attr
|
6271 |
|
|
xgrid
|
6272 |
|
|
.attr('transform', null)
|
6273 |
|
|
.attr($$.xgridAttr);
|
6274 |
|
|
xgridLines
|
6275 |
|
|
.attr('transform', null);
|
6276 |
|
|
xgridLines.select('line')
|
6277 |
|
|
.attr("x1", config.axis_rotated ? 0 : xv)
|
6278 |
|
|
.attr("x2", config.axis_rotated ? $$.width : xv);
|
6279 |
|
|
xgridLines.select('text')
|
6280 |
|
|
.attr("x", config.axis_rotated ? $$.width : 0)
|
6281 |
|
|
.attr("y", xv);
|
6282 |
|
|
mainBar
|
6283 |
|
|
.attr('transform', null)
|
6284 |
|
|
.attr("d", drawBar);
|
6285 |
|
|
mainLine
|
6286 |
|
|
.attr('transform', null)
|
6287 |
|
|
.attr("d", drawLine);
|
6288 |
|
|
mainArea
|
6289 |
|
|
.attr('transform', null)
|
6290 |
|
|
.attr("d", drawArea);
|
6291 |
|
|
mainCircle
|
6292 |
|
|
.attr('transform', null)
|
6293 |
|
|
.attr("cx", cx)
|
6294 |
|
|
.attr("cy", cy);
|
6295 |
|
|
mainText
|
6296 |
|
|
.attr('transform', null)
|
6297 |
|
|
.attr('x', xForText)
|
6298 |
|
|
.attr('y', yForText)
|
6299 |
|
|
.style('fill-opacity', $$.opacityForText.bind($$));
|
6300 |
|
|
mainRegion
|
6301 |
|
|
.attr('transform', null);
|
6302 |
|
|
mainRegion.select('rect').filter($$.isRegionOnX)
|
6303 |
|
|
.attr("x", $$.regionX.bind($$))
|
6304 |
|
|
.attr("width", $$.regionWidth.bind($$));
|
6305 |
|
|
|
6306 |
|
|
if (config.interaction_enabled) {
|
6307 |
|
|
$$.redrawEventRect();
|
6308 |
|
|
}
|
6309 |
|
|
|
6310 |
|
|
// callback for end of flow
|
6311 |
|
|
done();
|
6312 |
|
|
|
6313 |
|
|
$$.flowing = false;
|
6314 |
|
|
});
|
6315 |
|
|
};
|
6316 |
|
|
};
|
6317 |
|
|
|
6318 |
|
|
c3_chart_fn.selected = function (targetId) {
|
6319 |
|
|
var $$ = this.internal, d3 = $$.d3;
|
6320 |
|
|
return d3.merge(
|
6321 |
|
|
$$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape)
|
6322 |
|
|
.filter(function () { return d3.select(this).classed(CLASS.SELECTED); })
|
6323 |
|
|
.map(function (d) { return d.map(function (d) { var data = d.__data__; return data.data ? data.data : data; }); })
|
6324 |
|
|
);
|
6325 |
|
|
};
|
6326 |
|
|
c3_chart_fn.select = function (ids, indices, resetOther) {
|
6327 |
|
|
var $$ = this.internal, d3 = $$.d3, config = $$.config;
|
6328 |
|
|
if (! config.data_selection_enabled) { return; }
|
6329 |
|
|
$$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
|
6330 |
|
|
var shape = d3.select(this), id = d.data ? d.data.id : d.id,
|
6331 |
|
|
toggle = $$.getToggle(this, d).bind($$),
|
6332 |
|
|
isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
|
6333 |
|
|
isTargetIndex = !indices || indices.indexOf(i) >= 0,
|
6334 |
|
|
isSelected = shape.classed(CLASS.SELECTED);
|
6335 |
|
|
// line/area selection not supported yet
|
6336 |
|
|
if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
|
6337 |
|
|
return;
|
6338 |
|
|
}
|
6339 |
|
|
if (isTargetId && isTargetIndex) {
|
6340 |
|
|
if (config.data_selection_isselectable(d) && !isSelected) {
|
6341 |
|
|
toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
|
6342 |
|
|
}
|
6343 |
|
|
} else if (isDefined(resetOther) && resetOther) {
|
6344 |
|
|
if (isSelected) {
|
6345 |
|
|
toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
|
6346 |
|
|
}
|
6347 |
|
|
}
|
6348 |
|
|
});
|
6349 |
|
|
};
|
6350 |
|
|
c3_chart_fn.unselect = function (ids, indices) {
|
6351 |
|
|
var $$ = this.internal, d3 = $$.d3, config = $$.config;
|
6352 |
|
|
if (! config.data_selection_enabled) { return; }
|
6353 |
|
|
$$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
|
6354 |
|
|
var shape = d3.select(this), id = d.data ? d.data.id : d.id,
|
6355 |
|
|
toggle = $$.getToggle(this, d).bind($$),
|
6356 |
|
|
isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
|
6357 |
|
|
isTargetIndex = !indices || indices.indexOf(i) >= 0,
|
6358 |
|
|
isSelected = shape.classed(CLASS.SELECTED);
|
6359 |
|
|
// line/area selection not supported yet
|
6360 |
|
|
if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
|
6361 |
|
|
return;
|
6362 |
|
|
}
|
6363 |
|
|
if (isTargetId && isTargetIndex) {
|
6364 |
|
|
if (config.data_selection_isselectable(d)) {
|
6365 |
|
|
if (isSelected) {
|
6366 |
|
|
toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
|
6367 |
|
|
}
|
6368 |
|
|
}
|
6369 |
|
|
}
|
6370 |
|
|
});
|
6371 |
|
|
};
|
6372 |
|
|
|
6373 |
|
|
c3_chart_fn.transform = function (type, targetIds) {
|
6374 |
|
|
var $$ = this.internal,
|
6375 |
|
|
options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null;
|
6376 |
|
|
$$.transformTo(targetIds, type, options);
|
6377 |
|
|
};
|
6378 |
|
|
|
6379 |
|
|
c3_chart_internal_fn.transformTo = function (targetIds, type, optionsForRedraw) {
|
6380 |
|
|
var $$ = this,
|
6381 |
|
|
withTransitionForAxis = !$$.hasArcType(),
|
6382 |
|
|
options = optionsForRedraw || {withTransitionForAxis: withTransitionForAxis};
|
6383 |
|
|
options.withTransitionForTransform = false;
|
6384 |
|
|
$$.transiting = false;
|
6385 |
|
|
$$.setTargetType(targetIds, type);
|
6386 |
|
|
$$.updateTargets($$.data.targets); // this is needed when transforming to arc
|
6387 |
|
|
$$.updateAndRedraw(options);
|
6388 |
|
|
};
|
6389 |
|
|
|
6390 |
|
|
c3_chart_fn.groups = function (groups) {
|
6391 |
|
|
var $$ = this.internal, config = $$.config;
|
6392 |
|
|
if (isUndefined(groups)) { return config.data_groups; }
|
6393 |
|
|
config.data_groups = groups;
|
6394 |
|
|
$$.redraw();
|
6395 |
|
|
return config.data_groups;
|
6396 |
|
|
};
|
6397 |
|
|
|
6398 |
|
|
c3_chart_fn.xgrids = function (grids) {
|
6399 |
|
|
var $$ = this.internal, config = $$.config;
|
6400 |
|
|
if (! grids) { return config.grid_x_lines; }
|
6401 |
|
|
config.grid_x_lines = grids;
|
6402 |
|
|
$$.redrawWithoutRescale();
|
6403 |
|
|
return config.grid_x_lines;
|
6404 |
|
|
};
|
6405 |
|
|
c3_chart_fn.xgrids.add = function (grids) {
|
6406 |
|
|
var $$ = this.internal;
|
6407 |
|
|
return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
|
6408 |
|
|
};
|
6409 |
|
|
c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple
|
6410 |
|
|
var $$ = this.internal;
|
6411 |
|
|
$$.removeGridLines(params, true);
|
6412 |
|
|
};
|
6413 |
|
|
|
6414 |
|
|
c3_chart_fn.ygrids = function (grids) {
|
6415 |
|
|
var $$ = this.internal, config = $$.config;
|
6416 |
|
|
if (! grids) { return config.grid_y_lines; }
|
6417 |
|
|
config.grid_y_lines = grids;
|
6418 |
|
|
$$.redrawWithoutRescale();
|
6419 |
|
|
return config.grid_y_lines;
|
6420 |
|
|
};
|
6421 |
|
|
c3_chart_fn.ygrids.add = function (grids) {
|
6422 |
|
|
var $$ = this.internal;
|
6423 |
|
|
return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
|
6424 |
|
|
};
|
6425 |
|
|
c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple
|
6426 |
|
|
var $$ = this.internal;
|
6427 |
|
|
$$.removeGridLines(params, false);
|
6428 |
|
|
};
|
6429 |
|
|
|
6430 |
|
|
c3_chart_fn.regions = function (regions) {
|
6431 |
|
|
var $$ = this.internal, config = $$.config;
|
6432 |
|
|
if (!regions) { return config.regions; }
|
6433 |
|
|
config.regions = regions;
|
6434 |
|
|
$$.redrawWithoutRescale();
|
6435 |
|
|
return config.regions;
|
6436 |
|
|
};
|
6437 |
|
|
c3_chart_fn.regions.add = function (regions) {
|
6438 |
|
|
var $$ = this.internal, config = $$.config;
|
6439 |
|
|
if (!regions) { return config.regions; }
|
6440 |
|
|
config.regions = config.regions.concat(regions);
|
6441 |
|
|
$$.redrawWithoutRescale();
|
6442 |
|
|
return config.regions;
|
6443 |
|
|
};
|
6444 |
|
|
c3_chart_fn.regions.remove = function (options) {
|
6445 |
|
|
var $$ = this.internal, config = $$.config,
|
6446 |
|
|
duration, classes, regions;
|
6447 |
|
|
|
6448 |
|
|
options = options || {};
|
6449 |
|
|
duration = $$.getOption(options, "duration", config.transition_duration);
|
6450 |
|
|
classes = $$.getOption(options, "classes", [CLASS.region]);
|
6451 |
|
|
|
6452 |
|
|
regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) { return '.' + c; }));
|
6453 |
|
|
(duration ? regions.transition().duration(duration) : regions)
|
6454 |
|
|
.style('opacity', 0)
|
6455 |
|
|
.remove();
|
6456 |
|
|
|
6457 |
|
|
config.regions = config.regions.filter(function (region) {
|
6458 |
|
|
var found = false;
|
6459 |
|
|
if (!region['class']) {
|
6460 |
|
|
return true;
|
6461 |
|
|
}
|
6462 |
|
|
region['class'].split(' ').forEach(function (c) {
|
6463 |
|
|
if (classes.indexOf(c) >= 0) { found = true; }
|
6464 |
|
|
});
|
6465 |
|
|
return !found;
|
6466 |
|
|
});
|
6467 |
|
|
|
6468 |
|
|
return config.regions;
|
6469 |
|
|
};
|
6470 |
|
|
|
6471 |
|
|
c3_chart_fn.data = function (targetIds) {
|
6472 |
|
|
var targets = this.internal.data.targets;
|
6473 |
|
|
return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) {
|
6474 |
|
|
return [].concat(targetIds).indexOf(t.id) >= 0;
|
6475 |
|
|
});
|
6476 |
|
|
};
|
6477 |
|
|
c3_chart_fn.data.shown = function (targetIds) {
|
6478 |
|
|
return this.internal.filterTargetsToShow(this.data(targetIds));
|
6479 |
|
|
};
|
6480 |
|
|
c3_chart_fn.data.values = function (targetId) {
|
6481 |
|
|
var targets, values = null;
|
6482 |
|
|
if (targetId) {
|
6483 |
|
|
targets = this.data(targetId);
|
6484 |
|
|
values = targets[0] ? targets[0].values.map(function (d) { return d.value; }) : null;
|
6485 |
|
|
}
|
6486 |
|
|
return values;
|
6487 |
|
|
};
|
6488 |
|
|
c3_chart_fn.data.names = function (names) {
|
6489 |
|
|
this.internal.clearLegendItemTextBoxCache();
|
6490 |
|
|
return this.internal.updateDataAttributes('names', names);
|
6491 |
|
|
};
|
6492 |
|
|
c3_chart_fn.data.colors = function (colors) {
|
6493 |
|
|
return this.internal.updateDataAttributes('colors', colors);
|
6494 |
|
|
};
|
6495 |
|
|
c3_chart_fn.data.axes = function (axes) {
|
6496 |
|
|
return this.internal.updateDataAttributes('axes', axes);
|
6497 |
|
|
};
|
6498 |
|
|
|
6499 |
|
|
c3_chart_fn.category = function (i, category) {
|
6500 |
|
|
var $$ = this.internal, config = $$.config;
|
6501 |
|
|
if (arguments.length > 1) {
|
6502 |
|
|
config.axis_x_categories[i] = category;
|
6503 |
|
|
$$.redraw();
|
6504 |
|
|
}
|
6505 |
|
|
return config.axis_x_categories[i];
|
6506 |
|
|
};
|
6507 |
|
|
c3_chart_fn.categories = function (categories) {
|
6508 |
|
|
var $$ = this.internal, config = $$.config;
|
6509 |
|
|
if (!arguments.length) { return config.axis_x_categories; }
|
6510 |
|
|
config.axis_x_categories = categories;
|
6511 |
|
|
$$.redraw();
|
6512 |
|
|
return config.axis_x_categories;
|
6513 |
|
|
};
|
6514 |
|
|
|
6515 |
|
|
// TODO: fix
|
6516 |
|
|
c3_chart_fn.color = function (id) {
|
6517 |
|
|
var $$ = this.internal;
|
6518 |
|
|
return $$.color(id); // more patterns
|
6519 |
|
|
};
|
6520 |
|
|
|
6521 |
|
|
c3_chart_fn.x = function (x) {
|
6522 |
|
|
var $$ = this.internal;
|
6523 |
|
|
if (arguments.length) {
|
6524 |
|
|
$$.updateTargetX($$.data.targets, x);
|
6525 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
|
6526 |
|
|
}
|
6527 |
|
|
return $$.data.xs;
|
6528 |
|
|
};
|
6529 |
|
|
c3_chart_fn.xs = function (xs) {
|
6530 |
|
|
var $$ = this.internal;
|
6531 |
|
|
if (arguments.length) {
|
6532 |
|
|
$$.updateTargetXs($$.data.targets, xs);
|
6533 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
|
6534 |
|
|
}
|
6535 |
|
|
return $$.data.xs;
|
6536 |
|
|
};
|
6537 |
|
|
|
6538 |
|
|
c3_chart_fn.axis = function () {};
|
6539 |
|
|
c3_chart_fn.axis.labels = function (labels) {
|
6540 |
|
|
var $$ = this.internal;
|
6541 |
|
|
if (arguments.length) {
|
6542 |
|
|
Object.keys(labels).forEach(function (axisId) {
|
6543 |
|
|
$$.axis.setLabelText(axisId, labels[axisId]);
|
6544 |
|
|
});
|
6545 |
|
|
$$.axis.updateLabels();
|
6546 |
|
|
}
|
6547 |
|
|
// TODO: return some values?
|
6548 |
|
|
};
|
6549 |
|
|
c3_chart_fn.axis.max = function (max) {
|
6550 |
|
|
var $$ = this.internal, config = $$.config;
|
6551 |
|
|
if (arguments.length) {
|
6552 |
|
|
if (typeof max === 'object') {
|
6553 |
|
|
if (isValue(max.x)) { config.axis_x_max = max.x; }
|
6554 |
|
|
if (isValue(max.y)) { config.axis_y_max = max.y; }
|
6555 |
|
|
if (isValue(max.y2)) { config.axis_y2_max = max.y2; }
|
6556 |
|
|
} else {
|
6557 |
|
|
config.axis_y_max = config.axis_y2_max = max;
|
6558 |
|
|
}
|
6559 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
|
6560 |
|
|
} else {
|
6561 |
|
|
return {
|
6562 |
|
|
x: config.axis_x_max,
|
6563 |
|
|
y: config.axis_y_max,
|
6564 |
|
|
y2: config.axis_y2_max
|
6565 |
|
|
};
|
6566 |
|
|
}
|
6567 |
|
|
};
|
6568 |
|
|
c3_chart_fn.axis.min = function (min) {
|
6569 |
|
|
var $$ = this.internal, config = $$.config;
|
6570 |
|
|
if (arguments.length) {
|
6571 |
|
|
if (typeof min === 'object') {
|
6572 |
|
|
if (isValue(min.x)) { config.axis_x_min = min.x; }
|
6573 |
|
|
if (isValue(min.y)) { config.axis_y_min = min.y; }
|
6574 |
|
|
if (isValue(min.y2)) { config.axis_y2_min = min.y2; }
|
6575 |
|
|
} else {
|
6576 |
|
|
config.axis_y_min = config.axis_y2_min = min;
|
6577 |
|
|
}
|
6578 |
|
|
$$.redraw({withUpdateOrgXDomain: true, withUpdateXDomain: true});
|
6579 |
|
|
} else {
|
6580 |
|
|
return {
|
6581 |
|
|
x: config.axis_x_min,
|
6582 |
|
|
y: config.axis_y_min,
|
6583 |
|
|
y2: config.axis_y2_min
|
6584 |
|
|
};
|
6585 |
|
|
}
|
6586 |
|
|
};
|
6587 |
|
|
c3_chart_fn.axis.range = function (range) {
|
6588 |
|
|
if (arguments.length) {
|
6589 |
|
|
if (isDefined(range.max)) { this.axis.max(range.max); }
|
6590 |
|
|
if (isDefined(range.min)) { this.axis.min(range.min); }
|
6591 |
|
|
} else {
|
6592 |
|
|
return {
|
6593 |
|
|
max: this.axis.max(),
|
6594 |
|
|
min: this.axis.min()
|
6595 |
|
|
};
|
6596 |
|
|
}
|
6597 |
|
|
};
|
6598 |
|
|
|
6599 |
|
|
c3_chart_fn.legend = function () {};
|
6600 |
|
|
c3_chart_fn.legend.show = function (targetIds) {
|
6601 |
|
|
var $$ = this.internal;
|
6602 |
|
|
$$.showLegend($$.mapToTargetIds(targetIds));
|
6603 |
|
|
$$.updateAndRedraw({withLegend: true});
|
6604 |
|
|
};
|
6605 |
|
|
c3_chart_fn.legend.hide = function (targetIds) {
|
6606 |
|
|
var $$ = this.internal;
|
6607 |
|
|
$$.hideLegend($$.mapToTargetIds(targetIds));
|
6608 |
|
|
$$.updateAndRedraw({withLegend: true});
|
6609 |
|
|
};
|
6610 |
|
|
|
6611 |
|
|
c3_chart_fn.resize = function (size) {
|
6612 |
|
|
var $$ = this.internal, config = $$.config;
|
6613 |
|
|
config.size_width = size ? size.width : null;
|
6614 |
|
|
config.size_height = size ? size.height : null;
|
6615 |
|
|
this.flush();
|
6616 |
|
|
};
|
6617 |
|
|
|
6618 |
|
|
c3_chart_fn.flush = function () {
|
6619 |
|
|
var $$ = this.internal;
|
6620 |
|
|
$$.updateAndRedraw({withLegend: true, withTransition: false, withTransitionForTransform: false});
|
6621 |
|
|
};
|
6622 |
|
|
|
6623 |
|
|
c3_chart_fn.destroy = function () {
|
6624 |
|
|
var $$ = this.internal;
|
6625 |
|
|
|
6626 |
|
|
window.clearInterval($$.intervalForObserveInserted);
|
6627 |
|
|
window.onresize = null;
|
6628 |
|
|
|
6629 |
|
|
$$.selectChart.classed('c3', false).html("");
|
6630 |
|
|
|
6631 |
|
|
// MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
|
6632 |
|
|
Object.keys($$).forEach(function (key) {
|
6633 |
|
|
$$[key] = null;
|
6634 |
|
|
});
|
6635 |
|
|
|
6636 |
|
|
return null;
|
6637 |
|
|
};
|
6638 |
|
|
|
6639 |
|
|
c3_chart_fn.tooltip = function () {};
|
6640 |
|
|
c3_chart_fn.tooltip.show = function (args) {
|
6641 |
|
|
var $$ = this.internal, index, mouse;
|
6642 |
|
|
|
6643 |
|
|
// determine mouse position on the chart
|
6644 |
|
|
if (args.mouse) {
|
6645 |
|
|
mouse = args.mouse;
|
6646 |
|
|
}
|
6647 |
|
|
|
6648 |
|
|
// determine focus data
|
6649 |
|
|
if (args.data) {
|
6650 |
|
|
if ($$.isMultipleX()) {
|
6651 |
|
|
// if multiple xs, target point will be determined by mouse
|
6652 |
|
|
mouse = [$$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value)];
|
6653 |
|
|
index = null;
|
6654 |
|
|
} else {
|
6655 |
|
|
// TODO: when tooltip_grouped = false
|
6656 |
|
|
index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x);
|
6657 |
|
|
}
|
6658 |
|
|
}
|
6659 |
|
|
else if (typeof args.x !== 'undefined') {
|
6660 |
|
|
index = $$.getIndexByX(args.x);
|
6661 |
|
|
}
|
6662 |
|
|
else if (typeof args.index !== 'undefined') {
|
6663 |
|
|
index = args.index;
|
6664 |
|
|
}
|
6665 |
|
|
|
6666 |
|
|
// emulate mouse events to show
|
6667 |
|
|
$$.dispatchEvent('mouseover', index, mouse);
|
6668 |
|
|
$$.dispatchEvent('mousemove', index, mouse);
|
6669 |
|
|
};
|
6670 |
|
|
c3_chart_fn.tooltip.hide = function () {
|
6671 |
|
|
// TODO: get target data by checking the state of focus
|
6672 |
|
|
this.internal.dispatchEvent('mouseout', 0);
|
6673 |
|
|
};
|
6674 |
|
|
|
6675 |
|
|
// Features:
|
6676 |
|
|
// 1. category axis
|
6677 |
|
|
// 2. ceil values of translate/x/y to int for half pixel antialiasing
|
6678 |
|
|
// 3. multiline tick text
|
6679 |
|
|
var tickTextCharSize;
|
6680 |
|
|
function c3_axis(d3, params) {
|
6681 |
|
|
var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments;
|
6682 |
|
|
|
6683 |
|
|
var tickOffset = 0, tickCulling = true, tickCentered;
|
6684 |
|
|
|
6685 |
|
|
params = params || {};
|
6686 |
|
|
outerTickSize = params.withOuterTick ? 6 : 0;
|
6687 |
|
|
|
6688 |
|
|
function axisX(selection, x) {
|
6689 |
|
|
selection.attr("transform", function (d) {
|
6690 |
|
|
return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)";
|
6691 |
|
|
});
|
6692 |
|
|
}
|
6693 |
|
|
function axisY(selection, y) {
|
6694 |
|
|
selection.attr("transform", function (d) {
|
6695 |
|
|
return "translate(0," + Math.ceil(y(d)) + ")";
|
6696 |
|
|
});
|
6697 |
|
|
}
|
6698 |
|
|
function scaleExtent(domain) {
|
6699 |
|
|
var start = domain[0], stop = domain[domain.length - 1];
|
6700 |
|
|
return start < stop ? [ start, stop ] : [ stop, start ];
|
6701 |
|
|
}
|
6702 |
|
|
function generateTicks(scale) {
|
6703 |
|
|
var i, domain, ticks = [];
|
6704 |
|
|
if (scale.ticks) {
|
6705 |
|
|
return scale.ticks.apply(scale, tickArguments);
|
6706 |
|
|
}
|
6707 |
|
|
domain = scale.domain();
|
6708 |
|
|
for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
|
6709 |
|
|
ticks.push(i);
|
6710 |
|
|
}
|
6711 |
|
|
if (ticks.length > 0 && ticks[0] > 0) {
|
6712 |
|
|
ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
|
6713 |
|
|
}
|
6714 |
|
|
return ticks;
|
6715 |
|
|
}
|
6716 |
|
|
function copyScale() {
|
6717 |
|
|
var newScale = scale.copy(), domain;
|
6718 |
|
|
if (params.isCategory) {
|
6719 |
|
|
domain = scale.domain();
|
6720 |
|
|
newScale.domain([domain[0], domain[1] - 1]);
|
6721 |
|
|
}
|
6722 |
|
|
return newScale;
|
6723 |
|
|
}
|
6724 |
|
|
function textFormatted(v) {
|
6725 |
|
|
var formatted = tickFormat ? tickFormat(v) : v;
|
6726 |
|
|
return typeof formatted !== 'undefined' ? formatted : '';
|
6727 |
|
|
}
|
6728 |
|
|
function getSizeFor1Char(tick) {
|
6729 |
|
|
if (tickTextCharSize) {
|
6730 |
|
|
return tickTextCharSize;
|
6731 |
|
|
}
|
6732 |
|
|
var size = {
|
6733 |
|
|
h: 11.5,
|
6734 |
|
|
w: 5.5
|
6735 |
|
|
};
|
6736 |
|
|
tick.select('text').text(textFormatted).each(function (d) {
|
6737 |
|
|
var box = this.getBoundingClientRect(),
|
6738 |
|
|
text = textFormatted(d),
|
6739 |
|
|
h = box.height,
|
6740 |
|
|
w = text ? (box.width / text.length) : undefined;
|
6741 |
|
|
if (h && w) {
|
6742 |
|
|
size.h = h;
|
6743 |
|
|
size.w = w;
|
6744 |
|
|
}
|
6745 |
|
|
}).text('');
|
6746 |
|
|
tickTextCharSize = size;
|
6747 |
|
|
return size;
|
6748 |
|
|
}
|
6749 |
|
|
function transitionise(selection) {
|
6750 |
|
|
return params.withoutTransition ? selection : d3.transition(selection);
|
6751 |
|
|
}
|
6752 |
|
|
function axis(g) {
|
6753 |
|
|
g.each(function () {
|
6754 |
|
|
var g = axis.g = d3.select(this);
|
6755 |
|
|
|
6756 |
|
|
var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale();
|
6757 |
|
|
|
6758 |
|
|
var ticks = tickValues ? tickValues : generateTicks(scale1),
|
6759 |
|
|
tick = g.selectAll(".tick").data(ticks, scale1),
|
6760 |
|
|
tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6),
|
6761 |
|
|
// MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
|
6762 |
|
|
tickExit = tick.exit().remove(),
|
6763 |
|
|
tickUpdate = transitionise(tick).style("opacity", 1),
|
6764 |
|
|
tickTransform, tickX, tickY;
|
6765 |
|
|
|
6766 |
|
|
var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()),
|
6767 |
|
|
path = g.selectAll(".domain").data([ 0 ]),
|
6768 |
|
|
pathUpdate = (path.enter().append("path").attr("class", "domain"), transitionise(path));
|
6769 |
|
|
tickEnter.append("line");
|
6770 |
|
|
tickEnter.append("text");
|
6771 |
|
|
|
6772 |
|
|
var lineEnter = tickEnter.select("line"),
|
6773 |
|
|
lineUpdate = tickUpdate.select("line"),
|
6774 |
|
|
textEnter = tickEnter.select("text"),
|
6775 |
|
|
textUpdate = tickUpdate.select("text");
|
6776 |
|
|
|
6777 |
|
|
if (params.isCategory) {
|
6778 |
|
|
tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
|
6779 |
|
|
tickX = tickCentered ? 0 : tickOffset;
|
6780 |
|
|
tickY = tickCentered ? tickOffset : 0;
|
6781 |
|
|
} else {
|
6782 |
|
|
tickOffset = tickX = 0;
|
6783 |
|
|
}
|
6784 |
|
|
|
6785 |
|
|
var text, tspan, sizeFor1Char = getSizeFor1Char(g.select('.tick')), counts = [];
|
6786 |
|
|
var tickLength = Math.max(innerTickSize, 0) + tickPadding,
|
6787 |
|
|
isVertical = orient === 'left' || orient === 'right';
|
6788 |
|
|
|
6789 |
|
|
// this should be called only when category axis
|
6790 |
|
|
function splitTickText(d, maxWidth) {
|
6791 |
|
|
var tickText = textFormatted(d),
|
6792 |
|
|
subtext, spaceIndex, textWidth, splitted = [];
|
6793 |
|
|
|
6794 |
|
|
if (Object.prototype.toString.call(tickText) === "[object Array]") {
|
6795 |
|
|
return tickText;
|
6796 |
|
|
}
|
6797 |
|
|
|
6798 |
|
|
if (!maxWidth || maxWidth <= 0) {
|
6799 |
|
|
maxWidth = isVertical ? 95 : params.isCategory ? (Math.ceil(scale1(ticks[1]) - scale1(ticks[0])) - 12) : 110;
|
6800 |
|
|
}
|
6801 |
|
|
|
6802 |
|
|
function split(splitted, text) {
|
6803 |
|
|
spaceIndex = undefined;
|
6804 |
|
|
for (var i = 1; i < text.length; i++) {
|
6805 |
|
|
if (text.charAt(i) === ' ') {
|
6806 |
|
|
spaceIndex = i;
|
6807 |
|
|
}
|
6808 |
|
|
subtext = text.substr(0, i + 1);
|
6809 |
|
|
textWidth = sizeFor1Char.w * subtext.length;
|
6810 |
|
|
// if text width gets over tick width, split by space index or crrent index
|
6811 |
|
|
if (maxWidth < textWidth) {
|
6812 |
|
|
return split(
|
6813 |
|
|
splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)),
|
6814 |
|
|
text.slice(spaceIndex ? spaceIndex + 1 : i)
|
6815 |
|
|
);
|
6816 |
|
|
}
|
6817 |
|
|
}
|
6818 |
|
|
return splitted.concat(text);
|
6819 |
|
|
}
|
6820 |
|
|
|
6821 |
|
|
return split(splitted, tickText + "");
|
6822 |
|
|
}
|
6823 |
|
|
|
6824 |
|
|
function tspanDy(d, i) {
|
6825 |
|
|
var dy = sizeFor1Char.h;
|
6826 |
|
|
if (i === 0) {
|
6827 |
|
|
if (orient === 'left' || orient === 'right') {
|
6828 |
|
|
dy = -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3);
|
6829 |
|
|
} else {
|
6830 |
|
|
dy = ".71em";
|
6831 |
|
|
}
|
6832 |
|
|
}
|
6833 |
|
|
return dy;
|
6834 |
|
|
}
|
6835 |
|
|
|
6836 |
|
|
function tickSize(d) {
|
6837 |
|
|
var tickPosition = scale(d) + (tickCentered ? 0 : tickOffset);
|
6838 |
|
|
return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
|
6839 |
|
|
}
|
6840 |
|
|
|
6841 |
|
|
text = tick.select("text");
|
6842 |
|
|
tspan = text.selectAll('tspan')
|
6843 |
|
|
.data(function (d, i) {
|
6844 |
|
|
var splitted = params.tickMultiline ? splitTickText(d, params.tickWidth) : [].concat(textFormatted(d));
|
6845 |
|
|
counts[i] = splitted.length;
|
6846 |
|
|
return splitted.map(function (s) {
|
6847 |
|
|
return { index: i, splitted: s };
|
6848 |
|
|
});
|
6849 |
|
|
});
|
6850 |
|
|
tspan.enter().append('tspan');
|
6851 |
|
|
tspan.exit().remove();
|
6852 |
|
|
tspan.text(function (d) { return d.splitted; });
|
6853 |
|
|
|
6854 |
|
|
var rotate = params.tickTextRotate;
|
6855 |
|
|
|
6856 |
|
|
function textAnchorForText(rotate) {
|
6857 |
|
|
if (!rotate) {
|
6858 |
|
|
return 'middle';
|
6859 |
|
|
}
|
6860 |
|
|
return rotate > 0 ? "start" : "end";
|
6861 |
|
|
}
|
6862 |
|
|
function textTransform(rotate) {
|
6863 |
|
|
if (!rotate) {
|
6864 |
|
|
return '';
|
6865 |
|
|
}
|
6866 |
|
|
return "rotate(" + rotate + ")";
|
6867 |
|
|
}
|
6868 |
|
|
function dxForText(rotate) {
|
6869 |
|
|
if (!rotate) {
|
6870 |
|
|
return 0;
|
6871 |
|
|
}
|
6872 |
|
|
return 8 * Math.sin(Math.PI * (rotate / 180));
|
6873 |
|
|
}
|
6874 |
|
|
function yForText(rotate) {
|
6875 |
|
|
if (!rotate) {
|
6876 |
|
|
return tickLength;
|
6877 |
|
|
}
|
6878 |
|
|
return 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1);
|
6879 |
|
|
}
|
6880 |
|
|
|
6881 |
|
|
switch (orient) {
|
6882 |
|
|
case "bottom":
|
6883 |
|
|
{
|
6884 |
|
|
tickTransform = axisX;
|
6885 |
|
|
lineEnter.attr("y2", innerTickSize);
|
6886 |
|
|
textEnter.attr("y", tickLength);
|
6887 |
|
|
lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize);
|
6888 |
|
|
textUpdate.attr("x", 0).attr("y", yForText(rotate))
|
6889 |
|
|
.style("text-anchor", textAnchorForText(rotate))
|
6890 |
|
|
.attr("transform", textTransform(rotate));
|
6891 |
|
|
tspan.attr('x', 0).attr("dy", tspanDy).attr('dx', dxForText(rotate));
|
6892 |
|
|
pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
|
6893 |
|
|
break;
|
6894 |
|
|
}
|
6895 |
|
|
case "top":
|
6896 |
|
|
{
|
6897 |
|
|
// TODO: rotated tick text
|
6898 |
|
|
tickTransform = axisX;
|
6899 |
|
|
lineEnter.attr("y2", -innerTickSize);
|
6900 |
|
|
textEnter.attr("y", -tickLength);
|
6901 |
|
|
lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
|
6902 |
|
|
textUpdate.attr("x", 0).attr("y", -tickLength);
|
6903 |
|
|
text.style("text-anchor", "middle");
|
6904 |
|
|
tspan.attr('x', 0).attr("dy", "0em");
|
6905 |
|
|
pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
|
6906 |
|
|
break;
|
6907 |
|
|
}
|
6908 |
|
|
case "left":
|
6909 |
|
|
{
|
6910 |
|
|
tickTransform = axisY;
|
6911 |
|
|
lineEnter.attr("x2", -innerTickSize);
|
6912 |
|
|
textEnter.attr("x", -tickLength);
|
6913 |
|
|
lineUpdate.attr("x2", -innerTickSize).attr("y1", tickY).attr("y2", tickY);
|
6914 |
|
|
textUpdate.attr("x", -tickLength).attr("y", tickOffset);
|
6915 |
|
|
text.style("text-anchor", "end");
|
6916 |
|
|
tspan.attr('x', -tickLength).attr("dy", tspanDy);
|
6917 |
|
|
pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
|
6918 |
|
|
break;
|
6919 |
|
|
}
|
6920 |
|
|
case "right":
|
6921 |
|
|
{
|
6922 |
|
|
tickTransform = axisY;
|
6923 |
|
|
lineEnter.attr("x2", innerTickSize);
|
6924 |
|
|
textEnter.attr("x", tickLength);
|
6925 |
|
|
lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
|
6926 |
|
|
textUpdate.attr("x", tickLength).attr("y", 0);
|
6927 |
|
|
text.style("text-anchor", "start");
|
6928 |
|
|
tspan.attr('x', tickLength).attr("dy", tspanDy);
|
6929 |
|
|
pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
|
6930 |
|
|
break;
|
6931 |
|
|
}
|
6932 |
|
|
}
|
6933 |
|
|
if (scale1.rangeBand) {
|
6934 |
|
|
var x = scale1, dx = x.rangeBand() / 2;
|
6935 |
|
|
scale0 = scale1 = function (d) {
|
6936 |
|
|
return x(d) + dx;
|
6937 |
|
|
};
|
6938 |
|
|
} else if (scale0.rangeBand) {
|
6939 |
|
|
scale0 = scale1;
|
6940 |
|
|
} else {
|
6941 |
|
|
tickExit.call(tickTransform, scale1);
|
6942 |
|
|
}
|
6943 |
|
|
tickEnter.call(tickTransform, scale0);
|
6944 |
|
|
tickUpdate.call(tickTransform, scale1);
|
6945 |
|
|
});
|
6946 |
|
|
}
|
6947 |
|
|
axis.scale = function (x) {
|
6948 |
|
|
if (!arguments.length) { return scale; }
|
6949 |
|
|
scale = x;
|
6950 |
|
|
return axis;
|
6951 |
|
|
};
|
6952 |
|
|
axis.orient = function (x) {
|
6953 |
|
|
if (!arguments.length) { return orient; }
|
6954 |
|
|
orient = x in {top: 1, right: 1, bottom: 1, left: 1} ? x + "" : "bottom";
|
6955 |
|
|
return axis;
|
6956 |
|
|
};
|
6957 |
|
|
axis.tickFormat = function (format) {
|
6958 |
|
|
if (!arguments.length) { return tickFormat; }
|
6959 |
|
|
tickFormat = format;
|
6960 |
|
|
return axis;
|
6961 |
|
|
};
|
6962 |
|
|
axis.tickCentered = function (isCentered) {
|
6963 |
|
|
if (!arguments.length) { return tickCentered; }
|
6964 |
|
|
tickCentered = isCentered;
|
6965 |
|
|
return axis;
|
6966 |
|
|
};
|
6967 |
|
|
axis.tickOffset = function () {
|
6968 |
|
|
return tickOffset;
|
6969 |
|
|
};
|
6970 |
|
|
axis.tickInterval = function () {
|
6971 |
|
|
var interval, length;
|
6972 |
|
|
if (params.isCategory) {
|
6973 |
|
|
interval = tickOffset * 2;
|
6974 |
|
|
}
|
6975 |
|
|
else {
|
6976 |
|
|
length = axis.g.select('path.domain').node().getTotalLength() - outerTickSize * 2;
|
6977 |
|
|
interval = length / axis.g.selectAll('line').size();
|
6978 |
|
|
}
|
6979 |
|
|
return interval === Infinity ? 0 : interval;
|
6980 |
|
|
};
|
6981 |
|
|
axis.ticks = function () {
|
6982 |
|
|
if (!arguments.length) { return tickArguments; }
|
6983 |
|
|
tickArguments = arguments;
|
6984 |
|
|
return axis;
|
6985 |
|
|
};
|
6986 |
|
|
axis.tickCulling = function (culling) {
|
6987 |
|
|
if (!arguments.length) { return tickCulling; }
|
6988 |
|
|
tickCulling = culling;
|
6989 |
|
|
return axis;
|
6990 |
|
|
};
|
6991 |
|
|
axis.tickValues = function (x) {
|
6992 |
|
|
if (typeof x === 'function') {
|
6993 |
|
|
tickValues = function () {
|
6994 |
|
|
return x(scale.domain());
|
6995 |
|
|
};
|
6996 |
|
|
}
|
6997 |
|
|
else {
|
6998 |
|
|
if (!arguments.length) { return tickValues; }
|
6999 |
|
|
tickValues = x;
|
7000 |
|
|
}
|
7001 |
|
|
return axis;
|
7002 |
|
|
};
|
7003 |
|
|
return axis;
|
7004 |
|
|
}
|
7005 |
|
|
|
7006 |
|
|
c3_chart_internal_fn.isSafari = function () {
|
7007 |
|
|
var ua = window.navigator.userAgent;
|
7008 |
|
|
return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;
|
7009 |
|
|
};
|
7010 |
|
|
c3_chart_internal_fn.isChrome = function () {
|
7011 |
|
|
var ua = window.navigator.userAgent;
|
7012 |
|
|
return ua.indexOf('Chrome') >= 0;
|
7013 |
|
|
};
|
7014 |
|
|
|
7015 |
|
|
// PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use
|
7016 |
|
|
// this polyfill to avoid the confusion.
|
7017 |
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill
|
7018 |
|
|
|
7019 |
|
|
if (!Function.prototype.bind) {
|
7020 |
|
|
Function.prototype.bind = function(oThis) {
|
7021 |
|
|
if (typeof this !== 'function') {
|
7022 |
|
|
// closest thing possible to the ECMAScript 5
|
7023 |
|
|
// internal IsCallable function
|
7024 |
|
|
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
|
7025 |
|
|
}
|
7026 |
|
|
|
7027 |
|
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
7028 |
|
|
fToBind = this,
|
7029 |
|
|
fNOP = function() {},
|
7030 |
|
|
fBound = function() {
|
7031 |
|
|
return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
|
7032 |
|
|
};
|
7033 |
|
|
|
7034 |
|
|
fNOP.prototype = this.prototype;
|
7035 |
|
|
fBound.prototype = new fNOP();
|
7036 |
|
|
|
7037 |
|
|
return fBound;
|
7038 |
|
|
};
|
7039 |
|
|
}
|
7040 |
|
|
|
7041 |
|
|
if (typeof define === 'function' && define.amd) {
|
7042 |
|
|
define("c3", ["d3"], c3);
|
7043 |
|
|
} else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
|
7044 |
|
|
module.exports = c3;
|
7045 |
|
|
} else {
|
7046 |
|
|
window.c3 = c3;
|
7047 |
|
|
}
|
7048 |
|
|
|
7049 |
|
|
})(window);
|