diff --git a/src/base-chart.js b/src/base-chart.js index 0d4bec5d9..6e7660e81 100644 --- a/src/base-chart.js +++ b/src/base-chart.js @@ -15,6 +15,13 @@ dc.baseChart = function (_chart) { var _svg; var _width = 200, _height = 200; + var _calculateWidth = false, _calculateHeight = false; + var _widthCalculation = function (element) { + return element.getBoundingClientRect().width; + }; + var _heightCalculation = function (element) { + return element.getBoundingClientRect().height; + }; var _keyAccessor = function (d) { return d.key; @@ -104,6 +111,71 @@ dc.baseChart = function (_chart) { 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; + }; + + /** + #### .widthCalculation + Set or get chart's auto-width function, which will be used to set width on render if calculateWidth is true. + + This function will be passed the anchor element as an argument. + + 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.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; + } + /** #### .dimension([value]) - **mandatory** Set or get dimension attribute of a chart. In dc a dimension can be any valid @@ -373,6 +445,16 @@ 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(); diff --git a/test/base-chart-test.js b/test/base-chart-test.js index 48a689321..6e61d690c 100644 --- a/test/base-chart-test.js +++ b/test/base-chart-test.js @@ -179,5 +179,60 @@ 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); + }, + + 'width is determined using supplied function when width calculation is enabled': function (chart) { + var calculation = sinon.stub().returns(800); + chart.calculateWidth(true).widthCalculation(calculation); + chart.render(); + + assert.isTrue(calculation.called) + assert.equal(chart.width(), 800); + }, + + 'height not calculated when height calculation is disabled': function (chart) { + var calculation = sinon.stub().returns(800); + chart.height(400); + chart.calculateHeight(false).heightCalculation(calculation); + chart.render(); + + assert.isFalse(calculation.called) + assert.equal(chart.height(), 400); + }, + + 'width not calculated when width calculation is disabled': function (chart) { + var calculation = sinon.stub().returns(800); + chart.width(400); + chart.calculateWidth(false).widthCalculation(calculation); + chart.render(); + + assert.isFalse(calculation.called) + assert.equal(chart.width(), 400); + } + }, + + teardown: function (topic) { + resetAllFilters(); + resetBody(); + dc.chartRegistry.clear(); + } +}); + suite.export(module);