@@ -14,19 +14,28 @@ var isNumeric = require('fast-isnumeric');
1414
1515// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying
1616module . exports = function calc ( gd , trace ) {
17- var cellsValues = trace . cells . values ;
17+ var cellsValues = squareStringMatrix ( trace . cells . values ) ;
1818 var slicer = function ( a ) {
1919 return a . slice ( trace . header . values . length , a . length ) ;
2020 } ;
21- var headerValues = trace . header . values . map ( function ( c ) {
22- return Array . isArray ( c ) ? c : [ c ] ;
23- } ) . concat ( slicer ( cellsValues ) . map ( function ( ) { return [ '' ] ; } ) ) ;
21+ var headerValuesIn = squareStringMatrix ( trace . header . values ) ;
22+ if ( headerValuesIn . length && ! headerValuesIn [ 0 ] . length ) {
23+ headerValuesIn [ 0 ] = [ '' ] ;
24+ headerValuesIn = squareStringMatrix ( headerValuesIn ) ;
25+ }
26+ var headerValues = headerValuesIn
27+ . concat ( slicer ( cellsValues ) . map ( function ( ) {
28+ return emptyStrings ( ( headerValuesIn [ 0 ] || [ '' ] ) . length ) ;
29+ } ) ) ;
30+
2431 var domain = trace . domain ;
2532 var groupWidth = Math . floor ( gd . _fullLayout . _size . w * ( domain . x [ 1 ] - domain . x [ 0 ] ) ) ;
2633 var groupHeight = Math . floor ( gd . _fullLayout . _size . h * ( domain . y [ 1 ] - domain . y [ 0 ] ) ) ;
27- var headerRowHeights = trace . header . values . length ? headerValues [ 0 ] . map ( function ( ) { return trace . header . height ; } ) : [ c . emptyHeaderHeight ] ;
28- var rowHeights = cellsValues . length ? cellsValues [ 0 ] . map ( function ( ) { return trace . cells . height ; } ) : [ ] ;
29- var headerHeight = headerRowHeights . reduce ( function ( a , b ) { return a + b ; } , 0 ) ;
34+ var headerRowHeights = trace . header . values . length ?
35+ headerValues [ 0 ] . map ( function ( ) { return trace . header . height ; } ) :
36+ [ c . emptyHeaderHeight ] ;
37+ var rowHeights = cellsValues . length ? cellsValues [ 0 ] . map ( function ( ) { return trace . cells . height ; } ) : [ ] ;
38+ var headerHeight = headerRowHeights . reduce ( sum , 0 ) ;
3039 var scrollHeight = groupHeight - headerHeight ;
3140 var minimumFillHeight = scrollHeight + c . uplift ;
3241 var anchorToRowBlock = makeAnchorToRowBlock ( rowHeights , minimumFillHeight ) ;
@@ -41,24 +50,27 @@ module.exports = function calc(gd, trace) {
4150 trace . columnwidth ;
4251 return isNumeric ( value ) ? Number ( value ) : 1 ;
4352 } ) ;
44- var totalColumnWidths = columnWidths . reduce ( function ( p , n ) { return p + n ; } , 0 ) ;
53+ var totalColumnWidths = columnWidths . reduce ( sum , 0 ) ;
4554
4655 // fit columns in the available vertical space as there's no vertical scrolling now
47- columnWidths = columnWidths . map ( function ( d ) { return d / totalColumnWidths * groupWidth ; } ) ;
56+ columnWidths = columnWidths . map ( function ( d ) { return d / totalColumnWidths * groupWidth ; } ) ;
57+
58+ var maxLineWidth = Math . max ( arrayMax ( trace . header . line . width ) , arrayMax ( trace . cells . line . width ) ) ;
4859
4960 var calcdata = {
5061 key : trace . index ,
5162 translateX : domain . x [ 0 ] * gd . _fullLayout . _size . w ,
5263 translateY : gd . _fullLayout . _size . h * ( 1 - domain . y [ 1 ] ) ,
5364 size : gd . _fullLayout . _size ,
5465 width : groupWidth ,
66+ maxLineWidth : maxLineWidth ,
5567 height : groupHeight ,
5668 columnOrder : columnOrder , // will be mutated on column move, todo use in callback
5769 groupHeight : groupHeight ,
5870 rowBlocks : rowBlocks ,
5971 headerRowBlocks : headerRowBlocks ,
6072 scrollY : 0 , // will be mutated on scroll
61- cells : trace . cells ,
73+ cells : extendFlat ( { } , trace . cells , { values : cellsValues } ) ,
6274 headerCells : extendFlat ( { } , trace . header , { values : headerValues } ) ,
6375 gdColumns : headerValues . map ( function ( d ) { return d [ 0 ] ; } ) ,
6476 gdColumnsOriginalOrder : headerValues . map ( function ( d ) { return d [ 0 ] ; } ) ,
@@ -89,6 +101,47 @@ module.exports = function calc(gd, trace) {
89101 return calcdata ;
90102} ;
91103
104+ function arrayMax ( maybeArray ) {
105+ if ( Array . isArray ( maybeArray ) ) {
106+ var max = 0 ;
107+ for ( var i = 0 ; i < maybeArray . length ; i ++ ) {
108+ max = Math . max ( max , arrayMax ( maybeArray [ i ] ) ) ;
109+ }
110+ return max ;
111+ }
112+ return maybeArray ;
113+ }
114+
115+ function sum ( a , b ) { return a + b ; }
116+
117+ // fill matrix in place to equal lengths
118+ // and ensure it's uniformly 2D
119+ function squareStringMatrix ( matrixIn ) {
120+ var matrix = matrixIn . slice ( ) ;
121+ var minLen = Infinity ;
122+ var maxLen = 0 ;
123+ var i ;
124+ for ( i = 0 ; i < matrix . length ; i ++ ) {
125+ if ( ! Array . isArray ( matrix [ i ] ) ) matrix [ i ] = [ matrix [ i ] ] ;
126+ minLen = Math . min ( minLen , matrix [ i ] . length ) ;
127+ maxLen = Math . max ( maxLen , matrix [ i ] . length ) ;
128+ }
129+
130+ if ( minLen !== maxLen ) {
131+ for ( i = 0 ; i < matrix . length ; i ++ ) {
132+ var padLen = maxLen - matrix [ i ] . length ;
133+ if ( padLen ) matrix [ i ] = matrix [ i ] . concat ( emptyStrings ( padLen ) ) ;
134+ }
135+ }
136+ return matrix ;
137+ }
138+
139+ function emptyStrings ( len ) {
140+ var padArray = new Array ( len ) ;
141+ for ( var j = 0 ; j < len ; j ++ ) padArray [ j ] = '' ;
142+ return padArray ;
143+ }
144+
92145function xScale ( d ) {
93146 return d . calcdata . columns . reduce ( function ( prev , next ) {
94147 return next . xIndex < d . xIndex ? prev + next . columnWidth : prev ;
0 commit comments