diff --git a/spec/heatmap-spec.js b/spec/heatmap-spec.js index cba059eb4..53d18a507 100644 --- a/spec/heatmap-spec.js +++ b/spec/heatmap-spec.js @@ -154,6 +154,64 @@ describe("dc.heatmap", function() { }); + describe('override scale domains', function () { + beforeEach( function () { + chart.rows([1]); + chart.cols([1]); + chart.render(); + }); + + it ('should only have 1 row on the y axis', function () { + var yaxisTexts = chart.selectAll(".rows.axis text"); + expect(yaxisTexts[0].length).toEqual(1); + expect(yaxisTexts[0][0].textContent).toEqual('1'); + }); + + it ('should only have 1 col on the x axis', function () { + var xaxisTexts = chart.selectAll(".cols.axis text"); + expect(xaxisTexts[0].length).toEqual(1); + expect(xaxisTexts[0][0].textContent).toEqual('1'); + }); + + it ('should reset the rows to using the chart data on the y axis', function () { + chart.rows(null); + chart.redraw(); + var yaxisTexts = chart.selectAll(".rows.axis text"); + expect(yaxisTexts[0].length).toEqual(2); + expect(yaxisTexts[0][0].textContent).toEqual('1'); + expect(yaxisTexts[0][1].textContent).toEqual('2'); + }); + + it ('should reset the cols to using the chart data on the y axis', function () { + chart.cols(null); + chart.redraw(); + var xaxisTexts = chart.selectAll(".cols.axis text"); + expect(xaxisTexts[0].length).toEqual(2); + expect(xaxisTexts[0][0].textContent).toEqual('1'); + expect(xaxisTexts[0][1].textContent).toEqual('2'); + }); + }); + + describe('use a custom ordering on x and y axes', function () { + beforeEach( function () { + chart.rowOrdering(d3.descending); + chart.colOrdering(d3.descending); + chart.render(); + }); + + it ('should have descending rows', function () { + var yaxisTexts = chart.selectAll(".rows.axis text"); + expect(yaxisTexts[0][0].textContent).toEqual('2'); + expect(yaxisTexts[0][1].textContent).toEqual('1'); + }); + + it ('should have descending cols', function () { + var yaxisTexts = chart.selectAll(".rows.axis text"); + expect(yaxisTexts[0][0].textContent).toEqual('2'); + expect(yaxisTexts[0][1].textContent).toEqual('1'); + }); + }); + describe('change crossfilter', function () { var data2, dimension2, group2, originalDomain, newDomain; diff --git a/src/heatmap.js b/src/heatmap.js index 7b32169d1..16c625f10 100644 --- a/src/heatmap.js +++ b/src/heatmap.js @@ -35,6 +35,11 @@ dc.heatMap = function (parent, chartGroup) { var _cols; var _rows; + var _colOrdering = d3.ascending; + var _rowOrdering = d3.ascending; + var _colScale = d3.scale.ordinal(); + var _rowScale = d3.scale.ordinal(); + var _xBorderRadius = DEFAULT_BORDER_RADIUS; var _yBorderRadius = DEFAULT_BORDER_RADIUS; @@ -122,47 +127,55 @@ dc.heatMap = function (parent, chartGroup) { return _chart._filter(dc.filters.TwoDimensionalFilter(filter)); }); - function uniq(d, i, a) { - return !i || a[i - 1] !== d; - } - /** #### .rows([values]) Gets or sets the values used to create the rows of the heatmap, as an array. By default, all - the values will be fetched from the data using the value accessor, and they will be sorted in - ascending order. + the values will be fetched from the data using the value accessor. **/ _chart.rows = function (_) { - if (arguments.length) { - _rows = _; - return _chart; - } - if (_rows) { + if (!arguments.length) { return _rows; } - var rowValues = _chart.data().map(_chart.valueAccessor()); - rowValues.sort(d3.ascending); - return d3.scale.ordinal().domain(rowValues.filter(uniq)); + _rows = _; + return _chart; + }; + + /** + #### .rowOrdering([orderFunction]) + Get or set an accessor to order the rows. Default is d3.ascending. + */ + _chart.rowOrdering = function (_) { + if (!arguments.length) { + return _rowOrdering; + } + _rowOrdering = _; + return _chart; }; /** #### .cols([keys]) Gets or sets the keys used to create the columns of the heatmap, as an array. By default, all - the values will be fetched from the data using the key accessor, and they will be sorted in - ascending order. + the values will be fetched from the data using the key accessor. **/ _chart.cols = function (_) { - if (arguments.length) { - _cols = _; - return _chart; - } - if (_cols) { + if (!arguments.length) { return _cols; } - var colValues = _chart.data().map(_chart.keyAccessor()); - colValues.sort(d3.ascending); - return d3.scale.ordinal().domain(colValues.filter(uniq)); + _cols = _; + return _chart; + }; + + /** + #### .colOrdering([orderFunction]) + Get or set an accessor to order the cols. Default is ascending. + */ + _chart.colOrdering = function (_) { + if (!arguments.length) { + return _colOrdering; + } + _colOrdering = _; + return _chart; }; _chart._doRender = function () { @@ -177,9 +190,19 @@ dc.heatMap = function (parent, chartGroup) { }; _chart._doRedraw = function () { - var rows = _chart.rows(), - cols = _chart.cols(), - rowCount = rows.domain().length, + var data = _chart.data(), + rows = _chart.rows() || data.map(_chart.valueAccessor()), + cols = _chart.cols() || data.map(_chart.keyAccessor()); + if (_rowOrdering) { + rows = rows.sort(_rowOrdering); + } + if (_colOrdering) { + cols = cols.sort(_colOrdering); + } + rows = _rowScale.domain(rows); + cols = _colScale.domain(cols); + + var rowCount = rows.domain().length, colCount = cols.domain().length, boxWidth = Math.floor(_chart.effectiveWidth() / colCount), boxHeight = Math.floor(_chart.effectiveHeight() / rowCount);