diff --git a/src/TableRenderers.jsx b/src/TableRenderers.jsx index 205f2a6..eb7b9fb 100644 --- a/src/TableRenderers.jsx +++ b/src/TableRenderers.jsx @@ -3,28 +3,6 @@ import PropTypes from 'prop-types'; import {PivotData} from './Utilities'; import memoize from 'memoize-one'; -// helper function for setting row/col-span in pivotTableRenderer -const sliceSame = function(arr, i1, i2, j) { - // Compare a slice of the passed in column/row attribute array up to depth j. - for (let x = 0; x <= j; x++) { - if (arr[i1][x] !== arr[i2][x]) { - return false; - } - } - return true; -} - -const spanSize = function(arr, i, j) { - if (i !== 0 && sliceSame(arr, i, i - 1, j)) { - return -1; - } - let k = i + 1; - while (k < arr.length && sliceSame(arr, i, k, j)) { - k++; - } - return k - i; -}; - function redColorScaleGenerator(values) { const min = Math.min.apply(Math, values); const max = Math.max.apply(Math, values); @@ -60,6 +38,8 @@ function makeRenderer(opts = {}) { rowAttrs, colKeys, rowKeys, + colAttrSpans: this.calcAttrSpans(colKeys), + rowAttrSpans: this.calcAttrSpans(rowKeys), rowTotals, colTotals, ...this.heatmapMappers( @@ -71,6 +51,41 @@ function makeRenderer(opts = {}) { }; }); + calcAttrSpans = (attrArr) => { + // Given an array of attribute values (i.e. each element is another array with + // the value at every level), compute the spans for every attribute value at + // every level. The return value is a nested array of the same shape. It has + // -1's for repeated values and the span number otherwise. + + if (attrArr.length === 0) { + return [] + } + + const spans = []; + const li = attrArr[0].map(() => 0); // Index of the last new value + let lv = attrArr[0].map(() => null); + for(let i = 0;i < attrArr.length;i++) { + // Keep increasing span values as long as the last keys are the same. For + // the rest, record spans of 1. Update the indices too. + let cv = attrArr[i]; + let ent = []; + let depth = 0; + while (lv[depth] === cv[depth]) { + ent.push(-1); + spans[li[depth]][depth]++; + depth++; + } + while (depth < cv.length) { + li[depth] = i; + ent.push(1); + depth++; + } + spans.push(ent); + lv = cv; + } + return spans; + } + heatmapMappers = (pivotData, colorScaleGenerator, colTotals, rowTotals) => { let valueCellColors = () => {}; let rowTotalColors = () => {}; @@ -150,7 +165,7 @@ function makeRenderer(opts = {}) { renderColHeaderRow = (attrName, attrIdx, pivotSettings) => { // Render a single row in the column header at the top of the pivot table. - const {rowAttrs, colAttrs, colKeys, rowTotals} = pivotSettings; + const {rowAttrs, colAttrs, colKeys, colAttrSpans, rowTotals} = pivotSettings; const spaceCell = (attrIdx === 0 && rowAttrs.length !== 0) ? (