diff --git a/.eslintrc b/.eslintrc index 066e1b5..4e2e45f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -16,5 +16,7 @@ "prefer-spread": 0, "no-shadow": 0, "no-underscore-dangle": 0, + "import/prefer-default-export": 0, + "one-var-declaration-per-line": 0, } } diff --git a/c3.js b/c3.js index 1c02c57..13b749e 100644 --- a/c3.js +++ b/c3.js @@ -1214,266 +1214,193 @@ if(flowLength){for(i=0;i=0&&ua.indexOf('Chrome')<0;};c3_chart_internal_fn.isChrome=function(){var ua=window.navigator.userAgent;return ua.indexOf('Chrome')>=0;}; -var c3_chart_fn = void 0; - -function Chart(config) { - var $$ = this.internal = new ChartInternal(this); - $$.loadConfig(config); - - $$.beforeInit(config); - $$.init(); - $$.afterInit(config); - - // bind "this" to nested API - (function bindThis(fn, target, argThis) { - Object.keys(fn).forEach(function (key) { - target[key] = fn[key].bind(argThis); - if (Object.keys(fn[key]).length > 0) { - bindThis(fn[key], target[key], argThis); - } +var axis = function axis() {}; +axis.labels = function (labels) { + var $$ = this.internal; + if (arguments.length) { + Object.keys(labels).forEach(function (axisId) { + $$.axis.setLabelText(axisId, labels[axisId]); }); - })(c3_chart_fn, this, this); -} - -c3_chart_fn = Chart.prototype; - -c3_chart_fn.focus = function (targetIds) { - var $$ = this.internal, - candidates = void 0; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), this.revert(); - this.defocus(); - candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.expandArc(targetIds); + $$.axis.updateLabels(); } - $$.toggleFocusLegend(targetIds, true); - - $$.focusedTargetIds = targetIds; - $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) { - return targetIds.indexOf(id) < 0; - }); + // TODO: return some values? }; - -c3_chart_fn.defocus = function (targetIds) { +axis.max = function (max) { var $$ = this.internal, - candidates = void 0; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); + config = $$.config; + if (arguments.length) { + if ((typeof max === 'undefined' ? 'undefined' : _typeof(max)) === 'object') { + if (isValue(max.x)) { + config.axis_x_max = max.x; + } + if (isValue(max.y)) { + config.axis_y_max = max.y; + } + if (isValue(max.y2)) { + config.axis_y2_max = max.y2; + } + } else { + config.axis_y_max = config.axis_y2_max = max; + } + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } else { + return { + x: config.axis_x_max, + y: config.axis_y_max, + y2: config.axis_y2_max + }; } - $$.toggleFocusLegend(targetIds, false); - - $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) { - return targetIds.indexOf(id) < 0; - }); - $$.defocusedTargetIds = targetIds; }; - -c3_chart_fn.revert = function (targetIds) { +axis.min = function (min) { var $$ = this.internal, - candidates = void 0; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets - - candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); + config = $$.config; + if (arguments.length) { + if ((typeof min === 'undefined' ? 'undefined' : _typeof(min)) === 'object') { + if (isValue(min.x)) { + config.axis_x_min = min.x; + } + if (isValue(min.y)) { + config.axis_y_min = min.y; + } + if (isValue(min.y2)) { + config.axis_y2_min = min.y2; + } + } else { + config.axis_y_min = config.axis_y2_min = min; + } + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } else { + return { + x: config.axis_x_min, + y: config.axis_y_min, + y2: config.axis_y2_min + }; } - if ($$.config.legend_show) { - $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$))); - $$.legend.selectAll($$.selectorLegends(targetIds)).filter(function () { - return $$.d3.select(this).classed(CLASS.legendItemFocused); - }).classed(CLASS.legendItemFocused, false); +}; +axis.range = function (range) { + if (arguments.length) { + if (isDefined(range.max)) { + this.axis.max(range.max); + } + if (isDefined(range.min)) { + this.axis.min(range.min); + } + } else { + return { + max: this.axis.max(), + min: this.axis.min() + }; } - - $$.focusedTargetIds = []; - $$.defocusedTargetIds = []; }; -c3_chart_fn.show = function (targetIds, options) { +var category = function category(i, _category) { var $$ = this.internal, - targets = void 0; - - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; - - $$.removeHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - - targets.transition().style('opacity', 1, 'important').call($$.endall, function () { - targets.style('opacity', null).style('opacity', 1); - }); - - if (options.withLegend) { - $$.showLegend(targetIds); + config = $$.config; + if (arguments.length > 1) { + config.axis_x_categories[i] = _category; + $$.redraw(); } - - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); + return config.axis_x_categories[i]; +}; +var categories = function categories(_categories) { + var $$ = this.internal, + config = $$.config; + if (!arguments.length) { + return config.axis_x_categories; + } + config.axis_x_categories = _categories; + $$.redraw(); + return config.axis_x_categories; }; -c3_chart_fn.hide = function (targetIds, options) { +var resize = function resize(size) { var $$ = this.internal, - targets = void 0; + config = $$.config; + config.size_width = size ? size.width : null; + config.size_height = size ? size.height : null; + this.flush(); +}; - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; +var flush = function flush() { + var $$ = this.internal; + $$.updateAndRedraw({ withLegend: true, withTransition: false, withTransitionForTransform: false }); +}; - $$.addHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); +var destroy = function destroy() { + var $$ = this.internal; - targets.transition().style('opacity', 0, 'important').call($$.endall, function () { - targets.style('opacity', null).style('opacity', 0); - }); + window.clearInterval($$.intervalForObserveInserted); - if (options.withLegend) { - $$.hideLegend(targetIds); + if ($$.resizeTimeout !== undefined) { + window.clearTimeout($$.resizeTimeout); } - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); -}; + if (window.detachEvent) { + window.detachEvent('onresize', $$.resizeFunction); + } else if (window.removeEventListener) { + window.removeEventListener('resize', $$.resizeFunction); + } else { + var wrapper = window.onresize; + // check if no one else removed our wrapper and remove our resizeFunction from it + if (wrapper && wrapper.add && wrapper.remove) { + wrapper.remove($$.resizeFunction); + } + } -c3_chart_fn.toggle = function (targetIds, options) { - var that = this, - $$ = this.internal; - $$.mapToTargetIds(targetIds).forEach(function (targetId) { - $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options); + $$.selectChart.classed('c3', false).html(''); + + // MEMO: this is needed because the reference of some elements will not be released, + // then memory leak will happen. + Object.keys($$).forEach(function (key) { + $$[key] = null; }); -}; -c3_chart_fn.zoom = function (domain) { - var $$ = this.internal; - if (domain) { - if ($$.isTimeSeries()) { - domain = domain.map(function (x) { - return $$.parseDate(x); - }); - } - $$.brush.extent(domain); - $$.redraw({ withUpdateXDomain: true, withY: $$.config.zoom_rescale }); - $$.config.zoom_onzoom.call(this, $$.x.orgDomain()); - } - return $$.brush.extent(); + return null; }; -c3_chart_fn.zoom.enable = function (enabled) { + +// TODO: fix +var color = function color(id) { var $$ = this.internal; - $$.config.zoom_enabled = enabled; - $$.updateAndRedraw(); + return $$.color(id); // more patterns }; -c3_chart_fn.unzoom = function () { - var $$ = this.internal; - $$.brush.clear().update(); - $$.redraw({ withUpdateXDomain: true }); + +var data = function data(targetIds) { + var targets = this.internal.data.targets; + return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) { + return [].concat(targetIds).indexOf(t.id) >= 0; + }); }; -c3_chart_fn.zoom.max = function (max) { - var $$ = this.internal, - config = $$.config, - d3$$1 = $$.d3; - if (max === 0 || max) { - config.zoom_x_max = d3$$1.max([$$.orgXDomain[1], max]); - } else { - return config.zoom_x_max; - } +data.shown = function (targetIds) { + return this.internal.filterTargetsToShow(this.data(targetIds)); }; -c3_chart_fn.zoom.min = function (min) { - var $$ = this.internal, - config = $$.config, - d3$$1 = $$.d3; - if (min === 0 || min) { - config.zoom_x_min = d3$$1.min([$$.orgXDomain[0], min]); - } else { - return config.zoom_x_min; +data.values = function (targetId) { + var targets = void 0, + values = null; + if (targetId) { + targets = this.data(targetId); + values = targets[0] ? targets[0].values.map(function (d) { + return d.value; + }) : null; } + return values; }; -c3_chart_fn.zoom.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { - this.domain.max(range.max); - } - if (isDefined(range.min)) { - this.domain.min(range.min); - } - } else { - return { - max: this.domain.max(), - min: this.domain.min() - }; - } +data.names = function (names) { + this.internal.clearLegendItemTextBoxCache(); + return this.internal.updateDataAttributes('names', names); }; -c3_chart_fn.load = function (args) { - var $$ = this.internal, - config = $$.config; - // update xs if specified - if (args.xs) { - $$.addXs(args.xs); - } - // update names if exists - if ('names' in args) { - c3_chart_fn.data.names.bind(this)(args.names); - } - // update classes if exists - if ('classes' in args) { - Object.keys(args.classes).forEach(function (id) { - config.data_classes[id] = args.classes[id]; - }); - } - // update categories if exists - if ('categories' in args && $$.isCategorized()) { - config.axis_x_categories = args.categories; - } - // update axes if exists - if ('axes' in args) { - Object.keys(args.axes).forEach(function (id) { - config.data_axes[id] = args.axes[id]; - }); - } - // update colors if exists - if ('colors' in args) { - Object.keys(args.colors).forEach(function (id) { - config.data_colors[id] = args.colors[id]; - }); - } - // use cache if exists - if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { - $$.load($$.getCaches(args.cacheIds), args.done); - return; - } - // unload if needed - if ('unload' in args) { - // TODO: do not unload if target will load (included in url/rows/columns) - $$.unload($$.mapToTargetIds(typeof args.unload === 'boolean' && args.unload ? null : args.unload), function () { - $$.loadFromArgs(args); - }); - } else { - $$.loadFromArgs(args); - } +data.colors = function (colors) { + return this.internal.updateDataAttributes('colors', colors); }; -c3_chart_fn.unload = function (args) { - var $$ = this.internal; - args = args || {}; - if (args instanceof Array) { - args = { ids: args }; - } else if (typeof args === 'string') { - args = { ids: [args] }; - } - $$.unload($$.mapToTargetIds(args.ids), function () { - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); - if (args.done) { - args.done(); - } - }); +data.axes = function (axes) { + return this.internal.updateDataAttributes('axes', axes); }; -c3_chart_fn.flow = function (args) { +var flow = function flow(args) { var $$ = this.internal, targets = void 0, data = void 0, @@ -1625,98 +1552,71 @@ c3_chart_fn.flow = function (args) { orgDataCount: orgDataCount }, withLegend: true, - withTransition: orgDataCount > 1, - withTrimXDomain: false, - withUpdateXAxis: true - }); -}; - -c3_chart_fn.selected = function (targetId) { - var $$ = this.internal, - d3$$1 = $$.d3; - return d3$$1.merge($$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape).filter(function () { - return d3$$1.select(this).classed(CLASS.SELECTED); - }).map(function (d) { - return d.map(function (d) { - var data = d.__data__;return data.data ? data.data : data; - }); - })); -}; -c3_chart_fn.select = function (ids, indices, resetOther) { - var $$ = this.internal, - d3$$1 = $$.d3, - config = $$.config; - if (!config.data_selection_enabled) { - return; - } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - var shape = d3$$1.select(this), - id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d) && !isSelected) { - toggle(true, shape.classed(CLASS.SELECTED, true), d, i); - } - } else if (isDefined(resetOther) && resetOther) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } + withTransition: orgDataCount > 1, + withTrimXDomain: false, + withUpdateXAxis: true }); }; -c3_chart_fn.unselect = function (ids, indices) { + +var focus = function focus(targetIds) { var $$ = this.internal, - d3$$1 = $$.d3, - config = $$.config; - if (!config.data_selection_enabled) { - return; + candidates = void 0; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), this.revert(); + this.defocus(); + candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false); + if ($$.hasArcType()) { + $$.expandArc(targetIds); } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - var shape = d3$$1.select(this), - id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d)) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } - } + $$.toggleFocusLegend(targetIds, true); + + $$.focusedTargetIds = targetIds; + $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) { + return targetIds.indexOf(id) < 0; }); }; -c3_chart_fn.transform = function (type, targetIds) { +var defocus = function defocus(targetIds) { var $$ = this.internal, - options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null; - $$.transformTo(targetIds, type, options); + candidates = void 0; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true); + if ($$.hasArcType()) { + $$.unexpandArc(targetIds); + } + $$.toggleFocusLegend(targetIds, false); + + $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) { + return targetIds.indexOf(id) < 0; + }); + $$.defocusedTargetIds = targetIds; }; -c3_chart_fn.groups = function (groups) { +var revert = function revert(targetIds) { var $$ = this.internal, - config = $$.config; - if (isUndefined(groups)) { - return config.data_groups; + candidates = void 0; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets + + candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false); + if ($$.hasArcType()) { + $$.unexpandArc(targetIds); } - config.data_groups = groups; - $$.redraw(); - return config.data_groups; + if ($$.config.legend_show) { + $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$))); + $$.legend.selectAll($$.selectorLegends(targetIds)).filter(function () { + return $$.d3.select(this).classed(CLASS.legendItemFocused); + }).classed(CLASS.legendItemFocused, false); + } + + $$.focusedTargetIds = []; + $$.defocusedTargetIds = []; }; -c3_chart_fn.xgrids = function (grids) { +var xgrids = function xgrids(grids) { var $$ = this.internal, config = $$.config; if (!grids) { @@ -1726,17 +1626,19 @@ c3_chart_fn.xgrids = function (grids) { $$.redrawWithoutRescale(); return config.grid_x_lines; }; -c3_chart_fn.xgrids.add = function (grids) { + +xgrids.add = function (grids) { var $$ = this.internal; return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : [])); }; -c3_chart_fn.xgrids.remove = function (params) { + +xgrids.remove = function (params) { // TODO: multiple var $$ = this.internal; $$.removeGridLines(params, true); }; -c3_chart_fn.ygrids = function (grids) { +var ygrids = function ygrids(grids) { var $$ = this.internal, config = $$.config; if (!grids) { @@ -1746,27 +1648,120 @@ c3_chart_fn.ygrids = function (grids) { $$.redrawWithoutRescale(); return config.grid_y_lines; }; -c3_chart_fn.ygrids.add = function (grids) { + +ygrids.add = function (grids) { var $$ = this.internal; return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : [])); }; -c3_chart_fn.ygrids.remove = function (params) { + +ygrids.remove = function (params) { // TODO: multiple var $$ = this.internal; $$.removeGridLines(params, false); }; -c3_chart_fn.regions = function (regions) { +var groups = function groups(_groups) { var $$ = this.internal, config = $$.config; - if (!regions) { + if (isUndefined(_groups)) { + return config.data_groups; + } + config.data_groups = _groups; + $$.redraw(); + return config.data_groups; +}; + +var legend = function legend() {}; + +legend.show = function (targetIds) { + var $$ = this.internal; + $$.showLegend($$.mapToTargetIds(targetIds)); + $$.updateAndRedraw({ withLegend: true }); +}; + +legend.hide = function (targetIds) { + var $$ = this.internal; + $$.hideLegend($$.mapToTargetIds(targetIds)); + $$.updateAndRedraw({ withLegend: true }); +}; + +var load = function load(args) { + var $$ = this.internal, + config = $$.config; + // update xs if specified + if (args.xs) { + $$.addXs(args.xs); + } + // update names if exists + if ('names' in args) { + c3_chart_fn.data.names.bind(this)(args.names); + } + // update classes if exists + if ('classes' in args) { + Object.keys(args.classes).forEach(function (id) { + config.data_classes[id] = args.classes[id]; + }); + } + // update categories if exists + if ('categories' in args && $$.isCategorized()) { + config.axis_x_categories = args.categories; + } + // update axes if exists + if ('axes' in args) { + Object.keys(args.axes).forEach(function (id) { + config.data_axes[id] = args.axes[id]; + }); + } + // update colors if exists + if ('colors' in args) { + Object.keys(args.colors).forEach(function (id) { + config.data_colors[id] = args.colors[id]; + }); + } + // use cache if exists + if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { + $$.load($$.getCaches(args.cacheIds), args.done); + return; + } + // unload if needed + if ('unload' in args) { + // TODO: do not unload if target will load (included in url/rows/columns) + $$.unload($$.mapToTargetIds(typeof args.unload === 'boolean' && args.unload ? null : args.unload), function () { + $$.loadFromArgs(args); + }); + } else { + $$.loadFromArgs(args); + } +}; + +var unload = function unload(args) { + var $$ = this.internal; + args = args || {}; + if (args instanceof Array) { + args = { ids: args }; + } else if (typeof args === 'string') { + args = { ids: [args] }; + } + $$.unload($$.mapToTargetIds(args.ids), function () { + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); + if (args.done) { + args.done(); + } + }); +}; + +var regions = function regions(_regions) { + var $$ = this.internal, + config = $$.config; + if (!_regions) { return config.regions; } - config.regions = regions; + config.regions = _regions; $$.redrawWithoutRescale(); return config.regions; }; -c3_chart_fn.regions.add = function (regions) { + +regions.add = function (regions) { var $$ = this.internal, config = $$.config; if (!regions) { @@ -1776,7 +1771,8 @@ c3_chart_fn.regions.add = function (regions) { $$.redrawWithoutRescale(); return config.regions; }; -c3_chart_fn.regions.remove = function (options) { + +regions.remove = function (options) { var $$ = this.internal, config = $$.config, duration = void 0, @@ -1808,217 +1804,129 @@ c3_chart_fn.regions.remove = function (options) { return config.regions; }; -c3_chart_fn.data = function (targetIds) { - var targets = this.internal.data.targets; - return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) { - return [].concat(targetIds).indexOf(t.id) >= 0; - }); -}; -c3_chart_fn.data.shown = function (targetIds) { - return this.internal.filterTargetsToShow(this.data(targetIds)); -}; -c3_chart_fn.data.values = function (targetId) { - var targets = void 0, - values = null; - if (targetId) { - targets = this.data(targetId); - values = targets[0] ? targets[0].values.map(function (d) { - return d.value; - }) : null; - } - return values; -}; -c3_chart_fn.data.names = function (names) { - this.internal.clearLegendItemTextBoxCache(); - return this.internal.updateDataAttributes('names', names); -}; -c3_chart_fn.data.colors = function (colors) { - return this.internal.updateDataAttributes('colors', colors); -}; -c3_chart_fn.data.axes = function (axes) { - return this.internal.updateDataAttributes('axes', axes); -}; - -c3_chart_fn.category = function (i, category) { - var $$ = this.internal, - config = $$.config; - if (arguments.length > 1) { - config.axis_x_categories[i] = category; - $$.redraw(); - } - return config.axis_x_categories[i]; -}; -c3_chart_fn.categories = function (categories) { - var $$ = this.internal, - config = $$.config; - if (!arguments.length) { - return config.axis_x_categories; - } - config.axis_x_categories = categories; - $$.redraw(); - return config.axis_x_categories; -}; - -// TODO: fix -c3_chart_fn.color = function (id) { - var $$ = this.internal; - return $$.color(id); // more patterns -}; - -c3_chart_fn.x = function (x) { - var $$ = this.internal; - if (arguments.length) { - $$.updateTargetX($$.data.targets, x); - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } - return $$.data.xs; -}; -c3_chart_fn.xs = function (xs) { - var $$ = this.internal; - if (arguments.length) { - $$.updateTargetXs($$.data.targets, xs); - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } - return $$.data.xs; -}; - -c3_chart_fn.axis = function () {}; -c3_chart_fn.axis.labels = function (labels) { - var $$ = this.internal; - if (arguments.length) { - Object.keys(labels).forEach(function (axisId) { - $$.axis.setLabelText(axisId, labels[axisId]); - }); - $$.axis.updateLabels(); - } - // TODO: return some values? -}; -c3_chart_fn.axis.max = function (max) { - var $$ = this.internal, - config = $$.config; - if (arguments.length) { - if ((typeof max === 'undefined' ? 'undefined' : _typeof(max)) === 'object') { - if (isValue(max.x)) { - config.axis_x_max = max.x; - } - if (isValue(max.y)) { - config.axis_y_max = max.y; - } - if (isValue(max.y2)) { - config.axis_y2_max = max.y2; - } - } else { - config.axis_y_max = config.axis_y2_max = max; - } - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } else { - return { - x: config.axis_x_max, - y: config.axis_y_max, - y2: config.axis_y2_max - }; - } +var selected = function selected(targetId) { + var $$ = this.internal, + d3$$1 = $$.d3; + return d3$$1.merge($$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape).filter(function () { + return d3$$1.select(this).classed(CLASS.SELECTED); + }).map(function (d) { + return d.map(function (d) { + var data = d.__data__;return data.data ? data.data : data; + }); + })); }; -c3_chart_fn.axis.min = function (min) { + +var select = function select(ids, indices, resetOther) { var $$ = this.internal, + d3$$1 = $$.d3, config = $$.config; - if (arguments.length) { - if ((typeof min === 'undefined' ? 'undefined' : _typeof(min)) === 'object') { - if (isValue(min.x)) { - config.axis_x_min = min.x; - } - if (isValue(min.y)) { - config.axis_y_min = min.y; + if (!config.data_selection_enabled) { + return; + } + $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { + var shape = d3$$1.select(this), + id = d.data ? d.data.id : d.id, + toggle = $$.getToggle(this, d).bind($$), + isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, + isTargetIndex = !indices || indices.indexOf(i) >= 0, + isSelected = shape.classed(CLASS.SELECTED); + // line/area selection not supported yet + if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { + return; + } + if (isTargetId && isTargetIndex) { + if (config.data_selection_isselectable(d) && !isSelected) { + toggle(true, shape.classed(CLASS.SELECTED, true), d, i); } - if (isValue(min.y2)) { - config.axis_y2_min = min.y2; + } else if (isDefined(resetOther) && resetOther) { + if (isSelected) { + toggle(false, shape.classed(CLASS.SELECTED, false), d, i); } - } else { - config.axis_y_min = config.axis_y2_min = min; } - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } else { - return { - x: config.axis_x_min, - y: config.axis_y_min, - y2: config.axis_y2_min - }; - } + }); }; -c3_chart_fn.axis.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { - this.axis.max(range.max); + +var unselect = function unselect(ids, indices) { + var $$ = this.internal, + d3$$1 = $$.d3, + config = $$.config; + if (!config.data_selection_enabled) { + return; + } + $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { + var shape = d3$$1.select(this), + id = d.data ? d.data.id : d.id, + toggle = $$.getToggle(this, d).bind($$), + isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, + isTargetIndex = !indices || indices.indexOf(i) >= 0, + isSelected = shape.classed(CLASS.SELECTED); + // line/area selection not supported yet + if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { + return; } - if (isDefined(range.min)) { - this.axis.min(range.min); + if (isTargetId && isTargetIndex) { + if (config.data_selection_isselectable(d)) { + if (isSelected) { + toggle(false, shape.classed(CLASS.SELECTED, false), d, i); + } + } } - } else { - return { - max: this.axis.max(), - min: this.axis.min() - }; - } -}; - -c3_chart_fn.legend = function () {}; -c3_chart_fn.legend.show = function (targetIds) { - var $$ = this.internal; - $$.showLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({ withLegend: true }); -}; -c3_chart_fn.legend.hide = function (targetIds) { - var $$ = this.internal; - $$.hideLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({ withLegend: true }); + }); }; -c3_chart_fn.resize = function (size) { +var show = function show(targetIds, options) { var $$ = this.internal, - config = $$.config; - config.size_width = size ? size.width : null; - config.size_height = size ? size.height : null; - this.flush(); -}; + targets = void 0; -c3_chart_fn.flush = function () { - var $$ = this.internal; - $$.updateAndRedraw({ withLegend: true, withTransition: false, withTransitionForTransform: false }); -}; + targetIds = $$.mapToTargetIds(targetIds); + options = options || {}; -c3_chart_fn.destroy = function () { - var $$ = this.internal; + $$.removeHiddenTargetIds(targetIds); + targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - window.clearInterval($$.intervalForObserveInserted); + targets.transition().style('opacity', 1, 'important').call($$.endall, function () { + targets.style('opacity', null).style('opacity', 1); + }); - if ($$.resizeTimeout !== undefined) { - window.clearTimeout($$.resizeTimeout); + if (options.withLegend) { + $$.showLegend(targetIds); } - if (window.detachEvent) { - window.detachEvent('onresize', $$.resizeFunction); - } else if (window.removeEventListener) { - window.removeEventListener('resize', $$.resizeFunction); - } else { - var wrapper = window.onresize; - // check if no one else removed our wrapper and remove our resizeFunction from it - if (wrapper && wrapper.add && wrapper.remove) { - wrapper.remove($$.resizeFunction); - } - } + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); +}; - $$.selectChart.classed('c3', false).html(''); +var hide = function hide(targetIds, options) { + var $$ = this.internal, + targets = void 0; - // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen. - Object.keys($$).forEach(function (key) { - $$[key] = null; + targetIds = $$.mapToTargetIds(targetIds); + options = options || {}; + + $$.addHiddenTargetIds(targetIds); + targets = $$.svg.selectAll($$.selectorTargets(targetIds)); + + targets.transition().style('opacity', 0, 'important').call($$.endall, function () { + targets.style('opacity', null).style('opacity', 0); }); - return null; + if (options.withLegend) { + $$.hideLegend(targetIds); + } + + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); +}; + +var toggle = function toggle(targetIds, options) { + var that = this, + $$ = this.internal; + $$.mapToTargetIds(targetIds).forEach(function (targetId) { + $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options); + }); }; -c3_chart_fn.tooltip = function () {}; -c3_chart_fn.tooltip.show = function (args) { +var tooltip = function tooltip() {}; + +tooltip.show = function (args) { var $$ = this.internal, index = void 0, mouse = void 0; @@ -2050,13 +1958,158 @@ c3_chart_fn.tooltip.show = function (args) { $$.config.tooltip_onshow.call($$, args.data); }; -c3_chart_fn.tooltip.hide = function () { + +tooltip.hide = function () { // TODO: get target data by checking the state of focus this.internal.dispatchEvent('mouseout', 0); this.internal.config.tooltip_onhide.call(this); }; +var transform = function transform(type, targetIds) { + var $$ = this.internal, + options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null; + $$.transformTo(targetIds, type, options); +}; + +var x = function x(_x) { + var $$ = this.internal; + if (arguments.length) { + $$.updateTargetX($$.data.targets, _x); + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } + return $$.data.xs; +}; + +var xs = function xs(_xs) { + var $$ = this.internal; + if (arguments.length) { + $$.updateTargetXs($$.data.targets, _xs); + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } + return $$.data.xs; +}; + +var zoom = function zoom(domain) { + var $$ = this.internal; + if (domain) { + if ($$.isTimeSeries()) { + domain = domain.map(function (x) { + return $$.parseDate(x); + }); + } + $$.brush.extent(domain); + $$.redraw({ withUpdateXDomain: true, withY: $$.config.zoom_rescale }); + $$.config.zoom_onzoom.call(this, $$.x.orgDomain()); + } + return $$.brush.extent(); +}; + +var unzoom = function unzoom() { + var $$ = this.internal; + $$.brush.clear().update(); + $$.redraw({ withUpdateXDomain: true }); +}; + +zoom.enable = function (enabled) { + var $$ = this.internal; + $$.config.zoom_enabled = enabled; + $$.updateAndRedraw(); +}; + +zoom.max = function (max) { + var $$ = this.internal, + config = $$.config, + d3$$1 = $$.d3; + if (max === 0 || max) { + config.zoom_x_max = d3$$1.max([$$.orgXDomain[1], max]); + } else { + return config.zoom_x_max; + } +}; + +zoom.min = function (min) { + var $$ = this.internal, + config = $$.config, + d3$$1 = $$.d3; + if (min === 0 || min) { + config.zoom_x_min = d3$$1.min([$$.orgXDomain[0], min]); + } else { + return config.zoom_x_min; + } +}; + +zoom.range = function (range) { + if (arguments.length) { + if (isDefined(range.max)) { + this.domain.max(range.max); + } + if (isDefined(range.min)) { + this.domain.min(range.min); + } + } else { + return { + max: this.domain.max(), + min: this.domain.min() + }; + } +}; + +var c3_chart_fn$1 = void 0; + +function Chart(config) { + var $$ = this.internal = new ChartInternal(this); + $$.loadConfig(config); + + $$.beforeInit(config); + $$.init(); + $$.afterInit(config); + + // bind "this" to nested API + (function bindThis(fn, target, argThis) { + Object.keys(fn).forEach(function (key) { + target[key] = fn[key].bind(argThis); + if (Object.keys(fn[key]).length > 0) { + bindThis(fn[key], target[key], argThis); + } + }); + })(c3_chart_fn$1, this, this); +} + +c3_chart_fn$1 = Chart.prototype; + +c3_chart_fn$1.axis = axis; +c3_chart_fn$1.category = category; +c3_chart_fn$1.categories = categories; +c3_chart_fn$1.resize = resize; +c3_chart_fn$1.flush = flush; +c3_chart_fn$1.destroy = destroy; +c3_chart_fn$1.color = color; +c3_chart_fn$1.data = data; +c3_chart_fn$1.flow = flow; +c3_chart_fn$1.focus = focus; +c3_chart_fn$1.defocus = defocus; +c3_chart_fn$1.revert = revert; +c3_chart_fn$1.xgrids = xgrids; +c3_chart_fn$1.ygrids = ygrids; +c3_chart_fn$1.groups = groups; +c3_chart_fn$1.legend = legend; +c3_chart_fn$1.load = load; +c3_chart_fn$1.unload = unload; +c3_chart_fn$1.regions = regions; +c3_chart_fn$1.selected = selected; +c3_chart_fn$1.select = select; +c3_chart_fn$1.unselect = unselect; +c3_chart_fn$1.show = show; +c3_chart_fn$1.hide = hide; +c3_chart_fn$1.toggle = toggle; +c3_chart_fn$1.tooltip = tooltip; +c3_chart_fn$1.transform = transform; +c3_chart_fn$1.x = x; +c3_chart_fn$1.xs = xs; +c3_chart_fn$1.zoom = zoom; +c3_chart_fn$1.unzoom = unzoom; + /** * C3.js * (c) 2016 Masayuki Tanaka and the C3.js contributors (See package.json) diff --git a/es6_modules/chart.js b/es6_modules/chart.js deleted file mode 100644 index f29f280..0000000 --- a/es6_modules/chart.js +++ /dev/null @@ -1,770 +0,0 @@ -import { CLASS, - isValue, - isUndefined, - isDefined, - ChartInternal, -} from './chartinternal.js'; - -let c3_chart_fn; - - -function Chart(config) { - const $$ = this.internal = new ChartInternal(this); - $$.loadConfig(config); - - $$.beforeInit(config); - $$.init(); - $$.afterInit(config); - - // bind "this" to nested API - (function bindThis(fn, target, argThis) { - Object.keys(fn).forEach((key) => { - target[key] = fn[key].bind(argThis); - if (Object.keys(fn[key]).length > 0) { - bindThis(fn[key], target[key], argThis); - } - }); - })(c3_chart_fn, this, this); -} - -c3_chart_fn = Chart.prototype; - -c3_chart_fn.focus = function (targetIds) { - let $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), - - this.revert(); - this.defocus(); - candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.expandArc(targetIds); - } - $$.toggleFocusLegend(targetIds, true); - - $$.focusedTargetIds = targetIds; - $$.defocusedTargetIds = $$.defocusedTargetIds.filter((id) => { - return targetIds.indexOf(id) < 0; - }); -}; - -c3_chart_fn.defocus = function (targetIds) { - let $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), - - candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); - } - $$.toggleFocusLegend(targetIds, false); - - $$.focusedTargetIds = $$.focusedTargetIds.filter((id) => { - return targetIds.indexOf(id) < 0; - }); - $$.defocusedTargetIds = targetIds; -}; - -c3_chart_fn.revert = function (targetIds) { - let $$ = this.internal, candidates; - - targetIds = $$.mapToTargetIds(targetIds); - candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets - - candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false); - if ($$.hasArcType()) { - $$.unexpandArc(targetIds); - } - if ($$.config.legend_show) { - $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$))); - $$.legend.selectAll($$.selectorLegends(targetIds)) - .filter(function () { - return $$.d3.select(this).classed(CLASS.legendItemFocused); - }) - .classed(CLASS.legendItemFocused, false); - } - - $$.focusedTargetIds = []; - $$.defocusedTargetIds = []; -}; - -c3_chart_fn.show = function (targetIds, options) { - let $$ = this.internal, targets; - - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; - - $$.removeHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - - targets.transition() - .style('opacity', 1, 'important') - .call($$.endall, () => { - targets.style('opacity', null).style('opacity', 1); - }); - - if (options.withLegend) { - $$.showLegend(targetIds); - } - - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); -}; - -c3_chart_fn.hide = function (targetIds, options) { - let $$ = this.internal, targets; - - targetIds = $$.mapToTargetIds(targetIds); - options = options || {}; - - $$.addHiddenTargetIds(targetIds); - targets = $$.svg.selectAll($$.selectorTargets(targetIds)); - - targets.transition() - .style('opacity', 0, 'important') - .call($$.endall, () => { - targets.style('opacity', null).style('opacity', 0); - }); - - if (options.withLegend) { - $$.hideLegend(targetIds); - } - - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); -}; - -c3_chart_fn.toggle = function (targetIds, options) { - let that = this, $$ = this.internal; - $$.mapToTargetIds(targetIds).forEach((targetId) => { - $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options); - }); -}; - -c3_chart_fn.zoom = function (domain) { - const $$ = this.internal; - if (domain) { - if ($$.isTimeSeries()) { - domain = domain.map((x) => { return $$.parseDate(x); }); - } - $$.brush.extent(domain); - $$.redraw({ withUpdateXDomain: true, withY: $$.config.zoom_rescale }); - $$.config.zoom_onzoom.call(this, $$.x.orgDomain()); - } - return $$.brush.extent(); -}; -c3_chart_fn.zoom.enable = function (enabled) { - const $$ = this.internal; - $$.config.zoom_enabled = enabled; - $$.updateAndRedraw(); -}; -c3_chart_fn.unzoom = function () { - const $$ = this.internal; - $$.brush.clear().update(); - $$.redraw({ withUpdateXDomain: true }); -}; - -c3_chart_fn.zoom.max = function (max) { - let $$ = this.internal, config = $$.config, d3 = $$.d3; - if (max === 0 || max) { - config.zoom_x_max = d3.max([$$.orgXDomain[1], max]); - } - else { - return config.zoom_x_max; - } -}; - -c3_chart_fn.zoom.min = function (min) { - let $$ = this.internal, config = $$.config, d3 = $$.d3; - if (min === 0 || min) { - config.zoom_x_min = d3.min([$$.orgXDomain[0], min]); - } - else { - return config.zoom_x_min; - } -}; - -c3_chart_fn.zoom.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { this.domain.max(range.max); } - if (isDefined(range.min)) { this.domain.min(range.min); } - } else { - return { - max: this.domain.max(), - min: this.domain.min(), - }; - } -}; - -c3_chart_fn.load = function (args) { - let $$ = this.internal, config = $$.config; - // update xs if specified - if (args.xs) { - $$.addXs(args.xs); - } - // update names if exists - if ('names' in args) { - c3_chart_fn.data.names.bind(this)(args.names); - } - // update classes if exists - if ('classes' in args) { - Object.keys(args.classes).forEach((id) => { - config.data_classes[id] = args.classes[id]; - }); - } - // update categories if exists - if ('categories' in args && $$.isCategorized()) { - config.axis_x_categories = args.categories; - } - // update axes if exists - if ('axes' in args) { - Object.keys(args.axes).forEach((id) => { - config.data_axes[id] = args.axes[id]; - }); - } - // update colors if exists - if ('colors' in args) { - Object.keys(args.colors).forEach((id) => { - config.data_colors[id] = args.colors[id]; - }); - } - // use cache if exists - if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { - $$.load($$.getCaches(args.cacheIds), args.done); - return; - } - // unload if needed - if ('unload' in args) { - // TODO: do not unload if target will load (included in url/rows/columns) - $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), () => { - $$.loadFromArgs(args); - }); - } else { - $$.loadFromArgs(args); - } -}; - -c3_chart_fn.unload = function (args) { - const $$ = this.internal; - args = args || {}; - if (args instanceof Array) { - args = { ids: args }; - } else if (typeof args === 'string') { - args = { ids: [args] }; - } - $$.unload($$.mapToTargetIds(args.ids), () => { - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); - if (args.done) { args.done(); } - }); -}; - -c3_chart_fn.flow = function (args) { - let $$ = this.internal, - targets, data, notfoundIds = [], - orgDataCount = $$.getMaxDataCount(), - dataCount, domain, baseTarget, baseValue, length = 0, - tail = 0, - diff, to; - - if (args.json) { - data = $$.convertJsonToData(args.json, args.keys); - } else if (args.rows) { - data = $$.convertRowsToData(args.rows); - } else if (args.columns) { - data = $$.convertColumnsToData(args.columns); - } else { - return; - } - targets = $$.convertDataToTargets(data, true); - - // Update/Add data - $$.data.targets.forEach((t) => { - let found = false, - i, j; - for (i = 0; i < targets.length; i++) { - if (t.id === targets[i].id) { - found = true; - - if (t.values[t.values.length - 1]) { - tail = t.values[t.values.length - 1].index + 1; - } - length = targets[i].values.length; - - for (j = 0; j < length; j++) { - targets[i].values[j].index = tail + j; - if (!$$.isTimeSeries()) { - targets[i].values[j].x = tail + j; - } - } - t.values = t.values.concat(targets[i].values); - - targets.splice(i, 1); - break; - } - } - if (!found) { notfoundIds.push(t.id); } - }); - - // Append null for not found targets - $$.data.targets.forEach((t) => { - let i, j; - for (i = 0; i < notfoundIds.length; i++) { - if (t.id === notfoundIds[i]) { - tail = t.values[t.values.length - 1].index + 1; - for (j = 0; j < length; j++) { - t.values.push({ - id: t.id, - index: tail + j, - x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j, - value: null, - }); - } - } - } - }); - - // Generate null values for new target - if ($$.data.targets.length) { - targets.forEach((t) => { - let i, missing = []; - for (i = $$.data.targets[0].values[0].index; i < tail; i++) { - missing.push({ - id: t.id, - index: i, - x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i, - value: null, - }); - } - t.values.forEach((v) => { - v.index += tail; - if (!$$.isTimeSeries()) { - v.x += tail; - } - }); - t.values = missing.concat(t.values); - }); - } - $$.data.targets = $$.data.targets.concat(targets); // add remained - - // check data count because behavior needs to change when it's only one - dataCount = $$.getMaxDataCount(); - baseTarget = $$.data.targets[0]; - baseValue = baseTarget.values[0]; - - // Update length to flow if needed - if (isDefined(args.to)) { - length = 0; - to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to; - baseTarget.values.forEach((v) => { - if (v.x < to) { length++; } - }); - } else if (isDefined(args.length)) { - length = args.length; - } - - // If only one data, update the domain to flow from left edge of the chart - if (!orgDataCount) { - if ($$.isTimeSeries()) { - if (baseTarget.values.length > 1) { - diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x; - } else { - diff = baseValue.x - $$.getXDomain($$.data.targets)[0]; - } - } else { - diff = 1; - } - domain = [baseValue.x - diff, baseValue.x]; - $$.updateXDomain(null, true, true, false, domain); - } else if (orgDataCount === 1) { - if ($$.isTimeSeries()) { - diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2; - domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)]; - $$.updateXDomain(null, true, true, false, domain); - } - } - - // Set targets - $$.updateTargets($$.data.targets); - - // Redraw with new targets - $$.redraw({ - flow: { - index: baseValue.index, - length, - duration: isValue(args.duration) ? args.duration : $$.config.transition_duration, - done: args.done, - orgDataCount, - }, - withLegend: true, - withTransition: orgDataCount > 1, - withTrimXDomain: false, - withUpdateXAxis: true, - }); -}; - -c3_chart_fn.selected = function (targetId) { - let $$ = this.internal, d3 = $$.d3; - return d3.merge( - $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape) - .filter(function () { return d3.select(this).classed(CLASS.SELECTED); }) - .map((d) => { return d.map((d) => { const data = d.__data__; return data.data ? data.data : data; }); }) - ); -}; -c3_chart_fn.select = function (ids, indices, resetOther) { - let $$ = this.internal, d3 = $$.d3, config = $$.config; - if (!config.data_selection_enabled) { return; } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - let shape = d3.select(this), id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d) && !isSelected) { - toggle(true, shape.classed(CLASS.SELECTED, true), d, i); - } - } else if (isDefined(resetOther) && resetOther) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } - }); -}; -c3_chart_fn.unselect = function (ids, indices) { - let $$ = this.internal, d3 = $$.d3, config = $$.config; - if (!config.data_selection_enabled) { return; } - $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { - let shape = d3.select(this), id = d.data ? d.data.id : d.id, - toggle = $$.getToggle(this, d).bind($$), - isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, - isTargetIndex = !indices || indices.indexOf(i) >= 0, - isSelected = shape.classed(CLASS.SELECTED); - // line/area selection not supported yet - if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { - return; - } - if (isTargetId && isTargetIndex) { - if (config.data_selection_isselectable(d)) { - if (isSelected) { - toggle(false, shape.classed(CLASS.SELECTED, false), d, i); - } - } - } - }); -}; - -c3_chart_fn.transform = function (type, targetIds) { - let $$ = this.internal, - options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null; - $$.transformTo(targetIds, type, options); -}; - -c3_chart_fn.groups = function (groups) { - let $$ = this.internal, config = $$.config; - if (isUndefined(groups)) { return config.data_groups; } - config.data_groups = groups; - $$.redraw(); - return config.data_groups; -}; - -c3_chart_fn.xgrids = function (grids) { - let $$ = this.internal, config = $$.config; - if (!grids) { return config.grid_x_lines; } - config.grid_x_lines = grids; - $$.redrawWithoutRescale(); - return config.grid_x_lines; -}; -c3_chart_fn.xgrids.add = function (grids) { - const $$ = this.internal; - return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : [])); -}; -c3_chart_fn.xgrids.remove = function (params) { // TODO: multiple - const $$ = this.internal; - $$.removeGridLines(params, true); -}; - -c3_chart_fn.ygrids = function (grids) { - let $$ = this.internal, config = $$.config; - if (!grids) { return config.grid_y_lines; } - config.grid_y_lines = grids; - $$.redrawWithoutRescale(); - return config.grid_y_lines; -}; -c3_chart_fn.ygrids.add = function (grids) { - const $$ = this.internal; - return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : [])); -}; -c3_chart_fn.ygrids.remove = function (params) { // TODO: multiple - const $$ = this.internal; - $$.removeGridLines(params, false); -}; - -c3_chart_fn.regions = function (regions) { - let $$ = this.internal, config = $$.config; - if (!regions) { return config.regions; } - config.regions = regions; - $$.redrawWithoutRescale(); - return config.regions; -}; -c3_chart_fn.regions.add = function (regions) { - let $$ = this.internal, config = $$.config; - if (!regions) { return config.regions; } - config.regions = config.regions.concat(regions); - $$.redrawWithoutRescale(); - return config.regions; -}; -c3_chart_fn.regions.remove = function (options) { - let $$ = this.internal, config = $$.config, - duration, classes, regions; - - options = options || {}; - duration = $$.getOption(options, 'duration', config.transition_duration); - classes = $$.getOption(options, 'classes', [CLASS.region]); - - regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map((c) => { return '.' + c; })); - (duration ? regions.transition().duration(duration) : regions) - .style('opacity', 0) - .remove(); - - config.regions = config.regions.filter((region) => { - let found = false; - if (!region.class) { - return true; - } - region.class.split(' ').forEach((c) => { - if (classes.indexOf(c) >= 0) { found = true; } - }); - return !found; - }); - - return config.regions; -}; - -c3_chart_fn.data = function (targetIds) { - const targets = this.internal.data.targets; - return typeof targetIds === 'undefined' ? targets : targets.filter((t) => { - return [].concat(targetIds).indexOf(t.id) >= 0; - }); -}; -c3_chart_fn.data.shown = function (targetIds) { - return this.internal.filterTargetsToShow(this.data(targetIds)); -}; -c3_chart_fn.data.values = function (targetId) { - let targets, values = null; - if (targetId) { - targets = this.data(targetId); - values = targets[0] ? targets[0].values.map((d) => { return d.value; }) : null; - } - return values; -}; -c3_chart_fn.data.names = function (names) { - this.internal.clearLegendItemTextBoxCache(); - return this.internal.updateDataAttributes('names', names); -}; -c3_chart_fn.data.colors = function (colors) { - return this.internal.updateDataAttributes('colors', colors); -}; -c3_chart_fn.data.axes = function (axes) { - return this.internal.updateDataAttributes('axes', axes); -}; - -c3_chart_fn.category = function (i, category) { - let $$ = this.internal, config = $$.config; - if (arguments.length > 1) { - config.axis_x_categories[i] = category; - $$.redraw(); - } - return config.axis_x_categories[i]; -}; -c3_chart_fn.categories = function (categories) { - let $$ = this.internal, config = $$.config; - if (!arguments.length) { return config.axis_x_categories; } - config.axis_x_categories = categories; - $$.redraw(); - return config.axis_x_categories; -}; - -// TODO: fix -c3_chart_fn.color = function (id) { - const $$ = this.internal; - return $$.color(id); // more patterns -}; - -c3_chart_fn.x = function (x) { - const $$ = this.internal; - if (arguments.length) { - $$.updateTargetX($$.data.targets, x); - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } - return $$.data.xs; -}; -c3_chart_fn.xs = function (xs) { - const $$ = this.internal; - if (arguments.length) { - $$.updateTargetXs($$.data.targets, xs); - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } - return $$.data.xs; -}; - -c3_chart_fn.axis = function () {}; -c3_chart_fn.axis.labels = function (labels) { - const $$ = this.internal; - if (arguments.length) { - Object.keys(labels).forEach((axisId) => { - $$.axis.setLabelText(axisId, labels[axisId]); - }); - $$.axis.updateLabels(); - } - // TODO: return some values? -}; -c3_chart_fn.axis.max = function (max) { - let $$ = this.internal, config = $$.config; - if (arguments.length) { - if (typeof max === 'object') { - if (isValue(max.x)) { config.axis_x_max = max.x; } - if (isValue(max.y)) { config.axis_y_max = max.y; } - if (isValue(max.y2)) { config.axis_y2_max = max.y2; } - } else { - config.axis_y_max = config.axis_y2_max = max; - } - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } else { - return { - x: config.axis_x_max, - y: config.axis_y_max, - y2: config.axis_y2_max, - }; - } -}; -c3_chart_fn.axis.min = function (min) { - let $$ = this.internal, config = $$.config; - if (arguments.length) { - if (typeof min === 'object') { - if (isValue(min.x)) { config.axis_x_min = min.x; } - if (isValue(min.y)) { config.axis_y_min = min.y; } - if (isValue(min.y2)) { config.axis_y2_min = min.y2; } - } else { - config.axis_y_min = config.axis_y2_min = min; - } - $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); - } else { - return { - x: config.axis_x_min, - y: config.axis_y_min, - y2: config.axis_y2_min, - }; - } -}; -c3_chart_fn.axis.range = function (range) { - if (arguments.length) { - if (isDefined(range.max)) { this.axis.max(range.max); } - if (isDefined(range.min)) { this.axis.min(range.min); } - } else { - return { - max: this.axis.max(), - min: this.axis.min(), - }; - } -}; - -c3_chart_fn.legend = function () {}; -c3_chart_fn.legend.show = function (targetIds) { - const $$ = this.internal; - $$.showLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({ withLegend: true }); -}; -c3_chart_fn.legend.hide = function (targetIds) { - const $$ = this.internal; - $$.hideLegend($$.mapToTargetIds(targetIds)); - $$.updateAndRedraw({ withLegend: true }); -}; - -c3_chart_fn.resize = function (size) { - let $$ = this.internal, config = $$.config; - config.size_width = size ? size.width : null; - config.size_height = size ? size.height : null; - this.flush(); -}; - -c3_chart_fn.flush = function () { - const $$ = this.internal; - $$.updateAndRedraw({ withLegend: true, withTransition: false, withTransitionForTransform: false }); -}; - -c3_chart_fn.destroy = function () { - const $$ = this.internal; - - window.clearInterval($$.intervalForObserveInserted); - - if ($$.resizeTimeout !== undefined) { - window.clearTimeout($$.resizeTimeout); - } - - if (window.detachEvent) { - window.detachEvent('onresize', $$.resizeFunction); - } else if (window.removeEventListener) { - window.removeEventListener('resize', $$.resizeFunction); - } else { - const wrapper = window.onresize; - // check if no one else removed our wrapper and remove our resizeFunction from it - if (wrapper && wrapper.add && wrapper.remove) { - wrapper.remove($$.resizeFunction); - } - } - - $$.selectChart.classed('c3', false).html(''); - - // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen. - Object.keys($$).forEach((key) => { - $$[key] = null; - }); - - return null; -}; - -c3_chart_fn.tooltip = function () {}; -c3_chart_fn.tooltip.show = function (args) { - let $$ = this.internal, index, mouse; - - // determine mouse position on the chart - if (args.mouse) { - mouse = args.mouse; - } - - // determine focus data - if (args.data) { - if ($$.isMultipleX()) { - // if multiple xs, target point will be determined by mouse - mouse = [$$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value)]; - index = null; - } else { - // TODO: when tooltip_grouped = false - index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x); - } - } - else if (typeof args.x !== 'undefined') { - index = $$.getIndexByX(args.x); - } - else if (typeof args.index !== 'undefined') { - index = args.index; - } - - // emulate mouse events to show - $$.dispatchEvent('mouseover', index, mouse); - $$.dispatchEvent('mousemove', index, mouse); - - $$.config.tooltip_onshow.call($$, args.data); -}; -c3_chart_fn.tooltip.hide = function () { - // TODO: get target data by checking the state of focus - this.internal.dispatchEvent('mouseout', 0); - - this.internal.config.tooltip_onhide.call(this); -}; -export { Chart }; -export default Chart; diff --git a/es6_modules/chart/api.axis.js b/es6_modules/chart/api.axis.js new file mode 100644 index 0000000..fd334ce --- /dev/null +++ b/es6_modules/chart/api.axis.js @@ -0,0 +1,81 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const axis = function () {}; +axis.labels = function (labels) { + const $$ = this.internal; + if (arguments.length) { + Object.keys(labels).forEach((axisId) => { + $$.axis.setLabelText(axisId, labels[axisId]); + }); + $$.axis.updateLabels(); + } + // TODO: return some values? +}; +axis.max = function (max) { + let $$ = this.internal, config = $$.config; + if (arguments.length) { + if (typeof max === 'object') { + if (isValue(max.x)) { config.axis_x_max = max.x; } + if (isValue(max.y)) { config.axis_y_max = max.y; } + if (isValue(max.y2)) { config.axis_y2_max = max.y2; } + } else { + config.axis_y_max = config.axis_y2_max = max; + } + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } else { + return { + x: config.axis_x_max, + y: config.axis_y_max, + y2: config.axis_y2_max, + }; + } +}; +axis.min = function (min) { + let $$ = this.internal, config = $$.config; + if (arguments.length) { + if (typeof min === 'object') { + if (isValue(min.x)) { config.axis_x_min = min.x; } + if (isValue(min.y)) { config.axis_y_min = min.y; } + if (isValue(min.y2)) { config.axis_y2_min = min.y2; } + } else { + config.axis_y_min = config.axis_y2_min = min; + } + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } else { + return { + x: config.axis_x_min, + y: config.axis_y_min, + y2: config.axis_y2_min, + }; + } +}; +axis.range = function (range) { + if (arguments.length) { + if (isDefined(range.max)) { this.axis.max(range.max); } + if (isDefined(range.min)) { this.axis.min(range.min); } + } else { + return { + max: this.axis.max(), + min: this.axis.min(), + }; + } +}; + +export { axis }; diff --git a/es6_modules/chart/api.category.js b/es6_modules/chart/api.category.js new file mode 100644 index 0000000..dafeb21 --- /dev/null +++ b/es6_modules/chart/api.category.js @@ -0,0 +1,36 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal, +} from '../chartinternal.js'; + +const category = function (i, category) { + let $$ = this.internal, config = $$.config; + if (arguments.length > 1) { + config.axis_x_categories[i] = category; + $$.redraw(); + } + return config.axis_x_categories[i]; +}; +const categories = function (categories) { + let $$ = this.internal, config = $$.config; + if (!arguments.length) { return config.axis_x_categories; } + config.axis_x_categories = categories; + $$.redraw(); + return config.axis_x_categories; +}; + +export { category, categories }; diff --git a/es6_modules/chart/api.chart.js b/es6_modules/chart/api.chart.js new file mode 100644 index 0000000..81e1ce1 --- /dev/null +++ b/es6_modules/chart/api.chart.js @@ -0,0 +1,64 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const resize = function (size) { + let $$ = this.internal, config = $$.config; + config.size_width = size ? size.width : null; + config.size_height = size ? size.height : null; + this.flush(); +}; + +const flush = function () { + const $$ = this.internal; + $$.updateAndRedraw({ withLegend: true, withTransition: false, withTransitionForTransform: false }); +}; + +const destroy = function () { + const $$ = this.internal; + + window.clearInterval($$.intervalForObserveInserted); + + if ($$.resizeTimeout !== undefined) { + window.clearTimeout($$.resizeTimeout); + } + + if (window.detachEvent) { + window.detachEvent('onresize', $$.resizeFunction); + } else if (window.removeEventListener) { + window.removeEventListener('resize', $$.resizeFunction); + } else { + const wrapper = window.onresize; + // check if no one else removed our wrapper and remove our resizeFunction from it + if (wrapper && wrapper.add && wrapper.remove) { + wrapper.remove($$.resizeFunction); + } + } + + $$.selectChart.classed('c3', false).html(''); + + // MEMO: this is needed because the reference of some elements will not be released, + // then memory leak will happen. + Object.keys($$).forEach((key) => { + $$[key] = null; + }); + + return null; +}; + +export { resize, flush, destroy }; diff --git a/es6_modules/chart/api.color.js b/es6_modules/chart/api.color.js new file mode 100644 index 0000000..6f665e0 --- /dev/null +++ b/es6_modules/chart/api.color.js @@ -0,0 +1,26 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +// TODO: fix +const color = function (id) { + const $$ = this.internal; + return $$.color(id); // more patterns +}; + +export { color }; diff --git a/es6_modules/chart/api.data.js b/es6_modules/chart/api.data.js new file mode 100644 index 0000000..e357ca2 --- /dev/null +++ b/es6_modules/chart/api.data.js @@ -0,0 +1,53 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const data = function (targetIds) { + const targets = this.internal.data.targets; + return typeof targetIds === 'undefined' ? targets : targets.filter((t) => { + return [].concat(targetIds).indexOf(t.id) >= 0; + }); +}; + +data.shown = function (targetIds) { + return this.internal.filterTargetsToShow(this.data(targetIds)); +}; + +data.values = function (targetId) { + let targets, values = null; + if (targetId) { + targets = this.data(targetId); + values = targets[0] ? targets[0].values.map((d) => { return d.value; }) : null; + } + return values; +}; + +data.names = function (names) { + this.internal.clearLegendItemTextBoxCache(); + return this.internal.updateDataAttributes('names', names); +}; + +data.colors = function (colors) { + return this.internal.updateDataAttributes('colors', colors); +}; + +data.axes = function (axes) { + return this.internal.updateDataAttributes('axes', axes); +}; + +export { data }; diff --git a/es6_modules/chart/api.flow.js b/es6_modules/chart/api.flow.js new file mode 100644 index 0000000..aaf73c2 --- /dev/null +++ b/es6_modules/chart/api.flow.js @@ -0,0 +1,164 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const flow = function (args) { + let $$ = this.internal, + targets, data, notfoundIds = [], + orgDataCount = $$.getMaxDataCount(), + dataCount, domain, baseTarget, baseValue, length = 0, + tail = 0, + diff, to; + + if (args.json) { + data = $$.convertJsonToData(args.json, args.keys); + } else if (args.rows) { + data = $$.convertRowsToData(args.rows); + } else if (args.columns) { + data = $$.convertColumnsToData(args.columns); + } else { + return; + } + targets = $$.convertDataToTargets(data, true); + + // Update/Add data + $$.data.targets.forEach((t) => { + let found = false, + i, j; + for (i = 0; i < targets.length; i++) { + if (t.id === targets[i].id) { + found = true; + + if (t.values[t.values.length - 1]) { + tail = t.values[t.values.length - 1].index + 1; + } + length = targets[i].values.length; + + for (j = 0; j < length; j++) { + targets[i].values[j].index = tail + j; + if (!$$.isTimeSeries()) { + targets[i].values[j].x = tail + j; + } + } + t.values = t.values.concat(targets[i].values); + + targets.splice(i, 1); + break; + } + } + if (!found) { notfoundIds.push(t.id); } + }); + + // Append null for not found targets + $$.data.targets.forEach((t) => { + let i, j; + for (i = 0; i < notfoundIds.length; i++) { + if (t.id === notfoundIds[i]) { + tail = t.values[t.values.length - 1].index + 1; + for (j = 0; j < length; j++) { + t.values.push({ + id: t.id, + index: tail + j, + x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j, + value: null, + }); + } + } + } + }); + + // Generate null values for new target + if ($$.data.targets.length) { + targets.forEach((t) => { + let i, missing = []; + for (i = $$.data.targets[0].values[0].index; i < tail; i++) { + missing.push({ + id: t.id, + index: i, + x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i, + value: null, + }); + } + t.values.forEach((v) => { + v.index += tail; + if (!$$.isTimeSeries()) { + v.x += tail; + } + }); + t.values = missing.concat(t.values); + }); + } + $$.data.targets = $$.data.targets.concat(targets); // add remained + + // check data count because behavior needs to change when it's only one + dataCount = $$.getMaxDataCount(); + baseTarget = $$.data.targets[0]; + baseValue = baseTarget.values[0]; + + // Update length to flow if needed + if (isDefined(args.to)) { + length = 0; + to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to; + baseTarget.values.forEach((v) => { + if (v.x < to) { length++; } + }); + } else if (isDefined(args.length)) { + length = args.length; + } + + // If only one data, update the domain to flow from left edge of the chart + if (!orgDataCount) { + if ($$.isTimeSeries()) { + if (baseTarget.values.length > 1) { + diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x; + } else { + diff = baseValue.x - $$.getXDomain($$.data.targets)[0]; + } + } else { + diff = 1; + } + domain = [baseValue.x - diff, baseValue.x]; + $$.updateXDomain(null, true, true, false, domain); + } else if (orgDataCount === 1) { + if ($$.isTimeSeries()) { + diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2; + domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)]; + $$.updateXDomain(null, true, true, false, domain); + } + } + + // Set targets + $$.updateTargets($$.data.targets); + + // Redraw with new targets + $$.redraw({ + flow: { + index: baseValue.index, + length, + duration: isValue(args.duration) ? args.duration : $$.config.transition_duration, + done: args.done, + orgDataCount, + }, + withLegend: true, + withTransition: orgDataCount > 1, + withTrimXDomain: false, + withUpdateXAxis: true, + }); +}; + +export { flow }; diff --git a/es6_modules/chart/api.focus.js b/es6_modules/chart/api.focus.js new file mode 100644 index 0000000..e69852a --- /dev/null +++ b/es6_modules/chart/api.focus.js @@ -0,0 +1,81 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const focus = function (targetIds) { + let $$ = this.internal, candidates; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), + + this.revert(); + this.defocus(); + candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false); + if ($$.hasArcType()) { + $$.expandArc(targetIds); + } + $$.toggleFocusLegend(targetIds, true); + + $$.focusedTargetIds = targetIds; + $$.defocusedTargetIds = $$.defocusedTargetIds.filter((id) => { + return targetIds.indexOf(id) < 0; + }); +}; + +const defocus = function (targetIds) { + let $$ = this.internal, candidates; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), + + candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true); + if ($$.hasArcType()) { + $$.unexpandArc(targetIds); + } + $$.toggleFocusLegend(targetIds, false); + + $$.focusedTargetIds = $$.focusedTargetIds.filter((id) => { + return targetIds.indexOf(id) < 0; + }); + $$.defocusedTargetIds = targetIds; +}; + +const revert = function (targetIds) { + let $$ = this.internal, candidates; + + targetIds = $$.mapToTargetIds(targetIds); + candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets + + candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false); + if ($$.hasArcType()) { + $$.unexpandArc(targetIds); + } + if ($$.config.legend_show) { + $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$))); + $$.legend.selectAll($$.selectorLegends(targetIds)) + .filter(function () { + return $$.d3.select(this).classed(CLASS.legendItemFocused); + }) + .classed(CLASS.legendItemFocused, false); + } + + $$.focusedTargetIds = []; + $$.defocusedTargetIds = []; +}; + +export { focus, defocus, revert }; diff --git a/es6_modules/chart/api.grid.js b/es6_modules/chart/api.grid.js new file mode 100644 index 0000000..f84f25f --- /dev/null +++ b/es6_modules/chart/api.grid.js @@ -0,0 +1,56 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const xgrids = function (grids) { + let $$ = this.internal, config = $$.config; + if (!grids) { return config.grid_x_lines; } + config.grid_x_lines = grids; + $$.redrawWithoutRescale(); + return config.grid_x_lines; +}; + +xgrids.add = function (grids) { + const $$ = this.internal; + return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : [])); +}; + +xgrids.remove = function (params) { // TODO: multiple + const $$ = this.internal; + $$.removeGridLines(params, true); +}; + +const ygrids = function (grids) { + let $$ = this.internal, config = $$.config; + if (!grids) { return config.grid_y_lines; } + config.grid_y_lines = grids; + $$.redrawWithoutRescale(); + return config.grid_y_lines; +}; + +ygrids.add = function (grids) { + const $$ = this.internal; + return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : [])); +}; + +ygrids.remove = function (params) { // TODO: multiple + const $$ = this.internal; + $$.removeGridLines(params, false); +}; + +export { xgrids, ygrids }; diff --git a/es6_modules/chart/api.group.js b/es6_modules/chart/api.group.js new file mode 100644 index 0000000..3045483 --- /dev/null +++ b/es6_modules/chart/api.group.js @@ -0,0 +1,28 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const groups = function (groups) { + let $$ = this.internal, config = $$.config; + if (isUndefined(groups)) { return config.data_groups; } + config.data_groups = groups; + $$.redraw(); + return config.data_groups; +}; + +export { groups }; diff --git a/es6_modules/chart/api.legend.js b/es6_modules/chart/api.legend.js new file mode 100644 index 0000000..8c57761 --- /dev/null +++ b/es6_modules/chart/api.legend.js @@ -0,0 +1,34 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const legend = function () {}; + +legend.show = function (targetIds) { + const $$ = this.internal; + $$.showLegend($$.mapToTargetIds(targetIds)); + $$.updateAndRedraw({ withLegend: true }); +}; + +legend.hide = function (targetIds) { + const $$ = this.internal; + $$.hideLegend($$.mapToTargetIds(targetIds)); + $$.updateAndRedraw({ withLegend: true }); +}; + +export { legend }; diff --git a/es6_modules/chart/api.load.js b/es6_modules/chart/api.load.js new file mode 100644 index 0000000..560e50c --- /dev/null +++ b/es6_modules/chart/api.load.js @@ -0,0 +1,82 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const load = function (args) { + let $$ = this.internal, config = $$.config; + // update xs if specified + if (args.xs) { + $$.addXs(args.xs); + } + // update names if exists + if ('names' in args) { + c3_chart_fn.data.names.bind(this)(args.names); + } + // update classes if exists + if ('classes' in args) { + Object.keys(args.classes).forEach((id) => { + config.data_classes[id] = args.classes[id]; + }); + } + // update categories if exists + if ('categories' in args && $$.isCategorized()) { + config.axis_x_categories = args.categories; + } + // update axes if exists + if ('axes' in args) { + Object.keys(args.axes).forEach((id) => { + config.data_axes[id] = args.axes[id]; + }); + } + // update colors if exists + if ('colors' in args) { + Object.keys(args.colors).forEach((id) => { + config.data_colors[id] = args.colors[id]; + }); + } + // use cache if exists + if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) { + $$.load($$.getCaches(args.cacheIds), args.done); + return; + } + // unload if needed + if ('unload' in args) { + // TODO: do not unload if target will load (included in url/rows/columns) + $$.unload($$.mapToTargetIds((typeof args.unload === 'boolean' && args.unload) ? null : args.unload), () => { + $$.loadFromArgs(args); + }); + } else { + $$.loadFromArgs(args); + } +}; + +const unload = function (args) { + const $$ = this.internal; + args = args || {}; + if (args instanceof Array) { + args = { ids: args }; + } else if (typeof args === 'string') { + args = { ids: [args] }; + } + $$.unload($$.mapToTargetIds(args.ids), () => { + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); + if (args.done) { args.done(); } + }); +}; + +export { load, unload }; diff --git a/es6_modules/chart/api.region.js b/es6_modules/chart/api.region.js new file mode 100644 index 0000000..b921d43 --- /dev/null +++ b/es6_modules/chart/api.region.js @@ -0,0 +1,63 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const regions = function (regions) { + let $$ = this.internal, config = $$.config; + if (!regions) { return config.regions; } + config.regions = regions; + $$.redrawWithoutRescale(); + return config.regions; +}; + +regions.add = function (regions) { + let $$ = this.internal, config = $$.config; + if (!regions) { return config.regions; } + config.regions = config.regions.concat(regions); + $$.redrawWithoutRescale(); + return config.regions; +}; + +regions.remove = function (options) { + let $$ = this.internal, config = $$.config, + duration, classes, regions; + + options = options || {}; + duration = $$.getOption(options, 'duration', config.transition_duration); + classes = $$.getOption(options, 'classes', [CLASS.region]); + + regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map((c) => { return '.' + c; })); + (duration ? regions.transition().duration(duration) : regions) + .style('opacity', 0) + .remove(); + + config.regions = config.regions.filter((region) => { + let found = false; + if (!region.class) { + return true; + } + region.class.split(' ').forEach((c) => { + if (classes.indexOf(c) >= 0) { found = true; } + }); + return !found; + }); + + return config.regions; +}; + +export { regions }; diff --git a/es6_modules/chart/api.selection.js b/es6_modules/chart/api.selection.js new file mode 100644 index 0000000..cfb6954 --- /dev/null +++ b/es6_modules/chart/api.selection.js @@ -0,0 +1,77 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const selected = function (targetId) { + let $$ = this.internal, d3 = $$.d3; + return d3.merge( + $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape) + .filter(function () { return d3.select(this).classed(CLASS.SELECTED); }) + .map((d) => { return d.map((d) => { const data = d.__data__; return data.data ? data.data : data; }); }) + ); +}; + +const select = function (ids, indices, resetOther) { + let $$ = this.internal, d3 = $$.d3, config = $$.config; + if (!config.data_selection_enabled) { return; } + $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { + let shape = d3.select(this), id = d.data ? d.data.id : d.id, + toggle = $$.getToggle(this, d).bind($$), + isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, + isTargetIndex = !indices || indices.indexOf(i) >= 0, + isSelected = shape.classed(CLASS.SELECTED); + // line/area selection not supported yet + if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { + return; + } + if (isTargetId && isTargetIndex) { + if (config.data_selection_isselectable(d) && !isSelected) { + toggle(true, shape.classed(CLASS.SELECTED, true), d, i); + } + } else if (isDefined(resetOther) && resetOther) { + if (isSelected) { + toggle(false, shape.classed(CLASS.SELECTED, false), d, i); + } + } + }); +}; + +const unselect = function (ids, indices) { + let $$ = this.internal, d3 = $$.d3, config = $$.config; + if (!config.data_selection_enabled) { return; } + $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) { + let shape = d3.select(this), id = d.data ? d.data.id : d.id, + toggle = $$.getToggle(this, d).bind($$), + isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, + isTargetIndex = !indices || indices.indexOf(i) >= 0, + isSelected = shape.classed(CLASS.SELECTED); + // line/area selection not supported yet + if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) { + return; + } + if (isTargetId && isTargetIndex) { + if (config.data_selection_isselectable(d)) { + if (isSelected) { + toggle(false, shape.classed(CLASS.SELECTED, false), d, i); + } + } + } + }); +}; + +export { selected, select, unselect }; diff --git a/es6_modules/chart/api.show.js b/es6_modules/chart/api.show.js new file mode 100644 index 0000000..5b533db --- /dev/null +++ b/es6_modules/chart/api.show.js @@ -0,0 +1,71 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const show = function (targetIds, options) { + let $$ = this.internal, targets; + + targetIds = $$.mapToTargetIds(targetIds); + options = options || {}; + + $$.removeHiddenTargetIds(targetIds); + targets = $$.svg.selectAll($$.selectorTargets(targetIds)); + + targets.transition() + .style('opacity', 1, 'important') + .call($$.endall, () => { + targets.style('opacity', null).style('opacity', 1); + }); + + if (options.withLegend) { + $$.showLegend(targetIds); + } + + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); +}; + +const hide = function (targetIds, options) { + let $$ = this.internal, targets; + + targetIds = $$.mapToTargetIds(targetIds); + options = options || {}; + + $$.addHiddenTargetIds(targetIds); + targets = $$.svg.selectAll($$.selectorTargets(targetIds)); + + targets.transition() + .style('opacity', 0, 'important') + .call($$.endall, () => { + targets.style('opacity', null).style('opacity', 0); + }); + + if (options.withLegend) { + $$.hideLegend(targetIds); + } + + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true }); +}; + +const toggle = function (targetIds, options) { + let that = this, $$ = this.internal; + $$.mapToTargetIds(targetIds).forEach((targetId) => { + $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options); + }); +}; + +export { show, hide, toggle }; diff --git a/es6_modules/chart/api.tooltip.js b/es6_modules/chart/api.tooltip.js new file mode 100644 index 0000000..2397bd9 --- /dev/null +++ b/es6_modules/chart/api.tooltip.js @@ -0,0 +1,60 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const tooltip = function () {}; + +tooltip.show = function (args) { + let $$ = this.internal, index, mouse; + + // determine mouse position on the chart + if (args.mouse) { + mouse = args.mouse; + } + + // determine focus data + if (args.data) { + if ($$.isMultipleX()) { + // if multiple xs, target point will be determined by mouse + mouse = [$$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value)]; + index = null; + } else { + // TODO: when tooltip_grouped = false + index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x); + } + } else if (typeof args.x !== 'undefined') { + index = $$.getIndexByX(args.x); + } else if (typeof args.index !== 'undefined') { + index = args.index; + } + + // emulate mouse events to show + $$.dispatchEvent('mouseover', index, mouse); + $$.dispatchEvent('mousemove', index, mouse); + + $$.config.tooltip_onshow.call($$, args.data); +}; + +tooltip.hide = function () { + // TODO: get target data by checking the state of focus + this.internal.dispatchEvent('mouseout', 0); + + this.internal.config.tooltip_onhide.call(this); +}; + +export { tooltip }; diff --git a/es6_modules/chart/api.transform.js b/es6_modules/chart/api.transform.js new file mode 100644 index 0000000..ca3ffd0 --- /dev/null +++ b/es6_modules/chart/api.transform.js @@ -0,0 +1,26 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const transform = function (type, targetIds) { + let $$ = this.internal, + options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null; + $$.transformTo(targetIds, type, options); +}; + +export { transform }; diff --git a/es6_modules/chart/api.x.js b/es6_modules/chart/api.x.js new file mode 100644 index 0000000..cb1a2a1 --- /dev/null +++ b/es6_modules/chart/api.x.js @@ -0,0 +1,38 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const x = function (x) { + const $$ = this.internal; + if (arguments.length) { + $$.updateTargetX($$.data.targets, x); + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } + return $$.data.xs; +}; + +const xs = function (xs) { + const $$ = this.internal; + if (arguments.length) { + $$.updateTargetXs($$.data.targets, xs); + $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true }); + } + return $$.data.xs; +}; + +export { x, xs }; diff --git a/es6_modules/chart/api.zoom.js b/es6_modules/chart/api.zoom.js new file mode 100644 index 0000000..570857d --- /dev/null +++ b/es6_modules/chart/api.zoom.js @@ -0,0 +1,77 @@ +import { + CLASS, + isValue, + isFunction, + isString, + isUndefined, + isDefined, + ceil10, + asHalfPixel, + diffDomain, + isEmpty, + notEmpty, + getOption, + hasValue, + sanitise, + getPathBox, + ChartInternal +} from '../chartinternal.js'; + +const zoom = function (domain) { + const $$ = this.internal; + if (domain) { + if ($$.isTimeSeries()) { + domain = domain.map((x) => { return $$.parseDate(x); }); + } + $$.brush.extent(domain); + $$.redraw({ withUpdateXDomain: true, withY: $$.config.zoom_rescale }); + $$.config.zoom_onzoom.call(this, $$.x.orgDomain()); + } + return $$.brush.extent(); +}; + +const unzoom = function () { + const $$ = this.internal; + $$.brush.clear().update(); + $$.redraw({ withUpdateXDomain: true }); +}; + +zoom.enable = function (enabled) { + const $$ = this.internal; + $$.config.zoom_enabled = enabled; + $$.updateAndRedraw(); +}; + +zoom.max = function (max) { + let $$ = this.internal, config = $$.config, d3 = $$.d3; + if (max === 0 || max) { + config.zoom_x_max = d3.max([$$.orgXDomain[1], max]); + } + else { + return config.zoom_x_max; + } +}; + +zoom.min = function (min) { + let $$ = this.internal, config = $$.config, d3 = $$.d3; + if (min === 0 || min) { + config.zoom_x_min = d3.min([$$.orgXDomain[0], min]); + } + else { + return config.zoom_x_min; + } +}; + +zoom.range = function (range) { + if (arguments.length) { + if (isDefined(range.max)) { this.domain.max(range.max); } + if (isDefined(range.min)) { this.domain.min(range.min); } + } else { + return { + max: this.domain.max(), + min: this.domain.min(), + }; + } +}; + +export { zoom, unzoom }; diff --git a/es6_modules/chart/index.js b/es6_modules/chart/index.js new file mode 100644 index 0000000..d05e122 --- /dev/null +++ b/es6_modules/chart/index.js @@ -0,0 +1,77 @@ +import { ChartInternal } from '../chartinternal.js'; + +import { axis } from './api.axis'; +import { category, categories } from './api.category'; +import { resize, flush, destroy } from './api.chart'; +import { color } from './api.color'; +import { data } from './api.data'; +import { flow } from './api.flow'; +import { focus, defocus, revert } from './api.focus'; +import { xgrids, ygrids } from './api.grid'; +import { groups } from './api.group'; +import { legend } from './api.legend'; +import { load, unload } from './api.load'; +import { regions } from './api.region'; +import { selected, select, unselect } from './api.selection'; +import { show, hide, toggle } from './api.show'; +import { tooltip } from './api.tooltip'; +import { transform } from './api.transform'; +import { x, xs } from './api.x'; +import { zoom, unzoom } from './api.zoom'; + +let c3_chart_fn; + +function Chart(config) { + const $$ = this.internal = new ChartInternal(this); + $$.loadConfig(config); + + $$.beforeInit(config); + $$.init(); + $$.afterInit(config); + + // bind "this" to nested API + (function bindThis(fn, target, argThis) { + Object.keys(fn).forEach((key) => { + target[key] = fn[key].bind(argThis); + if (Object.keys(fn[key]).length > 0) { + bindThis(fn[key], target[key], argThis); + } + }); + })(c3_chart_fn, this, this); +} + +c3_chart_fn = Chart.prototype; + +c3_chart_fn.axis = axis; +c3_chart_fn.category = category; +c3_chart_fn.categories = categories; +c3_chart_fn.resize = resize; +c3_chart_fn.flush = flush; +c3_chart_fn.destroy = destroy; +c3_chart_fn.color = color; +c3_chart_fn.data = data; +c3_chart_fn.flow = flow; +c3_chart_fn.focus = focus; +c3_chart_fn.defocus = defocus; +c3_chart_fn.revert = revert; +c3_chart_fn.xgrids = xgrids; +c3_chart_fn.ygrids = ygrids; +c3_chart_fn.groups = groups; +c3_chart_fn.legend = legend; +c3_chart_fn.load = load; +c3_chart_fn.unload = unload; +c3_chart_fn.regions = regions; +c3_chart_fn.selected = selected; +c3_chart_fn.select = select; +c3_chart_fn.unselect = unselect; +c3_chart_fn.show = show; +c3_chart_fn.hide = hide; +c3_chart_fn.toggle = toggle; +c3_chart_fn.tooltip = tooltip; +c3_chart_fn.transform = transform; +c3_chart_fn.x = x; +c3_chart_fn.xs = xs; +c3_chart_fn.zoom = zoom; +c3_chart_fn.unzoom = unzoom; + +export { Chart }; diff --git a/es6_modules/rollup.entry.js b/es6_modules/rollup.entry.js index a19db85..9c10b52 100644 --- a/es6_modules/rollup.entry.js +++ b/es6_modules/rollup.entry.js @@ -5,7 +5,7 @@ */ import { ChartInternal } from './chartinternal.js'; -import { Chart } from './chart.js'; +import { Chart } from './chart/index'; import { Axis } from './axis/index';