Skip to content

Commit

Permalink
Merge branch 'feature/remove-group-top' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
gordonwoodhull committed Jan 18, 2017
2 parents 3326423 + 87ec109 commit f415126
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 134 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ Daniel Gall <Daniel.Gall@noaa.gov>
Renoth
Alexander Bouriakov <abtmp-github@yahoo.com>
Kyle Doherty <kyle.l.doherty@gmail.com>
Macy Abbey
10 changes: 10 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 2.1.2
* Lift `elasticRadius` from `bubbleChart` to `bubbleMixin`, making it available to `bubbleOverlay` ([#661](https://github.com/dc-js/dc.js/issues/661))
Stop using `group.top()` in favor of `group.all()` sorting and slicing. ([#934](https://github.com/dc-js/dc.js/issues/934))
* Eliminate use of `group.top()` in cap mixin, by Macy Abbey ([#1184](https://github.com/dc-js/dc.js/pull/1184)). It already had to agree with `chart.ordering()` for the results to make sense.
* Eliminate `group.top()` in number display. This one is more problematic but probably less common. Although the number display now defaults ordering to `function (kv) { return kv.value; }`, applications which use a group with multiple bins with the number display, which were using `group.order()` to specify which bin should be displayed, must now specify `numberDisplay.ordering()` instead.
* Eliminate `group.top()` in bubble mixin, which was used to draw the bubbles in descending order of size, when the `group.order()` specified the radius. The bubble chart's `sortBubbleSize` is more general and is lifted to the mixin.

## 2.1.1
* Merges 2.0.1

## 2.1.0
* `dc.selectMenu`, implementing a `<select>` menu or multiple-select widget, by Andrea Singh ([#771](https://github.com/dc-js/dc.js/pull/771))
* Heatmap allows customizing the ordering separately from the values, by Matt Traynham ([#869](https://github.com/dc-js/dc.js/pull/869) - thanks also to Quinn Lee for [#837](https://github.com/dc-js/dc.js/pull/837))
Expand Down
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "dc.js",
"repository": "dc-js/dc.js",
"description": "Multi-Dimensional charting built to work natively with crossfilter rendered with d3.js",
"version": "2.1.1",
"version": "2.1.2",
"keywords": [
"visualization",
"svg",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dc",
"version": "2.1.1",
"version": "2.1.2",
"license": "Apache-2.0",
"copyright": "2017",
"description": "A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js ",
Expand Down
52 changes: 28 additions & 24 deletions spec/bubble-chart-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ describe('dc.bubbleChart', function () {

it('draws bubbles in appropriate locations', function () {
var coords = [
[170.4,0], [820,155], [489.9,155], [394,310], [149.1,310], [0,310]
[0,310], [149.1,310], [170.4,0], [394,310], [489.9,155], [820,155],
];
chart.selectAll('g.node').each(function (d, i) {
expect(d3.select(this).attr('transform'))
Expand Down Expand Up @@ -594,6 +594,7 @@ describe('dc.bubbleChart', function () {
.keyAccessor(key_part(0))
.valueAccessor(key_part(1))
.radiusValueAccessor(function (kv) { return kv.value.total; })
.elasticRadius(true)
.colors(d3.scale.ordinal()
.domain(species.concat('none'))
.range(['#e41a1c','#377eb8','#4daf4a', '#f8f8f8']))
Expand Down Expand Up @@ -659,35 +660,38 @@ describe('dc.bubbleChart', function () {

function testBubbleRadiiCol3 (chart) {
var bubbles = chart.selectAll('circle.bubble')[0];
expect(d3.select(bubbles[0]).attr('r')).toBe('0');
expect(d3.select(bubbles[3]).attr('r')).toBe('0');
expect(d3.select(bubbles[6]).attr('r')).toBe('0');
expect(+d3.select(bubbles[11]).attr('r')).toBeWithinDelta(21.5, 0.5);
expect(d3.select(bubbles[14]).attr('r')).toBe('0');
expect(+d3.select(bubbles[16]).attr('r')).toBeWithinDelta(33, 0.5);
expect(+d3.select(bubbles[19]).attr('r')).toBeWithinDelta(50, 0.5);
expect(d3.select(bubbles[24]).attr('r')).toBe('0');
var expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34.5, 16.1, 0, 0, 16.1, 59.1, 34.5, 16.1, 96, 0, 22.2, 0, 0, 0, 0];
bubbles.forEach(function (b, i) {
expect(+d3.select(b).attr('r')).toBeWithinDelta(expected[i], 0.1);
});
}
function testBubbleTitlesCol3 (chart) {
var titles = chart.selectAll('g.node title')[0];
expect(JSON.parse(d3.select(titles[4]).text()).total).toBe(0);
expect(JSON.parse(d3.select(titles[11]).text()).virginica).toBe(4);
expect(JSON.parse(d3.select(titles[12]).text()).virginica).toBe(1);
expect(JSON.parse(d3.select(titles[16]).text()).virginica).toBe(7);
expect(JSON.parse(d3.select(titles[16]).text()).versicolor).toBe(1);
expect(JSON.parse(d3.select(titles[19]).text()).virginica).toBe(13);
expect(JSON.parse(d3.select(titles[19]).text()).versicolor).toBe(1);
var expected = [
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 4,'setosa': 0,'versicolor': 0,'virginica': 4},{'total': 1,'setosa': 0,'versicolor': 0,'virginica': 1},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 1,'setosa': 0,'versicolor': 0,'virginica': 1},{'total': 8,'setosa': 0,'versicolor': 1,'virginica': 7},
{'total': 4,'setosa': 0,'versicolor': 0,'virginica': 4},{'total': 1,'setosa': 0,'versicolor': 0,'virginica': 1},
{'total': 14,'setosa': 0,'versicolor': 1,'virginica': 13},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 2,'setosa': 0,'versicolor': 0,'virginica': 2},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0},
{'total': 0,'setosa': 0,'versicolor': 0,'virginica': 0}];
titles.forEach(function (t, i) {
expect(JSON.parse(d3.select(t).text())).toEqual(expected[i]);
});
}
function testBubbleLabelsCol3 (chart) {
var labels = chart.selectAll('g.node text')[0];
expect(d3.select(labels[0]).text()).toBe('0');
expect(d3.select(labels[2]).text()).toBe('0');
expect(d3.select(labels[4]).text()).toBe('0');
expect(d3.select(labels[5]).text()).toBe('0');
expect(d3.select(labels[11]).text()).toBe('4');
expect(d3.select(labels[12]).text()).toBe('1');
expect(d3.select(labels[16]).text()).toBe('8');
expect(d3.select(labels[19]).text()).toBe('14');
var expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 1, 8, 4, 1, 14, 0, 2, 0, 0, 0, 0];
labels.forEach(function (l, i) {
expect(+d3.select(l).text()).toBe(expected[i]);
});
}
describe('column filtering with straight crossfilter', function () {
beforeEach(function () {
Expand Down
112 changes: 81 additions & 31 deletions spec/bubble-overlay-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,39 @@ describe('dc.bubbleOverlay', function () {
var chart, data;
var dimension, group;

describe('creation', function () {
beforeEach(function () {
data = crossfilter(loadDateFixture());
dimension = data.dimension(function (d) {return d.state;});
group = dimension.group().reduceSum(function (d) {return d.value;});

var id = 'bubble-overlay';
var parent = appendChartID(id);
var svg = parent.append('svg');

chart = dc.bubbleOverlay('#' + id)
.svg(svg)
.dimension(dimension)
.group(group)
.width(300)
.height(200)
.transitionDuration(0)
.title(function (d) {return 'Title: ' + d.key;})
.r(d3.scale.linear().domain([0, 500]))
.ordinalColors(['blue'])
.point('California', 100, 120)
.point('Colorado', 300, 120)
.point('Delaware', 500, 220)
.point('Ontario', 180, 90)
.point('Mississippi', 120, 220)
.point('Oklahoma', 200, 350);

chart.render();
});
beforeEach(function () {
data = crossfilter(loadDateFixture());
dimension = data.dimension(function (d) {return d.state;});
group = dimension.group().reduceSum(function (d) {return d.value;});

var id = 'bubble-overlay';
var parent = appendChartID(id);
var width = 600, height = 400;
var svg = parent.append('svg')
.attr({width: width, height: height});

chart = dc.bubbleOverlay('#' + id)
.svg(svg)
.dimension(dimension)
.group(group)
.width(width)
.height(height)
.transitionDuration(0)
.title(function (d) {return 'Title: ' + d.key;})
.r(d3.scale.linear().domain([0, 100]))
.maxBubbleRelativeSize(0.1)
.ordinalColors(['blue'])
.point('California', 100, 120)
.point('Colorado', 300, 120)
.point('Delaware', 500, 220)
.point('Ontario', 180, 90)
.point('Mississippi', 120, 220)
.point('Oklahoma', 200, 350);

chart.render();
});

describe('creation', function () {
it('should generate an instance of the dc chart', function () {
expect(dc.instanceOfChart(chart)).toBeTruthy();
});
Expand Down Expand Up @@ -60,8 +63,8 @@ describe('dc.bubbleOverlay', function () {
});

it('should generate correct radii for circles', function () {
expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('r')).toEqual('34.64');
expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('r')).toEqual('22.32');
expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('r')).toEqual('87');
expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('r')).toEqual('48.5');
});

it('should generate correct labels', function () {
Expand Down Expand Up @@ -98,5 +101,52 @@ describe('dc.bubbleOverlay', function () {
expect(d3.select(chart.selectAll('g.node')[0][3]).attr('class')).toEqual('node ontario deselected');
});
});

function removeEmptyBins (group) {
return {
all: function () {
return group.all().filter(function (d) {
return d.value !== 0;
});
}
};
}
describe('filtering another dimension', function () {
var regionDim;
beforeEach(function () {
chart.group(removeEmptyBins(group)).render();
regionDim = data.dimension(function (d) { return d.region; });
});
function expectRadii (expected) {
var circles = chart.selectAll('circle.bubble')[0];
console.log(circles.map(function (c) { return +d3.select(c).attr('r'); }));
circles.forEach(function (c, i) {
expect(+d3.select(c).attr('r')).toBeWithinDelta(expected[i], 0.1);
});
}
describe('without elastic radius', function () {
it('should have reasonable radii', function () {
expectRadii([87, 21, 26.5, 48.5, 48.5, 37.5]);
});
it('filtering should zero out some radii', function () {
regionDim.filter('Central');
dc.redrawAll();
expectRadii([0, 0, 0, 37.5, 48.5, 0]);
});
});
describe('with elastic radius', function () {
beforeEach(function () {
chart.elasticRadius(true).render();
});
it('should lock to the minimum and maximum radius sizes', function () {
expectRadii([60, 10, 14.1, 30.8, 30.8, 22.5]);
});
it('filtering should lock the remaining bubbles to min and max radius sizes', function () {
regionDim.filter('Central');
dc.redrawAll();
expectRadii([0, 0, 0, 10, 60, 0]);
});
});
});
});

34 changes: 16 additions & 18 deletions spec/heatmap-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,21 @@ describe('dc.heatmap', function () {
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
// 2-chart version of from http://bl.ocks.org/gordonwoodhull/14c623b95993808d69620563508edba6
var irisData, bubbleChart, petalDim, petalGroup;
var fields = {
sl: 'sepal_length',
sw: 'sepal_width',
pl: 'petal_length',
pw: 'petal_width'
};
var keyfuncs = {};
function duo_key (ab1, ab2) {
return function (d) {
return [keyfuncs[ab1](d[fields[ab1]]), keyfuncs[ab2](d[fields[ab2]])];
};
}
beforeEach(function () {
irisData = loadIrisFixture();

var fields = {
sl: 'sepal_length',
sw: 'sepal_width',
pl: 'petal_length',
pw: 'petal_width'
};
var species = ['setosa', 'versicolor', 'virginica'];

irisData.forEach(function (d) {
Expand All @@ -447,17 +453,11 @@ describe('dc.heatmap', function () {
};
}
var extents = {};
var keyfuncs = {};
Object.keys(fields).forEach(function (ab) {
extents[ab] = d3.extent(irisData, function (d) { return d[fields[ab]]; });
keyfuncs[ab] = key_function(extents[ab]);
});
data = crossfilter(irisData);
function duo_key (ab1, ab2) {
return function (d) {
return [keyfuncs[ab1](d[fields[ab1]]), keyfuncs[ab2](d[fields[ab2]])];
};
}
function key_part (i) {
return function (kv) {
return kv.key[i];
Expand Down Expand Up @@ -494,13 +494,15 @@ describe('dc.heatmap', function () {
bubbleChart
.width(400)
.height(400)
.transitionDuration(0)
.x(d3.scale.linear()).xAxisPadding(0.5)
.y(d3.scale.linear()).yAxisPadding(0.5)
.elasticX(true)
.elasticY(true)
.label(d3.functor(''))
.keyAccessor(key_part(0))
.valueAccessor(key_part(1))
.r(d3.scale.linear().domain([0,20]).range([4,25]))
.radiusValueAccessor(function (kv) { return kv.value.total; })
.colors(d3.scale.ordinal()
.domain(species.concat('none'))
Expand Down Expand Up @@ -588,9 +590,7 @@ describe('dc.heatmap', function () {

describe('bubble filtering with straight crossfilter', function () {
beforeEach(function () {
var aBubble = d3.select(bubbleChart.selectAll('circle.bubble')[0][12]);
aBubble.on('click')(aBubble.datum());
d3.timer.flush();
bubbleChart.filter(duo_key('sl', 'sw')({sepal_length: 5.5, sepal_width: 3})).redrawGroup();
});
it('updates rect fills correctly', function () {
testRectFillsBubble12(chart);
Expand All @@ -603,9 +603,7 @@ describe('dc.heatmap', function () {
beforeEach(function () {
chart.group(clone_group(petalGroup));
chart.render();
var aBubble = d3.select(bubbleChart.selectAll('circle.bubble')[0][12]);
aBubble.on('click')(aBubble.datum());
d3.timer.flush();
bubbleChart.filter(duo_key('sl', 'sw')({sepal_length: 5.5, sepal_width: 3})).redrawGroup();
});
it('updates rect fills correctly', function () {
testRectFillsBubble12(chart);
Expand Down
31 changes: 31 additions & 0 deletions spec/number-display-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,37 @@ describe('dc.numberDisplay', function () {
d3.select('#number-display-test-section').remove();
});
});
describe('with group with multiple values', function () {
var group, chart;
beforeEach(function () {
countryDimension.filterAll();
group = countryDimension.group().reduceSum(function (d) { return +d.value; });
var id = 'empty-div';
appendChartID(id);
chart = buildChart('#' + id);
chart
.group(group)
.valueAccessor(function (kv) { return kv.value; })
.render();
d3.timer.flush();
});

it('should show the largest value', function () {
expect(chart.select('span.number-display').text()).toEqual('341');
});

describe('with reversed ordering', function () {
beforeEach(function () {
chart.ordering(function (kv) { return -kv.value; })
.render();
d3.timer.flush();
});
it('should show the smallest value', function () {
expect(chart.select('span.number-display').text()).toEqual('77.0');
});
});

});
describe('Infinity', function () {
var chart;
beforeEach(function () {
Expand Down
Loading

0 comments on commit f415126

Please sign in to comment.