From 4d28aed20a44ec31a36381ed214c8b310293c6fa Mon Sep 17 00:00:00 2001 From: Jakob Lublin Date: Fri, 29 Jun 2018 14:39:43 +0200 Subject: [PATCH 1/6] Version groupstack --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index deb093d28..3a3b07260 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dc", - "version": "3.0.4", + "version": "3.0.4-groupstack", "license": "Apache-2.0", "copyright": "2017", "description": "A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js ", From 2165711e01e1d1752c4b7c5b3d6983ca21f78766 Mon Sep 17 00:00:00 2001 From: Flavio Date: Tue, 12 Dec 2017 09:19:07 +0000 Subject: [PATCH 2/6] Grouped and Staked Bars (cherry picked from commit bd883a9c29c91708aad630b5244db486964a9fba) --- src/bar-chart.js | 163 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 49 deletions(-) diff --git a/src/bar-chart.js b/src/bar-chart.js index 03d1581d6..8ee566546 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -27,16 +27,21 @@ dc.barChart = function (parent, chartGroup) { var MIN_BAR_WIDTH = 1; var DEFAULT_GAP_BETWEEN_BARS = 2; + var DEFAULT_GAP_BETWEEN_BAR_SERIES = 5; var LABEL_PADDING = 3; + var _type = "dc.BAR_CHART"; var _chart = dc.stackMixin(dc.coordinateGridMixin({})); var _gap = DEFAULT_GAP_BETWEEN_BARS; + var _serieGap = DEFAULT_GAP_BETWEEN_BAR_SERIES; var _centerBar = false; var _alwaysUseRounding = false; var _barWidth; + + _chart.type = _type; dc.override(_chart, 'rescale', function () { _chart._rescale(); _barWidth = undefined; @@ -46,7 +51,7 @@ dc.barChart = function (parent, chartGroup) { dc.override(_chart, 'render', function () { if (_chart.round() && _centerBar && !_alwaysUseRounding) { dc.logger.warn('By default, brush rounding is disabled if bars are centered. ' + - 'See dc.js bar chart API documentation for details.'); + 'See dc.js bar chart API documentation for details.'); } return _chart._render(); @@ -82,32 +87,24 @@ dc.barChart = function (parent, chartGroup) { }); }; - function barHeight (d) { + function barHeight(d) { return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0))); } - function labelXPos (d) { - var x = _chart.x()(d.x); - if (!_centerBar) { - x += _barWidth / 2; - } - if (_chart.isOrdinal() && _gap !== undefined) { - x += _gap / 2; - } - return dc.utils.safeNumber(x); - } - - function labelYPos (d) { - var y = _chart.y()(d.y + d.y0); - if (d.y < 0) { - y -= barHeight(d); + function getCharts() { + if (parent instanceof Object) { + if (parent.children() instanceof Array) { + return parent.children().filter(function (chart) { + return chart.type === _type; + }); + } } + return []; - return dc.utils.safeNumber(y - LABEL_PADDING); } - function renderLabels (layer, layerIndex, d) { + function renderLabels(layer, layerIndex, d) { var labels = layer.selectAll('text.barLabel') .data(d.values, dc.pluck('x')); @@ -125,9 +122,34 @@ dc.barChart = function (parent, chartGroup) { labelsEnterUpdate.attr('cursor', 'pointer'); } - dc.transition(labelsEnterUpdate, _chart.transitionDuration(), _chart.transitionDelay()) - .attr('x', labelXPos) - .attr('y', labelYPos) + dc.transition(labels, _chart.transitionDuration(), _chart.transitionDelay()) + .attr('x', function (d) { + var x = _chart.x()(d.x); + var charts = getCharts(); + if (charts.length > 1) { + x += _chart.serieGap() / 2; + x += layerIndex * (_barWidth + _gap); + x += _gap / 2; + } + x += _barWidth / 2; + if (_centerBar && !_chart.isOrdinal()) { + if (charts.length > 1) { + x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; + } else { + x -= _barWidth / 2; + } + } + return dc.utils.safeNumber(x); + }) + .attr('y', function (d) { + var y = _chart.y()(d.y + d.y0); + + if (d.y < 0) { + y -= barHeight(d); + } + + return dc.utils.safeNumber(y - LABEL_PADDING); + }) .text(function (d) { return _chart.label()(d); }); @@ -137,18 +159,7 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function barXPos (d) { - var x = _chart.x()(d.x); - if (_centerBar) { - x -= _barWidth / 2; - } - if (_chart.isOrdinal() && _gap !== undefined) { - x += _gap / 2; - } - return dc.utils.safeNumber(x); - } - - function renderBars (layer, layerIndex, d) { + function renderBars(layer, layerIndex, d) { var bars = layer.selectAll('rect.bar') .data(d.values, dc.pluck('x')); @@ -170,8 +181,28 @@ dc.barChart = function (parent, chartGroup) { barsEnterUpdate.on('click', _chart.onClick); } - dc.transition(barsEnterUpdate, _chart.transitionDuration(), _chart.transitionDelay()) - .attr('x', barXPos) + dc.transition(bars, _chart.transitionDuration(), _chart.transitionDelay()) + .attr('x', function (d) { + var x = _chart.x()(d.x); + var charts = getCharts(); + var chartIndex = charts.indexOf(_chart); + if (charts.length > 1) { + x += _chart.serieGap() / 2; + x += chartIndex * (_barWidth + _gap); + x += _gap / 2; + } + if (_centerBar && !_chart.isOrdinal()) { + if (charts.length > 1) { + x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; + } else { + x -= _barWidth / 2; + } + } + if (_chart.isOrdinal() && _gap !== undefined) { + x += _gap / 2; + } + return dc.utils.safeNumber(x); + }) .attr('y', function (d) { var y = _chart.y()(d.y + d.y0); @@ -194,19 +225,31 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function calculateBarWidth () { + function calculateBarWidth() { if (_barWidth === undefined) { var numberOfBars = _chart.xUnitCount(); - - // please can't we always use rangeBands for bar charts? - if (_chart.isOrdinal() && _gap === undefined) { - _barWidth = Math.floor(_chart.x().bandwidth()); - } else if (_gap) { - _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); + var charts = getCharts(); + if (charts.length > 1) { + var numberOfCharts = charts.length; + if (_chart.isOrdinal()) { + _barWidth = Math.floor((_chart.x().rangeBand() - _chart.serieGap()) / numberOfCharts - _gap); + } else { + _barWidth = Math.floor((_chart.xAxisLength() - (_chart.xUnitCount() - 1) * _chart.serieGap() - + (numberOfBars - 1) * (numberOfCharts) * _gap) / (numberOfBars * numberOfCharts)); + } } else { - _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); + // please can't we always use rangeBands for bar charts? + if (_chart.isOrdinal() && _gap === undefined) { + _barWidth = Math.floor(_chart.x().rangeBand()); + } else if (_gap) { + _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); + } else { + _barWidth = Math.floor(_chart.xAxisLength() / (1 + _chart.barPadding()) / numberOfBars); + } } + + if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) { _barWidth = MIN_BAR_WIDTH; } @@ -315,10 +358,32 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; - _chart.extendBrush = function (brushSelection) { - if (brushSelection && _chart.round() && (!_centerBar || _alwaysUseRounding)) { - brushSelection[0] = _chart.round()(brushSelection[0]); - brushSelection[1] = _chart.round()(brushSelection[1]); + /** + * Manually set fixed gap (in px) between bar groups instead of relying on the default auto-generated + * gap. Only applicable for grouped bar charts. + * @name serieGap + * @memberof dc.barChart + * @instance + * @param {Number} [serieGap=5] + * @return {Number} + * @return {dc.barChart} + */ + _chart.serieGap = function (serieGap) { + if (!arguments.length) { + return _serieGap; + } + _serieGap = serieGap; + return _chart; + }; + + _chart.extendBrush = function () { + var extent = _chart.brush().extent(); + if (_chart.round() && (!_centerBar || _alwaysUseRounding)) { + extent[0] = extent.map(_chart.round())[0]; + extent[1] = extent.map(_chart.round())[1]; + + _chart.chartBodyG().select('.brush') + .call(_chart.brush().extent(extent)); } return brushSelection; }; @@ -346,7 +411,7 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; - function colorFilter (color, inv) { + function colorFilter(color, inv) { return function () { var item = d3.select(this); var match = item.attr('fill') === color; From 2b369458f3cb0ef2176bd31b8cd3416960ec2d07 Mon Sep 17 00:00:00 2001 From: Flavio Date: Wed, 13 Dec 2017 09:44:46 +0000 Subject: [PATCH 3/6] Change validation of parent in bar chart (cherry picked from commit 27214a4bbe368ca51491200fb5c59c6794a5784d) --- src/bar-chart.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bar-chart.js b/src/bar-chart.js index 8ee566546..2ca5e1e9a 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -42,6 +42,7 @@ dc.barChart = function (parent, chartGroup) { _chart.type = _type; + dc.override(_chart, 'rescale', function () { _chart._rescale(); _barWidth = undefined; @@ -93,9 +94,10 @@ dc.barChart = function (parent, chartGroup) { function getCharts() { - if (parent instanceof Object) { - if (parent.children() instanceof Array) { - return parent.children().filter(function (chart) { + if (dc.instanceOfChart(parent) && typeof parent.children === 'function') { + var children = parent.children(); + if (children instanceof Array) { + return children.filter(function (chart) { return chart.type === _type; }); } From c3a8f91e0d77e19ad8707f291b553a93d1245255 Mon Sep 17 00:00:00 2001 From: Jakob Lublin Date: Fri, 29 Jun 2018 17:46:59 +0200 Subject: [PATCH 4/6] Updated bar-chart.js to work with version 3 and added example --- src/bar-chart.js | 237 ++++++++++++++++++++-------------- web/examples/bar-grouped.html | 105 +++++++++++++++ 2 files changed, 242 insertions(+), 100 deletions(-) create mode 100644 web/examples/bar-grouped.html diff --git a/src/bar-chart.js b/src/bar-chart.js index 2ca5e1e9a..880c10b3a 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -29,7 +29,7 @@ dc.barChart = function (parent, chartGroup) { var DEFAULT_GAP_BETWEEN_BARS = 2; var DEFAULT_GAP_BETWEEN_BAR_SERIES = 5; var LABEL_PADDING = 3; - var _type = "dc.BAR_CHART"; + var _type = 'dc.BAR_CHART'; var _chart = dc.stackMixin(dc.coordinateGridMixin({})); @@ -40,9 +40,8 @@ dc.barChart = function (parent, chartGroup) { var _barWidth; - _chart.type = _type; - + dc.override(_chart, 'rescale', function () { _chart._rescale(); _barWidth = undefined; @@ -88,12 +87,11 @@ dc.barChart = function (parent, chartGroup) { }); }; - function barHeight(d) { + function barHeight (d) { return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0))); } - - function getCharts() { + function getCharts () { if (dc.instanceOfChart(parent) && typeof parent.children === 'function') { var children = parent.children(); if (children instanceof Array) { @@ -103,10 +101,30 @@ dc.barChart = function (parent, chartGroup) { } } return []; + } + + function labelXPos (d) { + var x = _chart.x()(d.x); + if (!_centerBar) { + x += _barWidth / 2; + } + if (_chart.isOrdinal() && _gap !== undefined) { + x += _gap / 2; + } + return dc.utils.safeNumber(x); + } + function labelYPos (d) { + var y = _chart.y()(d.y + d.y0); + + if (d.y < 0) { + y -= barHeight(d); + } + + return dc.utils.safeNumber(y - LABEL_PADDING); } - function renderLabels(layer, layerIndex, d) { + function renderLabels (layer, layerIndex, d) { var labels = layer.selectAll('text.barLabel') .data(d.values, dc.pluck('x')); @@ -124,34 +142,9 @@ dc.barChart = function (parent, chartGroup) { labelsEnterUpdate.attr('cursor', 'pointer'); } - dc.transition(labels, _chart.transitionDuration(), _chart.transitionDelay()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - var charts = getCharts(); - if (charts.length > 1) { - x += _chart.serieGap() / 2; - x += layerIndex * (_barWidth + _gap); - x += _gap / 2; - } - x += _barWidth / 2; - if (_centerBar && !_chart.isOrdinal()) { - if (charts.length > 1) { - x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; - } else { - x -= _barWidth / 2; - } - } - return dc.utils.safeNumber(x); - }) - .attr('y', function (d) { - var y = _chart.y()(d.y + d.y0); - - if (d.y < 0) { - y -= barHeight(d); - } - - return dc.utils.safeNumber(y - LABEL_PADDING); - }) + dc.transition(labelsEnterUpdate, _chart.transitionDuration(), _chart.transitionDelay()) + .attr('x', labelXPos) + .attr('y', labelYPos) .text(function (d) { return _chart.label()(d); }); @@ -161,7 +154,38 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function renderBars(layer, layerIndex, d) { + function barXPos (d) { + var x = _chart.x()(d.x); + var charts = getCharts(); + var chartIndex = charts.indexOf(_chart); + // A grouped chart + if (charts.length > 1) { + if (_gap !== undefined) { + x += _chart.serieGap() / 2; + x += chartIndex * (_barWidth + _gap); + x += _gap / 2; + } else { + var numberOfCharts = charts.length; + var barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); + var barPadding = barWidth * (_chart.barPadding()); + + x += _chart.serieGap() / 2; + x += barPadding / 2; + x += chartIndex * (_barWidth + barPadding); + } + // Not a grouped chart + } else { + if (_centerBar) { + x -= _barWidth / 2; + } + if (_chart.isOrdinal() && _gap !== undefined) { + x += _gap / 2; + } + } + return dc.utils.safeNumber(x); + } + + function renderBars (layer, layerIndex, d) { var bars = layer.selectAll('rect.bar') .data(d.values, dc.pluck('x')); @@ -183,28 +207,8 @@ dc.barChart = function (parent, chartGroup) { barsEnterUpdate.on('click', _chart.onClick); } - dc.transition(bars, _chart.transitionDuration(), _chart.transitionDelay()) - .attr('x', function (d) { - var x = _chart.x()(d.x); - var charts = getCharts(); - var chartIndex = charts.indexOf(_chart); - if (charts.length > 1) { - x += _chart.serieGap() / 2; - x += chartIndex * (_barWidth + _gap); - x += _gap / 2; - } - if (_centerBar && !_chart.isOrdinal()) { - if (charts.length > 1) { - x -= ((_barWidth + _gap) * charts.length + _chart.serieGap()) / 2; - } else { - x -= _barWidth / 2; - } - } - if (_chart.isOrdinal() && _gap !== undefined) { - x += _gap / 2; - } - return dc.utils.safeNumber(x); - }) + dc.transition(barsEnterUpdate, _chart.transitionDuration(), _chart.transitionDelay()) + .attr('x', barXPos) .attr('y', function (d) { var y = _chart.y()(d.y + d.y0); @@ -227,22 +231,26 @@ dc.barChart = function (parent, chartGroup) { .remove(); } - function calculateBarWidth() { + function calculateBarWidth () { if (_barWidth === undefined) { var numberOfBars = _chart.xUnitCount(); var charts = getCharts(); + + // A grouped chart if (charts.length > 1) { var numberOfCharts = charts.length; - if (_chart.isOrdinal()) { - _barWidth = Math.floor((_chart.x().rangeBand() - _chart.serieGap()) / numberOfCharts - _gap); + var barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); + if (_gap !== undefined) { + _barWidth = Math.floor(barWidth - _gap); } else { - _barWidth = Math.floor((_chart.xAxisLength() - (_chart.xUnitCount() - 1) * _chart.serieGap() - - (numberOfBars - 1) * (numberOfCharts) * _gap) / (numberOfBars * numberOfCharts)); + var barPadding = barWidth * (_chart.barPadding()); + _barWidth = Math.floor(barWidth - barPadding); } + // Not a grouped chart } else { // please can't we always use rangeBands for bar charts? if (_chart.isOrdinal() && _gap === undefined) { - _barWidth = Math.floor(_chart.x().rangeBand()); + _barWidth = Math.floor(_chart.x().bandwidth()); } else if (_gap) { _barWidth = Math.floor((_chart.xAxisLength() - (numberOfBars - 1) * _gap) / numberOfBars); } else { @@ -250,8 +258,6 @@ dc.barChart = function (parent, chartGroup) { } } - - if (_barWidth === Infinity || isNaN(_barWidth) || _barWidth < MIN_BAR_WIDTH) { _barWidth = MIN_BAR_WIDTH; } @@ -259,30 +265,54 @@ dc.barChart = function (parent, chartGroup) { } _chart.fadeDeselectedArea = function (brushSelection) { - var bars = _chart.chartBodyG().selectAll('rect.bar'); - - if (_chart.isOrdinal()) { - if (_chart.hasFilter()) { - bars.classed(dc.constants.SELECTED_CLASS, function (d) { - return _chart.hasFilter(d.x); - }); - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return !_chart.hasFilter(d.x); - }); - } else { - bars.classed(dc.constants.SELECTED_CLASS, false); - bars.classed(dc.constants.DESELECTED_CLASS, false); - } - } else if (_chart.brushOn() || _chart.parentBrushOn()) { - if (!_chart.brushIsEmpty(brushSelection)) { - var start = brushSelection[0]; - var end = brushSelection[1]; - - bars.classed(dc.constants.DESELECTED_CLASS, function (d) { - return d.x < start || d.x >= end; - }); - } else { - bars.classed(dc.constants.DESELECTED_CLASS, false); + var charts = getCharts(); + var bars; + + // A grouped chart + if (charts.length > 1 && _chart.isOrdinal()) { + charts.forEach(function (chart, i) { + bars = chart.chartBodyG().selectAll('rect.bar'); + + if (chart.isOrdinal()) { + if (chart.hasFilter()) { + bars.classed(dc.constants.SELECTED_CLASS, function (d) { + return chart.hasFilter(d.x); + }); + bars.classed(dc.constants.DESELECTED_CLASS, function (d) { + return !chart.hasFilter(d.x); + }); + } else { + bars.classed(dc.constants.SELECTED_CLASS, false); + bars.classed(dc.constants.DESELECTED_CLASS, false); + } + } + }); + // Not a grouped chart + } else { + bars = _chart.chartBodyG().selectAll('rect.bar'); + if (_chart.isOrdinal()) { + if (_chart.hasFilter()) { + bars.classed(dc.constants.SELECTED_CLASS, function (d) { + return _chart.hasFilter(d.x); + }); + bars.classed(dc.constants.DESELECTED_CLASS, function (d) { + return !_chart.hasFilter(d.x); + }); + } else { + bars.classed(dc.constants.SELECTED_CLASS, false); + bars.classed(dc.constants.DESELECTED_CLASS, false); + } + } else if (_chart.brushOn() || _chart.parentBrushOn()) { + if (!_chart.brushIsEmpty(brushSelection)) { + var start = brushSelection[0]; + var end = brushSelection[1]; + + bars.classed(dc.constants.DESELECTED_CLASS, function (d) { + return d.x < start || d.x >= end; + }); + } else { + bars.classed(dc.constants.DESELECTED_CLASS, false); + } } } }; @@ -304,7 +334,18 @@ dc.barChart = function (parent, chartGroup) { }; dc.override(_chart, 'onClick', function (d) { - _chart._onClick(d.data); + var charts = getCharts(); + // A grouped chart + if (charts.length > 1) { + charts.forEach(function (chart, i) { + var filter = chart.keyAccessor()(d.data); + chart.filter(filter); + }); + _chart.redrawGroup(); + // Not a grouped chart + } else { + _chart._onClick(d.data); + } }); /** @@ -378,14 +419,10 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; - _chart.extendBrush = function () { - var extent = _chart.brush().extent(); - if (_chart.round() && (!_centerBar || _alwaysUseRounding)) { - extent[0] = extent.map(_chart.round())[0]; - extent[1] = extent.map(_chart.round())[1]; - - _chart.chartBodyG().select('.brush') - .call(_chart.brush().extent(extent)); + _chart.extendBrush = function (brushSelection) { + if (brushSelection && _chart.round() && (!_centerBar || _alwaysUseRounding)) { + brushSelection[0] = _chart.round()(brushSelection[0]); + brushSelection[1] = _chart.round()(brushSelection[1]); } return brushSelection; }; @@ -413,7 +450,7 @@ dc.barChart = function (parent, chartGroup) { return _chart; }; - function colorFilter(color, inv) { + function colorFilter (color, inv) { return function () { var item = d3.select(this); var match = item.attr('fill') === color; diff --git a/web/examples/bar-grouped.html b/web/examples/bar-grouped.html new file mode 100644 index 000000000..7f3ed0e52 --- /dev/null +++ b/web/examples/bar-grouped.html @@ -0,0 +1,105 @@ + + + + dc.js - Grouped Bar Chart Example + + + + + + +
+ +
+ + + + + + +
+ + From 8f0a5f43d3cdcf2011eaa4d307c0bd10bc963816 Mon Sep 17 00:00:00 2001 From: jaklub Date: Tue, 3 Jul 2018 19:27:31 +0200 Subject: [PATCH 5/6] Added example bar-group-twice --- web/examples/bar-grouped-twice.html | 206 +++++++++++++++++++++++++++ web/examples/bar-grouped.html | 210 ++++++++++++++-------------- 2 files changed, 311 insertions(+), 105 deletions(-) create mode 100644 web/examples/bar-grouped-twice.html diff --git a/web/examples/bar-grouped-twice.html b/web/examples/bar-grouped-twice.html new file mode 100644 index 000000000..716222bcb --- /dev/null +++ b/web/examples/bar-grouped-twice.html @@ -0,0 +1,206 @@ + + + + dc.js - Two Grouped Bar Chart Example + + + + + + +
+ +
+
+ + + + + + +
+ + diff --git a/web/examples/bar-grouped.html b/web/examples/bar-grouped.html index 7f3ed0e52..c91d1d863 100644 --- a/web/examples/bar-grouped.html +++ b/web/examples/bar-grouped.html @@ -1,105 +1,105 @@ - - - - dc.js - Grouped Bar Chart Example - - - - - - -
- -
- - - - - - -
- - + + + + dc.js - Grouped Bar Chart Example + + + + + + +
+ +
+ + + + + + +
+ + From b5236c4707b43f67462f52a45f903e6c73028ef8 Mon Sep 17 00:00:00 2001 From: Jakob Lublin Date: Thu, 5 Jul 2018 19:31:40 +0200 Subject: [PATCH 6/6] Uppdated barchart for non ordinal grouped charts and examples --- src/bar-chart.js | 53 +- ...uped-twice.html => bar-grouped-multi.html} | 496 ++++++++++-------- web/examples/bar-grouped.html | 213 ++++---- 3 files changed, 437 insertions(+), 325 deletions(-) rename web/examples/{bar-grouped-twice.html => bar-grouped-multi.html} (63%) diff --git a/src/bar-chart.js b/src/bar-chart.js index 880c10b3a..c2a4ed6f0 100644 --- a/src/bar-chart.js +++ b/src/bar-chart.js @@ -158,21 +158,35 @@ dc.barChart = function (parent, chartGroup) { var x = _chart.x()(d.x); var charts = getCharts(); var chartIndex = charts.indexOf(_chart); + // A grouped chart if (charts.length > 1) { - if (_gap !== undefined) { - x += _chart.serieGap() / 2; - x += chartIndex * (_barWidth + _gap); - x += _gap / 2; + var numberOfCharts = charts.length; + var numberOfBars = _chart.xUnitCount(); + var barWidth; + var barPadding; + + if (_chart.isOrdinal()) { + barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); } else { - var numberOfCharts = charts.length; - var barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); - var barPadding = barWidth * (_chart.barPadding()); + barWidth = ((_chart.xAxisLength() / numberOfBars) - _chart.serieGap()) / numberOfCharts; + } + + if (_gap === undefined) { + barPadding = barWidth * (_chart.barPadding()); + } else { + barPadding = _gap; + } + x += chartIndex * (barWidth); + if (_chart.isOrdinal()) { x += _chart.serieGap() / 2; x += barPadding / 2; - x += chartIndex * (_barWidth + barPadding); + } else if (!_chart.isOrdinal() && _centerBar) { + x -= barWidth * numberOfCharts / 2; + x += barPadding / 2; } + // Not a grouped chart } else { if (_centerBar) { @@ -182,6 +196,7 @@ dc.barChart = function (parent, chartGroup) { x += _gap / 2; } } + return dc.utils.safeNumber(x); } @@ -238,14 +253,23 @@ dc.barChart = function (parent, chartGroup) { // A grouped chart if (charts.length > 1) { - var numberOfCharts = charts.length; - var barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); - if (_gap !== undefined) { - _barWidth = Math.floor(barWidth - _gap); + var numberOfCharts = charts.length, + barPadding, + barWidth; + + if (_chart.isOrdinal()) { + barWidth = (_chart.x().bandwidth() - _chart.serieGap()) / (numberOfCharts); } else { - var barPadding = barWidth * (_chart.barPadding()); - _barWidth = Math.floor(barWidth - barPadding); + barWidth = ((_chart.xAxisLength() / numberOfBars) - _chart.serieGap()) / numberOfCharts; } + + if (_gap === undefined) { + barPadding = barWidth * (_chart.barPadding()); + } else { + barPadding = _gap; + } + _barWidth = Math.floor(barWidth - barPadding); + // Not a grouped chart } else { // please can't we always use rangeBands for bar charts? @@ -287,6 +311,7 @@ dc.barChart = function (parent, chartGroup) { } } }); + // Not a grouped chart } else { bars = _chart.chartBodyG().selectAll('rect.bar'); diff --git a/web/examples/bar-grouped-twice.html b/web/examples/bar-grouped-multi.html similarity index 63% rename from web/examples/bar-grouped-twice.html rename to web/examples/bar-grouped-multi.html index 716222bcb..a073b96b9 100644 --- a/web/examples/bar-grouped-twice.html +++ b/web/examples/bar-grouped-multi.html @@ -1,206 +1,290 @@ - - - - dc.js - Two Grouped Bar Chart Example - - - - - - -
- -
-
- - - - - - -
- - + + + + dc.js - Two Grouped Bar Chart Example + + + + + + +
+ + +
+ Ordinal chart + +
+
+ Ordinal chart + +
+
+ Non ordinal chart with centerbar and brush on + +
+ + + + + + +
+ + diff --git a/web/examples/bar-grouped.html b/web/examples/bar-grouped.html index c91d1d863..f283c1743 100644 --- a/web/examples/bar-grouped.html +++ b/web/examples/bar-grouped.html @@ -1,105 +1,108 @@ - - - - dc.js - Grouped Bar Chart Example - - - - - - -
- -
- - - - - - -
- - + + + + dc.js - Grouped Bar Chart Example + + + + + + +
+ +
+ + + + + + +
+ +