|
| 1 | +/** |
| 2 | +* Copyright 2012-2017, Plotly, Inc. |
| 3 | +* All rights reserved. |
| 4 | +* |
| 5 | +* This source code is licensed under the MIT license found in the |
| 6 | +* LICENSE file in the root directory of this source tree. |
| 7 | +*/ |
| 8 | + |
| 9 | +'use strict'; |
| 10 | + |
| 11 | +var c = require('./constants'); |
| 12 | +var extendFlat = require('../../lib/extend').extendFlat; |
| 13 | + |
| 14 | +// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying |
| 15 | +module.exports = function calc(gd, trace) { |
| 16 | + var domain = trace.domain; |
| 17 | + var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); |
| 18 | + var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); |
| 19 | + var headerRowHeights = trace.header.values[0].map(function() {return trace.header.height;}); |
| 20 | + var rowHeights = trace.cells.values[0].map(function() {return trace.cells.height;}); |
| 21 | + var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); |
| 22 | + var scrollHeight = groupHeight - headerHeight; |
| 23 | + var minimumFillHeight = scrollHeight + c.uplift; |
| 24 | + var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); |
| 25 | + var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); |
| 26 | + var headerRowBlocks = makeRowBlock(anchorToHeaderRowBlock, []); |
| 27 | + var rowBlocks = makeRowBlock(anchorToRowBlock, headerRowBlocks); |
| 28 | + var uniqueKeys = {}; |
| 29 | + var columnOrder = trace._fullInput.columnorder; |
| 30 | + var columnWidths = trace.header.values.map(function(d, i) { |
| 31 | + return Array.isArray(trace.columnwidth) ? |
| 32 | + trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : |
| 33 | + isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; |
| 34 | + }); |
| 35 | + var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); |
| 36 | + |
| 37 | + // fit columns in the available vertical space as there's no vertical scrolling now |
| 38 | + columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); |
| 39 | + |
| 40 | + var calcdata = { |
| 41 | + key: trace.index, |
| 42 | + translateX: domain.x[0] * gd._fullLayout._size.w, |
| 43 | + translateY: gd._fullLayout._size.h * (1 - domain.y[1]), |
| 44 | + size: gd._fullLayout._size, |
| 45 | + width: groupWidth, |
| 46 | + height: groupHeight, |
| 47 | + columnOrder: columnOrder, // will be mutated on column move, todo use in callback |
| 48 | + groupHeight: groupHeight, |
| 49 | + rowBlocks: rowBlocks, |
| 50 | + headerRowBlocks: headerRowBlocks, |
| 51 | + scrollY: 0, // will be mutated on scroll |
| 52 | + cells: trace.cells, |
| 53 | + headerCells: trace.header, |
| 54 | + gdColumns: trace.header.values.map(function(d) {return d[0];}), |
| 55 | + gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}), |
| 56 | + prevPages: [0, 0], |
| 57 | + scrollbarState: {scrollbarScrollInProgress: false}, |
| 58 | + columns: trace.header.values.map(function(label, i) { |
| 59 | + var foundKey = uniqueKeys[label]; |
| 60 | + uniqueKeys[label] = (foundKey || 0) + 1; |
| 61 | + var key = label + '__' + uniqueKeys[label]; |
| 62 | + return { |
| 63 | + key: key, |
| 64 | + label: label, |
| 65 | + specIndex: i, |
| 66 | + xIndex: columnOrder[i], |
| 67 | + xScale: xScale, |
| 68 | + x: undefined, // initialized below |
| 69 | + calcdata: undefined, // initialized below |
| 70 | + columnWidth: columnWidths[i] |
| 71 | + }; |
| 72 | + }) |
| 73 | + }; |
| 74 | + |
| 75 | + calcdata.columns.forEach(function(col) { |
| 76 | + col.calcdata = calcdata; |
| 77 | + col.x = xScale(col); |
| 78 | + }); |
| 79 | + |
| 80 | + return calcdata; |
| 81 | +}; |
| 82 | + |
| 83 | +function xScale(d) { |
| 84 | + return d.calcdata.columns.reduce(function(prev, next) { |
| 85 | + return next.xIndex < d.xIndex ? prev + next.columnWidth : prev; |
| 86 | + }, 0); |
| 87 | +} |
| 88 | + |
| 89 | +function makeRowBlock(anchorToRowBlock, auxiliary) { |
| 90 | + var blockAnchorKeys = Object.keys(anchorToRowBlock); |
| 91 | + return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}); |
| 92 | +} |
| 93 | + |
| 94 | +function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { |
| 95 | + |
| 96 | + var anchorToRowBlock = {}; |
| 97 | + var currentRowHeight; |
| 98 | + var currentAnchor = 0; |
| 99 | + var currentBlockHeight = 0; |
| 100 | + var currentBlock = makeIdentity(); |
| 101 | + var currentFirstRowIndex = 0; |
| 102 | + var blockCounter = 0; |
| 103 | + for(var i = 0; i < rowHeights.length; i++) { |
| 104 | + currentRowHeight = rowHeights[i]; |
| 105 | + currentBlock.rows.push({ |
| 106 | + rowIndex: i, |
| 107 | + rowHeight: currentRowHeight |
| 108 | + }); |
| 109 | + currentBlockHeight += currentRowHeight; |
| 110 | + if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { |
| 111 | + anchorToRowBlock[currentAnchor] = currentBlock; |
| 112 | + currentBlock.key = blockCounter++; |
| 113 | + currentBlock.firstRowIndex = currentFirstRowIndex; |
| 114 | + currentBlock.lastRowIndex = i; |
| 115 | + currentBlock = makeIdentity(); |
| 116 | + currentAnchor += currentBlockHeight; |
| 117 | + currentFirstRowIndex = i + 1; |
| 118 | + currentBlockHeight = 0; |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + return anchorToRowBlock; |
| 123 | +} |
| 124 | + |
| 125 | +function makeIdentity() { |
| 126 | + return { |
| 127 | + firstRowIndex: null, |
| 128 | + lastRowIndex: null, |
| 129 | + rows: [] |
| 130 | + }; |
| 131 | +} |
0 commit comments