Skip to content

Commit

Permalink
Allow for dynamic chart sizing. Closes dc-js#295
Browse files Browse the repository at this point in the history
  • Loading branch information
jrideout committed Oct 10, 2013
1 parent f09f997 commit 0bb4331
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 157 deletions.
39 changes: 29 additions & 10 deletions dc.js
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,15 @@ dc.baseChart = function (_chart) {
var _root;
var _svg;

var _width = 200, _height = 200;
var _default_width = function (element) {
return element && element.getBoundingClientRect && element.getBoundingClientRect().width || 200;
};
var _width = _default_width;

var _default_height = function (element) {
return element && element.getBoundingClientRect && element.getBoundingClientRect().height || 200;
};
var _height = _default_height;

var _keyAccessor = function (d) {
return d.key;
Expand Down Expand Up @@ -757,27 +765,38 @@ dc.baseChart = function (_chart) {

/**
#### .width([value])
Set or get width attribute of a chart. If the value is given, then it will be used as the new width.
If no value specified then value of the current width attribute will be returned.
Set or get width attribute of a chart. See `.height` below for further description of the behavior.
**/
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
if (!arguments.length) return _width(_root.node());
_width = d3.functor(w || _default_width);
return _chart;
};

/**
#### .height([value])
Set or get height attribute of a chart. If the value is given, then it will be used as the new height.
Set or get height attribute of a chart. The height is applied to the SVG element
generated by the chart when rendered (or rerendered). If a value is given, then it
will be used to calculate the new height and the chart returned for method chaining.
The value can either be a numeric, a function, or falsy. If no value specified then
value of the current height attribute will be returned.
If no value specified then value of the current height attribute will be returned.
By default, without an explicit height being given, the chart will select the width
of its anchor element. If that isn't possible it defaults to 200;
Examples:
```js
chart.height(250); // Set the chart's height to 250px;
chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function
chart.height(null); // reset the height to the default auto calculation
```
**/
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
if (!arguments.length) return _height(_root.node());
_height = d3.functor(h || _default_height);
return _chart;
};

Expand Down
4 changes: 2 additions & 2 deletions dc.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dc.min.js.map

Large diffs are not rendered by default.

115 changes: 26 additions & 89 deletions src/base-chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ dc.baseChart = function (_chart) {
var _root;
var _svg;

var _width = 200, _height = 200;
var _calculateWidth = false, _calculateHeight = false;
var _widthCalculation = function (element) {
return element.getBoundingClientRect().width;
var _default_width = function (element) {
return element && element.getBoundingClientRect && element.getBoundingClientRect().width || 200;
};
var _heightCalculation = function (element) {
return element.getBoundingClientRect().height;
var _width = _default_width;

var _default_height = function (element) {
return element && element.getBoundingClientRect && element.getBoundingClientRect().height || 200;
};
var _height = _default_height;

var _keyAccessor = function (d) {
return d.key;
Expand Down Expand Up @@ -87,94 +88,40 @@ dc.baseChart = function (_chart) {

/**
#### .width([value])
Set or get width attribute of a chart. If the value is given, then it will be used as the new width.
If no value specified then value of the current width attribute will be returned.
Set or get width attribute of a chart. See `.height` below for further description of the behavior.
**/
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
if (!arguments.length) return _width(_root.node());
_width = d3.functor(w || _default_width);
return _chart;
};

/**
#### .height([value])
Set or get height attribute of a chart. If the value is given, then it will be used as the new height.
If no value specified then value of the current height attribute will be returned.
**/
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
return _chart;
};

/**
#### .calculateWidth([value])
Set or get chart's auto-width flag.
If set to a truthy value, chart width will be automatically calculated each time chart is rendered.
Calculation is determined by widthCalculation(), and by default is width of anchor element.
If no value is specified then the current setting will be returned.
**/
_chart.calculateWidth = function (d) {
if (!arguments.length) return _calculateWidth;
_calculateWidth = d;
return _chart;
};

/**
#### .calculateHeight([value])
Set or get chart's auto-height function.
If set to a truthy value, chart height will be automatically calculated each time chart is rendered.
Calculation is determined by heightCalculation(), and by default is height of anchor element.
If no value is specified then the current setting will be returned.
**/
_chart.calculateHeight = function (d) {
if (!arguments.length) return _calculateHeight;
_calculateHeight = d;
return _chart;
};
Set or get height attribute of a chart. The height is applied to the SVG element
generated by the chart when rendered (or rerendered). If a value is given, then it
will be used to calculate the new height and the chart returned for method chaining.
The value can either be a numeric, a function, or falsy. If no value specified then
value of the current height attribute will be returned.
/**
#### .widthCalculation
Set or get chart's auto-width function, which will be used to set width on render if calculateWidth is true.
By default, without an explicit height being given, the chart will select the width
of its anchor element. If that isn't possible it defaults to 200;
This function will be passed the anchor element as an argument.
Examples:
Defaults to returning the anchor element's width.
Example which sets width to be 30px greater than parent element:
```js
chart.widthCalculation(function (element) {
return element.parentNode.offsetWidth + 30;
});
chart.height(250); // Set the chart's height to 250px;
chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function
chart.height(null); // reset the height to the default auto calculation
```
**/
_chart.widthCalculation = function(_) {
if (!arguments.length) return _widthCalculation;
_widthCalculation = _;
return _chart;
}

/**
#### .heightCalculation
Set or get chart's auto-height function, which will be used to set height on render if calculateHeight is true.
This function will be passed the anchor element height and anchor element itself as arguments
Defaults to:
```js
return elementHeight
```
**/
_chart.heightCalculation = function(_) {
if (!arguments.length) return _heightCalculation;
_heightCalculation = _;
return _chart;
}
_chart.height = function (h) {
if (!arguments.length) return _height(_root.node());
_height = d3.functor(h || _default_height);
return _chart;
};

/**
#### .dimension([value]) - **mandatory**
Expand Down Expand Up @@ -445,16 +392,6 @@ dc.baseChart = function (_chart) {

_mandatoryAttributes.forEach(checkForMandatoryAttributes);

if (_calculateWidth) {
var element = d3.select(_chart.anchorName()).node();
_chart.width(_widthCalculation(element));
};

if (_calculateHeight) {
var element = d3.select(_chart.anchorName()).node();
_chart.height(_heightCalculation(element));
};

var result = _chart.doRender();

if (_legend) _legend.render();
Expand Down
54 changes: 22 additions & 32 deletions test/base-chart-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand Down Expand Up @@ -48,6 +49,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand Down Expand Up @@ -77,6 +79,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand Down Expand Up @@ -106,6 +109,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand All @@ -129,6 +133,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand All @@ -152,6 +157,7 @@ suite.addBatch({
teardown: function (topic) {
resetAllFilters();
resetBody();
dc.chartRegistry.clear();
}
});

Expand Down Expand Up @@ -182,48 +188,33 @@ suite.addBatch({
suite.addBatch({
'calculation of dimensions': {
topic: function () {
var chart = dc.baseChart({});
d3.select("body").append("div").attr("id", "ele").node();
chart.anchor("#ele").dimension(valueDimension).group(valueGroup);
return chart;
},

'height is determined using supplied function when height calculation is enabled': function (chart) {
var calculation = sinon.stub().returns(800);
chart.calculateHeight(true).heightCalculation(calculation);
chart.render();

assert.isTrue(calculation.called)
assert.equal(chart.height(), 800);
d3.select("body").append("div").attr("id", "ele");
return dc.baseChart({}).anchor('#ele').dimension(valueDimension).group(valueGroup);
},

'width is determined using supplied function when width calculation is enabled': function (chart) {
var calculation = sinon.stub().returns(800);
chart.calculateWidth(true).widthCalculation(calculation);
'set automatically': function (chart) {
chart.height(null);
chart.width(null);
chart.render();

assert.isTrue(calculation.called)
assert.equal(chart.width(), 800);
assert.equal(chart.height(), 200);
assert.equal(chart.width(), 200);
},

'height not calculated when height calculation is disabled': function (chart) {
var calculation = sinon.stub().returns(800);
chart.height(400);
chart.calculateHeight(false).heightCalculation(calculation);
'set to a specific number': function (chart) {
chart.height(300);
chart.width(500);
chart.render();

assert.isFalse(calculation.called)
assert.equal(chart.height(), 400);
assert.equal(chart.height(), 300);
assert.equal(chart.width(), 500);
},

'width not calculated when width calculation is disabled': function (chart) {
'set to a callback': function (chart) {
var calculation = sinon.stub().returns(800);
chart.width(400);
chart.calculateWidth(false).widthCalculation(calculation);
chart.width(calculation);
chart.render();

assert.isFalse(calculation.called)
assert.equal(chart.width(), 400);
assert.equal(chart.width(), 800);
assert.isTrue(calculation.called)
}
},

Expand All @@ -235,4 +226,3 @@ suite.addBatch({
});

suite.export(module);

33 changes: 26 additions & 7 deletions web/docs/api-1.7.0-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,25 @@ Base chart is an abstract functional object representing a basic dc chart object
Every function on base chart are also inherited available on all concrete chart implementation in dc library.

#### .width([value])
Set or get width attribute of a chart. If the value is given, then it will be used as the new width.

If no value specified then value of the current width attribute will be returned.
Set or get width attribute of a chart. See `.height` below for further description of the behavior.

#### .height([value])
Set or get height attribute of a chart. If the value is given, then it will be used as the new height.
Set or get height attribute of a chart. The height is applied to the SVG element
generated by the chart when rendered (or rerendered). If a value is given, then it
will be used to calculate the new height and the chart returned for method chaining.
The value can either be a numeric, a function, or falsy. If no value specified then
value of the current height attribute will be returned.

By default, without an explicit height being given, the chart will select the width
of its anchor element. If that isn't possible it defaults to 200;

Examples:

If no value specified then value of the current height attribute will be returned.
```js
chart.height(250); // Set the chart's height to 250px;
chart.height(function(anchor) { return doSomethingWith(anchor); }); // set the chart's height with a function
chart.height(null); // reset the height to the default auto calculation
```

#### .dimension([value]) - **mandatory**
Set or get dimension attribute of a chart. In dc a dimension can be any valid
Expand Down Expand Up @@ -531,8 +542,8 @@ chart.colorDomain(function() {
Stackable chart is an abstract chart introduced to provide cross-chart support of stackability. Concrete implementation of
charts can then selectively mix-in this capability.

#### .stack(group[, name, retriever])
Stack a new crossfilter group into this chart with optionally a custom value retriever. All stacks in the same chart will
#### .stack(group[, name, accessor])
Stack a new crossfilter group into this chart with optionally a custom value accessor. All stacks in the same chart will
share the same key accessor therefore share the same set of keys. In more concrete words, imagine in a stacked bar chart
all bars will be positioned using the same set of keys on the x axis while stacked vertically. If name is specified then
it will be used to generate legend label.
Expand All @@ -543,6 +554,14 @@ chart.stack(valueSumGroup)
.stack(avgByDayGroup, function(d){return d.value.avgByDay;});
```

#### .hideStack(name)
Hide all stacks on the chart with the given name.
The chart must be re-rendered for this change to appear.

#### .showStack(name)
Show all stacks on the chart with the given name.
The chart must be re-rendered for this change to appear.

## <a name="abstract-bubble-chart" href="#abstract-bubble-chart">#</a> Abstract Bubble Chart [Abstract] < [Color Chart](#color-chart)
An abstraction provides reusable functionalities for any chart that needs to visualize data using bubbles.

Expand Down
Loading

0 comments on commit 0bb4331

Please sign in to comment.