From 8f0f78b0c05900f7e63b66117b9296446a83f5b4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 29 Jun 2017 02:41:18 +0200 Subject: [PATCH 001/281] table - initial --- lib/index.js | 1 + lib/table.js | 11 + src/traces/table/attributes.js | 154 ++++++++++ src/traces/table/base_plot.js | 33 +++ src/traces/table/calc.js | 28 ++ src/traces/table/colorbar.js | 51 ++++ src/traces/table/constants.js | 28 ++ src/traces/table/defaults.js | 104 +++++++ src/traces/table/index.js | 31 ++ src/traces/table/plot.js | 100 +++++++ src/traces/table/render.js | 474 ++++++++++++++++++++++++++++++ test/image/mocks/table_large.json | 94 ++++++ 12 files changed, 1109 insertions(+) create mode 100644 lib/table.js create mode 100644 src/traces/table/attributes.js create mode 100644 src/traces/table/base_plot.js create mode 100644 src/traces/table/calc.js create mode 100644 src/traces/table/colorbar.js create mode 100644 src/traces/table/constants.js create mode 100644 src/traces/table/defaults.js create mode 100644 src/traces/table/index.js create mode 100644 src/traces/table/plot.js create mode 100644 src/traces/table/render.js create mode 100644 test/image/mocks/table_large.json diff --git a/lib/index.js b/lib/index.js index 8c1b11fff73..f287b9533b8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -34,6 +34,7 @@ Plotly.register([ require('./pointcloud'), require('./heatmapgl'), require('./parcoords'), + require('./table'), require('./scattermapbox'), diff --git a/lib/table.js b/lib/table.js new file mode 100644 index 00000000000..96a16d9f31c --- /dev/null +++ b/lib/table.js @@ -0,0 +1,11 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = require('../src/traces/table'); diff --git a/src/traces/table/attributes.js b/src/traces/table/attributes.js new file mode 100644 index 00000000000..2ce56c23846 --- /dev/null +++ b/src/traces/table/attributes.js @@ -0,0 +1,154 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = require('../../components/colorscale/color_attributes'); +var colorbarAttrs = require('../../components/colorbar/attributes'); +var colorscales = require('../../components/colorscale/scales'); +var axesAttrs = require('../../plots/cartesian/layout_attributes'); +var fontAttrs = require('../../plots/font_attributes'); + +var extendDeep = require('../../lib/extend').extendDeep; +var extendFlat = require('../../lib/extend').extendFlat; + +module.exports = { + + domain: { + x: { + valType: 'info_array', + role: 'info', + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + description: [ + 'Sets the horizontal domain of this `table` trace', + '(in plot fraction).' + ].join(' ') + }, + y: { + valType: 'info_array', + role: 'info', + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + description: [ + 'Sets the vertical domain of this `table` trace', + '(in plot fraction).' + ].join(' ') + } + }, + + labelfont: extendFlat({}, fontAttrs, { + description: 'Sets the font for the `dimension` labels.' + }), + + dimensions: { + _isLinkedToArray: 'dimension', + label: { + valType: 'string', + role: 'info', + description: 'The shown name of the dimension.' + }, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + font: extendFlat({}, fontAttrs, { + description: 'Sets the font for the `dimension` values.' + }), + valueformat: { + valType: 'string', + dflt: '3s', + role: 'style', + description: [ + 'Sets the tick label formatting rule using d3 formatting mini-language', + 'which is similar to those of Python. See', + 'https://github.com/d3/d3-format/blob/master/README.md#locale_format' + ].join(' ') + }, + visible: { + valType: 'boolean', + dflt: true, + role: 'info', + description: 'Shows the dimension when set to `true` (the default). Hides the dimension for `false`.' + }, + range: { + valType: 'info_array', + role: 'info', + items: [ + {valType: 'number'}, + {valType: 'number'} + ], + description: [ + 'The domain range for the purpose of coloring. Defaults to the `values` extent.', + 'Must be an array of `[fromValue, toValue]` with finite numbers as elements.' + ].join(' ') + }, + values: { + valType: 'data_array', + role: 'info', + dflt: [], + description: [ + 'Dimension values. `values[n]` represents the value of the `n`th point in the dataset,', + 'therefore the `values` vector for all dimensions must be the same (longer vectors', + 'will be truncated). Each value must be a finite number.' + ].join(' ') + }, + description: 'The dimensions (variables) of the table view.' + }, + + line: extendFlat({}, + + // the default autocolorscale is set to Viridis - autocolorscale therefore defaults to false too, + // to avoid being overridden by the blue-white-red autocolor palette + extendDeep( + {}, + colorAttributes('line'), + { + colorscale: extendDeep( + {}, + colorAttributes('line').colorscale, + {dflt: colorscales.Viridis} + ), + autocolorscale: extendDeep( + {}, + colorAttributes('line').autocolorscale, + { + dflt: false, + description: [ + 'Has an effect only if line.color` is set to a numerical array.', + 'Determines whether the colorscale is a default palette (`autocolorscale: true`)', + 'or the palette determined by `line.colorscale`.', + 'In case `colorscale` is unspecified or `autocolorscale` is true, the default ', + 'palette will be chosen according to whether numbers in the `color` array are', + 'all positive, all negative or mixed.', + 'The default value is false, so that `table` colorscale can default to `Viridis`.' + ].join(' ') + } + ) + + } + ), + + { + showscale: { + valType: 'boolean', + role: 'info', + dflt: false, + description: [ + 'Has an effect only if `line.color` is set to a numerical array.', + 'Determines whether or not a colorbar is displayed.' + ].join(' ') + }, + colorbar: colorbarAttrs + } + ) +}; diff --git a/src/traces/table/base_plot.js b/src/traces/table/base_plot.js new file mode 100644 index 00000000000..e98c443179e --- /dev/null +++ b/src/traces/table/base_plot.js @@ -0,0 +1,33 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); +var Plots = require('../../plots/plots'); +var tablePlot = require('./plot'); + +exports.name = 'table'; + +exports.attr = 'type'; + +exports.plot = function(gd) { + var calcData = Plots.getSubplotCalcData(gd.calcdata, 'table', 'table'); + if(calcData.length) tablePlot(gd, calcData); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadTable = (oldFullLayout._has && oldFullLayout._has('table')); + var hasTable = (newFullLayout._has && newFullLayout._has('table')); + + if(hadTable && !hasTable) { + oldFullLayout._paperdiv.selectAll('.table').remove(); + oldFullLayout._paperdiv.selectAll('.table').remove(); + oldFullLayout._glimages.selectAll('*').remove(); + } +}; diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js new file mode 100644 index 00000000000..dc8c55c352b --- /dev/null +++ b/src/traces/table/calc.js @@ -0,0 +1,28 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var calcColorscale = require('../../components/colorscale/calc'); +var Lib = require('../../lib'); + +module.exports = function calc(gd, trace) { + var cs = !!trace.line.colorscale && Lib.isArray(trace.line.color); + var color = cs ? trace.line.color : Array.apply(0, Array(trace.dimensions.reduce(function(p, n) {return Math.max(p, n.values.length);}, 0))).map(function() {return 0.5;}); + var cscale = cs ? trace.line.colorscale : [[0, trace.line.color], [1, trace.line.color]]; + + if(hasColorscale(trace, 'line')) { + calcColorscale(trace, trace.line.color, 'line', 'c'); + } + + return [{ + lineColor: color, + cscale: cscale + }]; +}; diff --git a/src/traces/table/colorbar.js b/src/traces/table/colorbar.js new file mode 100644 index 00000000000..c4a8e54c69a --- /dev/null +++ b/src/traces/table/colorbar.js @@ -0,0 +1,51 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Plots = require('../../plots/plots'); +var Colorscale = require('../../components/colorscale'); +var drawColorbar = require('../../components/colorbar/draw'); + +module.exports = function colorbar(gd, cd) { + var trace = cd[0].trace, + line = trace.line, + cbId = 'cb' + trace.uid; + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + + if((line === undefined) || !line.showscale) { + Plots.autoMargin(gd, cbId); + return; + } + + var vals = line.color, + cmin = line.cmin, + cmax = line.cmax; + + if(!isNumeric(cmin)) cmin = Lib.aggNums(Math.min, null, vals); + if(!isNumeric(cmax)) cmax = Lib.aggNums(Math.max, null, vals); + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + line.colorscale, + cmin, + cmax + ), + { noNumericCheck: true } + ); + + cb.fillcolor(sclFunc) + .filllevels({start: cmin, end: cmax, size: (cmax - cmin) / 254}) + .options(line.colorbar)(); +}; diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js new file mode 100644 index 00000000000..b3993c0128e --- /dev/null +++ b/src/traces/table/constants.js @@ -0,0 +1,28 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + maxDimensionCount: 60, + overdrag: 45, + columnTitleOffset: 28, + columnExtentOffset: 10, + bar: { + width: 4, // Visible width of the filter bar + capturewidth: 10, // Mouse-sensitive width for interaction (Fitts law) + fillcolor: 'magenta', // Color of the filter bar fill + fillopacity: 1, // Filter bar fill opacity + strokecolor: 'white', // Color of the filter bar side lines + strokeopacity: 1, // Filter bar side stroke opacity + strokewidth: 1, // Filter bar side stroke width in pixels + handleheight: 16, // Height of the filter bar vertical resize areas on top and bottom + handleopacity: 1, // Opacity of the filter bar vertical resize areas on top and bottom + handleoverlap: 0 // A larger than 0 value causes overlaps with the filter bar, represented as pixels.' + } +}; diff --git a/src/traces/table/defaults.js b/src/traces/table/defaults.js new file mode 100644 index 00000000000..f459da69b52 --- /dev/null +++ b/src/traces/table/defaults.js @@ -0,0 +1,104 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var attributes = require('./attributes'); +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = require('../../components/colorscale/defaults'); +var maxDimensionCount = require('./constants').maxDimensionCount; + +function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { + + if(hasColorscale(traceIn, 'line')) { + coerce('line.colorscale'); + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); + } +} + +function dimensionsDefaults(traceIn, traceOut, fontDflt) { + var dimensionsIn = traceIn.dimensions || [], + dimensionsOut = traceOut.dimensions = []; + + var dimensionIn, dimensionOut, i; + var commonLength = Infinity; + + if(dimensionsIn.length > maxDimensionCount) { + Lib.log('table views support up to ' + maxDimensionCount + ' dimensions at the moment'); + dimensionsIn.splice(maxDimensionCount); + } + + function coerce(attr, dflt) { + return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); + } + + for(i = 0; i < dimensionsIn.length; i++) { + dimensionIn = dimensionsIn[i]; + dimensionOut = {}; + + if(!Lib.isPlainObject(dimensionIn)) { + continue; + } + + var values = coerce('values'); + var visible = coerce('visible', values.length > 0); + + if(visible) { + coerce('label'); + coerce('tickvals'); + coerce('ticktext'); + coerce('valueformat'); + coerce('range'); + Lib.coerceFont(coerce, 'font', fontDflt); + + commonLength = Math.min(commonLength, dimensionOut.values.length); + } + + dimensionOut._index = i; + dimensionsOut.push(dimensionOut); + } + + if(isFinite(commonLength)) { + for(i = 0; i < dimensionsOut.length; i++) { + dimensionOut = dimensionsOut[i]; + if(dimensionOut.visible && dimensionOut.values.length > commonLength) { + dimensionOut.values = dimensionOut.values.slice(0, commonLength); + } + } + } + + return dimensionsOut; +} + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + // make default font size 10px, + // scale linearly with global font size + var fontDflt = { + family: layout.font.family, + size: Math.round(layout.font.size * (10 / 12)), + color: layout.font.color + }; + + var dimensions = dimensionsDefaults(traceIn, traceOut, fontDflt); + + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + + coerce('domain.x'); + coerce('domain.y'); + + if(!Array.isArray(dimensions) || !dimensions.length) { + traceOut.visible = false; + } + + Lib.coerceFont(coerce, 'labelfont', fontDflt); +}; diff --git a/src/traces/table/index.js b/src/traces/table/index.js new file mode 100644 index 00000000000..bcdf85f12e9 --- /dev/null +++ b/src/traces/table/index.js @@ -0,0 +1,31 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Table = {}; + +Table.attributes = require('./attributes'); +Table.supplyDefaults = require('./defaults'); +Table.calc = require('./calc'); +Table.plot = require('./plot'); +Table.colorbar = require('./colorbar'); + +Table.moduleType = 'trace'; +Table.name = 'table'; +Table.basePlotModule = require('./base_plot'); +Table.categories = []; +Table.meta = { + description: [ + 'Table view for multidimensional exploratory data analysis.', + 'The samples are specified in `dimensions`.', + 'The colors are set in `line.color`.' + ].join(' ') +}; + +module.exports = Table; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js new file mode 100644 index 00000000000..eb10cebf018 --- /dev/null +++ b/src/traces/table/plot.js @@ -0,0 +1,100 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var table = require('./render'); + +module.exports = function plot(gd, cdTable) { + + var fullLayout = gd._fullLayout; + var svg = fullLayout._paper; + var root = fullLayout._paperdiv; + + var gdDimensions = {}; + var gdDimensionsOriginalOrder = {}; + + var size = fullLayout._size; + + cdTable.forEach(function(d, i) { + gdDimensions[i] = gd.data[i].dimensions; + gdDimensionsOriginalOrder[i] = gd.data[i].dimensions.slice(); + }); + + var hover = function(eventData) { + gd.emit('plotly_hover', eventData); + }; + + var unhover = function(eventData) { + gd.emit('plotly_unhover', eventData); + }; + + var columnMoved = function(i, visibleIndices) { + + // Have updated order data on `gd.data` and raise `Plotly.restyle` event + // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call + + function visible(dimension) {return !('visible' in dimension) || dimension.visible;} + + function newIdx(visibleIndices, orig, dim) { + var origIndex = orig.indexOf(dim); + var currentIndex = visibleIndices.indexOf(origIndex); + if(currentIndex === -1) { + // invisible dimensions initially go to the end + currentIndex += orig.length; + } + return currentIndex; + } + + function sorter(orig) { + return function sorter(d1, d2) { + var i1 = newIdx(visibleIndices, orig, d1); + var i2 = newIdx(visibleIndices, orig, d2); + return i1 - i2; + }; + } + + // drag&drop sorting of the visible dimensions + var orig = sorter(gdDimensionsOriginalOrder[i].filter(visible)); + gdDimensions[i].sort(orig); + + // invisible dimensions are not interpreted in the context of drag&drop sorting as an invisible dimension + // cannot be dragged; they're interspersed into their original positions by this subsequent merging step + gdDimensionsOriginalOrder[i].filter(function(d) {return !visible(d);}) + .sort(function(d) { + // subsequent splicing to be done left to right, otherwise indices may be incorrect + return gdDimensionsOriginalOrder[i].indexOf(d); + }) + .forEach(function(d) { + gdDimensions[i].splice(gdDimensions[i].indexOf(d), 1); // remove from the end + gdDimensions[i].splice(gdDimensionsOriginalOrder[i].indexOf(d), 0, d); // insert at original index + }); + + gd.emit('plotly_restyle'); + }; + + table( + root, + svg, + cdTable, + { + width: size.w, + height: size.h, + margin: { + t: size.t, + r: size.r, + b: size.b, + l: size.l + } + }, + { + hover: hover, + unhover: unhover, + columnMoved: columnMoved + }); +}; diff --git a/src/traces/table/render.js b/src/traces/table/render.js new file mode 100644 index 00000000000..4dad86ad8f9 --- /dev/null +++ b/src/traces/table/render.js @@ -0,0 +1,474 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var c = require('./constants'); +var Lib = require('../../lib'); +var d3 = require('d3'); +var Drawing = require('../../components/drawing'); + +function keyFun(d) {return d.key;} + +function repeat(d) {return [d];} + +function visible(dimension) {return !('visible' in dimension) || dimension.visible;} + +function dimensionExtent(dimension) { + + var lo = dimension.range ? dimension.range[0] : d3.min(dimension.values); + var hi = dimension.range ? dimension.range[1] : d3.max(dimension.values); + + if(isNaN(lo) || !isFinite(lo)) { + lo = 0; + } + + if(isNaN(hi) || !isFinite(hi)) { + hi = 0; + } + + // avoid a degenerate (zero-width) domain + if(lo === hi) { + if(lo === void(0)) { + lo = 0; + hi = 1; + } else if(lo === 0) { + // no use to multiplying zero, so add/subtract in this case + lo -= 1; + hi += 1; + } else { + // this keeps the range in the order of magnitude of the data + lo *= 0.9; + hi *= 1.1; + } + } + + return [lo, hi]; +} + +function ordinalScaleSnap(scale, v) { + var i, a, prevDiff, prevValue, diff; + for(i = 0, a = scale.range(), prevDiff = Infinity, prevValue = a[0], diff = null; i < a.length; i++) { + if((diff = Math.abs(a[i] - v)) > prevDiff) { + return prevValue; + } + prevDiff = diff; + prevValue = a[i]; + } + return a[a.length - 1]; +} + +function domainScale(height, padding, dimension) { + var extent = dimensionExtent(dimension); + return dimension.tickvals ? + d3.scale.ordinal() + .domain(dimension.tickvals) + .range(dimension.tickvals + .map(function(d) {return (d - extent[0]) / (extent[1] - extent[0]);}) + .map(function(d) {return (height - padding + d * (padding - (height - padding)));})) : + d3.scale.linear() + .domain(extent) + .range([height - padding, padding]); +} + +function unitScale(height, padding) {return d3.scale.linear().range([height - padding, padding]);} +function domainToUnitScale(dimension) {return d3.scale.linear().domain(dimensionExtent(dimension));} + +function ordinalScale(dimension) { + var extent = dimensionExtent(dimension); + return dimension.tickvals && d3.scale.ordinal() + .domain(dimension.tickvals) + .range(dimension.tickvals.map(function(d) {return (d - extent[0]) / (extent[1] - extent[0]);})); +} + +function unitToColorScale(cscale) { + + var colorStops = cscale.map(function(d) {return d[0];}); + var colorStrings = cscale.map(function(d) {return d[1];}); + var colorTuples = colorStrings.map(function(c) {return d3.rgb(c);}); + var prop = function(n) {return function(o) {return o[n];};}; + + // We can't use d3 color interpolation as we may have non-uniform color palette raster + // (various color stop distances). + var polylinearUnitScales = 'rgb'.split('').map(function(key) { + return d3.scale.linear() + .clamp(true) + .domain(colorStops) + .range(colorTuples.map(prop(key))); + }); + + return function(d) { + return polylinearUnitScales.map(function(s) { + return s(d); + }); + }; +} + +function unwrap(d) { + return d[0]; // plotly data structure convention +} + +function model(layout, d, i) { + var cd0 = unwrap(d), + trace = cd0.trace, + lineColor = cd0.lineColor, + cscale = cd0.cscale, + line = trace.line, + domain = trace.domain, + dimensions = trace.dimensions, + width = layout.width, + labelFont = trace.labelfont; + + var lines = Lib.extendDeep({}, line, { + color: lineColor.map(domainToUnitScale({values: lineColor, range: [line.cmin, line.cmax]})), + blockLineCount: c.blockLineCount, + canvasOverdrag: c.overdrag * c.canvasPixelRatio + }); + + var groupWidth = Math.floor(width * (domain.x[1] - domain.x[0])); + var groupHeight = Math.floor(layout.height * (domain.y[1] - domain.y[0])); + + var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; + var rowContentWidth = groupWidth; + var rowHeight = groupHeight; + + return { + key: i, + colCount: dimensions.filter(visible).length, + dimensions: dimensions, + tickDistance: c.tickDistance, + unitToColor: unitToColorScale(cscale), + lines: lines, + labelFont: labelFont, + translateX: domain.x[0] * width, + translateY: layout.height - domain.y[1] * layout.height, + pad: pad, + canvasWidth: rowContentWidth * c.canvasPixelRatio + 2 * lines.canvasOverdrag, + canvasHeight: rowHeight * c.canvasPixelRatio, + width: rowContentWidth, + height: rowHeight, + canvasPixelRatio: c.canvasPixelRatio + }; +} + +function viewModel(model) { + + var width = model.width; + var height = model.height; + var dimensions = model.dimensions; + var canvasPixelRatio = model.canvasPixelRatio; + + var xScale = function(d) {return width * d / Math.max(1, model.colCount - 1);}; + + var unitPad = c.verticalPadding / (height * canvasPixelRatio); + var unitPadScale = (1 - 2 * unitPad); + var paddedUnitScale = function(d) {return unitPad + unitPadScale * d;}; + + var viewModel = { + key: model.key, + xScale: xScale, + model: model + }; + + var uniqueKeys = {}; + + viewModel.dimensions = dimensions.filter(visible).map(function(dimension, i) { + var domainToUnit = domainToUnitScale(dimension); + var foundKey = uniqueKeys[dimension.label]; + uniqueKeys[dimension.label] = (foundKey || 0) + 1; + var key = dimension.label + (foundKey ? '__' + foundKey : ''); + return { + key: key, + label: dimension.label, + valueFormat: dimension.valueformat, + tickvals: dimension.tickvals, + ticktext: dimension.ticktext, + font: dimension.font, + ordinal: !!dimension.tickvals, + scatter: c.scatter || dimension.scatter, + xIndex: i, + crossfilterDimensionIndex: i, + visibleIndex: dimension._index, + height: height, + values: dimension.values, + paddedUnitValues: dimension.values.map(domainToUnit).map(paddedUnitScale), + xScale: xScale, + x: xScale(i), + canvasX: xScale(i) * canvasPixelRatio, + unitScale: unitScale(height, c.verticalPadding), + domainScale: domainScale(height, c.verticalPadding, dimension), + ordinalScale: ordinalScale(dimension), + domainToUnitScale: domainToUnit, + filter: [0, 1], + parent: viewModel, + model: model + }; + }); + + return viewModel; +} + +function lineLayerModel(vm) { + return c.layers.map(function(key) { + return { + key: key, + context: key === 'contextLineLayer', + pick: key === 'pickLineLayer', + viewModel: vm, + model: vm.model + }; + }); +} + +module.exports = function(root, svg, styledData, layout, callbacks) { + + var domainBrushing = false; + var linePickActive = true; + + var vm = styledData + .filter(function(d) { return unwrap(d).trace.visible; }) + .map(model.bind(0, layout)) + .map(viewModel); + + svg.style('background', 'rgba(255, 255, 255, 0)'); + var tableControlOverlay = svg.selectAll('.table') + .data(vm, keyFun); + + tableControlOverlay.exit().remove(); + + tableControlOverlay.enter() + .append('g') + .classed('table', true) + .attr('overflow', 'visible') + .style('box-sizing', 'content-box') + .style('position', 'absolute') + .style('left', 0) + .style('overflow', 'visible') + .style('shape-rendering', 'crispEdges') + .style('pointer-events', 'none'); + + tableControlOverlay + .attr('width', function(d) {return d.model.width + d.model.pad.l + d.model.pad.r;}) + .attr('height', function(d) {return d.model.height + d.model.pad.t + d.model.pad.b;}) + .attr('transform', function(d) { + return 'translate(' + d.model.translateX + ',' + d.model.translateY + ')'; + }); + + var tableControlView = tableControlOverlay.selectAll('.tableControlView') + .data(repeat, keyFun); + + tableControlView.enter() + .append('g') + .classed('tableControlView', true) + .style('box-sizing', 'content-box'); + + tableControlView + .attr('transform', function(d) {return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')';}); + + var yColumn = tableControlView.selectAll('.yColumn') + .data(function(vm) {return vm.dimensions;}, keyFun); + + function updatePanelLayouttable(yColumn, vm) { + var panels = vm.panels || (vm.panels = []); + var yColumns = yColumn.each(function(d) {return d;})[vm.key].map(function(e) {return e.__data__;}); + var panelCount = yColumns.length - 1; + var rowCount = 1; + for(var row = 0; row < rowCount; row++) { + for(var p = 0; p < panelCount; p++) { + var panel = panels[p + row * panelCount] || (panels[p + row * panelCount] = {}); + var dim1 = yColumns[p]; + var dim2 = yColumns[p + 1]; + panel.dim1 = dim1; + panel.dim2 = dim2; + panel.canvasX = dim1.canvasX; + panel.panelSizeX = dim2.canvasX - dim1.canvasX; + panel.panelSizeY = vm.model.canvasHeight / rowCount; + panel.y = row * panel.panelSizeY; + panel.canvasY = vm.model.canvasHeight - panel.y - panel.panelSizeY; + } + } + } + + function updatePanelLayoutScatter(yColumn, vm) { + var panels = vm.panels || (vm.panels = []); + var yColumns = yColumn.each(function(d) {return d;})[vm.key].map(function(e) {return e.__data__;}); + var panelCount = yColumns.length - 1; + var rowCount = panelCount; + for(var row = 0; row < panelCount; row++) { + for(var p = 0; p < panelCount; p++) { + var panel = panels[p + row * panelCount] || (panels[p + row * panelCount] = {}); + var dim1 = yColumns[p]; + var dim2 = yColumns[p + 1]; + panel.dim1 = yColumns[row + 1]; + panel.dim2 = dim2; + panel.canvasX = dim1.canvasX; + panel.panelSizeX = dim2.canvasX - dim1.canvasX; + panel.panelSizeY = vm.model.canvasHeight / rowCount; + panel.y = row * panel.panelSizeY; + panel.canvasY = vm.model.canvasHeight - panel.y - panel.panelSizeY; + } + } + } + + function updatePanelLayout(yColumn, vm) { + return (c.scatter ? updatePanelLayoutScatter : updatePanelLayouttable)(yColumn, vm); + } + + yColumn.enter() + .append('g') + .classed('yColumn', true); + + tableControlView.each(function(vm) { + updatePanelLayout(yColumn, vm); + }); + + yColumn + .attr('transform', function(d) {return 'translate(' + d.xScale(d.xIndex) + ', 0)';}); + + yColumn + .call(d3.behavior.drag() + .origin(function(d) {return d;}) + .on('drag', function(d) { + var p = d.parent; + linePickActive = false; + if(domainBrushing) { + return; + } + d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag, d3.event.x)); + d.canvasX = d.x * d.model.canvasPixelRatio; + yColumn + .sort(function(a, b) {return a.x - b.x;}) + .each(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd.xIndex); + dd.canvasX = dd.x * dd.model.canvasPixelRatio; + }); + + updatePanelLayout(yColumn, p); + + yColumn.filter(function(dd) {return Math.abs(d.xIndex - dd.xIndex) !== 0;}) + .attr('transform', function(d) {return 'translate(' + d.xScale(d.xIndex) + ', 0)';}); + d3.select(this).attr('transform', 'translate(' + d.x + ', 0)'); + yColumn.each(function(dd, i, ii) {if(ii === d.parent.key) p.dimensions[i] = dd;}); + }) + .on('dragend', function(d) { + var p = d.parent; + if(domainBrushing) { + if(domainBrushing === 'ending') { + domainBrushing = false; + } + return; + } + d.x = d.xScale(d.xIndex); + d.canvasX = d.x * d.model.canvasPixelRatio; + updatePanelLayout(yColumn, p); + d3.select(this) + .attr('transform', function(d) {return 'translate(' + d.x + ', 0)';}); + linePickActive = true; + + if(callbacks && callbacks.columnsMoved) { + callbacks.columnsMoved(p.key, p.dimensions.map(function(dd) {return dd.crossfilterDimensionIndex;})); + } + }) + ); + + yColumn.exit() + .remove(); + + var columnOverlays = yColumn.selectAll('.columnOverlays') + .data(repeat, keyFun); + + columnOverlays.enter() + .append('g') + .classed('columnOverlays', true); + + columnOverlays.selectAll('.column').remove(); + + var column = columnOverlays.selectAll('.column') + .data(repeat, keyFun); + + column.enter() + .append('g') + .classed('column', true); + + column + .selectAll('.domain, .tick>line') + .attr('fill', 'none') + .attr('stroke', 'black') + .attr('stroke-opacity', 0.25) + .attr('stroke-width', '1px'); + + column + .selectAll('text') + .style('text-shadow', '1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff') + .style('cursor', 'default') + .style('user-select', 'none'); + + var columnHeading = columnOverlays.selectAll('.columnHeading') + .data(repeat, keyFun); + + columnHeading.enter() + .append('g') + .classed('columnHeading', true); + + var columnTitle = columnHeading.selectAll('.columnTitle') + .data(repeat, keyFun); + + columnTitle.enter() + .append('text') + .classed('columnTitle', true) + .attr('text-anchor', 'end') + .style('cursor', 'ew-resize') + .style('user-select', 'none') + .style('pointer-events', 'auto'); + + columnTitle + .attr('transform', 'translate(0,' + -c.columnTitleOffset + ')') + .text(function(d) {return d.label;}) + .each(function(d) {Drawing.font(columnTitle, d.model.labelFont);}); + + var columnCells = columnOverlays.selectAll('.columnCells') + .data(repeat, keyFun); + + columnCells.enter() + .append('g') + .classed('columnCells', true); + + columnCells.each(function(d) {Drawing.font(d3.select(this), d.font);}); + + var columnCell = columnCells.selectAll('.columnCell') + .data(function(d) {return d.values.map(function(v, i) {return {key: i, dimension: d, model: d.model, value: v};});}, keyFun); + + columnCell.enter() + .append('g') + .classed('columnCell', true); + + columnCell + .attr('transform', function(d, i) {return 'translate(' + 0 + ',' + i * 20 + ')';}); + + var columnCellText = columnCell.selectAll('.columnCellText') + .data(repeat, keyFun); + + columnCellText.enter() + .append('text') + .classed('columnCellText', true) + .attr('alignment-baseline', 'middle') + .attr('text-anchor', 'end'); + + columnCellText + .text(function(d) { + const starSchema = d.dimension.ticktext && d.dimension.tickvals + if(starSchema) { + var lookup = {} + for(var i = 0; i < d.dimension.ticktext.length; i++) { + lookup[d.dimension.tickvals[i]] = d.dimension.ticktext[i] + } + } + return starSchema ? lookup[d.value] : d3.format(d.dimension.valueFormat)(d.value); + }); +}; diff --git a/test/image/mocks/table_large.json b/test/image/mocks/table_large.json new file mode 100644 index 00000000000..5a748795127 --- /dev/null +++ b/test/image/mocks/table_large.json @@ -0,0 +1,94 @@ +{ + "layout": { + "width": 1184, + "height": 400, + "title": "Widget parameters and cost", + "font": { + "color": "blue", + "size": 2, + "family": "sans-serif" + }, + "margin": {"t": 106, "r": 70, "b": 54, "l": 90} + }, + + "data": [{ + + "type": "table", + + "line": { + "showscale": true, + "reversescale": true, + "colorscale": "Viridis", + "valueformat": ",.2r", + "cmin": -4000, + "cmax": -100 + }, + + "labelfont": { + "family": "PT Sans Narrow", + "size": 16, + "weight": "bold", + "color": "grey" + }, + + "dimensions": [ + { + "constraintrange": [100000, 150000], + "label": "Height", + "valueformat": ".2s", + "values": [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 86600, 163400, 162600, 90000, 93100, 163000, 140500, 130000, 100700, 164500, 147700, 121700, 107500, 176600, 133600, 111100, 93100, 72400, 130100, 54500, 182600, 160300, 218100, 66500, 95800, 164800, 107200, 101600, 91100, 91100, 78100, 63300, 75700, 69600, 88500, 115800, 195700, 88900, 74800, 65400, 74900, 115300, 91400, 67800, 85300, 171300, 32000, 227900, 163200, 122899, 112300, 101500, 111199, 73300, 120800, 93100, 117200, 118500, 104800, 108500, 146500, 90300, 32000, 93000, 110700, 103500, 93300, 106300, 118500, 93000, 67600, 51400, 89000, 94000, 88200, 109600, 102100, 123600, 81900, 100000, 218100, 223200, 97300, 162100, 97400, 145800, 67400, 156500, 201900, 94300, 67800, 76100, 98300, 112400, 141800, 111400, 74700, 67300, 71100, 68900, 62100, 73800, 85500, 94400, 68300, 79400, 96300, 70400, 67300, 67300, 128400, 80800, 87600, 165900, 35900, 76200, 79000, 38900, 157200, 64400, 67700, 65700, 125800, 59300, 66100, 198700, 96100, 65600, 70300, 69200, 65500, 129300, 62600, 64200, 61800, 60800, 83100, 58800, 69600, 60400, 63500, 63500, 59300, 56600, 77200, 62900, 57300, 68000, 227900, 53099, 59100, 63099, 65900, 60500, 158100, 60199, 66600, 57699, 58900, 62699, 62000, 58600, 78700, 60700, 60400, 66000, 66000, 133300, 60800, 63200, 60400, 68400, 64600, 61400, 61900, 59000, 155600, 53500, 62000, 60599, 63700, 118500, 48000, 57400, 58200, 56800, 62300, 54500, 61300, 62200, 53200, 51600, 88500, 125100, 60800, 61500, 59200, 56300, 60800, 179300, 58300, 199500, 102100, 60800, 183200, 58800, 125000, 56900, 58600, 53700, 56100, 127600, 96100, 56700, 120500, 58600, 53600, 59000, 113800, 59000, 59200, 54500, 135700, 161200, 57300, 53000, 127000, 54600, 55300, 89700, 59400, 54900, 64700, 56200, 127100, 57000, 35400, 51800, 170100, 54000, 56700, 73600, 83200, 53000, 60500, 52699, 51600, 92100, 56600, 57400, 65500, 58400, 97600, 52900, 56700, 207600, 221900, 56500, 57600, 63900, 54700, 56900, 56000, 49700, 51600, 53400, 58500, 65000, 57100, 55900, 56100, 59800, 55300, 57699, 57600, 53200, 53900, 63000, 58400, 57500, 61200, 62699, 61000, 60199, 57600, 128800, 57699, 59900, 94200, 60900, 55100, 56300, 54100, 61400, 55000, 223100, 57699, 52200, 55300, 54000, 61000, 54800, 59500, 59000, 54400, 57800, 57100, 53200, 56300, 58300, 56100, 53900, 55100, 54100, 59500, 188900, 92300, 105500, 67100, 100000, 202500, 101800, 55900, 86800, 55300, 56700, 59400, 51400, 49000, 54600, 49400, 65300, 56800, 55599, 184500, 55000, 55000, 86900, 60100, 89700, 52500, 52500, 55500, 91700, 104600, 67500, 50700, 63300, 55400, 54500, 62600, 52699, 54100, 53400, 54800, 53200, 59900, 74500, 134800, 52400, 105300, 53700, 215200, 101700, 57200, 54400, 60300, 50800, 129400, 55100, 165700, 55000, 51700, 56000, 54000, 56500, 54500, 56000, 78600, 56300, 54700, 59600, 58300, 58800, 52400, 54500, 57100, 119100, 50100, 56500, 58900, 66500, 55599, 225400, 57699, 97200, 57000, 212900, 57300, 101600, 216500, 55400, 65800, 53000, 164200, 124600, 86300, 56000, 95200, 152700, 208299, 32000, 60400, 60700, 196600, 55000, 77200, 37500, 52000, 55300, 54100, 53500, 52800, 55100, 60100, 125000, 62400, 63700, 106900, 54300, 54100, 217500, 56400, 69700, 101000, 57500, 55100, 153500, 53700, 54700, 58099, 53900, 37000, 53200, 62000, 52100, 53900, 54500, 61600, 59700, 218200, 54700, 189200, 55599, 70600, 63700, 107100, 68800, 55700, 56400, 57400, 32000, 83200, 61200, 217900, 62100, 62400, 60900, 60700, 56300, 57600, 105399, 60000, 56700, 221200, 157700, 58200, 58099, 54700, 60900, 61300, 162600, 60900, 224600, 57699, 52699, 59600, 71200, 52100, 57500, 60500, 134900, 67200, 63700, 55000, 65199, 161600, 80300, 70000, 73300, 56200, 68400, 183700, 180100, 56400, 77600, 197800, 215799, 56600, 73300, 57500, 57500, 55199, 54800, 55900, 63300, 106400, 163200, 70800, 71900, 166000, 114100, 100900, 164300, 93600, 150000, 98200, 161400, 200400, 92600, 127600, 97600, 84400, 96600, 55599, 100500, 112000, 110000, 89800, 97700, 84200, 79600, 102400, 84800, 86900, 166600, 91300, 79600, 78100, 85800, 88200, 104200, 76600, 83300, 110800, 75600, 76100, 113800, 86400, 86800, 74800, 77100, 95200, 86900, 172300, 69700, 87500, 79600, 65300, 80800, 82400, 67100, 79400, 78500, 84800, 76100, 47200, 79400, 78200, 220300, 66100, 78300, 85900, 92100, 80800, 74500, 72800, 36200, 75800, 77400, 69600, 62600, 90700, 70700, 93100, 40400, 62600, 94400, 73600, 72000, 138200, 75400, 73300, 170700, 75500, 144500, 76600, 72000, 78200, 33200, 74100, 67900, 35300, 72000, 69900, 68600, 69400, 74300, 73400, 128400, 71800, 217399, 86500, 174200, 67800, 86500, 136800, 125399, 75200, 108000, 72700, 223900, 67300, 73600, 86500, 83800, 70900, 72900, 71300, 71800, 88600, 60300, 77200, 65300, 63300, 68900, 127100, 70700, 223600, 68700, 66000, 70800, 69000, 60599, 65700, 64200, 150700, 65000, 68700, 75800, 154200, 63300, 103400, 70200, 66400, 69200, 71000, 65700, 62300, 70100, 72200, 68700, 64600, 67600, 61800, 68100, 129200, 54900, 77600, 169700, 67100, 64100, 69300, 65700, 64600, 71800, 65199, 61800, 198400, 208800, 72100, 59800, 66200, 62900, 152500, 72200, 57600, 61300, 61900, 54900, 177200, 79500, 60800, 67000, 61100, 155600, 63400, 61500, 65100, 150000, 64500, 56800, 59600, 59000, 63000, 59000, 56700, 59000, 58400, 60700, 56700, 56900, 54900, 54800, 52200, 54700, 54800, 62000, 134700, 115700, 59700, 51500, 66900, 55599, 56400, 52900, 56800, 52900, 58200, 57699, 59100, 53200, 55800, 53300, 60400, 58200, 107500, 55500, 56800, 54400, 56100, 201400, 56600, 176200, 84400, 54100, 214700, 55800, 123699, 173700, 73600, 55199, 169200, 82600, 56500, 62300, 59100, 151900, 122700, 66700, 58200, 56400, 57400, 55000, 56000, 111900, 60400, 149700, 71700, 56600, 93800, 178700, 80900, 54700, 87700, 118900, 52300, 195900, 190200, 58000, 51300, 211300, 54500, 56600, 56900, 111800, 54900, 79400, 69700, 62800, 78600, 57600, 55199, 57000, 56600, 57200, 68600, 53800, 53900, 54900, 122500, 63500, 179300, 57800, 55700, 89400, 61800, 32000, 79000, 214100, 61400, 56000, 54900, 61900, 55100, 58800, 54400, 82600, 176300, 56600, 55100, 59100, 141700, 60100, 54500, 71700, 58900, 58800, 52100, 60000, 56900, 77700, 62600, 57900, 53300, 52400, 59800, 218900, 70700, 218200, 144700, 53300, 57200, 53900, 54000, 55400, 107700, 53800, 121300, 52400, 54600, 199500, 118200, 80900, 202900, 56600, 53400, 52100, 56600, 222600, 50300, 65100, 54200, 54600, 60199, 183700, 134800, 146300, 62500, 52600, 56500, 53099, 180700, 57800, 53500, 52000, 54300, 87300, 57699, 54300, 64400, 68500, 213299, 57300, 51800, 56300, 50000, 67200, 49500, 51100, 63500, 62400, 165500, 49300, 51200, 58099, 77700, 40800, 55000, 63500, 78000, 208000, 56900, 58099, 53900, 83600, 55599, 53800, 86300, 55100, 55700, 58400, 59100, 206600, 55000, 51100, 61600, 187000, 54400, 57699, 55700, 56800, 54000, 52200, 53700, 57100, 55100, 56600, 76700, 56400, 58700, 58200, 58900, 56300, 182300, 59500, 57200, 52300, 54600, 77100, 54300, 57400, 54200, 54200, 55100, 54600, 57400, 57500, 55900, 54900, 54400, 54400, 54600, 82300, 54400, 41600, 56500, 54000, 55900, 53400, 55100, 57300, 55199, 53500, 56300, 57500, 55800, 64600, 53900, 54100, 58500, 49700, 53400, 59500, 53700, 56900, 53700, 57000, 53800, 51100, 55900, 54700, 47900, 53500, 57400, 54700, 88600, 58400, 56900, 53200, 127200, 58900, 57400, 56600, 52600, 121800, 56900, 44700, 120600, 90300, 61300, 60700, 58900, 56800, 120300, 57600, 54700, 56800, 62600, 85700, 86700, 52400, 83900, 51800, 64500, 51100, 59200, 56100, 43000, 53700, 56000, 63600, 56900, 57800, 54100, 53700, 116199, 52200, 73800, 56100, 157600, 54400, 54600, 53300, 68400, 55100, 198900, 54500, 52800, 51600, 225100, 129100, 63800, 55400, 157100, 54300, 53800, 69400, 55700, 72100, 54600, 71900, 54300, 53800, 55700, 53900, 60900, 52300, 53000, 56300, 53400, 54300, 179100, 57500, 54300, 84000, 53300, 53500, 51500, 54300, 37700, 105600, 55100, 53600, 206700, 51700, 54200, 64900, 52600, 57699, 79900, 52500, 51300, 53900, 54100, 59300, 54100, 55800, 57100, 63800, 56800, 65900, 54400, 56900, 79000, 59300, 44200, 53099, 57500, 49300, 123600, 180700, 112500, 97500, 58600, 220400, 54000, 55300, 53500, 51900, 172200, 58600, 99300, 65900, 54800, 52900, 148300, 53099, 65300, 50500, 86100, 54500, 109600, 60400, 90200, 56500, 56500, 73100, 153500, 120900, 118300, 144300, 57100, 52500, 53400, 51300, 98900, 54800, 53400, 54600, 101100, 54500, 136800, 54700, 50500, 55599, 52200, 54000, 57699, 46900, 208800, 105399, 55500, 32100, 174200, 32599, 52100, 104700, 137900, 61300, 46100, 151600, 55700, 191100, 168600, 107500, 59500, 58300, 83100, 65400, 60100, 65300, 73500, 63900, 59600, 58700, 57800, 175200, 159100, 56100, 61600, 57800, 58000, 204800, 52500, 60800, 51200, 56900, 158200, 193900, 56200, 154800, 58500, 54100, 45400, 53500, 57000, 58900, 57600, 55100, 130399, 59800, 57400, 59600, 161700, 52600, 57800, 57600, 57400, 55900, 55500, 59600, 138800, 212200, 102300, 66700, 39800, 128400, 53300, 75600, 59000, 45300, 65100, 55700, 59100, 160900, 111500, 170700, 56600, 57500, 61000, 53300, 42900, 82100, 54700, 197200, 141700, 53800, 72400, 72800, 227900, 183900, 53700, 120700, 92600, 51800, 54100, 57100, 120700, 99900, 52600, 65300, 59900, 112899, 56800, 53300, 57200, 139700, 63500, 65800, 64600, 50500, 55700, 55900, 55800, 45800, 63800, 56400, 151500, 200100, 51100, 56100, 55599, 64500, 192300, 76100, 55300, 55199, 48000, 65800, 66300, 64400, 127100, 54300, 57000, 56100, 52000, 91000, 51800, 206800, 91900, 196200, 65199, 220500, 214899, 85700, 50800, 56000, 57699, 188500, 72100, 67200, 67000, 53000, 86100, 147100, 92600, 63500, 99800, 209400, 32000, 66500, 113699, 86800, 65100, 64000, 62400, 60300, 144700, 73100, 67200, 42100, 78400, 58600, 61800, 67900, 56500, 56400, 59700, 59000, 51900, 60100, 58300, 54900, 67800, 55700, 55599, 58400, 59800, 62400, 51300, 59800, 41700, 51400, 59700, 61700, 56500, 147400, 56500, 98300, 183500, 58200, 56200, 56800, 82700, 52900, 50700, 55700, 53500, 58500, 117100, 180400, 61500, 154900, 54900, 225000, 59900, 123300, 99300, 63000, 136000, 57300, 93900, 127000, 50800, 102700, 133500, 93200, 150900, 113300, 111000, 53300, 85600, 68800, 54000, 181900, 193000, 76500, 70500, 50900, 62100, 113600, 66700, 49800, 182900, 51300, 71000, 67100, 51800, 61300, 68500, 67500, 153900, 98200, 69700, 101100, 61700, 55700, 62800, 61100, 57600, 204200, 57400, 56400, 56800, 188400, 79500, 115600, 46300, 62300, 63200, 60500, 61200, 94900, 59400, 85900, 63800, 61100, 131300, 86500, 59400, 80800, 64100, 58000, 59100, 47300, 67400, 57500, 62400, 95200, 65600, 57600, 171100, 62300, 54100, 60900, 97200, 65000, 45800, 61200, 64300, 43300, 32700, 62100, 69500, 58400, 61600, 223700, 41200, 60800, 91500, 226800, 58200, 89200, 64800, 63200, 71900, 52400, 59600, 52000, 39700, 65600, 148900, 59600, 50000, 136800, 62900, 64100, 58900, 135400, 63099, 58600, 53200, 55599, 117800, 73300, 70900, 72100, 55100, 72400, 67200, 53600, 55000, 63800, 56000, 53600, 54000, 68900, 51200, 57500, 56700, 54700, 56100, 53700, 58200, 135500, 57300, 182200, 57900, 85200, 121100, 58600, 111300, 60199, 55300, 57500, 118400, 222000, 123200, 193400, 131300, 77300, 57800, 70300, 58400, 63099, 118900, 79200, 52800, 74600, 58600, 172100, 86500, 55400, 65300, 57500, 60100, 50000, 110200, 54400, 49600, 51900, 62100, 66100, 63000, 44900, 67200, 59400, 54800, 56200, 179700, 56600, 63900, 56900, 54900, 59800, 58500, 55100, 55000, 56100, 57100, 146400, 83200, 54500, 57600, 53600, 56600, 57200, 56200, 110200, 51700, 87300, 57200, 73700, 57000, 58600, 58700, 177800, 54400, 60599, 58000, 53000, 68400, 147200, 103600, 53900, 56100, 54700, 57699, 155400, 57400, 225799, 56100, 202000, 52100, 55900, 80100, 59300, 59000, 89200, 65300, 86100, 78400, 58900, 63500, 63900, 55000, 55599, 64700, 68200, 53200, 60900, 93600, 132900, 67000, 61400, 64600, 42600, 93500, 54800, 55900, 56100, 54900, 59600, 58800, 137400, 87500, 59300, 54400, 51500, 183200, 57200, 55900, 65000, 58000, 50500, 48700, 58600, 60500, 140700, 122500, 192500, 65300, 122600, 59600, 162700, 106700, 61300, 60599, 57699, 74400, 55100, 49600, 49800, 190300, 80200, 81600, 58000, 128100, 40300, 64900, 81300, 61900, 55199, 59900, 59100, 57000, 55800, 57600, 56300, 68800, 69300, 58800, 145700, 58600, 164700, 61000, 55700, 168000, 139200, 167700, 172000, 65600, 155200, 46200, 84200, 64000, 54000, 51600, 54200, 95000, 47200, 58900, 140400, 53400, 52400, 56500, 51500, 223800, 181600, 65800, 92700, 114800, 169200, 138500, 59300, 60300, 87100, 63600, 83000, 53600, 55300, 53600, 140500, 155100, 66700, 56000, 57699, 60900, 173700, 84700, 86100, 104700, 65700, 61300, 38600, 57500, 59000, 61100, 57100, 57000, 77500, 58800, 173800, 73600, 71200, 69400, 61200, 60400, 55100, 60599, 53800, 58500, 57400, 59200, 58099, 62600, 57699, 168800, 72600, 58800, 65400, 35800, 152500, 32000, 60100, 60300, 57200, 223900, 55900, 54200, 147200, 55700, 57300, 68800, 56800, 60100, 58200, 58600, 56100, 74800, 54500, 70600, 49400, 132700, 56700, 57300, 57000, 189800, 46300, 86100, 58700, 62500, 38900, 74000, 65500, 73200, 188900, 71000, 60199, 81700, 50100, 221900, 52500, 53099, 163500, 61000, 69000, 51800, 51200, 197600, 56600, 61600, 68800, 56900, 59700, 47800, 54600, 54800, 62200, 69300, 52300, 36000, 213600, 56600, 94200, 52500, 39100, 49600, 181000, 64200, 57300, 60100, 169800, 54400, 55400, 62600, 112700, 118500, 58000, 61100, 52600, 85800, 84400, 57600, 58800, 62200, 75200, 95900, 51800, 60100, 56500, 87300, 54300, 56300, 51500, 68300, 56700, 49100, 56800, 127700, 59400, 54100, 66900, 50900, 94900, 62900, 56700, 71300, 55700, 57600, 184300, 100500, 63000, 39000, 69400, 65100, 32000, 69300, 113500, 60000, 80100, 87600, 62100, 216000, 74700, 64300, 65500, 61700, 54100, 135300, 73100, 55100, 61500, 59200, 60900, 63600, 62200, 105800, 63500, 49500, 214600, 63400, 59900, 95600, 62000, 64000, 58099, 63300, 35500, 58700, 63300, 44200, 55599, 56000, 32000, 60199, 57000, 86100, 74700, 49600, 59100, 57400, 65400, 55900, 60700, 53200, 177300, 53200, 52100, 92700, 74300, 73900, 129600, 64500, 52699, 56000, 60800, 58300, 76400, 57000, 65500, 177100, 66800, 49900, 58900, 57300, 66700, 58200, 61600, 62100, 68200, 55199, 64300, 53500, 60199, 60700, 47600, 57000, 94400, 95200, 59600, 61200, 161400, 51800, 56900, 59000, 165500, 69500, 61800, 62600, 205200, 52600, 58800, 61100, 55599, 58600, 53900, 60400, 53400, 115399, 50100, 58700, 56300, 37900, 61800, 63400, 75100, 52400, 59800, 113300, 210700, 55800, 138900, 59600, 185300, 102700, 42100, 54900, 87200, 40900, 58200, 135400, 51700, 62500, 171300, 109000, 59800, 102700, 62600, 77800, 198400, 61200, 65400, 55100, 153700, 165900, 62000, 58600, 71000, 56500, 63099, 40900, 83200, 60599, 73800, 59800, 70900, 58500, 61300, 56300, 55100, 58000, 57800, 38000, 53500, 61800, 53800, 55500, 54300, 56000, 54700, 55700, 71500, 179800, 53500, 64100, 58400, 63700, 55500, 54600, 60800, 64300, 58800, 56600, 186600, 58200, 61500, 35100, 60100, 212399, 58600, 171800, 58300, 96700, 56900, 66400, 60300, 58500, 71300, 65100, 56300, 59600, 196000, 57800, 60000, 42600, 181600, 57300, 195500, 54200, 55400, 61500, 44500, 55000, 56300, 66700, 52699, 143500, 54400, 58400, 56300, 53300, 191900, 38000, 76000, 111000, 198900, 160900, 54500, 55400, 56100, 55000, 81500, 57100, 119400, 74200, 55700, 70200, 57600, 58600, 134700, 53000, 55100, 60199, 224100, 58000, 62500, 56500, 134200, 60300, 73800, 209400, 57000, 55900, 62200, 55900, 57500, 159200, 61200, 55300, 168000, 55700, 55300, 219200, 76600, 128800, 211000, 87500, 58600, 57500, 56300, 202600, 56200, 61100, 56800, 153900, 88400, 97400, 166600, 54900, 220000, 81800, 98600, 66900, 86500, 152300, 59100, 86400, 73100, 55000, 57100, 54800, 65500, 138200, 177700, 51600, 108699, 67000, 61500, 45500, 58500, 55400, 133800, 59200, 213100, 66600, 122100, 97100, 92100, 135300, 49600, 73000, 58200, 51900, 61400, 60700, 58099, 53300, 192600, 55800, 121500, 139700, 40100, 115700, 54300, 56000, 58400, 54400, 57699, 98800, 214800, 161400, 39300, 56900, 41700, 57000, 39600, 65600, 56600, 65900, 219100, 55800, 54300, 56300, 52600, 61100, 60800, 65500, 53700, 57100, 54800, 52500, 46500, 50900, 55199, 46300, 57100, 56300, 58900, 53500, 59800, 217399, 59300, 185900, 43300, 59000, 51700, 133000, 75300, 58000, 57699, 97800, 117400, 57200, 185500, 53800, 56700, 115600, 170200, 65900, 79000, 55199, 100000, 96700, 123699, 76700, 169400, 136700, 71400, 61000, 127400, 58800, 62400, 48400, 44200, 55599, 91600, 67000, 55599, 62800, 58000, 65600, 61700, 59300, 54300, 201700, 62699, 108400, 64100, 71100, 59900, 56300, 227900, 54100, 53900, 61700, 165200, 59100, 115800, 62400, 92400, 55599, 59500, 58800, 60500, 57400, 80700, 58500, 56500, 59800, 60400, 63300, 55199, 118900, 63500, 195000, 54700, 53099, 67100, 55700, 219200, 56900, 70300, 156000, 83600, 95100, 210200, 67000, 48000, 56700, 172100, 59400, 62800, 195400, 133800, 44800, 54900, 57300, 63000, 95000, 57600, 32000, 138600, 71000, 61200, 73500, 53400, 194800, 56900, 49200, 51900, 60300, 60900, 57000, 116100, 61300, 81000, 205000, 57800, 117000, 61300, 51800, 54300, 58600, 57800, 61500, 82400, 55900, 156600, 59300, 227800, 55000, 54400, 52000, 58900, 54100, 55599, 177500, 92500, 57100, 148600, 53400, 52200, 113200, 57300, 87100, 227100, 215200, 195700, 144300, 91500, 148700, 91100, 198200, 52600, 108500, 90700, 68600, 56500, 174600, 103400, 215600, 60500, 41600, 102899, 81100, 121300, 79200, 67400, 64400, 109400, 57000, 61400, 54800, 56300, 41500, 175700, 140300, 61000, 68200, 59700, 84600, 43300, 82600, 112300, 34900, 168200, 71700, 79800, 60800, 79500, 61700, 60800, 54800, 69300, 60100, 64100, 64500, 52100, 58600, 58900, 56200, 65500, 58700, 70400, 216700, 103400, 62699, 64600, 66600, 56300, 66300, 73800, 50500, 170100, 122000, 55300, 56000, 58099, 126500, 52200, 147000, 65900, 193200, 115300, 62600, 65900, 202300, 52800, 53900, 101000, 95000, 53700, 73300, 84400, 227900, 54300, 93200, 60500, 38400, 57300, 61400, 170400, 224500, 57100, 95000, 53400, 208900, 138800, 73200, 59600, 223600, 70400, 111900, 72900, 100500, 76000, 71600, 68000, 71100, 67700, 75900, 74200, 72800, 66500, 69400, 66200, 59400, 61000, 52300, 62900, 71200, 55400, 67000, 59300, 63200, 64500, 65100, 222600, 183400, 59600, 40400, 55599, 58500, 125000, 64700, 115399, 66400, 54500, 81700, 124400, 60500, 56300, 53900, 32000, 64200, 64800, 58300, 56800, 65000, 62800, 62300, 53200, 58300, 61300, 58600, 64400, 58099, 55700, 158400, 155100, 49700, 170000, 213500, 75600, 162300, 59900, 47000, 223600, 187300] + }, + { + "label": "Width", + "valueformat": "#0x", + "font": { + "color": "blue" + }, + "range": [0, 700000], + "values": [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 436900, 373600, 268630, 439000, 381800, 491200, 402800, 381400, 485600, 600000, 372200, 394700, 383800, 401100, 356500, 313200, 487100, 490700, 432299, 530300, 521500, 456700, 333800, 343200, 394000, 328200, 487700, 383600, 317700, 324600, 482900, 515100, 500100, 562700, 486000, 453400, 352900, 331300, 496200, 469099, 472500, 354700, 507700, 509000, 439300, 525300, 347600, 379000, 432800, 378800, 383200, 523800, 600000, 313600, 497700, 411300, 420000, 381100, 342800, 385900, 268630, 495800, 488000, 446400, 397900, 373300, 385700, 396500, 475700, 510600, 586800, 596000, 407600, 439200, 440800, 393100, 274600, 291900, 509799, 432800, 303000, 530600, 515900, 376800, 377400, 553500, 433600, 270800, 288000, 488000, 306800, 418000, 456900, 526300, 524500, 524000, 418800, 442800, 443200, 497200, 427500, 510300, 476000, 382700, 472200, 380400, 472900, 541100, 528200, 441599, 374600, 414099, 437299, 272500, 550000, 417299, 443700, 268630, 545800, 403400, 534400, 557200, 545200, 537400, 464300, 571200, 589400, 564000, 466500, 514500, 433200, 293600, 550100, 466599, 450100, 557200, 489000, 512200, 445600, 531000, 504400, 459799, 528800, 579800, 352900, 520700, 532000, 477900, 395600, 478900, 461300, 481400, 507500, 487200, 522299, 496000, 499600, 485200, 491500, 548300, 526000, 489600, 444000, 500900, 527600, 533200, 450000, 566500, 486300, 500700, 534900, 493000, 481100, 482500, 490900, 510200, 584700, 560700, 492000, 474600, 495300, 594100, 433700, 522500, 513100, 507500, 488100, 506400, 510400, 482700, 500400, 532000, 477700, 369600, 491200, 499400, 489200, 509099, 513600, 479600, 507299, 547600, 415300, 485900, 410400, 507700, 546700, 503300, 503600, 547700, 509200, 522400, 319700, 517200, 473000, 506800, 511400, 559200, 537900, 515300, 487500, 519000, 361100, 270800, 519000, 518200, 508200, 503900, 516500, 508600, 504900, 506500, 505300, 522000, 507500, 521400, 504600, 521400, 418700, 516700, 508400, 515400, 387000, 522299, 557300, 516599, 510600, 383600, 514700, 516700, 515600, 528200, 491500, 517900, 505000, 430300, 425300, 517800, 512600, 511599, 511300, 501599, 519099, 359700, 522400, 510400, 501100, 524600, 516000, 513800, 503100, 517000, 511400, 513700, 504000, 506900, 517000, 535700, 572700, 497900, 501900, 512600, 513800, 515000, 520700, 295100, 509700, 522299, 338800, 521300, 517200, 519500, 520800, 509300, 520700, 356000, 523000, 513600, 525100, 515700, 510000, 528300, 565200, 509300, 515500, 526900, 514200, 522200, 518500, 557400, 565100, 530700, 511100, 538200, 483700, 588800, 285200, 569100, 520800, 406300, 278300, 569500, 513900, 289000, 519600, 513600, 526900, 525500, 530300, 502000, 480000, 518500, 513000, 516900, 507000, 534300, 520400, 488500, 536000, 518900, 519000, 509400, 535500, 533600, 384900, 542700, 517200, 535700, 520500, 517100, 538700, 525900, 524200, 517100, 523600, 512900, 542400, 306800, 544600, 516599, 582200, 519900, 510900, 427200, 521300, 525900, 438200, 523500, 480000, 519600, 325400, 523300, 525200, 526500, 516400, 523800, 525400, 518700, 530800, 526400, 524400, 566400, 519500, 519700, 518400, 580400, 520600, 567600, 585000, 519300, 524300, 520800, 520900, 533400, 529500, 583500, 531400, 450000, 557600, 420700, 402900, 524500, 518700, 521800, 316400, 497100, 518900, 504400, 539400, 507000, 339700, 493800, 496700, 517500, 523400, 524400, 526200, 311300, 519200, 327600, 520400, 524800, 526400, 519200, 485200, 361000, 519300, 574400, 330400, 511800, 511200, 592800, 520900, 390400, 322200, 524600, 513300, 542400, 517200, 527300, 512700, 516100, 570800, 508900, 523500, 543500, 513700, 519700, 469000, 557400, 515000, 511000, 382700, 521400, 497900, 571100, 514099, 461100, 505600, 563300, 509200, 446300, 458000, 518000, 316500, 525600, 515700, 468600, 516300, 515400, 499000, 487500, 486900, 519099, 270200, 290900, 518000, 509900, 519300, 517299, 468700, 582300, 517200, 461100, 558600, 490500, 499099, 507100, 517600, 535200, 512100, 375300, 506100, 502200, 519600, 559900, 531200, 508100, 553600, 510700, 538600, 525200, 286400, 581800, 534900, 503500, 345400, 428300, 539400, 552000, 523400, 516300, 514099, 519200, 515800, 508000, 500400, 374900, 529900, 527100, 600000, 309600, 583500, 600000, 376000, 473900, 484799, 419300, 287200, 596600, 464600, 398900, 383900, 487000, 431900, 490700, 600000, 381100, 515800, 381500, 540900, 539100, 416500, 428800, 439300, 441300, 496000, 550800, 414300, 422100, 598200, 387800, 561100, 364000, 359700, 523400, 455300, 600000, 380400, 424000, 458600, 382500, 401100, 425100, 550500, 436599, 493200, 393200, 437900, 401100, 386300, 432299, 444799, 428200, 368800, 415700, 369900, 413400, 413000, 482100, 436000, 368600, 369300, 401300, 400400, 418300, 432299, 278800, 436100, 411800, 431300, 551100, 406300, 541500, 404200, 547200, 437000, 390200, 417900, 415800, 460600, 434900, 442600, 309300, 452000, 272200, 459700, 423300, 414799, 468900, 429300, 436700, 427400, 438800, 421100, 421700, 434000, 470700, 474799, 521599, 414400, 307300, 416700, 579600, 432400, 566100, 416200, 432500, 483100, 373200, 494799, 507400, 489700, 440800, 389200, 436599, 418000, 446500, 450700, 445200, 594100, 443900, 489000, 493300, 448900, 449700, 406000, 437400, 278100, 453400, 509500, 433000, 431200, 308600, 507500, 452500, 524700, 451700, 468700, 423600, 447200, 472600, 418500, 466000, 457000, 442299, 455000, 458400, 463800, 450900, 452900, 544200, 456500, 521700, 490900, 457200, 502500, 499099, 446800, 597000, 440600, 478700, 428700, 556900, 498300, 442000, 437900, 419000, 486000, 490700, 463000, 505500, 496700, 486200, 528300, 434200, 502600, 502400, 477800, 470500, 533400, 520700, 508400, 346400, 498900, 511300, 486900, 499300, 508100, 545700, 458400, 524300, 504700, 497299, 454300, 501100, 499900, 497800, 506900, 494500, 501000, 515300, 515000, 505300, 520200, 524099, 502600, 483000, 413400, 562300, 511700, 523500, 478800, 514600, 511100, 505500, 505300, 519099, 499600, 506900, 510500, 519900, 512400, 520400, 504500, 500900, 433200, 515900, 500700, 517100, 508200, 505900, 498900, 274800, 523200, 518100, 434600, 491100, 439900, 508300, 338800, 513900, 464600, 524000, 511100, 565900, 503700, 331700, 484200, 533800, 530700, 519799, 544000, 513200, 466100, 484799, 537100, 541300, 513500, 515100, 495600, 580400, 514600, 517000, 519600, 552000, 538400, 399700, 448000, 522100, 503600, 353100, 511300, 515700, 487700, 421700, 509200, 600000, 422400, 523700, 526700, 513000, 521500, 516400, 518100, 513300, 516700, 524400, 499099, 517299, 428600, 514700, 540300, 507500, 517200, 464900, 519099, 512100, 537200, 440900, 507900, 522500, 514799, 513900, 523500, 510100, 525100, 548400, 361100, 512700, 518100, 524400, 588900, 527800, 528500, 341500, 500100, 510300, 516000, 504200, 502900, 424200, 506599, 502700, 511000, 512200, 524099, 595200, 415700, 460400, 361800, 519700, 514300, 527300, 516900, 512900, 532100, 514900, 312800, 510400, 515100, 518500, 383900, 269400, 547800, 515000, 515100, 514300, 518700, 316300, 508700, 503200, 512700, 511599, 515500, 506599, 384900, 362200, 527700, 527500, 515600, 510100, 289800, 517400, 510600, 531900, 513800, 530100, 517600, 522700, 522900, 525700, 376000, 520100, 512100, 513900, 512400, 528600, 521900, 498500, 530200, 514700, 494200, 315900, 527900, 514700, 521599, 521599, 526700, 516400, 507900, 542600, 518600, 521500, 523500, 459700, 513400, 517900, 515400, 521400, 512900, 517600, 522100, 274700, 520800, 511599, 517000, 428600, 520500, 519799, 522800, 526400, 506700, 514000, 513100, 517900, 520200, 517600, 583600, 526800, 524400, 523900, 515900, 523300, 498700, 524200, 519200, 517500, 525100, 549400, 526000, 517200, 516900, 520700, 521000, 521300, 525700, 527200, 519400, 518600, 516900, 519600, 517400, 496300, 527400, 322400, 518300, 519200, 518400, 523400, 523100, 516599, 516100, 517900, 512500, 514600, 519500, 514200, 517600, 520200, 519200, 515200, 520100, 517000, 519600, 509900, 520900, 519799, 519900, 518200, 512400, 517700, 526200, 516700, 519799, 519900, 382200, 518900, 520000, 518200, 488700, 523600, 522299, 522299, 521900, 295200, 511599, 499400, 526900, 572800, 478500, 570100, 520000, 516599, 530600, 509799, 526000, 512000, 491599, 530200, 581800, 525800, 529700, 522200, 598700, 517400, 508500, 510200, 428700, 522200, 507100, 517299, 527600, 534400, 526500, 520700, 486900, 526200, 525600, 514799, 510400, 514900, 529600, 520100, 330400, 520800, 401100, 520600, 516000, 525100, 388800, 404700, 525800, 526400, 480100, 525700, 515300, 391100, 518100, 431599, 527800, 430300, 517400, 518700, 523500, 512400, 514300, 516100, 517299, 508200, 520900, 527200, 296700, 514400, 520100, 289600, 513900, 528000, 522700, 527600, 308500, 415200, 522800, 527500, 402800, 521400, 523300, 518800, 521200, 522200, 547400, 525300, 522800, 518000, 524800, 518300, 518300, 534100, 518400, 530400, 512800, 520500, 524900, 522500, 520200, 537200, 307300, 517200, 527300, 514099, 557900, 521599, 525600, 492800, 533800, 359300, 522299, 546000, 514200, 401500, 475200, 523900, 394000, 517800, 525400, 517600, 382800, 513200, 414900, 519000, 517100, 525300, 421700, 515300, 453800, 522299, 525300, 522200, 297000, 402100, 440400, 462900, 517700, 514200, 522299, 526700, 382000, 513200, 519799, 521000, 436200, 516400, 490400, 514099, 526800, 510600, 513400, 509900, 518900, 512400, 500400, 521700, 517100, 390400, 589900, 327700, 517100, 499799, 565300, 522299, 589000, 495000, 519099, 502299, 433100, 413000, 540000, 503200, 563400, 521599, 553100, 511500, 503200, 558600, 510200, 499799, 510100, 308500, 410700, 518400, 522700, 532000, 502400, 386700, 512700, 538900, 522900, 516300, 396900, 545300, 517400, 393900, 495600, 529600, 552900, 516900, 519300, 521800, 495100, 513500, 583300, 516800, 516300, 526400, 550500, 526300, 517100, 516800, 510400, 525000, 526500, 518200, 414300, 548400, 395800, 447800, 419799, 530100, 532300, 493200, 522600, 373100, 445500, 530000, 520500, 560400, 440000, 297700, 524200, 526100, 518600, 528400, 400700, 503000, 508600, 545500, 555400, 520600, 494900, 473200, 521599, 471700, 509099, 526800, 510800, 525700, 516900, 498300, 595700, 526300, 520600, 525600, 519400, 380300, 514099, 506100, 524000, 321100, 522500, 520000, 520600, 529700, 521800, 510300, 520500, 385100, 522200, 518300, 577600, 588400, 536100, 513100, 518000, 419000, 480700, 392500, 515900, 517400, 353900, 520800, 448300, 511200, 502700, 518500, 512900, 521300, 519799, 535700, 512299, 407000, 517100, 322600, 518700, 297300, 366500, 600000, 515200, 516300, 490700, 408800, 525700, 504300, 509600, 521300, 481400, 359700, 371300, 511900, 504300, 451300, 467600, 507700, 532300, 470600, 516800, 590300, 522000, 526000, 463900, 455600, 518500, 406100, 475600, 529000, 547300, 529000, 531400, 517500, 527800, 526600, 459500, 494200, 500000, 487000, 469000, 511300, 511700, 508600, 504500, 519900, 521700, 522299, 400400, 511100, 513900, 513900, 511100, 408500, 498900, 490600, 559100, 514200, 505500, 506300, 503800, 516599, 524200, 510100, 510600, 505700, 395700, 523100, 506599, 542700, 512700, 366700, 511800, 386800, 397700, 511000, 404200, 518300, 499400, 520500, 511800, 555900, 465500, 268630, 582200, 305800, 500800, 518400, 472200, 512700, 483300, 405400, 573000, 465600, 516500, 476000, 472000, 546000, 496200, 503400, 414000, 516800, 514000, 520800, 523700, 502900, 513900, 515400, 318200, 511500, 469900, 379700, 515300, 504200, 506500, 495500, 523200, 297100, 508100, 525600, 522800, 321100, 507299, 423900, 536700, 394000, 527100, 506900, 515400, 447800, 509900, 490900, 508000, 493400, 523200, 429900, 486800, 522100, 505400, 517299, 506800, 448600, 489000, 496800, 504300, 486200, 500300, 525300, 278500, 501900, 512400, 510400, 530000, 511500, 370200, 507600, 504500, 373400, 485300, 497600, 504200, 501100, 505400, 587500, 373900, 511500, 492299, 560600, 506500, 421500, 506100, 509099, 509300, 508600, 511300, 515200, 376500, 499900, 558600, 500200, 514400, 293900, 470700, 407400, 490100, 375800, 406100, 506100, 520900, 514099, 415600, 506200, 581600, 435400, 512500, 432800, 504200, 513900, 529300, 506000, 507000, 518400, 520600, 515900, 512200, 508200, 517900, 497500, 497100, 523300, 506800, 471000, 500600, 269500, 508100, 512600, 584400, 505900, 425000, 501900, 513300, 526800, 584700, 472500, 287400, 573200, 510700, 492200, 517600, 506300, 502800, 509200, 514400, 508800, 520600, 518200, 515100, 340000, 510500, 521000, 517400, 516800, 519900, 476700, 357200, 514000, 404600, 519300, 514900, 501200, 521200, 559700, 503000, 514500, 518100, 515100, 458600, 519200, 518300, 530500, 501100, 520600, 503800, 521599, 527200, 519300, 534200, 433200, 521599, 512100, 510400, 518500, 511599, 516500, 505600, 594900, 528900, 407600, 510400, 425800, 517100, 508700, 516599, 543700, 520400, 506300, 511599, 523000, 554000, 332400, 379900, 511500, 525100, 513700, 516400, 513600, 503400, 510400, 511200, 352600, 515200, 524000, 382400, 521900, 536300, 445300, 427200, 508700, 523800, 518800, 538100, 470400, 511300, 520900, 518700, 516200, 520700, 526600, 367700, 362200, 507200, 528800, 508200, 380900, 372500, 520300, 521500, 517900, 464000, 525900, 522299, 345600, 597300, 549000, 507000, 508800, 569100, 513400, 511599, 539300, 519700, 517299, 519300, 507600, 523200, 493300, 465700, 577300, 538600, 589000, 460100, 325400, 440200, 552600, 537500, 514200, 528100, 474900, 460000, 463300, 401500, 340400, 340200, 518700, 517400, 560500, 505200, 276800, 510800, 530500, 513100, 515000, 523300, 512000, 510600, 517400, 365200, 596600, 517500, 358600, 515700, 545500, 553000, 505000, 487000, 484700, 349200, 488700, 532400, 436200, 411300, 492600, 477600, 511000, 506500, 517299, 358800, 400700, 555400, 494900, 372200, 507800, 511300, 520300, 542100, 355900, 571500, 552800, 467500, 430700, 339400, 564100, 600000, 478700, 454500, 554800, 458400, 519300, 521700, 484099, 359500, 567700, 535200, 555500, 541900, 520500, 479700, 501100, 533700, 554300, 552300, 379700, 522500, 404900, 508300, 538600, 573200, 532700, 557100, 565900, 518500, 309200, 522100, 538500, 509400, 533200, 539900, 511900, 535400, 519900, 542900, 556800, 523100, 505900, 382700, 527400, 451500, 518400, 479300, 535600, 493100, 516300, 510800, 529600, 274700, 516500, 522400, 470500, 526800, 519300, 401300, 519000, 518900, 441599, 526800, 510100, 349400, 505000, 531900, 461100, 272200, 521500, 514799, 519200, 535000, 424300, 505000, 525600, 510500, 375100, 407500, 408600, 425000, 583700, 420700, 508100, 574900, 513700, 324400, 512299, 522900, 552100, 510800, 418200, 498000, 510900, 444700, 528100, 526300, 504099, 521300, 509500, 565800, 509700, 531100, 512400, 506400, 528700, 368900, 346700, 520300, 599300, 519400, 364400, 520100, 445700, 520200, 531600, 504500, 295700, 500200, 513200, 460600, 547600, 481400, 515700, 518100, 499700, 337200, 330600, 517500, 525300, 479000, 460400, 536200, 470500, 516100, 506500, 482200, 507800, 499600, 519099, 504400, 518800, 331800, 498100, 469400, 486200, 518400, 504099, 518000, 399400, 511000, 512200, 571100, 518000, 524900, 447600, 368500, 511200, 382200, 521000, 513400, 515600, 514300, 529500, 519400, 347900, 516200, 522900, 295600, 464799, 514099, 465600, 512000, 522000, 334300, 401000, 522700, 514200, 513900, 459099, 507700, 510500, 316200, 518900, 550100, 458700, 513200, 480300, 445900, 513400, 519000, 510700, 519000, 448300, 486200, 514400, 441700, 471200, 537400, 381700, 503700, 484799, 485800, 483000, 505100, 496599, 502100, 497800, 518000, 502500, 517100, 363100, 511400, 489600, 484900, 485300, 508000, 419300, 473900, 511800, 505800, 483300, 503700, 501200, 515200, 486100, 589600, 479300, 520400, 517299, 513300, 522100, 451700, 510600, 495600, 434900, 513400, 498600, 527900, 507400, 500300, 489300, 500700, 290900, 432000, 493800, 553300, 327400, 519799, 510100, 501500, 451400, 512400, 504400, 498200, 522200, 517800, 498900, 507200, 508300, 494099, 507400, 485200, 523800, 351500, 529700, 500700, 504500, 386000, 506400, 508300, 491700, 432100, 502800, 357100, 512700, 503000, 560900, 514400, 352000, 333500, 377100, 500500, 450100, 377500, 499799, 303100, 501800, 511000, 356300, 425300, 513500, 418000, 490600, 410700, 543000, 496700, 533000, 520000, 528400, 360400, 504900, 497400, 445000, 508600, 509300, 431700, 387900, 444799, 436200, 496000, 490500, 496900, 499000, 516800, 493000, 498700, 503200, 387400, 512900, 516900, 499400, 519400, 505500, 531300, 510900, 517700, 556400, 538300, 512500, 581200, 497200, 464200, 506200, 515000, 505400, 529900, 506100, 502600, 440800, 505600, 589800, 503100, 504099, 508200, 511700, 497200, 507800, 530800, 495000, 513100, 505600, 500700, 551700, 502600, 501599, 497900, 566800, 511100, 501800, 352200, 562800, 513500, 563100, 503000, 499099, 587700, 512900, 508300, 512700, 591100, 514200, 523800, 511000, 516700, 511900, 514300, 279100, 381800, 511700, 527600, 598300, 434600, 511000, 519900, 522200, 531000, 483500, 519700, 600000, 503700, 505800, 498400, 515800, 516900, 322900, 523700, 511500, 519600, 399600, 518500, 519700, 397500, 484600, 513700, 268630, 315400, 517200, 514500, 505900, 515300, 516000, 473100, 509099, 514500, 301900, 490500, 486900, 380200, 531800, 455000, 425100, 448300, 515200, 527100, 522299, 344700, 514200, 518500, 519099, 497800, 475100, 440200, 459700, 515900, 376300, 304500, 445500, 485800, 375000, 354000, 513200, 309700, 472900, 507299, 516300, 521900, 569700, 546300, 327100, 517900, 578300, 518800, 524000, 386000, 531300, 510600, 378600, 521400, 354000, 520200, 596800, 524200, 557800, 525100, 383600, 433600, 528500, 305900, 526000, 530100, 519200, 523900, 543400, 527400, 310200, 525900, 442000, 404400, 515800, 516599, 558500, 523300, 514200, 479700, 357800, 457800, 380700, 514900, 341800, 524500, 407400, 516300, 532800, 476599, 281100, 520600, 519500, 524300, 527000, 526200, 522400, 488700, 523100, 524200, 536500, 530300, 396000, 514700, 540900, 428100, 531600, 520600, 525500, 525100, 537000, 330700, 552700, 497800, 318000, 537300, 472299, 298100, 377500, 529200, 533300, 531200, 380000, 537300, 583800, 535800, 511200, 379700, 472600, 579400, 444400, 509799, 433500, 430500, 523700, 500600, 277800, 535700, 518500, 530200, 560800, 516200, 522700, 525000, 561000, 531700, 549000, 517200, 522600, 514000, 512200, 516500, 511400, 522600, 519700, 402100, 524900, 339000, 534900, 541700, 546700, 519600, 348100, 527100, 523700, 498600, 535500, 504700, 456200, 509300, 499500, 503600, 517700, 507100, 513500, 520900, 545600, 515300, 525500, 515300, 412700, 550000, 507800, 594700, 275700, 284100, 531200, 524300, 497600, 526100, 424000, 513200, 406100, 520600, 524000, 484600, 590700, 573700, 402900, 521400, 450200, 520500, 366400, 414500, 531300, 404700, 504400, 503100, 531300, 546200, 517299, 348800, 351000, 496900, 513600, 514900, 515200, 393600, 515800, 400400, 521400, 497700, 537300, 484200, 535100, 510100, 426100, 502400, 537200, 305700, 509200, 510900, 516200, 509900, 523000, 490000, 433000, 508700, 337600, 515800, 347200, 507700, 498500, 514099, 498000, 521300, 513600, 467700, 597800, 512600, 535700, 517600, 510400, 361500, 508400, 550900, 367600, 326100, 352700, 579200, 483200, 352800, 434600, 462100, 510700, 564600, 600000, 268630, 519400, 565500, 555200, 466900, 521900, 390200, 552600, 512000, 563600, 513800, 519600, 439900, 383100, 544900, 522200, 525900, 529000, 361000, 420000, 490000, 522000, 410200, 540600, 563200, 493900, 507500, 523200, 600000, 556000, 453800, 507800, 517100, 504300, 532700, 512000, 529500, 501800, 467100, 515700, 526900, 522299, 534600, 511400, 522400, 508400, 554200, 512900, 341500, 455800, 525300, 509400, 524099, 519400, 471200, 597300, 448200, 402800, 519300, 537200, 513000, 532300, 529800, 535000, 522700, 516200, 455400, 429700, 479799, 516400, 359000, 518400, 520400, 427200, 536700, 515900, 576100, 518100, 320200, 297400, 368200, 432600, 571800, 517600, 515400, 534900, 474200, 513300, 530600, 524099, 399500, 497299, 507500, 516500, 362100, 471800, 480600, 538100, 500400, 515800, 518200, 522000, 498000, 538500, 440800, 533600, 514300, 538000, 552600, 556500, 512000, 523900, 514099, 505700, 535800, 505900, 485100, 515300, 503500, 510400, 492200, 462600, 375000, 511599, 384700, 514500, 516400, 414300, 577900, 320200, 513300, 504300, 522200, 308000, 521500, 531300, 499300, 535800, 502600, 509300, 505600, 545000, 453800, 505700, 502000, 526500, 452900, 522100, 510900, 503100, 523600, 526500, 512800, 272000, 427299, 365300, 554800, 590700, 407900, 475500, 575700, 412299, 351000] + }, + { + "label": "Cylinder", + "tickvals": [0, 0.5, 1, 2, 3], + "ticktext": ["A", "AB", "B", "Y", "Z"], + "values": [0, 0, 1, 0.5, 2, 3, 3, 0, 1, 1, 2, 2, 3, 0, 0, 1, 2, 2, 3, 3, 0, 1, 1, 2, 3, 3, 3, 0, 2, 3, 1, 0, 1, 3, 1, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 3, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2, 0, 3, 0, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0, 3, 1, 1, 3, 0, 0, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 3, 2, 0, 2, 2, 2, 0, 2, 2, 2, 3, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 3, 2, 0, 2, 0, 0, 3, 0, 2, 0, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 3, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 0, 2, 3, 3, 2, 2, 0, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 3, 2, 0, 2, 2, 0, 1, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 3, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 0, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 3, 0, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 2, 1, 0, 2, 0, 2, 3, 2, 0, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1] + }, + { + "label": "Weight", + "visible": true, + "valueformat": ",.2f", + "values": [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797, 377, 1327, 462, 1009, 166, 1415, 1118, 1063, 593, 498, 959, 1331, 1146, 645, 921, 1596, 663, 568, 492, 833, 630, 445, 504, 394, 647, 314, 1039, 829, 911, 282, 925, 681, 581, 506, 368, 373, 628, 538, 418, 419, 478, 884, 847, 369, 410, 344, 396, 501, 510, 379, 733, 1649, 239, 1035, 1839, 967, 514, 875, 794, 414, 664, 447, 839, 540, 636, 499, 1059, 743, 173, 473, 519, 465, 623, 726, 631, 521, 643, 323, 424, 472, 657, 510, 521, 661, 690, 497, 1664, 2162, 828, 1062, 479, 1452, 574, 604, 1069, 766, 268, 369, 755, 644, 811, 636, 363, 375, 359, 378, 336, 413, 680, 431, 361, 493, 761, 412, 386, 339, 628, 390, 648, 611, 323, 369, 555, 142, 2133, 653, 392, 597, 740, 345, 345, 1211, 600, 396, 369, 390, 481, 498, 371, 337, 316, 363, 676, 330, 353, 527, 352, 329, 341, 349, 334, 357, 501, 363, 1066, 284, 307, 338, 367, 327, 901, 330, 367, 311, 543, 370, 355, 318, 398, 335, 346, 382, 337, 807, 365, 349, 350, 415, 346, 330, 337, 330, 2201, 489, 338, 322, 349, 744, 239, 327, 327, 317, 763, 303, 343, 334, 293, 298, 472, 558, 331, 769, 321, 315, 342, 2161, 325, 1667, 493, 328, 878, 328, 737, 315, 325, 317, 529, 727, 390, 320, 953, 729, 300, 538, 663, 333, 320, 309, 596, 591, 325, 300, 709, 303, 312, 501, 737, 306, 360, 320, 1585, 324, 196, 294, 827, 305, 316, 415, 557, 302, 550, 332, 289, 730, 319, 324, 369, 335, 532, 422, 315, 1423, 1091, 320, 323, 358, 307, 314, 317, 218, 414, 299, 323, 371, 322, 314, 311, 338, 310, 324, 319, 674, 305, 366, 356, 316, 338, 352, 343, 339, 327, 497, 323, 780, 427, 346, 311, 319, 307, 343, 312, 1695, 329, 293, 316, 429, 341, 315, 548, 330, 307, 331, 321, 427, 319, 530, 516, 310, 344, 724, 479, 2748, 667, 977, 426, 696, 755, 944, 474, 331, 314, 319, 381, 294, 282, 302, 264, 370, 449, 314, 1029, 318, 312, 706, 349, 508, 297, 293, 322, 531, 480, 396, 286, 367, 315, 308, 365, 302, 467, 302, 313, 421, 351, 295, 792, 296, 651, 305, 1207, 501, 325, 311, 302, 290, 693, 312, 681, 474, 296, 321, 305, 322, 312, 317, 453, 322, 312, 550, 331, 334, 297, 560, 324, 812, 311, 320, 336, 533, 316, 1305, 502, 857, 329, 1089, 521, 495, 1025, 316, 373, 301, 935, 685, 547, 311, 622, 851, 880, 175, 331, 343, 1122, 314, 494, 211, 329, 228, 307, 306, 302, 312, 324, 549, 354, 390, 443, 305, 303, 1364, 320, 352, 412, 328, 522, 1509, 303, 314, 326, 304, 376, 297, 354, 305, 303, 309, 324, 543, 1231, 306, 865, 477, 388, 388, 603, 532, 310, 1249, 321, 162, 431, 346, 880, 355, 789, 320, 383, 317, 317, 571, 324, 321, 810, 1075, 329, 363, 310, 385, 322, 1005, 344, 1169, 526, 286, 328, 558, 295, 505, 339, 608, 526, 352, 312, 391, 933, 448, 590, 411, 463, 391, 697, 1113, 327, 604, 845, 1066, 330, 435, 750, 325, 709, 523, 315, 353, 882, 736, 456, 1111, 1050, 454, 955, 1728, 423, 796, 793, 1348, 761, 970, 668, 459, 386, 783, 276, 820, 708, 501, 764, 445, 492, 464, 496, 419, 967, 1243, 751, 472, 377, 419, 628, 480, 701, 368, 486, 949, 668, 720, 570, 425, 576, 352, 449, 427, 1551, 349, 478, 370, 327, 381, 379, 333, 403, 387, 378, 368, 450, 382, 376, 1184, 330, 349, 416, 435, 381, 362, 362, 426, 379, 372, 345, 841, 432, 952, 441, 238, 313, 437, 392, 763, 719, 376, 370, 679, 387, 531, 591, 352, 377, 174, 366, 340, 383, 361, 341, 335, 346, 392, 390, 731, 477, 861, 419, 1073, 337, 523, 972, 624, 404, 485, 398, 1249, 366, 371, 400, 419, 344, 823, 365, 506, 925, 305, 628, 357, 323, 489, 662, 354, 833, 353, 369, 352, 342, 493, 366, 329, 862, 333, 361, 816, 785, 500, 502, 368, 343, 349, 366, 340, 325, 359, 371, 403, 333, 385, 336, 352, 716, 424, 395, 1525, 338, 342, 504, 392, 808, 362, 327, 300, 1073, 1137, 376, 332, 363, 340, 876, 396, 319, 339, 330, 290, 1026, 452, 339, 286, 336, 873, 514, 339, 363, 883, 334, 324, 331, 324, 324, 326, 313, 324, 325, 332, 313, 321, 309, 692, 296, 312, 303, 333, 649, 697, 374, 294, 357, 313, 316, 294, 316, 422, 450, 321, 331, 302, 713, 303, 335, 321, 916, 350, 313, 307, 313, 1121, 312, 1299, 481, 306, 1072, 304, 622, 970, 310, 310, 980, 472, 317, 535, 328, 898, 661, 386, 335, 320, 337, 309, 293, 1362, 351, 876, 403, 319, 514, 1102, 456, 309, 498, 706, 305, 922, 1655, 330, 284, 915, 305, 319, 522, 546, 307, 502, 341, 358, 450, 324, 314, 322, 320, 321, 388, 307, 297, 310, 605, 358, 1048, 322, 315, 468, 350, 179, 1056, 1079, 342, 319, 345, 348, 314, 329, 311, 488, 775, 318, 312, 510, 884, 776, 313, 304, 488, 329, 294, 501, 315, 381, 348, 450, 299, 414, 481, 1377, 342, 1135, 637, 302, 322, 309, 305, 311, 696, 303, 486, 293, 308, 1131, 541, 295, 1198, 319, 301, 293, 321, 1268, 281, 361, 304, 306, 339, 1439, 618, 644, 359, 302, 319, 297, 690, 327, 299, 300, 305, 503, 326, 309, 367, 392, 964, 325, 291, 317, 281, 386, 282, 281, 366, 351, 906, 198, 294, 733, 442, 350, 315, 359, 435, 1220, 322, 330, 307, 434, 313, 304, 1111, 313, 313, 330, 336, 764, 312, 286, 348, 924, 309, 327, 317, 364, 423, 294, 337, 323, 313, 718, 676, 323, 335, 332, 332, 321, 1004, 340, 324, 296, 312, 512, 311, 324, 306, 308, 313, 310, 367, 330, 317, 311, 307, 308, 309, 451, 312, 169, 320, 462, 316, 304, 314, 324, 311, 303, 316, 324, 316, 364, 305, 307, 332, 628, 303, 336, 305, 318, 305, 323, 305, 289, 314, 309, 274, 302, 326, 469, 404, 331, 323, 301, 690, 755, 327, 322, 299, 470, 319, 246, 692, 551, 327, 369, 334, 321, 694, 322, 313, 319, 758, 494, 536, 300, 483, 295, 407, 289, 330, 314, 212, 306, 312, 360, 326, 335, 310, 461, 1065, 299, 1554, 316, 883, 306, 314, 302, 381, 313, 939, 310, 298, 295, 1040, 613, 365, 317, 842, 311, 427, 322, 315, 358, 313, 356, 307, 305, 727, 303, 343, 674, 300, 314, 303, 311, 694, 456, 434, 320, 422, 307, 293, 311, 149, 510, 314, 704, 1070, 294, 309, 368, 299, 328, 471, 300, 292, 305, 309, 336, 306, 323, 323, 367, 319, 374, 311, 324, 449, 345, 175, 300, 330, 390, 740, 1029, 644, 532, 339, 966, 307, 325, 301, 245, 916, 334, 463, 373, 313, 671, 678, 298, 315, 286, 820, 312, 535, 340, 464, 322, 323, 416, 595, 571, 596, 753, 725, 295, 304, 294, 451, 308, 303, 310, 506, 308, 744, 308, 289, 311, 293, 455, 327, 263, 1153, 1348, 473, 148, 1811, 134, 294, 577, 834, 349, 287, 1848, 316, 1058, 839, 759, 799, 323, 501, 372, 598, 366, 454, 383, 334, 324, 323, 696, 763, 318, 351, 334, 321, 1631, 295, 354, 292, 321, 741, 1141, 318, 722, 320, 311, 303, 302, 323, 335, 442, 310, 807, 338, 324, 341, 958, 301, 327, 458, 321, 319, 318, 337, 670, 1254, 1019, 340, 193, 740, 308, 413, 336, 203, 330, 321, 336, 966, 561, 1178, 323, 329, 582, 306, 202, 455, 305, 1161, 845, 341, 396, 428, 1298, 973, 300, 692, 519, 296, 306, 441, 759, 572, 299, 628, 340, 514, 320, 296, 326, 569, 823, 373, 618, 410, 317, 313, 712, 210, 363, 717, 1324, 1247, 297, 315, 315, 313, 1031, 354, 312, 312, 208, 374, 338, 361, 704, 433, 320, 319, 295, 528, 291, 1356, 520, 802, 369, 856, 954, 612, 286, 316, 440, 901, 413, 373, 375, 301, 462, 645, 414, 356, 554, 2389, 377, 371, 735, 458, 368, 400, 355, 345, 756, 377, 381, 275, 417, 337, 611, 390, 326, 319, 383, 338, 375, 329, 730, 416, 532, 312, 312, 326, 741, 396, 292, 480, 196, 288, 375, 347, 477, 969, 311, 535, 1560, 328, 312, 719, 459, 299, 324, 312, 505, 325, 547, 1029, 342, 908, 308, 999, 336, 568, 466, 353, 645, 324, 518, 722, 285, 613, 699, 610, 1555, 792, 683, 302, 676, 582, 290, 865, 1675, 559, 398, 271, 459, 1523, 366, 276, 882, 488, 562, 381, 295, 339, 543, 381, 623, 551, 367, 459, 348, 309, 350, 335, 328, 792, 320, 323, 324, 767, 443, 567, 380, 290, 362, 337, 345, 483, 560, 467, 356, 334, 749, 631, 321, 460, 356, 328, 329, 241, 366, 703, 346, 515, 362, 465, 841, 344, 304, 341, 560, 364, 355, 381, 357, 194, 176, 341, 386, 322, 342, 1393, 185, 341, 499, 3154, 324, 435, 542, 353, 402, 292, 334, 413, 179, 806, 892, 494, 281, 527, 332, 655, 724, 1253, 300, 326, 302, 701, 570, 408, 669, 360, 466, 795, 373, 301, 316, 355, 312, 303, 307, 434, 287, 321, 321, 300, 686, 306, 324, 716, 316, 875, 323, 479, 751, 326, 547, 371, 438, 329, 734, 1176, 495, 2745, 736, 421, 327, 436, 323, 353, 670, 442, 300, 595, 369, 727, 484, 352, 369, 325, 341, 266, 481, 306, 323, 294, 493, 365, 400, 382, 372, 540, 310, 317, 932, 321, 404, 328, 303, 340, 324, 313, 315, 318, 331, 729, 1063, 306, 322, 339, 317, 455, 312, 693, 332, 416, 320, 362, 322, 327, 331, 1044, 309, 337, 363, 426, 407, 613, 471, 337, 321, 308, 326, 976, 318, 1265, 314, 874, 294, 319, 366, 337, 343, 453, 322, 481, 447, 749, 370, 337, 308, 316, 516, 385, 426, 349, 416, 585, 373, 353, 360, 194, 419, 311, 318, 317, 287, 341, 335, 587, 551, 393, 303, 288, 1113, 322, 313, 863, 329, 285, 276, 327, 345, 769, 956, 1183, 866, 765, 309, 668, 1849, 516, 395, 363, 427, 293, 359, 260, 1235, 339, 465, 329, 725, 242, 361, 302, 347, 318, 337, 333, 325, 313, 544, 318, 304, 436, 332, 638, 741, 969, 362, 309, 909, 751, 721, 934, 535, 1328, 221, 459, 341, 302, 287, 306, 883, 222, 351, 769, 326, 292, 353, 412, 3017, 791, 401, 1250, 603, 839, 584, 358, 381, 465, 455, 495, 609, 313, 305, 1283, 680, 404, 325, 344, 356, 987, 453, 530, 606, 391, 364, 175, 327, 610, 341, 333, 794, 448, 351, 1603, 417, 283, 395, 540, 338, 319, 354, 302, 339, 364, 526, 347, 357, 542, 840, 416, 301, 370, 191, 1251, 174, 512, 338, 329, 828, 721, 309, 777, 319, 325, 325, 322, 341, 293, 336, 314, 321, 303, 408, 257, 955, 322, 323, 323, 1101, 227, 478, 336, 350, 175, 486, 313, 359, 1170, 346, 336, 500, 282, 910, 295, 303, 971, 1226, 335, 285, 653, 1002, 325, 353, 382, 323, 334, 289, 305, 316, 349, 430, 677, 160, 914, 453, 595, 419, 173, 281, 920, 364, 331, 502, 657, 421, 311, 360, 665, 636, 327, 346, 407, 632, 471, 326, 336, 749, 391, 557, 381, 478, 442, 469, 303, 310, 292, 379, 453, 274, 312, 673, 321, 516, 371, 288, 446, 352, 318, 617, 315, 329, 939, 646, 497, 178, 394, 409, 180, 390, 922, 380, 465, 495, 396, 835, 391, 362, 511, 346, 308, 565, 345, 314, 346, 333, 316, 355, 348, 427, 360, 415, 1113, 813, 321, 486, 349, 363, 363, 359, 181, 317, 356, 223, 294, 326, 146, 372, 307, 465, 402, 275, 324, 317, 359, 316, 336, 506, 782, 298, 283, 500, 401, 412, 631, 342, 296, 311, 327, 323, 422, 321, 354, 1106, 357, 399, 333, 322, 380, 298, 345, 340, 340, 310, 354, 307, 336, 470, 258, 315, 361, 473, 326, 553, 666, 1079, 318, 326, 848, 390, 516, 344, 1169, 449, 324, 340, 310, 320, 300, 326, 305, 498, 288, 324, 312, 174, 344, 354, 409, 260, 331, 494, 1185, 309, 835, 336, 801, 428, 190, 303, 446, 185, 321, 532, 286, 493, 746, 536, 336, 499, 340, 373, 1164, 336, 378, 313, 883, 728, 344, 322, 360, 315, 353, 203, 384, 426, 369, 328, 386, 321, 337, 318, 301, 319, 320, 175, 300, 349, 296, 315, 686, 323, 698, 315, 427, 1174, 506, 396, 321, 464, 309, 308, 338, 370, 327, 313, 941, 323, 384, 194, 333, 1186, 329, 1325, 325, 558, 311, 373, 335, 323, 977, 542, 311, 460, 1188, 324, 332, 184, 2534, 322, 1325, 300, 305, 383, 250, 307, 316, 417, 297, 1378, 305, 330, 316, 506, 717, 173, 426, 637, 1256, 803, 305, 314, 718, 317, 439, 324, 755, 411, 310, 386, 325, 331, 550, 302, 309, 341, 1055, 328, 355, 265, 1013, 477, 533, 1710, 322, 315, 346, 719, 324, 844, 342, 311, 700, 424, 419, 998, 442, 664, 1037, 446, 754, 369, 321, 864, 316, 346, 322, 847, 470, 490, 865, 310, 994, 322, 501, 361, 390, 661, 332, 344, 657, 431, 322, 440, 398, 1876, 732, 292, 1528, 380, 351, 209, 476, 467, 1304, 337, 925, 378, 769, 555, 551, 774, 227, 503, 334, 205, 351, 493, 368, 304, 1131, 320, 484, 800, 281, 549, 306, 316, 809, 310, 325, 529, 939, 836, 179, 321, 176, 326, 189, 370, 327, 351, 822, 317, 308, 321, 301, 494, 346, 355, 306, 326, 318, 302, 298, 287, 323, 316, 329, 320, 475, 306, 527, 902, 575, 1023, 309, 520, 273, 723, 341, 373, 334, 854, 534, 333, 1296, 312, 318, 525, 1259, 406, 441, 309, 498, 663, 706, 423, 631, 794, 452, 393, 766, 371, 356, 309, 265, 321, 542, 379, 317, 394, 325, 522, 346, 378, 308, 1310, 358, 457, 372, 698, 799, 319, 978, 310, 307, 339, 959, 328, 598, 491, 509, 463, 337, 328, 340, 326, 475, 330, 323, 337, 290, 375, 308, 747, 310, 736, 315, 303, 369, 536, 1075, 539, 717, 1493, 477, 513, 1314, 409, 494, 454, 881, 337, 278, 2065, 1757, 212, 458, 708, 363, 560, 326, 137, 598, 390, 785, 928, 301, 1965, 321, 232, 295, 751, 354, 307, 674, 343, 398, 1135, 336, 462, 343, 290, 306, 328, 329, 334, 410, 312, 659, 335, 976, 342, 449, 293, 324, 703, 313, 2091, 583, 731, 863, 337, 292, 1122, 320, 784, 1010, 885, 1148, 1264, 492, 644, 454, 1033, 294, 655, 574, 250, 320, 1056, 617, 1132, 344, 192, 611, 686, 732, 672, 382, 449, 500, 474, 350, 314, 324, 182, 856, 1291, 347, 327, 349, 1909, 536, 461, 641, 507, 1004, 369, 445, 344, 441, 356, 341, 315, 855, 315, 404, 370, 297, 339, 465, 732, 366, 349, 396, 918, 534, 359, 508, 380, 357, 388, 465, 257, 805, 975, 321, 315, 335, 1028, 458, 838, 372, 997, 571, 335, 372, 886, 299, 306, 498, 552, 303, 449, 478, 927, 280, 415, 301, 234, 324, 346, 1107, 1192, 321, 548, 305, 983, 763, 455, 337, 985, 372, 600, 476, 555, 429, 612, 387, 391, 394, 530, 429, 410, 387, 412, 395, 333, 348, 294, 350, 413, 308, 361, 334, 350, 361, 355, 1161, 1772, 334, 185, 313, 330, 603, 397, 469, 373, 302, 465, 493, 344, 325, 297, 185, 355, 362, 324, 334, 334, 349, 345, 305, 299, 349, 328, 357, 467, 319, 891, 570, 245, 1310, 1273, 472, 775, 318, 288, 1076, 1412] + }, + { + "label": "Cost", + "visible": true, + "valueformat": "$,", + "values": [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939, 24258, 62488, 27363, 61924, 12511, 106196, 24444, 7443, 9111, 12527, 50738, 9320, 12291, 17571, 9508, 11176, 9142, 7687, 6724, 11219, 17825, 6506, 6367, 4966, 8495, 3860, 12844, 10688, 13026, 4007, 57281, 9790, 7335, 13748, 5358, 5393, 4401, 3769, 5233, 5058, 6047, 6188, 11899, 5297, 5154, 4406, 5061, 7022, 6358, 4721, 7723, 16745, 2651, 14194, 100772, 10504, 7021, 6131, 16730, 2904, 8334, 5968, 5876, 7394, 4454, 6800, 18376, 5204, 2190, 6146, 7013, 6412, 4361, 5082, 8028, 6484, 4504, 3832, 5687, 6174, 4603, 6913, 3651, 4631, 4833, 6532, 97138, 21918, 5801, 7435, 13138, 14597, 6070, 19943, 7487, 5362, 3945, 4907, 5287, 7937, 9998, 7852, 4820, 9385, 4686, 4751, 8594, 5144, 4760, 5899, 4614, 30326, 5332, 5030, 4759, 4429, 17294, 5192, 4542, 9333, 2261, 4911, 34968, 2179, 34658, 16325, 4811, 4185, 9017, 4224, 4435, 14536, 7129, 4772, 4726, 4840, 3369, 7428, 4504, 4316, 4097, 4399, 4733, 4105, 4597, 3691, 4405, 4245, 4195, 4168, 4694, 4421, 3507, 4615, 14408, 3607, 3956, 4295, 4583, 4138, 11128, 4147, 4602, 3940, 5590, 4505, 4377, 4016, 5191, 4199, 4269, 4686, 4375, 9716, 8664, 4371, 4294, 9779, 4396, 4183, 4247, 4112, 129671, 3426, 4257, 4102, 4386, 8822, 3138, 4040, 4066, 3950, 12502, 3787, 4273, 4238, 3678, 3660, 6006, 7725, 4172, 12580, 4056, 3920, 4249, 35461, 4054, 108185, 6568, 4154, 11735, 4090, 8971, 3943, 4062, 3857, 5408, 8982, 5662, 3974, 6673, 18248, 3739, 3770, 8110, 4129, 4050, 3826, 8314, 9053, 4022, 3718, 8838, 3786, 3874, 6244, 18434, 3815, 4491, 3954, 39629, 4009, 2456, 3643, 10976, 3783, 3946, 5151, 3900, 3730, 3854, 7621, 3597, 7909, 3959, 4022, 4585, 4130, 6699, 27180, 3935, 89225, 14401, 3962, 4022, 4459, 3816, 3938, 3931, 3041, 26734, 3722, 4047, 4583, 3998, 3907, 3887, 4191, 3858, 4033, 3994, 11019, 3777, 4482, 4277, 3968, 4237, 4378, 4264, 4212, 4049, 7410, 4020, 12723, 12452, 4283, 3862, 3953, 3803, 4276, 3866, 18642, 4063, 3648, 3901, 27631, 4251, 3875, 3837, 4109, 3808, 4083, 3993, 27553, 3950, 3715, 3617, 3819, 7947, 11786, 3358, 44432, 38355, 6845, 9723, 4878, 11458, 6609, 3321, 4964, 3884, 3963, 8633, 3627, 3471, 3780, 3359, 4582, 28916, 3896, 12827, 3908, 3865, 4945, 4276, 6296, 3685, 3657, 3948, 6513, 6549, 4829, 3554, 4503, 3893, 3820, 4464, 3720, 3270, 3743, 3861, 27079, 4284, 4335, 9658, 3671, 7768, 3772, 15008, 6611, 4023, 3840, 3957, 3579, 8798, 3870, 9817, 3319, 3647, 3955, 3782, 3981, 3845, 3930, 5570, 3975, 3856, 3851, 4094, 4130, 3676, 5579, 4013, 17649, 3704, 3967, 4152, 34352, 3909, 16007, 3517, 56056, 4041, 14115, 3652, 6567, 13776, 3906, 4618, 3729, 6550, 8592, 12494, 3885, 13919, 10616, 12510, 2200, 4164, 4256, 13850, 3877, 11216, 1477, 7529, 3283, 3802, 3773, 3728, 3868, 4104, 7658, 4381, 4671, 6364, 3789, 3774, 16177, 3965, 9465, 5965, 4054, 5330, 15225, 3764, 3865, 4058, 3775, 3758, 3704, 4368, 3729, 3767, 3828, 4150, 3804, 15268, 3815, 11823, 3345, 4872, 4659, 7489, 3729, 3868, 29343, 3997, 2114, 5553, 4292, 12800, 4382, 19742, 4101, 8777, 3940, 3978, 7211, 4103, 3980, 12415, 12316, 4082, 8375, 3841, 8810, 4128, 11997, 4269, 15031, 3683, 3614, 4116, 35845, 3653, 3538, 4223, 8373, 33766, 4411, 3863, 4728, 11456, 5587, 38362, 5111, 29991, 4825, 10478, 13283, 4010, 38799, 11943, 14042, 4038, 5282, 12235, 4027, 11570, 5328, 3914, 4404, 6180, 10126, 10305, 23044, 12414, 6658, 6690, 17090, 5813, 10147, 5552, 14343, 11440, 9605, 8565, 6188, 5280, 5483, 3629, 5741, 8375, 6864, 5353, 6098, 6015, 5678, 6594, 5520, 15985, 8704, 5263, 5731, 5020, 5553, 13258, 6541, 4909, 5117, 6779, 61602, 6992, 8510, 3993, 5627, 4035, 4817, 6048, 5638, 10862, 4568, 6015, 5021, 4284, 5133, 5166, 4381, 5240, 5107, 5232, 4897, 7559, 5099, 5020, 15005, 4330, 4830, 11538, 5852, 5130, 4805, 4753, 9282, 4965, 4964, 4540, 21046, 5789, 15483, 5931, 2900, 4104, 5939, 10136, 12664, 9245, 4934, 4829, 9958, 5014, 8126, 4141, 4664, 5028, 2236, 4825, 4450, 6349, 4727, 4520, 4438, 4538, 5013, 4969, 9032, 29764, 12658, 5571, 12826, 4427, 6303, 6807, 8189, 5126, 6691, 5004, 15571, 4613, 4841, 5437, 5492, 4572, 13590, 4729, 31885, 9172, 3977, 4397, 4489, 4192, 30894, 17398, 4636, 12650, 4567, 4597, 4625, 4501, 8431, 4569, 4265, 10628, 4315, 4627, 13535, 10198, 3503, 6671, 4717, 4428, 4557, 4727, 4387, 4179, 4651, 4798, 4920, 4306, 4756, 4240, 4542, 8949, 27217, 5130, 100064, 4412, 4353, 3534, 4753, 45902, 4727, 4278, 3988, 13557, 14324, 4833, 4152, 4563, 4299, 10786, 10025, 3990, 4245, 4201, 3703, 12584, 5588, 4231, 4049, 4219, 10855, 3598, 4248, 4530, 10756, 4306, 4004, 4135, 4069, 4192, 4082, 3919, 4071, 4059, 4177, 3922, 3982, 3841, 11321, 3668, 3855, 3796, 4226, 8651, 8405, 8613, 3628, 4544, 3889, 3934, 3673, 3943, 27240, 28881, 4011, 4120, 3737, 40767, 3746, 4190, 4026, 9678, 8023, 3928, 3813, 3904, 13989, 3909, 22474, 5945, 3795, 14047, 3829, 8130, 12089, 4416, 3859, 23854, 5822, 3941, 34877, 4097, 6289, 8372, 4738, 4124, 3961, 4110, 3843, 3763, 22330, 4302, 10698, 5011, 3960, 6460, 13165, 5659, 3833, 6159, 8569, 3728, 12430, 17360, 4081, 3556, 12850, 3802, 3962, 5382, 7233, 3823, 5937, 4512, 4425, 5552, 4024, 3882, 3993, 3970, 3997, 4806, 3793, 3723, 3848, 7973, 4442, 12803, 4020, 3904, 6002, 4338, 2233, 17184, 14084, 4271, 3942, 7932, 4327, 3882, 4098, 3837, 5936, 10801, 3953, 3865, 3573, 10508, 19422, 3855, 4313, 3419, 4098, 3648, 3507, 3942, 5038, 4350, 28905, 3717, 26636, 31080, 16310, 4550, 14594, 8871, 3743, 4000, 3809, 3784, 3870, 15692, 3764, 7100, 3653, 3821, 13999, 7394, 4537, 14574, 3960, 3737, 3643, 3972, 8878, 3501, 4511, 3785, 3810, 4214, 92394, 8440, 8972, 4418, 3717, 3955, 3701, 10342, 4052, 3730, 3688, 3796, 6183, 4046, 3823, 4535, 4834, 13248, 4026, 3616, 3936, 3491, 4754, 3483, 3528, 4498, 4365, 11386, 2894, 3620, 18349, 5466, 2455, 3885, 4448, 5426, 14879, 3993, 4086, 3797, 5588, 3885, 3773, 18127, 3875, 3891, 4095, 4159, 11648, 3866, 3565, 4317, 12171, 3823, 4053, 3922, 8253, 27165, 3649, 7753, 4005, 3871, 17967, 44240, 3984, 4138, 4101, 4124, 3966, 12588, 4194, 4016, 3667, 3851, 11327, 3833, 4023, 3798, 3810, 3874, 3840, 8337, 4063, 3925, 3852, 3812, 3820, 3828, 5671, 3844, 2457, 3964, 3237, 3922, 3762, 3880, 4014, 3866, 3752, 3931, 4022, 3918, 4517, 3779, 3801, 4107, 15710, 3752, 4170, 3771, 3965, 3775, 4004, 3779, 3585, 3903, 3836, 3382, 3748, 4032, 3283, 5534, 4099, 3997, 3732, 8711, 18895, 4040, 3984, 3701, 7008, 3970, 3088, 8520, 6614, 4162, 4436, 4138, 3979, 8524, 4013, 3861, 3965, 18961, 6070, 6394, 3698, 5940, 3645, 4818, 3582, 4120, 3910, 2799, 3779, 3893, 4458, 4022, 4108, 3820, 3227, 10985, 3685, 22218, 3925, 10987, 3806, 3865, 3745, 22845, 3873, 12636, 3830, 3697, 3640, 14144, 8228, 4503, 3912, 10683, 3832, 27508, 4369, 3907, 4705, 3860, 4686, 3807, 3775, 11854, 3763, 4259, 10998, 3715, 3918, 3754, 3837, 10320, 29350, 28013, 4806, 27181, 3783, 3626, 3838, 2197, 6793, 3880, 11481, 28248, 3636, 3818, 4555, 3699, 4061, 5737, 3704, 3612, 3780, 3815, 4160, 3795, 3964, 4006, 4520, 3967, 4631, 3837, 4005, 5551, 4224, 2573, 3722, 4063, 25150, 8949, 12712, 7939, 6700, 4162, 13481, 3801, 3966, 3741, 3298, 11662, 4130, 6268, 4621, 3866, 16793, 9268, 3710, 4199, 3545, 8357, 3845, 7090, 4227, 5999, 3976, 3986, 5145, 8848, 7687, 7778, 9672, 18129, 3671, 3758, 3623, 6176, 3829, 3751, 3839, 6623, 3818, 9382, 3824, 3567, 3876, 3648, 3187, 4050, 3274, 14438, 33701, 3315, 2019, 17972, 1935, 3651, 7236, 10042, 4314, 3418, 46207, 3910, 13235, 11016, 5315, 12999, 4040, 6042, 4600, 6015, 4556, 10560, 4629, 4154, 4057, 4028, 10213, 10194, 3936, 4337, 4100, 4017, 17640, 3666, 4336, 3605, 3985, 10013, 13900, 3940, 9771, 4029, 3830, 6681, 3749, 4002, 4144, 28335, 3851, 9628, 4190, 4020, 4209, 11639, 3714, 4051, 29534, 4001, 3943, 3919, 4181, 8921, 15249, 25498, 4413, 2570, 9094, 3781, 5196, 4153, 2806, 4299, 3944, 4153, 11672, 7329, 13429, 3990, 4059, 5928, 3770, 2724, 5689, 3807, 14139, 10239, 7795, 4983, 10307, 16032, 12418, 3739, 8526, 6457, 3656, 3791, 28264, 8997, 7054, 3697, 6385, 4206, 7040, 3971, 3702, 4031, 8243, 47305, 4623, 6289, 26518, 3919, 3896, 17804, 2868, 4490, 17926, 86514, 14833, 3636, 3919, 3900, 4163, 13083, 4797, 3872, 3870, 2921, 4626, 4389, 4492, 8805, 27930, 3981, 3945, 3652, 6474, 3616, 84260, 6441, 11593, 4576, 12714, 13232, 12893, 3555, 3922, 28141, 12058, 5088, 4661, 4667, 3727, 5861, 9001, 5727, 4432, 6923, 39382, 6197, 4625, 16568, 5855, 4562, 4751, 4391, 4257, 9707, 4869, 4715, 17117, 5311, 4147, 6155, 4805, 4006, 3954, 8680, 4167, 23759, 4134, 11938, 26580, 3728, 3886, 3880, 4065, 18544, 9038, 3609, 30977, 2647, 3585, 8622, 4313, 3341, 60270, 3902, 6742, 101532, 4069, 3902, 11753, 5734, 3706, 7359, 3882, 5163, 4062, 7403, 12706, 4274, 11082, 3834, 13857, 4180, 7733, 6289, 4394, 8664, 4020, 6487, 8926, 3545, 7424, 8967, 7105, 15471, 8990, 15930, 3739, 4733, 4080, 3681, 11600, 109361, 35468, 4939, 3449, 29173, 88421, 4596, 3452, 11753, 4978, 36214, 4717, 3650, 4247, 34932, 4724, 9055, 6852, 4699, 6300, 4318, 3863, 4364, 4208, 4057, 11771, 3994, 3980, 3999, 11116, 5528, 7493, 24623, 3933, 4465, 4205, 4283, 6279, 5729, 5893, 4439, 4200, 9248, 4421, 4061, 5686, 4450, 4066, 4108, 3132, 4617, 17583, 4328, 6506, 4535, 30003, 48630, 4313, 3777, 4245, 6884, 4535, 3881, 8812, 4461, 2683, 2233, 4284, 4820, 4040, 4277, 16571, 2554, 4242, 6285, 51154, 4044, 5770, 3800, 4401, 5008, 3647, 4158, 26583, 2467, 20174, 10786, 3461, 3497, 7861, 4243, 16393, 11861, 76828, 4026, 4071, 3740, 17541, 7580, 5092, 4687, 4720, 3266, 13157, 4661, 3747, 3893, 4432, 3893, 3761, 3795, 9961, 3574, 4001, 3976, 3773, 17165, 3782, 4045, 9144, 3962, 50212, 4029, 5950, 8949, 4070, 7221, 8644, 28169, 4062, 8752, 15000, 15842, 44456, 9155, 5309, 4053, 10116, 4046, 4394, 8316, 5514, 3711, 38351, 8468, 10339, 6030, 8029, 4578, 4029, 4222, 3390, 6727, 3803, 20095, 3644, 31728, 4573, 9131, 24869, 4656, 40536, 3844, 3932, 12001, 3974, 9248, 4031, 3798, 4203, 4056, 3876, 3886, 3939, 4057, 9567, 26598, 3804, 4015, 7758, 3949, 29312, 3902, 8209, 7521, 5578, 3987, 4785, 3995, 4079, 4112, 12730, 3823, 4210, 8367, 27490, 4937, 8779, 6457, 7775, 3957, 3823, 4042, 22441, 3978, 15741, 3913, 12279, 3646, 3940, 5004, 4172, 4199, 5890, 4245, 5994, 5525, 18737, 4526, 4310, 3837, 3909, 33292, 4777, 27477, 4301, 5769, 8151, 4658, 4344, 4495, 2657, 5789, 3851, 3932, 3934, 3683, 4207, 4138, 8298, 6530, 8710, 3782, 3585, 13380, 3997, 3900, 49974, 4074, 3540, 3419, 4076, 4261, 9672, 6695, 14148, 50140, 9092, 3985, 9640, 42657, 33535, 8852, 8334, 5261, 3730, 22730, 3339, 76534, 4819, 28020, 4070, 8981, 2923, 4505, 4593, 4316, 3911, 4185, 4135, 4015, 3895, 5559, 3947, 4231, 5169, 4122, 8906, 18540, 11809, 4399, 3866, 11489, 9502, 10162, 11780, 34617, 14012, 2961, 5785, 4343, 3766, 3585, 3799, 14853, 2997, 4256, 9665, 19975, 3645, 8150, 26579, 49058, 11073, 4814, 31254, 7724, 11033, 8315, 4314, 4509, 5916, 28810, 5994, 15238, 3883, 3771, 13249, 9488, 4866, 3982, 4169, 4354, 12208, 5757, 12358, 7437, 4743, 4418, 2405, 4048, 10157, 4252, 4071, 19869, 5500, 4254, 11221, 5164, 4153, 4884, 3785, 4207, 3912, 4325, 3755, 4161, 8314, 3687, 4203, 4409, 5546, 22831, 5131, 3903, 4589, 2432, 80943, 2199, 3585, 4205, 4049, 12623, 11762, 3815, 9929, 3934, 4023, 4371, 3987, 4218, 3830, 4139, 3910, 4533, 3782, 5007, 3306, 23891, 3988, 4008, 4002, 13496, 3002, 5976, 4142, 4357, 2414, 30186, 4189, 4749, 13952, 4589, 4189, 5993, 3502, 13135, 3665, 3739, 11784, 28602, 4450, 3574, 10675, 13041, 4002, 4349, 4771, 4001, 4159, 3482, 3804, 3884, 4343, 9972, 16927, 2221, 12913, 29211, 7041, 27050, 2402, 3485, 11956, 4511, 4063, 3515, 9775, 27027, 3871, 8808, 8094, 8066, 4060, 4286, 26107, 7034, 28205, 4038, 4148, 12288, 5029, 6825, 24260, 30775, 28412, 5946, 3777, 3890, 3615, 4738, 29181, 16464, 3920, 8606, 4059, 5257, 4640, 3570, 6020, 4387, 3958, 40271, 3907, 4062, 12193, 4527, 31964, 2436, 4879, 9400, 2240, 4846, 59578, 8689, 28097, 6135, 9008, 12433, 5015, 4496, 3579, 4307, 3807, 8084, 4643, 3879, 4300, 4138, 4068, 4424, 4336, 6213, 4457, 26961, 14333, 13269, 4073, 6316, 4332, 4492, 8378, 4443, 2350, 4011, 4427, 2909, 3752, 3989, 1997, 8651, 3891, 5882, 5091, 3443, 4074, 3974, 4512, 3921, 4204, 5164, 10883, 3711, 3570, 6328, 5074, 5141, 8367, 4363, 3678, 3889, 4145, 4042, 5286, 3989, 4476, 13140, 4539, 25758, 4129, 4004, 4694, 3864, 4295, 4277, 4463, 3857, 4439, 3782, 4186, 30163, 3261, 3942, 5408, 6214, 4099, 3875, 9581, 15415, 3965, 4083, 10985, 4853, 3614, 4321, 14442, 3146, 4061, 4248, 3869, 4031, 3748, 4124, 3763, 7007, 3547, 4060, 3906, 2375, 4294, 4412, 5156, 3421, 4143, 6916, 14716, 3866, 10080, 4168, 11257, 6132, 2617, 3796, 5781, 2543, 4022, 7851, 3579, 31698, 10449, 7074, 4179, 6623, 4294, 4985, 14197, 4219, 4643, 3871, 10871, 10158, 4303, 4042, 4687, 3933, 4395, 2669, 5223, 26888, 4835, 4120, 4863, 4033, 4234, 3945, 3787, 4005, 4006, 2384, 3737, 4331, 3717, 3897, 11221, 3970, 11405, 3906, 5170, 26275, 5172, 4725, 4027, 29448, 3856, 3820, 4221, 4553, 4084, 3920, 12274, 4041, 4563, 2432, 4168, 14781, 4089, 84860, 4055, 6853, 3917, 4639, 4187, 4046, 15864, 3795, 3896, 29479, 14289, 4031, 4153, 2588, 41096, 4004, 28909, 3755, 3826, 4556, 3108, 3827, 3932, 4954, 3685, 14009, 3794, 4092, 3929, 5161, 10867, 2372, 5304, 7846, 14855, 10527, 3801, 3892, 17953, 3898, 5557, 4010, 8929, 5144, 3868, 4846, 4033, 4106, 7961, 3734, 3844, 4228, 14218, 4070, 4390, 3578, 64666, 30739, 9257, 42766, 3995, 3910, 4320, 11739, 4026, 10762, 4262, 3868, 21774, 27155, 26769, 13667, 5432, 8575, 13691, 5792, 12304, 8357, 3962, 12225, 3930, 4287, 3987, 10619, 5986, 6403, 11136, 3844, 13668, 4749, 6511, 4570, 5367, 9270, 4129, 5042, 6824, 27699, 3999, 28366, 4786, 30493, 10545, 3619, 38201, 4702, 4334, 2851, 30809, 3274, 21828, 4164, 12971, 4680, 9109, 6845, 6667, 9545, 3102, 31606, 4117, 3017, 4334, 31897, 8413, 3756, 13786, 3943, 7094, 9861, 17684, 7372, 3802, 3923, 13130, 3832, 4035, 6716, 13120, 10771, 2451, 3981, 2509, 4019, 2530, 4595, 4017, 4468, 12432, 3922, 3813, 3969, 3716, 31879, 4280, 4485, 3782, 4025, 3901, 3719, 18455, 3560, 3943, 19801, 4049, 3957, 30692, 3774, 3690, 12946, 43153, 12827, 3480, 3642, 3492, 5065, 4683, 8439, 4097, 5979, 7318, 4074, 27698, 3828, 3955, 7204, 80055, 4851, 11026, 3846, 6536, 41579, 8716, 5304, 9580, 9725, 10335, 8879, 9245, 8502, 4393, 7028, 3207, 3943, 6586, 4696, 3914, 9070, 4049, 33617, 4304, 8600, 3814, 81235, 4422, 6506, 4557, 7048, 19991, 3954, 13795, 3822, 3798, 4260, 11751, 4101, 7718, 31546, 6384, 3247, 4172, 4088, 4228, 4035, 5786, 4094, 3987, 4185, 3877, 4554, 3840, 8856, 17877, 11098, 3877, 3743, 4629, 5448, 14210, 5504, 17927, 15188, 5892, 6491, 15609, 4910, 8230, 29322, 11412, 4175, 3866, 34283, 101349, 2855, 3210, 17724, 4466, 6815, 4038, 1938, 8412, 4895, 12817, 23221, 3737, 32782, 3984, 3123, 3650, 12300, 4338, 3889, 8256, 4272, 5260, 14199, 4117, 6801, 4269, 3612, 3803, 4083, 4070, 4216, 5383, 3891, 9386, 4152, 13778, 7919, 3149, 3636, 4064, 11473, 3886, 34380, 6906, 11939, 10572, 7726, 3639, 58427, 3988, 5494, 13997, 12759, 69547, 82624, 6238, 9041, 5960, 13276, 3667, 7896, 6782, 3844, 3967, 12716, 7470, 14500, 4257, 2617, 7419, 4804, 8821, 4705, 4733, 28271, 6839, 30762, 4321, 3868, 3984, 2542, 11350, 13299, 4292, 4368, 4264, 27377, 8775, 5744, 7910, 12689, 12160, 4769, 5551, 4261, 5514, 4379, 4244, 3879, 21386, 4042, 9266, 4556, 3667, 4165, 29895, 11939, 4558, 4237, 4917, 13036, 6889, 4424, 32664, 4694, 8153, 9377, 5507, 3342, 10823, 62847, 3939, 3912, 4122, 66439, 3210, 10350, 4615, 12868, 7511, 4255, 4616, 12370, 3704, 3788, 6565, 6764, 3760, 5382, 5920, 13436, 16417, 5747, 3951, 2810, 4018, 4297, 24861, 15191, 3990, 6731, 3764, 13253, 9573, 10539, 4175, 13712, 4754, 7612, 10652, 6949, 5321, 4285, 4785, 4906, 4827, 33385, 5270, 5091, 4739, 5003, 4787, 4146, 4299, 3657, 4368, 5066, 3848, 4575, 4150, 4381, 4496, 4471, 14916, 29694, 4159, 2529, 3889, 4098, 8034, 4757, 6803, 4640, 3780, 5750, 7248, 4255, 3991, 3723, 2276, 4447, 4513, 4048, 4071, 4323, 4361, 4313, 3757, 3874, 4314, 4087, 4463, 30169, 3933, 11064, 8721, 3231, 14337, 15420, 5613, 10373, 4057, 3450, 14347, 15572] + }, + { + "label": "Penalty", + "valueformat": "_>5", + "values": [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778, 760, 4349, 891, 4228, 123, 10800, 1593, 467, 260, 226, 2940, 803, 689, 420, 422, 1229, 275, 198, 150, 423, 423, 134, 146, 89, 248, 55, 612, 401, 546, 52, 4208, 307, 194, 257, 91, 93, 178, 133, 99, 98, 131, 345, 461, 90, 96, 69, 91, 160, 148, 81, 274, 1332, 31, 667, 11733, 502, 163, 354, 480, 67, 252, 120, 303, 181, 162, 153, 1142, 251, 17, 131, 165, 135, 162, 222, 230, 154, 198, 58, 109, 132, 189, 159, 102, 167, 218, 147, 11969, 2288, 316, 467, 234, 1025, 169, 497, 435, 265, 49, 82, 252, 234, 372, 229, 79, 127, 76, 82, 105, 97, 207, 115, 75, 1014, 259, 95, 84, 68, 404, 91, 183, 273, 49, 82, 1378, 14, 5405, 769, 86, 168, 308, 67, 69, 818, 200, 87, 79, 86, 100, 174, 77, 66, 58, 74, 206, 62, 73, 129, 71, 63, 65, 67, 71, 72, 116, 76, 696, 46, 55, 66, 77, 61, 460, 62, 77, 55, 146, 77, 71, 58, 93, 64, 68, 82, 66, 364, 113, 69, 69, 145, 69, 62, 65, 62, 19984, 113, 65, 60, 69, 307, 33, 60, 60, 57, 676, 52, 67, 64, 49, 50, 129, 196, 63, 690, 59, 56, 66, 5409, 60, 13549, 146, 62, 466, 61, 305, 56, 60, 56, 138, 299, 102, 58, 406, 1019, 51, 137, 247, 63, 59, 54, 226, 257, 59, 51, 286, 52, 55, 143, 1039, 53, 73, 58, 4807, 59, 22, 49, 411, 52, 57, 98, 129, 51, 143, 90, 47, 284, 57, 59, 77, 63, 162, 849, 56, 8935, 711, 58, 59, 73, 53, 56, 57, 30, 822, 50, 59, 78, 59, 56, 55, 65, 54, 60, 58, 532, 52, 75, 71, 57, 65, 70, 67, 65, 60, 173, 59, 717, 203, 68, 55, 57, 53, 67, 55, 1579, 61, 49, 56, 877, 66, 56, 142, 62, 53, 62, 58, 873, 57, 132, 126, 54, 98, 622, 103, 9106, 1860, 454, 148, 206, 412, 423, 103, 77, 55, 57, 118, 49, 45, 52, 40, 77, 960, 56, 603, 57, 55, 225, 68, 146, 50, 49, 58, 159, 142, 88, 46, 76, 56, 54, 75, 51, 100, 51, 55, 842, 69, 59, 353, 49, 236, 52, 829, 150, 60, 54, 54, 47, 277, 55, 309, 104, 49, 58, 52, 59, 55, 57, 116, 58, 55, 143, 62, 63, 50, 151, 59, 515, 53, 58, 64, 1357, 56, 961, 117, 3664, 61, 696, 128, 147, 639, 56, 79, 51, 342, 268, 245, 55, 311, 413, 505, 17, 63, 67, 713, 55, 199, 17, 89, 34, 53, 53, 51, 55, 60, 192, 71, 84, 130, 52, 52, 1033, 58, 122, 113, 61, 134, 1110, 52, 55, 60, 52, 68, 50, 71, 52, 52, 54, 61, 139, 861, 53, 464, 105, 86, 84, 207, 125, 54, 3281, 58, 15, 108, 68, 523, 71, 1197, 59, 120, 57, 57, 187, 60, 58, 483, 696, 61, 109, 54, 121, 60, 563, 67, 797, 130, 47, 61, 1473, 49, 119, 65, 231, 1307, 71, 55, 85, 491, 114, 1705, 96, 1039, 86, 346, 690, 60, 1724, 462, 677, 61, 106, 664, 59, 590, 134, 56, 71, 355, 338, 168, 1600, 612, 141, 437, 1438, 111, 367, 283, 942, 412, 453, 259, 128, 92, 277, 45, 304, 278, 156, 269, 123, 136, 121, 148, 104, 1063, 676, 257, 125, 85, 105, 301, 142, 232, 85, 150, 4912, 226, 287, 135, 108, 147, 77, 123, 109, 1131, 72, 131, 84, 63, 88, 88, 66, 95, 89, 90, 81, 222, 88, 85, 808, 64, 76, 179, 115, 88, 78, 77, 236, 85, 83, 71, 1381, 113, 1075, 118, 31, 58, 117, 144, 653, 301, 84, 81, 315, 88, 207, 155, 74, 86, 17, 80, 68, 166, 77, 69, 67, 71, 89, 88, 303, 989, 509, 105, 642, 67, 153, 405, 231, 94, 147, 90, 889, 76, 81, 98, 104, 71, 773, 78, 1146, 413, 55, 178, 73, 61, 1077, 421, 74, 503, 73, 77, 73, 69, 255, 76, 63, 420, 65, 76, 752, 363, 112, 151, 78, 68, 72, 78, 67, 61, 75, 80, 91, 65, 84, 65, 72, 292, 847, 91, 11709, 67, 67, 110, 86, 2467, 77, 63, 54, 662, 742, 82, 63, 75, 66, 434, 144, 58, 65, 63, 48, 594, 115, 65, 53, 64, 433, 119, 65, 75, 438, 65, 59, 62, 60, 61, 60, 56, 60, 60, 63, 56, 58, 54, 561, 49, 55, 52, 64, 254, 271, 115, 48, 73, 55, 56, 49, 56, 853, 954, 59, 62, 51, 1951, 52, 64, 59, 430, 100, 56, 53, 55, 717, 55, 1725, 131, 53, 681, 53, 229, 536, 63, 54, 842, 126, 57, 1413, 61, 321, 252, 84, 63, 58, 63, 54, 50, 2153, 69, 432, 92, 57, 151, 677, 118, 54, 140, 279, 52, 519, 1391, 61, 46, 538, 53, 58, 135, 178, 53, 140, 69, 72, 115, 59, 56, 58, 58, 58, 85, 53, 50, 54, 218, 72, 618, 59, 56, 127, 69, 18, 1321, 688, 67, 57, 98, 69, 56, 61, 54, 133, 382, 57, 55, 120, 434, 1165, 55, 60, 108, 61, 49, 114, 56, 86, 69, 957, 50, 814, 1112, 1052, 70, 751, 257, 51, 59, 54, 52, 55, 392, 52, 160, 49, 53, 726, 181, 64, 806, 57, 51, 49, 58, 629, 45, 74, 52, 53, 65, 9789, 237, 263, 72, 51, 57, 50, 337, 60, 51, 50, 53, 143, 60, 54, 76, 87, 580, 60, 48, 57, 44, 84, 45, 45, 75, 70, 470, 26, 48, 1034, 110, 56, 56, 73, 108, 837, 59, 62, 53, 110, 55, 52, 1450, 55, 55, 62, 64, 426, 55, 46, 68, 509, 54, 60, 57, 107, 846, 49, 93, 59, 55, 992, 2282, 59, 63, 62, 62, 58, 577, 65, 59, 49, 55, 208, 54, 59, 53, 53, 55, 54, 109, 61, 57, 55, 53, 54, 54, 116, 55, 19, 58, 98, 56, 52, 56, 59, 55, 52, 56, 59, 56, 75, 52, 53, 62, 758, 52, 64, 52, 57, 52, 59, 52, 47, 56, 54, 42, 51, 60, 101, 101, 62, 59, 51, 274, 1101, 60, 58, 50, 155, 58, 34, 270, 169, 62, 76, 63, 58, 272, 59, 55, 57, 1092, 137, 159, 51, 132, 49, 92, 47, 62, 56, 26, 53, 55, 73, 60, 63, 54, 98, 564, 50, 3025, 56, 444, 53, 55, 52, 564, 55, 537, 54, 50, 49, 667, 228, 75, 57, 409, 54, 869, 63, 56, 76, 55, 75, 53, 52, 623, 52, 66, 534, 51, 56, 52, 54, 337, 989, 902, 72, 848, 53, 48, 55, 15, 157, 55, 586, 1108, 49, 54, 76, 50, 61, 125, 51, 48, 52, 54, 64, 53, 59, 59, 76, 58, 79, 54, 59, 114, 67, 21, 51, 61, 726, 306, 600, 234, 162, 65, 594, 53, 59, 51, 36, 485, 63, 131, 79, 55, 867, 285, 50, 60, 46, 330, 55, 171, 66, 126, 58, 59, 98, 247, 199, 210, 330, 1010, 49, 52, 48, 126, 54, 52, 54, 151, 53, 318, 53, 47, 55, 49, 95, 60, 39, 760, 3499, 103, 13, 1582, 12, 49, 190, 388, 69, 45, 6497, 56, 640, 418, 246, 757, 59, 140, 78, 174, 76, 172, 82, 63, 60, 59, 331, 352, 57, 69, 63, 58, 1417, 49, 70, 48, 58, 336, 732, 57, 319, 58, 54, 72, 52, 59, 63, 918, 54, 363, 64, 59, 66, 515, 51, 60, 1002, 58, 57, 57, 64, 270, 883, 1867, 68, 22, 309, 53, 97, 64, 25, 64, 58, 64, 523, 186, 826, 59, 61, 166, 53, 24, 118, 53, 758, 400, 95, 90, 158, 954, 549, 51, 271, 153, 49, 53, 914, 320, 185, 50, 193, 65, 164, 58, 50, 60, 217, 2632, 79, 187, 810, 57, 55, 976, 27, 74, 988, 8719, 865, 49, 56, 56, 59, 614, 77, 55, 55, 27, 79, 67, 74, 283, 897, 58, 57, 49, 157, 48, 7908, 153, 430, 77, 511, 575, 285, 46, 56, 904, 492, 96, 79, 80, 51, 123, 265, 108, 72, 175, 6523, 163, 78, 437, 122, 76, 88, 71, 67, 333, 83, 82, 326, 100, 64, 181, 86, 60, 57, 119, 64, 639, 62, 622, 806, 126, 55, 55, 60, 1051, 128, 48, 1104, 23, 47, 116, 68, 104, 4048, 55, 164, 11963, 61, 55, 605, 120, 50, 85, 55, 125, 60, 183, 600, 67, 464, 54, 631, 64, 199, 132, 71, 253, 59, 153, 295, 46, 210, 284, 233, 1168, 369, 390, 51, 204, 156, 48, 454, 13920, 1427, 90, 42, 967, 9234, 76, 43, 469, 117, 1506, 82, 49, 65, 1401, 82, 262, 172, 78, 131, 68, 54, 69, 64, 61, 438, 58, 59, 59, 395, 112, 192, 700, 51, 74, 64, 67, 137, 155, 125, 72, 63, 318, 173, 59, 120, 72, 61, 61, 34, 77, 941, 68, 152, 75, 1036, 2493, 67, 52, 66, 177, 75, 68, 120, 72, 23, 17, 66, 85, 59, 67, 1079, 21, 66, 143, 11880, 59, 113, 134, 71, 92, 48, 63, 812, 20, 1241, 446, 111, 45, 195, 64, 778, 609, 7556, 54, 60, 51, 944, 195, 95, 214, 77, 100, 716, 79, 51, 56, 72, 55, 52, 53, 155, 47, 58, 58, 51, 897, 53, 60, 297, 57, 2646, 59, 130, 313, 60, 178, 115, 911, 61, 300, 801, 317, 9038, 308, 102, 60, 158, 59, 70, 255, 111, 51, 1691, 112, 345, 133, 101, 77, 60, 66, 41, 147, 53, 449, 49, 1156, 76, 131, 717, 79, 1595, 54, 57, 507, 58, 134, 60, 52, 65, 60, 55, 56, 57, 61, 315, 2179, 53, 59, 94, 57, 987, 55, 266, 89, 105, 58, 78, 59, 61, 62, 613, 54, 65, 109, 870, 93, 248, 138, 94, 58, 53, 60, 785, 57, 911, 56, 491, 49, 57, 83, 64, 66, 120, 61, 132, 113, 1080, 77, 66, 54, 56, 1274, 84, 868, 69, 109, 217, 79, 70, 74, 23, 110, 55, 57, 57, 48, 65, 63, 223, 169, 123, 52, 47, 692, 58, 56, 2946, 61, 46, 43, 60, 67, 339, 407, 779, 2965, 325, 56, 298, 6838, 1303, 125, 108, 103, 49, 585, 39, 6512, 75, 852, 61, 298, 32, 74, 66, 68, 57, 64, 63, 59, 55, 145, 57, 58, 105, 62, 259, 1056, 528, 73, 54, 476, 325, 335, 501, 1382, 903, 29, 121, 67, 52, 47, 53, 846, 30, 69, 339, 438, 48, 103, 812, 10805, 400, 89, 3049, 211, 419, 223, 71, 80, 125, 938, 137, 693, 55, 52, 820, 294, 91, 59, 66, 71, 553, 118, 235, 207, 85, 74, 19, 60, 416, 66, 62, 1242, 113, 69, 1218, 98, 54, 88, 136, 65, 57, 70, 51, 65, 108, 129, 67, 72, 145, 710, 98, 53, 78, 21, 7564, 17, 120, 65, 61, 500, 611, 54, 350, 57, 60, 64, 58, 65, 50, 63, 56, 66, 52, 93, 38, 1462, 59, 59, 59, 684, 30, 130, 63, 69, 19, 1015, 59, 77, 762, 71, 64, 139, 45, 552, 49, 52, 529, 3101, 67, 46, 501, 592, 59, 70, 83, 59, 63, 46, 53, 56, 69, 153, 885, 16, 541, 981, 196, 841, 18, 45, 498, 75, 61, 115, 302, 836, 55, 114, 248, 233, 60, 68, 780, 225, 860, 60, 64, 649, 89, 175, 668, 1088, 925, 127, 52, 55, 48, 82, 979, 293, 55, 263, 59, 130, 78, 47, 121, 70, 57, 1886, 56, 61, 519, 172, 1172, 19, 88, 137, 18, 86, 4092, 118, 859, 139, 127, 489, 89, 74, 116, 68, 53, 210, 72, 55, 68, 63, 58, 71, 69, 123, 73, 842, 723, 775, 59, 139, 69, 74, 109, 73, 19, 58, 72, 29, 50, 59, 13, 115, 54, 124, 93, 43, 60, 57, 74, 56, 64, 126, 388, 50, 46, 144, 92, 97, 238, 67, 49, 55, 61, 59, 102, 58, 72, 679, 73, 763, 63, 59, 81, 52, 67, 66, 68, 54, 71, 53, 64, 1041, 38, 56, 92, 133, 60, 144, 294, 1454, 57, 60, 422, 86, 121, 67, 775, 93, 60, 66, 54, 58, 51, 61, 52, 159, 47, 60, 55, 18, 67, 71, 96, 40, 62, 156, 798, 54, 390, 64, 412, 121, 22, 52, 116, 21, 59, 195, 46, 1153, 356, 171, 64, 149, 66, 84, 762, 64, 80, 55, 441, 337, 67, 59, 76, 56, 71, 24, 90, 815, 80, 61, 85, 59, 65, 57, 51, 58, 58, 18, 51, 69, 50, 56, 551, 59, 572, 56, 102, 1107, 126, 87, 59, 983, 54, 53, 65, 77, 61, 56, 523, 59, 82, 21, 63, 802, 61, 8238, 60, 175, 55, 79, 64, 59, 1136, 134, 55, 994, 788, 59, 63, 21, 7677, 59, 1377, 51, 53, 81, 35, 53, 57, 96, 50, 932, 53, 61, 56, 126, 371, 18, 103, 229, 875, 382, 53, 56, 993, 56, 111, 59, 316, 96, 54, 85, 60, 62, 203, 51, 54, 66, 679, 61, 71, 42, 4768, 1085, 289, 4911, 59, 56, 68, 608, 59, 412, 66, 55, 604, 842, 817, 619, 110, 258, 642, 117, 668, 110, 58, 484, 57, 68, 58, 410, 127, 142, 437, 54, 617, 71, 147, 75, 95, 280, 62, 80, 216, 879, 59, 926, 88, 4185, 356, 48, 4600, 81, 69, 27, 1094, 100, 1870, 64, 548, 81, 328, 174, 170, 339, 31, 1122, 63, 28, 70, 1173, 111, 52, 719, 58, 160, 362, 352, 183, 53, 56, 781, 54, 60, 161, 562, 408, 19, 58, 20, 60, 21, 78, 60, 71, 486, 57, 53, 58, 51, 1170, 68, 72, 53, 60, 57, 51, 377, 46, 58, 439, 61, 58, 1085, 53, 129, 538, 1842, 598, 55, 126, 43, 201, 72, 113, 62, 339, 177, 62, 1294, 55, 57, 172, 7283, 91, 176, 54, 147, 1940, 282, 102, 288, 355, 167, 125, 328, 113, 71, 78, 39, 58, 164, 81, 56, 128, 60, 1299, 68, 116, 53, 7338, 72, 136, 78, 237, 1244, 57, 618, 54, 53, 66, 519, 61, 209, 1141, 148, 98, 64, 61, 65, 60, 126, 61, 59, 64, 51, 78, 54, 310, 336, 388, 56, 52, 77, 141, 691, 143, 929, 1094, 129, 151, 960, 93, 272, 989, 455, 64, 49, 4784, 12101, 27, 96, 959, 74, 176, 60, 12, 230, 87, 724, 1656, 51, 4285, 58, 32, 49, 659, 70, 54, 256, 67, 94, 736, 63, 146, 66, 48, 53, 61, 61, 64, 100, 55, 284, 63, 616, 97, 92, 48, 60, 583, 55, 5038, 189, 627, 420, 93, 48, 3879, 58, 289, 644, 522, 5278, 7955, 139, 266, 122, 622, 49, 240, 182, 46, 58, 623, 213, 745, 67, 22, 209, 216, 299, 207, 83, 899, 155, 1094, 69, 55, 59, 21, 440, 828, 68, 64, 68, 4618, 334, 121, 232, 511, 565, 79, 113, 67, 111, 71, 66, 56, 1396, 57, 134, 77, 49, 65, 1026, 632, 76, 68, 89, 549, 166, 72, 1224, 82, 104, 131, 120, 39, 394, 4543, 58, 56, 63, 5089, 98, 398, 78, 581, 194, 64, 78, 500, 50, 53, 148, 172, 52, 112, 129, 577, 286, 108, 53, 30, 59, 68, 987, 823, 58, 169, 52, 590, 333, 172, 64, 616, 80, 207, 181, 176, 104, 172, 85, 87, 87, 1255, 104, 95, 84, 95, 87, 63, 68, 49, 69, 96, 54, 75, 63, 70, 74, 72, 786, 3447, 63, 21, 55, 62, 219, 88, 148, 79, 52, 122, 167, 67, 59, 50, 19, 72, 74, 60, 62, 65, 69, 67, 52, 52, 69, 61, 72, 1047, 57, 451, 238, 35, 934, 908, 124, 364, 58, 46, 698, 1102] + }, + { + "label": "H/W", + "valueformat": ",.1%", + "font": {"family": "monospace", size: 10}, + "values": [0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3503,0.2102,0.106,0.349,0.2887,0.3282,0.2623,0.2514,0.3849,0.4355,0.2245,0.273,0.2763,0.2245,0.2229,0.2021,0.394,0.4183,0.3022,0.4758,0.3389,0.2964,0.1157,0.2767,0.2982,0.1634,0.3805,0.282,0.2266,0.2335,0.4048,0.4518,0.4244,0.4931,0.3975,0.3376,0.1572,0.2424,0.4214,0.4037,0.3976,0.2394,0.4163,0.4412,0.354,0.354,0.3156,0.1511,0.2696,0.2559,0.2709,0.4223,0.4888,0.2403,0.3769,0.3182,0.3028,0.2626,0.238,0.2774,0.1221,0.4055,0.456,0.3534,0.2872,0.2698,0.2924,0.2902,0.3572,0.4176,0.5192,0.5446,0.3186,0.3452,0.3526,0.2835,0.1725,0.1683,0.4279,0.3328,0.0849,0.3074,0.4186,0.2147,0.28,0.4077,0.3662,0.1143,0.0861,0.3937,0.239,0.3419,0.3586,0.4139,0.3827,0.4126,0.3441,0.3755,0.3721,0.4283,0.3654,0.4365,0.3905,0.2883,0.4039,0.301,0.3766,0.4707,0.4609,0.3743,0.2462,0.3333,0.3497,0.1066,0.5141,0.3411,0.3647,0.2297,0.3886,0.339,0.4667,0.4915,0.4194,0.4781,0.3982,0.3725,0.4933,0.4984,0.3962,0.4453,0.3677,0.1643,0.4875,0.4024,0.3883,0.4964,0.4059,0.4534,0.376,0.4706,0.4409,0.3963,0.4695,0.5232,0.2757,0.4578,0.4747,0.4099,0.1677,0.4258,0.4022,0.4183,0.4416,0.4267,0.3642,0.4358,0.433,0.4275,0.4326,0.4856,0.464,0.431,0.3653,0.4402,0.4672,0.4672,0.384,0.4332,0.4255,0.4375,0.4745,0.4246,0.4165,0.4211,0.429,0.4512,0.4291,0.5072,0.43,0.414,0.4316,0.4756,0.3857,0.4651,0.4549,0.4507,0.4258,0.4519,0.4491,0.4205,0.4472,0.4804,0.3892,0.2445,0.4304,0.4379,0.43,0.4528,0.4528,0.3003,0.449,0.3481,0.3132,0.4251,0.2272,0.4489,0.4217,0.4464,0.445,0.494,0.4531,0.3948,0.2236,0.4605,0.3525,0.4482,0.4578,0.5002,0.4241,0.4563,0.4283,0.4645,0.2254,0.1096,0.4617,0.4652,0.3812,0.4493,0.4612,0.4189,0.4455,0.4516,0.4406,0.4658,0.3804,0.4644,0.4692,0.4696,0.2486,0.4627,0.4517,0.4418,0.3038,0.4693,0.4968,0.4639,0.459,0.2915,0.4581,0.4593,0.4501,0.4698,0.3939,0.465,0.4483,0.2227,0.2034,0.4613,0.455,0.4477,0.4566,0.4447,0.4631,0.31,0.4708,0.457,0.4426,0.4596,0.4589,0.4579,0.447,0.4572,0.4561,0.456,0.4464,0.4537,0.4631,0.4727,0.5143,0.4404,0.4407,0.4499,0.4528,0.4548,0.4631,0.1663,0.452,0.4624,0.2446,0.4604,0.4621,0.4632,0.4667,0.4479,0.4657,0.1329,0.4653,0.4614,0.4698,0.4617,0.449,0.4735,0.5057,0.4503,0.4611,0.4691,0.4571,0.469,0.4622,0.4991,0.509,0.4768,0.456,0.4841,0.4242,0.3999,0.1929,0.4636,0.4537,0.3063,0.0758,0.4677,0.458,0.2022,0.4643,0.4569,0.4675,0.4741,0.4813,0.4474,0.4306,0.4532,0.4562,0.4613,0.3225,0.4793,0.4654,0.4016,0.4759,0.4292,0.4665,0.4569,0.48,0.4419,0.2803,0.4752,0.4665,0.4724,0.4651,0.4626,0.4761,0.4732,0.4701,0.4637,0.4688,0.4597,0.4825,0.2323,0.4098,0.4642,0.4769,0.4662,0.2957,0.3255,0.4641,0.4715,0.3779,0.4727,0.3506,0.4645,0.1597,0.4683,0.4735,0.4705,0.4624,0.4673,0.4709,0.4627,0.4522,0.4701,0.4697,0.5068,0.4612,0.4609,0.466,0.5259,0.4635,0.4485,0.5349,0.4628,0.4654,0.4543,0.4653,0.308,0.4718,0.4863,0.4744,0.2371,0.5003,0.3191,0.1864,0.4691,0.4529,0.4688,0.1522,0.3725,0.4326,0.4484,0.4442,0.3543,0.1314,0.4618,0.4363,0.4568,0.3268,0.4694,0.449,0.2738,0.4672,0.2723,0.4663,0.4713,0.4736,0.4641,0.4251,0.236,0.4569,0.5107,0.2235,0.4575,0.4571,0.3753,0.4645,0.3207,0.2212,0.4671,0.4582,0.3889,0.4635,0.4726,0.4546,0.4622,0.5338,0.4557,0.4615,0.4914,0.4598,0.4652,0.4074,0.4977,0.2968,0.4563,0.1935,0.4658,0.4273,0.5074,0.407,0.3923,0.4499,0.5069,0.4518,0.4143,0.3748,0.4568,0.0986,0.4635,0.4533,0.4077,0.4556,0.4591,0.4414,0.3821,0.4269,0.4624,0.049,0.1332,0.4598,0.4518,0.4646,0.4564,0.4074,0.4197,0.4563,0.2365,0.5009,0.4378,0.4395,0.4359,0.4655,0.4777,0.4516,0.2404,0.4389,0.4385,0.4646,0.4947,0.3696,0.4278,0.4836,0.4374,0.4824,0.4568,0.1027,0.4017,0.4785,0.4259,0.1476,0.2125,0.4828,0.4787,0.4659,0.4588,0.4589,0.4644,0.4599,0.4447,0.394,0.2117,0.4591,0.4552,0.434,0.1955,0.4826,0.4357,0.2824,0.3239,0.3866,0.2579,0.0868,0.504,0.337,0.3013,0.2995,0.3904,0.3763,0.3902,0.488,0.2711,0.426,0.2838,0.4567,0.4595,0.3141,0.344,0.3524,0.2747,0.4047,0.4712,0.3362,0.3363,0.51,0.2836,0.4845,0.2807,0.2489,0.4478,0.3792,0.4862,0.294,0.3372,0.3838,0.3054,0.3059,0.3382,0.3782,0.3669,0.4057,0.3136,0.3726,0.3203,0.3039,0.3652,0.3654,0.3497,0.284,0.3396,0.3227,0.334,0.3348,0.2618,0.3699,0.2903,0.2834,0.3092,0.3196,0.3438,0.3595,0.2426,0.3603,0.3344,0.3617,0.4885,0.3156,0.4708,0.3111,0.5068,0.3744,0.2958,0.3443,0.3438,0.3224,0.3595,0.3693,0.1386,0.3765,0.1277,0.3831,0.3513,0.3366,0.4357,0.3552,0.3688,0.3921,0.3668,0.3512,0.3531,0.3646,0.3964,0.4014,0.3932,0.3426,0.0899,0.3302,0.4054,0.3646,0.4796,0.2794,0.3071,0.4079,0.2652,0.4221,0.2835,0.4224,0.3672,0.3027,0.3528,0.3471,0.3736,0.3794,0.3734,0.5055,0.3836,0.4118,0.428,0.3856,0.3808,0.2789,0.3667,0.0545,0.3847,0.4435,0.3622,0.3622,0.248,0.4418,0.3883,0.374,0.3867,0.4,0.3478,0.293,0.4093,0.3151,0.3958,0.3906,0.3731,0.384,0.3927,0.4015,0.3808,0.3807,0.4755,0.3919,0.4541,0.4291,0.3891,0.3733,0.4442,0.3692,0.4273,0.3735,0.4146,0.3594,0.4912,0.4337,0.3702,0.3727,0.3572,0.2876,0.2819,0.3909,0.4457,0.4305,0.4233,0.3758,0.362,0.445,0.4411,0.4159,0.4156,0.3562,0.4412,0.4476,0.2794,0.4378,0.3557,0.4235,0.4378,0.443,0.3957,0.3939,0.4675,0.4451,0.4383,0.3913,0.4421,0.4432,0.4388,0.4485,0.4338,0.4443,0.4584,0.4601,0.4505,0.468,0.4694,0.4478,0.421,0.2787,0.4466,0.452,0.472,0.4119,0.459,0.4547,0.4526,0.4485,0.4662,0.4414,0.4492,0.4514,0.4667,0.4566,0.4671,0.4441,0.4427,0.3257,0.4604,0.4439,0.4627,0.4521,0.3045,0.4423,0.0986,0.4388,0.464,0.2199,0.4353,0.3162,0.3346,0.2652,0.4587,0.2954,0.4414,0.4546,0.5036,0.4446,0.1798,0.3615,0.4671,0.4725,0.4634,0.4866,0.4582,0.4101,0.3729,0.4767,0.3916,0.4418,0.4585,0.4018,0.4017,0.4337,0.4623,0.4319,0.4331,0.4861,0.2038,0.2578,0.4641,0.4523,0.1418,0.4568,0.4591,0.4308,0.3099,0.4543,0.5206,0.3527,0.4609,0.4481,0.4554,0.4663,0.4594,0.4615,0.4561,0.4481,0.4706,0.4452,0.4624,0.3061,0.4512,0.361,0.4497,0.4615,0.3755,0.4573,0.4801,0.4582,0.2268,0.4465,0.4665,0.4599,0.452,0.4684,0.4513,0.4707,0.4658,0.1848,0.4561,0.463,0.4653,0.4472,0.4677,0.474,0.2698,0.4412,0.4515,0.4639,0.4442,0.446,0.3465,0.444,0.4448,0.4577,0.4598,0.4643,0.3763,0.345,0.2422,0.2171,0.4664,0.4571,0.4734,0.4629,0.4575,0.4244,0.4611,0.1915,0.458,0.4605,0.319,0.2657,0.1885,0.3449,0.4584,0.4617,0.4622,0.4621,0.0937,0.4584,0.4381,0.4585,0.457,0.4553,0.3229,0.2501,0.2159,0.4652,0.4749,0.4591,0.457,0.1091,0.4596,0.4571,0.4799,0.4595,0.4428,0.4599,0.4684,0.4585,0.4572,0.1627,0.4628,0.4603,0.4576,0.4624,0.4614,0.4724,0.4474,0.4667,0.4523,0.3287,0.2666,0.4767,0.4566,0.4439,0.4808,0.4717,0.4529,0.4299,0.3346,0.4617,0.4634,0.4696,0.3761,0.4578,0.4641,0.4291,0.4663,0.4572,0.4592,0.463,0.0681,0.4658,0.4605,0.4554,0.2416,0.4661,0.4621,0.4671,0.4696,0.4527,0.4618,0.4594,0.4608,0.4651,0.461,0.5069,0.4704,0.4657,0.4657,0.457,0.467,0.3164,0.4647,0.462,0.4652,0.4705,0.4723,0.4717,0.4598,0.4627,0.4665,0.4659,0.4667,0.4683,0.4697,0.4635,0.4637,0.4625,0.4652,0.4628,0.414,0.473,0.2808,0.4618,0.4652,0.4625,0.47,0.468,0.4593,0.4609,0.4644,0.4562,0.4571,0.4637,0.4496,0.4637,0.4661,0.4607,0.4655,0.4667,0.4575,0.4659,0.453,0.4672,0.4628,0.4661,0.4671,0.4565,0.463,0.4783,0.4632,0.4624,0.4652,0.2936,0.4605,0.4631,0.465,0.3615,0.4647,0.4649,0.4657,0.4693,0.1734,0.4547,0.4547,0.4063,0.4825,0.4172,0.5094,0.4611,0.4598,0.4103,0.4522,0.4713,0.4552,0.429,0.4445,0.4951,0.4734,0.4458,0.4704,0.5342,0.4663,0.4493,0.4541,0.3857,0.4685,0.4511,0.4537,0.4707,0.4766,0.4724,0.467,0.3707,0.474,0.4518,0.4587,0.3528,0.4605,0.475,0.4668,0.262,0.4657,0.2022,0.4661,0.4632,0.4735,0.1637,0.2756,0.462,0.471,0.323,0.4714,0.4615,0.3217,0.4624,0.3595,0.4732,0.3584,0.4631,0.4649,0.4678,0.4585,0.4534,0.4638,0.4643,0.4519,0.4675,0.4729,0.1176,0.4569,0.4658,0.2056,0.4606,0.4745,0.4712,0.4733,0.2708,0.3096,0.4677,0.4739,0.1961,0.4697,0.4691,0.4539,0.4686,0.4645,0.4675,0.4728,0.4715,0.4641,0.4707,0.459,0.4642,0.4783,0.4613,0.4666,0.456,0.4546,0.4705,0.4656,0.4412,0.4779,0.2631,0.4641,0.4698,0.4648,0.4343,0.3409,0.4131,0.3953,0.4752,0.1389,0.4683,0.4907,0.4607,0.3496,0.303,0.4653,0.2947,0.4519,0.4706,0.4647,0.2345,0.4601,0.3496,0.4685,0.431,0.4708,0.3121,0.4549,0.3636,0.4658,0.4688,0.4491,0.1435,0.2812,0.3221,0.3186,0.4606,0.4617,0.4689,0.4754,0.2831,0.4584,0.4664,0.4664,0.3351,0.4619,0.3536,0.4594,0.4763,0.455,0.4612,0.4559,0.4612,0.4655,0.2916,0.4163,0.4616,0.3583,0.4157,0.2951,0.465,0.3951,0.4274,0.461,0.5429,0.3434,0.4634,0.3112,0.2645,0.3055,0.4805,0.4449,0.4803,0.4562,0.493,0.4462,0.4297,0.4947,0.4506,0.4411,0.4523,0.1333,0.2516,0.4623,0.4611,0.4742,0.4444,0.1819,0.4602,0.4781,0.4717,0.4594,0.2387,0.3514,0.4612,0.2391,0.4371,0.4755,0.5075,0.4634,0.4623,0.4629,0.4375,0.4584,0.4529,0.457,0.4589,0.4668,0.3888,0.4737,0.4593,0.4592,0.453,0.4691,0.471,0.4586,0.2755,0.3362,0.2935,0.3811,0.38,0.4017,0.479,0.4176,0.4636,0.3278,0.3804,0.4743,0.4614,0.3995,0.3285,0.127,0.4676,0.4686,0.4576,0.4751,0.3578,0.4209,0.4539,0.3483,0.4137,0.4668,0.4225,0.4004,0.2937,0.2878,0.4554,0.4061,0.4182,0.4739,0.4628,0.4412,0.475,0.4264,0.468,0.4603,0.4595,0.2674,0.4573,0.4528,0.4668,0.1814,0.459,0.4542,0.456,0.4792,0.4661,0.4544,0.4647,0.3393,0.4584,0.4619,0.4261,0.3883,0.485,0.457,0.4624,0.3545,0.2884,0.3164,0.4606,0.4622,0.3059,0.455,0.382,0.4468,0.3756,0.4642,0.4559,0.4652,0.4678,0.4447,0.4605,0.2002,0.4252,0.1264,0.4535,0.0768,0.1516,0.5143,0.4644,0.4603,0.433,0.2203,0.4536,0.4371,0.4426,0.4683,0.3953,0.2126,0.2787,0.4484,0.4045,0.2419,0.4356,0.4412,0.4186,0.3838,0.4517,0.5263,0.4596,0.4657,0.3192,0.3825,0.4513,0.364,0.3972,0.4704,0.4855,0.4611,0.4749,0.4611,0.4681,0.4676,0.4076,0.4341,0.4417,0.4321,0.4012,0.4556,0.4561,0.4502,0.4447,0.4575,0.4704,0.4625,0.3587,0.4597,0.4542,0.4522,0.4546,0.2611,0.4424,0.3923,0.3756,0.456,0.4493,0.4495,0.4211,0.4637,0.4735,0.4544,0.4571,0.4472,0.2786,0.3427,0.4451,0.3878,0.4578,0.1417,0.4519,0.2635,0.2984,0.448,0.2682,0.461,0.4055,0.3935,0.461,0.4532,0.332,0.1754,0.4313,0.1925,0.3898,0.4651,0.3866,0.4439,0.4293,0.2235,0.38,0.3891,0.446,0.4251,0.4099,0.4324,0.4295,0.4536,0.2311,0.4655,0.443,0.4537,0.4719,0.4416,0.4454,0.4479,0.1643,0.4133,0.4002,0.2786,0.4536,0.4485,0.4437,0.4344,0.4656,0.0929,0.4507,0.4692,0.466,0.1327,0.4278,0.3083,0.4904,0.3317,0.4639,0.4464,0.4542,0.3529,0.4505,0.405,0.4442,0.4323,0.3919,0.3434,0.4274,0.4413,0.4413,0.4593,0.4477,0.4013,0.4216,0.4393,0.4419,0.391,0.4347,0.4677,0.1074,0.4396,0.4583,0.4495,0.4328,0.4465,0.3244,0.4464,0.4402,0.3301,0.4526,0.4355,0.4347,0.4427,0.4438,0.3638,0.3327,0.4507,0.4008,0.3338,0.4483,0.3323,0.4413,0.4459,0.4374,0.4562,0.4517,0.4632,0.3368,0.4343,0.4097,0.4406,0.4644,0.1571,0.4078,0.3433,0.4312,0.2404,0.343,0.4475,0.4677,0.4585,0.2978,0.4329,0.5107,0.3633,0.4574,0.3604,0.437,0.4603,0.4743,0.4422,0.451,0.4648,0.4666,0.447,0.461,0.4507,0.4612,0.4428,0.441,0.4696,0.4486,0.3355,0.4433,0.0873,0.4502,0.4274,0.4633,0.4473,0.3137,0.4417,0.458,0.4693,0.4663,0.2505,0.1642,0.3798,0.3794,0.4149,0.4598,0.436,0.4444,0.4461,0.3955,0.4296,0.4678,0.4436,0.4565,0.1679,0.424,0.4656,0.4521,0.4593,0.4598,0.4267,0.247,0.4596,0.355,0.4674,0.4528,0.4351,0.4582,0.5148,0.4358,0.4551,0.4633,0.4589,0.2789,0.4626,0.4544,0.4736,0.4462,0.4608,0.4453,0.4665,0.4722,0.4632,0.4771,0.2868,0.4384,0.4576,0.4528,0.4649,0.455,0.4593,0.4494,0.4847,0.4772,0.3203,0.4532,0.3521,0.4601,0.4501,0.4579,0.3659,0.466,0.4457,0.4536,0.47,0.4856,0.1852,0.2763,0.4576,0.469,0.459,0.4587,0.3582,0.446,0.2846,0.4551,0.1506,0.4631,0.4681,0.3023,0.4626,0.4773,0.3561,0.3619,0.4226,0.4454,0.4599,0.4746,0.4065,0.4563,0.4653,0.454,0.448,0.4675,0.4657,0.2741,0.2293,0.4402,0.4674,0.4436,0.3383,0.279,0.4655,0.4656,0.4618,0.4091,0.4663,0.4635,0.2082,0.5098,0.4897,0.4526,0.4573,0.3859,0.4562,0.4557,0.4743,0.4617,0.4668,0.4706,0.449,0.4627,0.3526,0.3432,0.3848,0.4733,0.4664,0.4005,0.1627,0.3335,0.4913,0.4769,0.4565,0.4537,0.4198,0.4104,0.4135,0.2112,0.2602,0.2586,0.4607,0.3893,0.5202,0.4403,0.1955,0.4489,0.4753,0.4532,0.4559,0.4663,0.4562,0.453,0.4611,0.2964,0.5273,0.4587,0.2129,0.4571,0.3808,0.492,0.4493,0.319,0.3455,0.1815,0.3167,0.4668,0.281,0.3651,0.4084,0.4136,0.457,0.4549,0.4631,0.2638,0.3535,0.4965,0.3545,0.3188,0.4554,0.4548,0.4688,0.3183,0.1743,0.5057,0.4601,0.3527,0.2615,0.2009,0.5048,0.5397,0.3916,0.3909,0.4718,0.4048,0.464,0.4681,0.3436,0.2044,0.501,0.4792,0.4978,0.481,0.3468,0.395,0.415,0.429,0.4886,0.491,0.3411,0.465,0.3459,0.4472,0.4815,0.5162,0.4552,0.4983,0.3921,0.4449,0.238,0.4527,0.4773,0.449,0.4781,0.4793,0.4581,0.4769,0.4625,0.4837,0.4987,0.4605,0.4482,0.2139,0.4548,0.3927,0.453,0.4435,0.3831,0.4611,0.4562,0.4505,0.4724,0.0508,0.4606,0.4682,0.3233,0.4711,0.462,0.3325,0.4622,0.4588,0.3834,0.4682,0.454,0.2746,0.4505,0.4613,0.4117,0.1395,0.4648,0.4575,0.4622,0.3452,0.378,0.4189,0.4669,0.448,0.3362,0.3335,0.3431,0.3518,0.3948,0.3497,0.4479,0.4932,0.4636,0.1025,0.4598,0.4698,0.3886,0.4498,0.3492,0.4462,0.4597,0.2471,0.4715,0.4647,0.4353,0.4644,0.4498,0.518,0.4551,0.4763,0.4502,0.4371,0.4764,0.3329,0.1331,0.4637,0.5051,0.4669,0.3253,0.4705,0.2647,0.456,0.4743,0.4444,0.1259,0.4458,0.4578,0.398,0.4349,0.3629,0.4577,0.457,0.4471,0.2514,0.2462,0.4599,0.4665,0.4168,0.3852,0.4403,0.4187,0.456,0.45,0.3949,0.4535,0.4433,0.4676,0.4361,0.4621,0.2827,0.4413,0.3417,0.4268,0.4643,0.4372,0.4671,0.3045,0.4481,0.4555,0.4998,0.4623,0.4673,0.2633,0.268,0.4482,0.3432,0.4516,0.4483,0.4836,0.445,0.416,0.4594,0.2678,0.4286,0.4608,0.0796,0.3901,0.4498,0.4001,0.4503,0.4679,0.199,0.3279,0.4676,0.4527,0.4547,0.3982,0.4441,0.4483,0.2104,0.4554,0.5006,0.2441,0.4498,0.4204,0.3503,0.4514,0.455,0.4526,0.4557,0.4128,0.4275,0.4511,0.3975,0.4156,0.4814,0.3497,0.4435,0.4278,0.3997,0.4083,0.4555,0.4375,0.4447,0.4324,0.4621,0.4418,0.4639,0.1858,0.4582,0.4375,0.3922,0.411,0.4341,0.2897,0.4094,0.4591,0.4498,0.4225,0.4454,0.4248,0.4582,0.4206,0.4125,0.4125,0.4705,0.4584,0.456,0.4554,0.3935,0.449,0.4335,0.3667,0.4582,0.4343,0.4744,0.4472,0.4396,0.4417,0.4437,0.1965,0.3368,0.4342,0.4921,0.166,0.468,0.4532,0.4425,0.2859,0.4429,0.4426,0.4356,0.317,0.4652,0.4401,0.4461,0.4527,0.4355,0.4535,0.4248,0.4704,0.2361,0.4796,0.442,0.4482,0.3481,0.4446,0.4449,0.4166,0.3797,0.443,0.2438,0.302,0.4472,0.422,0.4548,0.1667,0.2308,0.335,0.4456,0.3629,0.3366,0.4416,0.1677,0.4501,0.4485,0.185,0.3163,0.4537,0.3153,0.428,0.3329,0.3446,0.4355,0.4676,0.4649,0.3747,0.1945,0.4429,0.4388,0.374,0.4521,0.4462,0.3908,0.3047,0.3842,0.3624,0.4362,0.4196,0.4384,0.4377,0.4605,0.4379,0.4407,0.4454,0.3494,0.4594,0.4551,0.4456,0.4639,0.4512,0.4753,0.4562,0.462,0.4849,0.3585,0.459,0.5171,0.4388,0.4005,0.4507,0.4604,0.4446,0.4656,0.4473,0.446,0.2542,0.4474,0.5283,0.468,0.444,0.2958,0.4531,0.3254,0.4495,0.4341,0.4381,0.4467,0.4453,0.4422,0.4804,0.4375,0.4453,0.4383,0.3708,0.4533,0.4418,0.3096,0.3812,0.4562,0.3676,0.4488,0.4437,0.5262,0.4684,0.4533,0.4564,0.5244,0.4615,0.3803,0.4566,0.4583,0.4556,0.461,0.0872,0.3438,0.4357,0.4166,0.3994,0.2737,0.4565,0.4645,0.4661,0.476,0.402,0.4626,0.4806,0.4295,0.4501,0.4282,0.4582,0.4583,0.1882,0.4707,0.4564,0.4594,0.1755,0.4605,0.4572,0.341,0.3504,0.4534,0.1948,0.106,0.4602,0.4586,0.4437,0.4594,0.4585,0.3139,0.4479,0.4592,0.1339,0.4348,0.4316,0.161,0.4552,0.3262,0.2141,0.3608,0.4566,0.4696,0.466,0.1421,0.458,0.4574,0.4623,0.3439,0.3867,0.3428,0.2931,0.461,0.1563,0.2227,0.3469,0.4189,0.2885,0.2017,0.4541,0.2233,0.3998,0.4523,0.4592,0.4671,0.5042,0.4081,0.1494,0.4663,0.4696,0.4518,0.4625,0.3405,0.4728,0.4552,0.2448,0.4622,0.1409,0.4536,0.4747,0.4271,0.4657,0.3898,0.334,0.3606,0.4703,0.254,0.4646,0.4694,0.4611,0.4706,0.3508,0.4716,0.1887,0.3862,0.4019,0.2887,0.4615,0.4606,0.5001,0.4689,0.4565,0.3809,0.143,0.2964,0.3414,0.458,0.3001,0.4675,0.3678,0.4507,0.4762,0.4107,0.062,0.4648,0.4652,0.468,0.4744,0.4651,0.4616,0.4232,0.4694,0.4671,0.4817,0.4778,0.3495,0.4638,0.4857,0.3818,0.4745,0.4643,0.4666,0.4716,0.4772,0.1133,0.4934,0.3119,0.2747,0.4783,0.4206,0.1651,0.3022,0.4712,0.4756,0.4334,0.2626,0.4801,0.3983,0.482,0.4545,0.2641,0.3024,0.5135,0.3654,0.4546,0.3335,0.3338,0.4,0.4239,0.1084,0.399,0.4471,0.4692,0.4334,0.4574,0.4603,0.4766,0.5168,0.4761,0.4574,0.4502,0.467,0.4512,0.4542,0.4509,0.4497,0.4633,0.4654,0.2004,0.4622,0.2306,0.4708,0.4706,0.4868,0.4633,0.1202,0.473,0.4698,0.4369,0.3703,0.4456,0.3404,0.4469,0.4071,0.448,0.4582,0.4483,0.453,0.4635,0.4649,0.4568,0.469,0.4555,0.3523,0.4867,0.4526,0.4758,0.2122,0.0891,0.4765,0.4712,0.4305,0.4704,0.2048,0.4563,0.3358,0.3646,0.4404,0.3895,0.3805,0.5067,0.3549,0.4647,0.2781,0.4611,0.3036,0.2191,0.3975,0.3599,0.4495,0.4458,0.4683,0.4512,0.4597,0.3168,0.2124,0.4259,0.4524,0.4414,0.4618,0.1988,0.4589,0.3512,0.4695,0.4374,0.4764,0.4272,0.419,0.4488,0.3451,0.2974,0.4794,0.1887,0.4479,0.4591,0.4619,0.4513,0.4652,0.4285,0.3506,0.4528,0.181,0.4565,0.1194,0.4527,0.4441,0.4621,0.4391,0.4672,0.458,0.2902,0.5053,0.4555,0.3871,0.4642,0.4582,0.2483,0.4511,0.4638,0.1405,0.1109,0.157,0.4349,0.3917,0.2041,0.3435,0.2639,0.4581,0.4561,0.5093,0.2,0.4629,0.3909,0.4518,0.2513,0.4614,0.3486,0.4497,0.4309,0.4423,0.4346,0.4522,0.3755,0.2737,0.4879,0.4608,0.4711,0.4727,0.3195,0.2443,0.3497,0.461,0.342,0.4809,0.4786,0.4506,0.4249,0.4109,0.5651,0.3878,0.3821,0.428,0.4563,0.4248,0.471,0.4512,0.4747,0.4325,0.407,0.4516,0.4624,0.4702,0.476,0.4525,0.4662,0.4429,0.4955,0.4425,0.1248,0.3524,0.4626,0.4448,0.4575,0.4631,0.4049,0.5235,0.3977,0.2327,0.3973,0.4819,0.457,0.4742,0.4033,0.4828,0.3757,0.4503,0.2622,0.3144,0.4172,0.4505,0.1567,0.4656,0.4665,0.3262,0.4417,0.4622,0.5028,0.4337,0.0923,0.2431,0.275,0.3721,0.5334,0.4603,0.454,0.3645,0.2497,0.4562,0.4356,0.4707,0.1906,0.3585,0.4343,0.4569,0.1385,0.4014,0.3687,0.4652,0.3999,0.4398,0.4466,0.454,0.4269,0.4708,0.3649,0.4594,0.4415,0.4715,0.4832,0.4903,0.4526,0.4629,0.4618,0.4428,0.4646,0.4505,0.4181,0.456,0.4403,0.4459,0.4271,0.24,0.1916,0.452,0.3443,0.4589,0.4579,0.2893,0.5132,0.2048,0.4469,0.4498,0.4405,0.1836,0.461,0.475,0.4454,0.5038,0.4384,0.4445,0.4473,0.4882,0.3888,0.4429,0.4397,0.4733,0.3946,0.4608,0.4523,0.4387,0.4655,0.4708,0.3544,0.1169,0.3776,0.1953,0.3413,0.5151,0.2456,0.4156,0.5287,0.1887,0.1637] + }, + { + "label": "Min H/W", + "values": [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, 42910, 126039, 135736, 46100, 54920, 113880, 100220, 91860, 52140, 104500, 110480, 82230, 69120, 136490, 97950, 79780, 44390, 23330, 86870, 1469, 130450, 114629, 184720, 32180, 56400, 131980, 58430, 63240, 59330, 58640, 29810, 11790, 25690, 13330, 39900, 70460, 160410, 55770, 25179, 18490, 27650, 79830, 40630, 16900, 41369, 118770, -2760, 190000, 119920, 85020, 73980, 49120, 51200, 41940, 71030, 51970, 75200, 80390, 70520, 69910, 119636, 40720, -16800, 48360, 70910, 66170, 54730, 66650, 70930, 41940, 8919, -8201, 48240, 50080, 44120, 70290, 74640, 94410, 30920, 56720, 187800, 170140, 45710, 124420, 59660, 90450, 24040, 129420, 173100, 45500, 37120, 34300, 52610, 59770, 89350, 59000, 32820, 23020, 26780, 19180, 19350, 22770, 37900, 56130, 21080, 41360, 49010, 16290, 14480, 23140, 90940, 39390, 43869, 138650, -19100, 34470, 34630, 12036, 102620, 24060, 14260, 9980, 71280, 5559, 19670, 141580, 37160, 9199, 23650, 17750, 22180, 99940, 7589, 17540, 16790, 5080, 34200, 7580, 25040, 7300, 13060, 17520, 6419, -1381, 41910, 10830, 4100, 20210, 188340, 5209, 12970, 14960, 15149, 11780, 105870, 10600, 16640, 9179, 9750, 7869, 9400, 9640, 34300, 10610, 7640, 12680, 21000, 76650, 12170, 13130, 6909, 19100, 16490, 13150, 12810, 7980, 97129, -2571, 12800, 13140, 14170, 59090, 4630, 5150, 6889, 6050, 13490, 3860, 10260, 13930, 3160, -1600, 40730, 88140, 11680, 11560, 10280, 5390, 9440, 131340, 7570, 144740, 60570, 12210, 142160, 8029, 70330, 6570, 8240, -1070, 5180, 75360, 64130, 4979, 73200, 7920, 2460, 3080, 60010, 7470, 10450, 2600, 99590, 134120, 5400, 1179, 76180, 4209, 3650, 38840, 8910, 4250, 14170, 3999, 76350, 4860, -15060, -341, 128230, 2330, 5859, 22060, 44500, 770, 4769, 1039, 539, 53740, 5130, 5729, 13939, 5580, 48450, 1110, 6199, 164570, 179370, 4720, 6339, 12740, 3569, 6740, 4089, 13730, -641, 2360, 8390, 12540, 5500, 4519, 5790, 8100, 4159, 6329, 7200, 2510, 2199, 9430, 1130, 7710, 11010, 11439, 9619, 8699, 5529, 99290, 6729, 7670, 60320, 8769, 3379, 4350, 2020, 10470, 2929, 187500, 5399, 839, 2790, 2430, 9999, 1970, 2979, 8070, 2849, 5110, 5679, 979, 4449, 2559, -410, 829, 3989, 279, 11130, 130020, 63780, 48590, 15020, 59370, 174670, 44850, 4510, 57900, 3340, 5340, 6710, -1150, -4031, 4400, 1400, 13450, 5500, 3909, 133800, 1570, 2959, 38050, 6499, 37810, 599, 1560, 1949, 38340, 66110, 13230, -1020, 9730, 3350, 2790, 8729, 109, 1679, 1690, 2440, 1910, 5659, 43820, 80340, 739, 47080, 1709, 164110, 58980, 5069, 1810, 16480, -1550, 81400, 3139, 133160, 2669, -821, 3349, 2360, 4120, 1960, 4129, 25520, 3660, 2260, 2959, 6350, 6830, 559, -3540, 5040, 62340, -8401, 4570, 6469, 14420, 3509, 172060, 4749, 38850, 3860, 167900, 1540, 59530, 176210, 2949, 13930, 819, 132560, 74890, 34410, 5559, 41260, 102000, 174330, -17380, 10730, 8950, 144260, 2560, 24580, 6370, 80, 22540, 2060, 1019, 160, 3180, 11580, 88900, 10470, 6260, 73860, 3119, 2980, 158220, 4309, 30660, 68780, 5040, 3770, 99260, 1980, 1970, 6829, 2289, -20080, 2310, 9650, -2251, 2529, 2530, 14700, 3959, 166700, 3599, 150930, 3459, 20810, 6590, 55690, 22690, 5139, 69, 6480, -12630, 37400, 9400, 186250, 9540, 10830, 14040, 9070, 4760, 7700, 56650, 11310, 4790, 194180, 128610, 6400, 7109, 2769, 9170, 14430, 104370, 9179, 178490, 1839, 3649, 9690, 20490, 339, 3980, 9289, 97370, 16590, 13480, 3039, 9209, 108480, 29490, 14640, 22230, 2340, 15880, 155060, 121920, 2909, 27250, 163260, 172970, 2660, 18100, 5159, 5870, 3790, 2880, 4320, 12500, 56360, 125710, 17810, 19190, 106000, 83140, 42550, 104300, 56000, 102609, 49720, 119469, 171680, 32940, 81140, 57710, 46010, 47900, 12410, 51430, 52000, 71890, 38220, 59550, 30110, 25690, 60750, 41920, 42970, 122470, 41700, 24520, 36670, 43590, 28380, 65420, 20490, 46900, 74830, 23260, 30570, 53800, 48360, 44400, 28940, 38850, 55090, 44390, 117250, 26040, 38180, 40279, 21509, 40690, 43770, 23870, 34920, 35680, 47920, 34530, 10209, 38060, 36900, 172090, 22500, 41440, 48970, 51970, 40759, 32670, 29570, 8320, 32190, 36220, 26469, 7490, 50070, 16550, 52680, -14320, 18900, 55380, 31810, 30419, 92140, 31910, 29040, 139770, 30299, 117280, 30630, 29670, 36720, -13690, 31170, 24230, -7440, 28120, 27790, 26429, 26000, 27230, 25920, 76240, 30360, 186670, 44830, 116240, 24560, 29890, 95180, 82150, 26890, 70680, 23220, 173160, 18330, 29520, 47580, 40140, 29100, 28250, 26230, 27280, 29190, 15910, 28300, 15970, 18410, 23929, 86500, 26960, 195790, 23360, 15049, 27500, 25880, 29740, 14950, 18950, 98230, 19830, 21830, 33440, 109480, 16040, 61550, 23600, 20700, 24970, 25500, 19860, 15920, 25010, 26910, 14280, 18950, 15430, 12709, 22380, 78950, 4990, 32920, 110000, 23040, 16230, 26429, 10009, 14770, 27599, 21410, 19900, 149800, 159730, 25800, 9250, 16530, 14280, 99670, 28780, 7340, 11060, 14120, 7850, 123859, 27430, 9960, 32360, 11210, 104469, 14710, 11570, 14290, 95429, 18660, 4369, 9129, 9270, 17570, 8890, 6709, 9220, 7710, 11250, 6599, 5370, 3400, 4270, 179, 2290, 4540, 13700, 93360, 59470, 8529, -851, 19020, 4139, 5289, 2350, 6269, 990, 8240, 7010, 8050, 1210, 4560, 1259, 9949, 8110, 64180, 3909, 6729, 2690, 5280, 150810, 6709, 148720, 32080, 2289, 171240, 6690, 79710, 122870, 39720, 3809, 122739, 30200, 5390, 5709, 8730, 118730, 74280, 13320, 5130, 4419, 3000, 3679, 9389, 63420, 6690, 95570, 20350, 5090, 44240, 120660, 29440, 2999, 35740, 63700, -1540, 155930, 145400, 5790, 939, 175990, 3370, 5030, 8129, 69630, 3980, 19400, 27460, 10430, 25930, 6300, 3050, 5360, 4789, 5870, 16930, 1360, 3990, 3170, 79640, 12030, 125269, 7050, 3980, 42910, 9890, -19210, 25280, 170010, 10610, 3749, 3420, 10510, 2749, 7790, 1890, 27759, 140190, 5329, 3289, 6660, 82810, 7319, 1650, 37550, 8889, 7769, 499, 9579, 6610, 35280, 11940, 7629, 2200, 1180, 7390, 159380, 29129, 172160, 108520, 1330, 5769, 1170, 2310, 4110, 54490, 2309, 90020, 1360, 3090, 147650, 79810, 53960, 148120, 5100, 1890, 669, 4730, 190970, -570, 14780, 2929, 3439, 8649, 133040, 96310, 110079, 9729, -151, 4940, 2090, 151720, 6060, 2439, -1190, 2919, 34290, 5939, 2029, 12110, 15930, 175700, 5290, 589, 4910, -1241, 14340, -2690, 1250, 10480, 10930, 116080, 17710, -1590, 6629, 25540, -11360, 2330, 11860, 27210, 153740, 5040, 5950, 1549, 37630, 4259, 2010, 34760, 2959, 4410, 6640, 6889, 179130, 2920, -60, 9899, 144140, 2350, 5719, 3420, 4159, 3330, 799, 2390, 5310, 3079, 4840, 18340, 3719, 6260, 5810, 7309, 3969, 132430, 7079, 5280, 549, 2090, 22160, 1699, 5679, 2509, 2129, 2999, 2469, 4830, 4780, 3960, 3040, 2710, 2440, 2859, 32670, 1659, 9360, 4670, 2080, 4059, 1059, 2789, 5639, 3589, 1709, 5050, 6039, 3850, 13180, 2140, 2079, 6579, -1821, 1389, 7799, 1739, 5910, 1610, 5020, 1809, -721, 4659, 2929, -4720, 1829, 5420, 2709, 50380, 6510, 4900, 1380, 78330, 6539, 5170, 4370, 409, 92280, 5740, -5240, 67910, 33020, 13450, 3690, 6899, 5139, 67240, 6620, 2099, 5599, 13440, 32679, 28520, -180, 30930, -421, 4630, -641, 8349, 5080, 129, 1480, 5289, 11870, 4140, 4360, 1450, 1629, 67510, -421, 21240, 4620, 106560, 2909, 1640, 1290, 35360, 3020, 158790, 2440, 1200, -911, 186220, 88630, 11220, 2760, 109090, 1729, 2269, 30290, 3889, 28940, 1820, 28870, 2559, 1930, 3350, 2659, 9469, 690, 1270, 5479, 1309, 1579, 149430, 6060, 2289, 55039, 1910, 699, -770, 1540, 6850, 64080, 2819, 850, 166420, -441, 1869, 13020, 480, 5479, 25160, -31, -981, 2100, 1620, 7470, 2270, 2390, 5259, 10760, 5520, 13850, 1910, 4650, 26980, 5580, 13470, 1379, 4770, -2110, 67810, 128539, 59940, 48220, 5219, 184470, 1770, 699, 2079, 11750, 124680, 6210, 59900, 14120, 2260, 1140, 110020, 1779, 23809, -1401, 34390, 1970, 67430, 8870, 44820, 4270, 3970, 20880, 123800, 80690, 74260, 98010, 5329, 1080, 1170, -1370, 60700, 3479, 1419, 2499, 57480, 2859, 87760, 3290, -2181, 4539, 859, 3010, 5810, -4340, 158760, 53230, 3790, -6940, 115210, -171, 389, 54720, 81370, 9070, -12800, 102100, 3790, 140870, 125290, 66200, 5500, 7980, 26760, 13240, 4789, 14150, 23180, 8039, 8580, 8720, 6790, 144350, 118030, 4259, 9330, 4600, 7759, 166130, 1229, 6909, -1090, 5270, 118510, 139370, 4460, 115410, 8939, 1140, -9890, 1809, 5070, 6720, 8089, 3749, 72070, 8120, 5770, 6959, 106649, -31, 6090, 5920, 6360, 3400, 2849, 7780, 97370, 157360, 62720, 21920, -2180, 75390, 69, 26280, 6740, 7990, 20550, 2700, 7050, 104860, 67500, 140930, 4179, 4890, 9140, 459, 2829, 31800, 3839, 142650, 86160, 1739, 22910, 25480, 175740, 136730, 2790, 68020, 41520, -771, 2410, 7269, 61130, 47270, 539, 12740, 7960, 74870, 5390, 2690, 4800, 107590, 11250, 13799, 12540, -2471, 3520, 4869, 3750, 7290, 11580, 4570, 93740, 141260, -2510, 4790, 3800, 22599, 144230, 36850, 3710, 3459, 12609, 13720, 21469, 13280, 76830, 2449, 5709, 3969, 19, 37430, 569, 166100, 40190, 163939, 13330, 190770, 178250, 25700, -721, 4369, 8630, 147620, 19530, 16770, 16040, 869, 37960, 111130, 55470, 12310, 49370, 164270, -14760, 15730, 60470, 39740, 13420, 4970, 10200, 7700, 98310, 27540, 15350, 1490, 30840, 5699, 7070, 15000, 3360, 4649, 6919, 6340, 5950, 10680, 8300, 6199, 20900, 4570, 4429, 7540, 9350, 10410, -871, 7570, 1659, 289, 8310, 10310, 5390, 106550, 6610, 49240, 127590, 6780, 5649, 6169, 32320, 1240, -1721, 4690, 2439, 7929, 77530, 128090, 10840, 100630, 3630, 188329, 8720, 84620, 59530, 11900, 95580, 5470, 43960, 74950, -381, 47110, 86950, 66336, 92680, 82720, 60920, 1459, 38380, 17530, 5669, 141360, 135700, 29940, 18850, 3299, 14900, 59000, 17080, -541, 141500, -381, 19600, 15020, -571, 11010, 17110, 15960, 122080, 47050, 22710, 63130, 10169, 5280, 12150, 11550, 5280, 174490, 6590, 3839, 4519, 156290, 28769, 73210, -7371, 22900, 10490, 9810, 9660, 50119, 8410, 36810, 13000, 11760, 78980, 43510, 10720, 28590, 13560, 6270, 8420, 2440, 18500, 7820, 11970, 46580, 15570, 5070, 143250, 12110, 2859, 9860, 44200, 13850, 8780, 10440, 13850, 5960, -15830, 12340, 19080, 8290, 11060, 164950, 3810, 9650, 42270, 170740, 7550, 47050, 14190, 12290, 20970, 1540, 8470, 479, 2050, 15610, 93040, 9579, -1440, 107410, 15830, 23360, 9890, 97820, 22490, 7990, 1110, 4190, 76240, 22679, 12740, 28560, 3850, 29120, 16780, 2210, 2070, 13200, 5299, 1759, 1940, 17310, -20, 6679, 4910, 4949, 6390, 1370, 7520, 88400, 7240, 155250, 7090, 33940, 62660, 8009, 68800, 10009, 3970, 4819, 59930, 174750, 94460, 136080, 80230, 28080, 6040, 19670, 8119, 12180, 67460, 28320, 739, 22780, 7090, 138100, 35450, 3299, 13560, 5820, 8109, 2330, 74480, 3000, 9140, -31, 10610, 15980, 10880, -11070, 16900, 7950, 2989, 4690, 133840, 4680, 12070, 3850, 4790, 7740, 8119, 2940, 2280, 4170, 3679, 103080, 31040, 3290, 6560, 1750, 5440, 5550, 5639, 50710, -1191, 46540, 6160, 31120, 5290, 7730, 7040, 123430, 2360, 9969, 6840, 699, 13000, 113960, 65610, 2749, 3590, 3329, 6059, 104040, 7060, 174760, 4980, 166740, 579, 3500, 41860, 7109, 5370, 44670, 22580, 35230, 26020, 7019, 9689, 16860, 3870, 3509, 12830, 16580, 1130, 8240, 56830, 96679, 16279, 8519, 13779, 4509, 56250, 2770, 3750, 4310, 8500, 7010, 6570, 102840, 27770, 4400, 3700, 619, 126290, 5859, 4740, 11070, 6030, -1230, -3230, 7840, 8179, 91370, 75930, 134770, 11439, 63700, 13590, 130160, 62680, 6040, 6850, 6279, 21589, 7609, 3599, 3469, 150150, 46160, 47580, 6130, 76360, -15750, 14380, 53620, 10820, 2150, 8590, 7600, 4670, 4599, 6539, 4560, 32280, 9640, 7049, 109840, 7030, 110150, 5699, 5200, 119300, 90730, 132780, 123130, 12360, 111580, 5070, 34940, 16240, 2900, 949, 2470, 59120, 7129, 3359, 90910, 16180, 1620, 5370, -530, 169590, 146010, 8650, 37420, 68050, 126130, 104560, 2890, 300, 39230, 18150, 27519, 7760, 3370, 1429, 92090, 119149, 9929, 2479, 2150, 6709, 121649, 36730, 35990, 51330, 10270, 6070, 629, 5249, 18510, 10270, 3240, -320, 24230, 3089, 117210, 21750, 40279, 17190, 7349, 9460, 1779, 6609, 2610, 4960, 5409, 4910, 2419, 10290, 7109, 130530, 19860, 13650, 13560, -12130, 98940, -17310, 8470, 9220, 4239, 196430, 4250, 1960, 100150, 3020, 5370, 28670, 4899, 8210, 14040, 5920, 5090, 39860, 3999, 17410, 3290, 105480, 4550, 5820, 5080, 136300, 3870, 35600, 6140, 11450, 1390, 33250, 24640, 30700, 130530, 28929, 9389, 24210, -1271, 189460, 1270, 809, 108290, 9919, 27180, 1999, 109, 153130, 3790, 8969, 18390, 4769, 8749, -8780, 3630, 1690, 10960, 18660, -570, -890, 178930, 4570, 34270, 560, 2660, -2411, 136430, 12180, 4140, 9649, 140230, 4380, 4079, 16540, 57939, 70360, 6430, 9289, 2630, 52080, 51340, 5849, 6270, 14300, 29160, 42280, 4750, 8489, 5850, 39080, 3519, 6339, -410, 17860, 4819, 15920, 6989, 80760, 10780, 2259, 16490, -900, 54960, 11800, 5480, 14190, 3900, 5109, 139540, 63650, 11880, 779, 17300, 13759, -19560, 17870, 60550, 8060, 45310, 35980, 9810, 186439, 28220, 12890, 18940, 10500, 1900, 101870, 33000, 2829, 10080, 7810, 14990, 12830, 11150, 74180, 11610, -5510, 168730, 12080, 11870, 51010, 10660, 12100, 7029, 11399, -9330, 10080, 11860, 29, 8480, 2259, -6170, 9830, 8520, 37520, 26400, -911, 9440, 7189, 15620, 4100, 10450, 1490, 140990, 2060, 3139, 44210, 25770, 23100, 87670, 17110, 1519, 5420, 12470, 7930, 26280, 5479, 16890, 118140, 18870, -2140, 7170, 5970, 14490, 13030, 10540, 12540, 24710, 3859, 14440, 709, 9459, 10670, -1331, 6929, 65310, 52000, 10220, 5870, 128660, -181, 5890, 8850, 120360, 18260, 11359, 12780, 152980, 819, 8909, 10380, 4769, 9190, 3159, 11880, 1019, 80250, -2871, 8630, 5849, -701, 11160, 12569, 25930, 9190, 9520, 77590, 159430, 5500, 82810, 8159, 150100, 69350, 4390, 4850, 42190, 3150, 8220, 105090, 1519, 11399, 135670, 66470, 8450, 60900, 13540, 36730, 144100, 11530, 12100, 3100, 100860, 129860, 11510, 8860, 26500, 5639, 12170, -2270, 44410, 16120, 30179, 10200, 21850, 8809, 11399, 4620, 5800, 8129, 7480, -741, 2209, 10109, 3860, 3560, 3750, 2869, 3609, 3930, 15860, 125970, 2250, 5980, 8679, 17280, 4880, 3100, 10260, 11310, 8189, 6340, 142520, 7639, 2520, -15210, 9689, 161580, 7429, 122080, 7520, 43620, 7400, 15089, 9739, 8429, 16130, 14840, 6140, 9810, 139320, 6690, 9819, 7380, 125320, 5950, 139190, 3900, 5490, 2730, -6791, 4170, 5029, 7589, 1279, 91120, 3300, 6729, 5110, 1869, 163990, -181, 24830, 58240, 139070, 117440, 3400, 3409, 3880, 1900, 33150, 5130, 59400, 23830, 5120, 20360, 6019, 6909, 102410, 629, 3950, 8239, 184140, 6149, 10530, 16750, 85740, 8930, 46936, 177860, 5280, 4449, 11610, 4369, 5900, 111890, 10290, 3850, 137810, 6650, 6610, 181180, 23420, 83300, 168490, 42670, 7079, 4789, 4069, 168130, 4780, 9250, 4890, 104120, 40890, 53380, 120630, 3310, 182369, 51350, 54050, 18320, 49000, 116900, 7780, 55430, 25810, 4270, 5470, 2610, 8530, 83570, 144990, -191, 50870, 15120, 9100, 6899, 5369, 4339, 95940, 7060, 177700, 14580, 62420, 44680, 36320, 82790, 11240, 29640, 5350, 21309, 8799, 7690, 6179, 909, 138260, 3059, 90480, 87110, -4101, 75260, 2719, 4339, 2549, 2070, 6279, 50830, 179020, 115620, 1230, 5409, 7520, 4549, -1141, 13970, 3320, 18240, 190990, 3740, 2349, 3870, -101, 8480, 8560, 16630, 1389, 4679, 1150, -531, 6899, -571, 1109, 3489, 3940, 4239, 6350, 989, 6099, 184330, 4029, 136120, 11500, 5270, 4470, 103190, 37550, 5079, 4369, 44680, 79400, 3469, 127120, 219, 5580, 77630, 122940, 7959, 34560, 4220, 56650, 53650, 71330, 26640, 141620, 83130, 19550, 7979, 71320, 7180, 10129, -4100, -11900, 2429, 36700, 15280, 3340, 11399, 6780, 13950, 10560, 7040, 2330, 161490, 10209, 74500, 10610, 16930, 5230, 4339, 193090, 1389, 1530, 11840, 111649, 8630, 70180, 11470, 42450, 5239, 7730, 8089, 9149, 5310, 26140, 6969, 3950, 8270, 19130, 8300, 4419, 59429, 35930, 166590, 1579, 669, 17340, 3090, 176800, 5580, 29690, 103940, 31200, 46640, 151130, 9630, 7710, 4560, 127080, 7350, 26160, 153950, 80670, 4330, 4460, 6990, 9869, 40380, 5870, -2880, 103500, 21309, 9840, 22010, 1879, 155440, 5320, 9159, -240, 10530, 7170, 8580, 62590, 10290, 38390, 154760, 4079, 86430, 10380, 709, 2680, 7610, 5500, 12500, 39100, 5030, 122840, 7719, 193080, 4229, 4550, 590, 9099, 1969, 4239, 130730, 32719, 5840, 95030, 1640, 1160, 77050, 6460, 32010, 190340, 182590, 160430, 86380, 43179, 113420, 47640, 151990, 1530, 52040, 30700, 41736, 4560, 118050, 47880, 168909, 8310, 2580, 47640, 29900, 64940, 27820, 15440, 20410, 71090, 2509, 9179, 2210, 3400, 5400, 133700, 91300, 8799, 27180, 5639, 28280, -6090, 31850, 59980, -25100, 112600, 26320, 29020, 9090, 29070, 8429, 9599, 1850, 19120, 13390, 12529, 11810, -130, 5140, 7759, 3960, 14660, 3279, 19110, 182550, 57820, 10169, 13660, 14190, 4360, 19180, 14070, 5679, 129820, 70070, 1580, 4700, 4869, 73520, -1301, 94730, 14280, 147660, 72330, 14620, 14260, 166400, 959, 1859, 58280, 41330, 2109, 15690, 32590, 195880, 24560, 56380, 17240, -18780, 5540, 9860, 116910, 177079, 5770, 41940, 990, 168950, 89070, 22450, 7950, 187390, 23220, 63840, 19090, 50460, 24420, 19780, 15800, 21300, 13850, 31820, 20840, 21370, 12700, 14140, 10550, 8199, 8609, 890, 12330, 17620, 4809, 18490, 7769, 12850, 13460, 15880, 176340, 145900, 8440, 1930, 4149, 6859, 83570, 6909, 83379, 15069, 4069, 29480, 93600, 8350, 3169, 3969, -21580, 13939, 13870, 7739, 2300, 19620, 12230, 12100, 549, 13010, 9090, 7509, 14090, 5739, 3050, 107120, 127899, 6969, 133470, 158020, 16530, 121510, 12350, -10570, 182369, 152200] + }, + { + "label": "Diameter", + "values": [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081, 319366, 124041, 455411, 280876, 147711, 368624, 315981, 203423, 170419, 318081, 237211, 321023, 258211, 260481, 341011, 429823, 273989, 296489, 285589, 302889, 235581, 214989, 388889, 392489, 334089, 432089, 423289, 358489, 235589, 244989, 223823, 229989, 389489, 262681, 219489, 226389, 312723, 344923, 401889, 464489, 387789, 283223, 254689, 233089, 397989, 370889, 374289, 256489, 409489, 410789, 294711, 380711, 203011, 280789, 288211, 234211, 284989, 353623, 479081, 143423, 399489, 313089, 249823, 282889, 172623, 287689, 170419, 325623, 389789, 348189, 299689, 275089, 215523, 226323, 377489, 412389, 416623, 497789, 309389, 340989, 270623, 294889, 104423, 121723, 339623, 334589, 132823, 386011, 345723, 206623, 256481, 408911, 289011, 149881, 117823, 317823, 208589, 319789, 286723, 428089, 426289, 425789, 320589, 321881, 344989, 398989, 306581, 412089, 305823, 284489, 373989, 282189, 302723, 442889, 429989, 343389, 253681, 315889, 267123, 174289, 379823, 319089, 345489, 170419, 447589, 305189, 436189, 387023, 446989, 439189, 366089, 472989, 491189, 465789, 368289, 416289, 263023, 195389, 451889, 368389, 351889, 458989, 318823, 413989, 347389, 360823, 406189, 361589, 430589, 481589, 254689, 422489, 361823, 379689, 297389, 380689, 363089, 383189, 409289, 388989, 424089, 397789, 401389, 386989, 346911, 450089, 427789, 391389, 345789, 402689, 429389, 434989, 351789, 468289, 365381, 402489, 436689, 372081, 382889, 384289, 392689, 411989, 440111, 390523, 393789, 376389, 397089, 495889, 335489, 424289, 414889, 409289, 389889, 408189, 412189, 384489, 402189, 433789, 379489, 271389, 392989, 401189, 390989, 410889, 415389, 381389, 409089, 449389, 317089, 387689, 312189, 409489, 448489, 405089, 405389, 449489, 364611, 424189, 221489, 418989, 302823, 408589, 413189, 389023, 439689, 417089, 389289, 420789, 262889, 172589, 420789, 419989, 409989, 405689, 418289, 410389, 406689, 408289, 407089, 423789, 409289, 423189, 406389, 423189, 320489, 418489, 410189, 417189, 216823, 424089, 387123, 395681, 412389, 239011, 416489, 418489, 417389, 429989, 393289, 419689, 406789, 332089, 327089, 419589, 414389, 413389, 413089, 403389, 420889, 261489, 424189, 412189, 402889, 426389, 417789, 415589, 404889, 418789, 413189, 415489, 405789, 408689, 418789, 437489, 474489, 399689, 403689, 414389, 415589, 416789, 422489, 196889, 411489, 424089, 217881, 423089, 418989, 421289, 422589, 411089, 422489, 211411, 424789, 415389, 426889, 417489, 411789, 430089, 395023, 411089, 417289, 428689, 415989, 423989, 420289, 387223, 394923, 432489, 390181, 439989, 313523, 490589, 115023, 398923, 399881, 236123, 180089, 399323, 343723, 190789, 421389, 415389, 405981, 427289, 432089, 403789, 381789, 420289, 414789, 418689, 408789, 436089, 422189, 318323, 437789, 420689, 420789, 411189, 437289, 435389, 286689, 444489, 418989, 437489, 422289, 418889, 440489, 427689, 354023, 418889, 425389, 414689, 444189, 208589, 446389, 418389, 483989, 421689, 412689, 328989, 423089, 427689, 339989, 425289, 381789, 421389, 227189, 353123, 426989, 428289, 418189, 425589, 427189, 420489, 432589, 428189, 426189, 396223, 421289, 421489, 420189, 435811, 422389, 446681, 486789, 421089, 426089, 422589, 422689, 435189, 359323, 485289, 433189, 351789, 387423, 322489, 304689, 426289, 420489, 423589, 146223, 398889, 397981, 406189, 418481, 408789, 241489, 395589, 398489, 419289, 425189, 426189, 405281, 141123, 398281, 229389, 422189, 426589, 428189, 420989, 386989, 262789, 421089, 476189, 232189, 413589, 412989, 494589, 422689, 269481, 223989, 426389, 368711, 397811, 418989, 429089, 414489, 417889, 426211, 410689, 425289, 445289, 415489, 421489, 370789, 387223, 416789, 412789, 284489, 351223, 399689, 472889, 415889, 290923, 407389, 393123, 410989, 348089, 359789, 419789, 218289, 427389, 417489, 370389, 395381, 417189, 400789, 389289, 388689, 420889, 171989, 146311, 419789, 388981, 421089, 396381, 370489, 484089, 418989, 362889, 388423, 392289, 400889, 408889, 419389, 365023, 413889, 277089, 407889, 403989, 421389, 461689, 432989, 409889, 455389, 412489, 440389, 426989, 188189, 483589, 436689, 405289, 247189, 330089, 441189, 453789, 425189, 418089, 415889, 374611, 417589, 409789, 330223, 276689, 408981, 406181, 501789, 211389, 413323, 455411, 277789, 375689, 314623, 274711, 188989, 452011, 366389, 300689, 285689, 316823, 333689, 320523, 501789, 282889, 345623, 283289, 442689, 440889, 318289, 330589, 341089, 271123, 325823, 452589, 316089, 323889, 477281, 289589, 390923, 265789, 261489, 353223, 310711, 501789, 210223, 325789, 288423, 284289, 302889, 326889, 380323, 338389, 394989, 294989, 339689, 302889, 288089, 334089, 346589, 329989, 270589, 317489, 271689, 315189, 314789, 383889, 337789, 270389, 248381, 303089, 302189, 320089, 334089, 134211, 337889, 313589, 333089, 452889, 308089, 443289, 305989, 448989, 338789, 291989, 296981, 317589, 362389, 336689, 344389, 211089, 353789, 173989, 289523, 325089, 316589, 370689, 331089, 338489, 329189, 340589, 322889, 323489, 335789, 372489, 376589, 423389, 316189, 209089, 318489, 481389, 334189, 467889, 246023, 334289, 384889, 274989, 396589, 409189, 391489, 342589, 290989, 338389, 319789, 348289, 352489, 346989, 449511, 345689, 318823, 395089, 350689, 351489, 285081, 339189, 179889, 355189, 411289, 334789, 332989, 210389, 409289, 354289, 426489, 353489, 370489, 325389, 348989, 302423, 320289, 367789, 358789, 344089, 356789, 360189, 365589, 352689, 354689, 445989, 358289, 423489, 392689, 358989, 404289, 400889, 348589, 498789, 342389, 380489, 258523, 458689, 353711, 343789, 339689, 320789, 387789, 392489, 364789, 407289, 398489, 387989, 430089, 313281, 404389, 404189, 379589, 372289, 435189, 422489, 410189, 248189, 400689, 413089, 316723, 401089, 409889, 447489, 360189, 426089, 406489, 399089, 356089, 402889, 401689, 399589, 408689, 396289, 402789, 417089, 416789, 407089, 421989, 425889, 404389, 384789, 315189, 464089, 390781, 425289, 380589, 416389, 412889, 407289, 407089, 420889, 401389, 408689, 412289, 421689, 367811, 422189, 406289, 402689, 288611, 394981, 402489, 418889, 409989, 407689, 400689, 176589, 424989, 419889, 336389, 392889, 341689, 410089, 240589, 415689, 343681, 425789, 412889, 467689, 405489, 161523, 385989, 435589, 432489, 421589, 445789, 414989, 367889, 386589, 438889, 443089, 415289, 416889, 397389, 482189, 416389, 418789, 421389, 453789, 440189, 301489, 303411, 423889, 405389, 254889, 413089, 417489, 343111, 323489, 410989, 501789, 324189, 425489, 428489, 414789, 423289, 418189, 419889, 415089, 418489, 426189, 400889, 419089, 330389, 416489, 442089, 409289, 418989, 366689, 420889, 413889, 438989, 342689, 409689, 424289, 393881, 415689, 425289, 411889, 426889, 450189, 262889, 414489, 419889, 354223, 490689, 429589, 430289, 243289, 329923, 412089, 417789, 334023, 404689, 325989, 408389, 404489, 412789, 413989, 425889, 496989, 317489, 362189, 263589, 421489, 416089, 429089, 418689, 414689, 411181, 416689, 214589, 412189, 416889, 420289, 285689, 171189, 449589, 416789, 416889, 416089, 420489, 146123, 410489, 404989, 414489, 413389, 417289, 408389, 286689, 263989, 429489, 429289, 417389, 411889, 191589, 419189, 412389, 433689, 415589, 431889, 419389, 424489, 424689, 427489, 277789, 421889, 413889, 415689, 414189, 430389, 423689, 400289, 431989, 416489, 395989, 217689, 429689, 416489, 423389, 351423, 428489, 418189, 409689, 444389, 420389, 423289, 425289, 361489, 415189, 419689, 417189, 423189, 414689, 419389, 423889, 176489, 422589, 413389, 418789, 330389, 422289, 421589, 424589, 405481, 408489, 415789, 392181, 419689, 421989, 419389, 485389, 428589, 426189, 425689, 417689, 425089, 400489, 425989, 420989, 419289, 426889, 428481, 427789, 418989, 418689, 422489, 422789, 423089, 404781, 428989, 421189, 420389, 418689, 421389, 419189, 398089, 429189, 224189, 420089, 349023, 420189, 425189, 424889, 418389, 417889, 419689, 414289, 416389, 421289, 415989, 419389, 421989, 420989, 416989, 421889, 418789, 421389, 411689, 422689, 421589, 421689, 419989, 414189, 419489, 427989, 418489, 421589, 349723, 283989, 420689, 421789, 419989, 390489, 425389, 424089, 424089, 423689, 196989, 413389, 401189, 428689, 474589, 380289, 471889, 421789, 418389, 432389, 411589, 427789, 413789, 393389, 431989, 483589, 427589, 431489, 423989, 500489, 419189, 410289, 411989, 330489, 423989, 408889, 419089, 429389, 436189, 428289, 350523, 342311, 427989, 355423, 416589, 412189, 416689, 431389, 421889, 232189, 422589, 302889, 422389, 417789, 426889, 290589, 306489, 427589, 428189, 381889, 427489, 417089, 292889, 419889, 333389, 429589, 332089, 419189, 420489, 425289, 414189, 416089, 417889, 419089, 409989, 422689, 428989, 198489, 416189, 421889, 191389, 415689, 429789, 424489, 429389, 210289, 316989, 424589, 429289, 281881, 423189, 425089, 420589, 422989, 423989, 449189, 427089, 424589, 419789, 426589, 420089, 420089, 435889, 420189, 432189, 414589, 422289, 426689, 424289, 421989, 438989, 209089, 418989, 429089, 415889, 459689, 423389, 427389, 394589, 435589, 261089, 424089, 447789, 415989, 303289, 376989, 425689, 295789, 419589, 427189, 419389, 284589, 414989, 316689, 420789, 372511, 427089, 323489, 417089, 355589, 424089, 427089, 423989, 198789, 303889, 342189, 364689, 419489, 415989, 424089, 428489, 283789, 414989, 421589, 422789, 337989, 418189, 392189, 415889, 428589, 412389, 415189, 339723, 420689, 414189, 402189, 423489, 346923, 292189, 445311, 229489, 418889, 401589, 467089, 424089, 490789, 396789, 420889, 404089, 334889, 242823, 441789, 404989, 465189, 423389, 408511, 413289, 382281, 460389, 411989, 401589, 411889, 210289, 312489, 420189, 424489, 433789, 404189, 242111, 414489, 440689, 424689, 418089, 298689, 447089, 419189, 295689, 397389, 431389, 431981, 418689, 421089, 423589, 396889, 415289, 485089, 418589, 418089, 428189, 452289, 428089, 418889, 418589, 412189, 426789, 428289, 419989, 316089, 450189, 297589, 349589, 321589, 431889, 434089, 394989, 424389, 274889, 347289, 431789, 422289, 462189, 341789, 153111, 425989, 427889, 374011, 430189, 302489, 404789, 410389, 447289, 457189, 399681, 396689, 352281, 423389, 373489, 410889, 428589, 412589, 427489, 418689, 400089, 497489, 428089, 422389, 381011, 421189, 282089, 415889, 407889, 425789, 222889, 377911, 421789, 376011, 431489, 423589, 412089, 422289, 286889, 423989, 420089, 479389, 490189, 437889, 414889, 419789, 320789, 382489, 294289, 417689, 419189, 255689, 422589, 350089, 412989, 404489, 420289, 414689, 423089, 421589, 437489, 414089, 308789, 418889, 224389, 420489, 199089, 268289, 479081, 416989, 418089, 392489, 310589, 427489, 406089, 411389, 423089, 383189, 261489, 273089, 413689, 406089, 353089, 369389, 409489, 411381, 372389, 418589, 492089, 423789, 427789, 365689, 357389, 420289, 307889, 377389, 430789, 402711, 430789, 433189, 419289, 406881, 428389, 361289, 395989, 401789, 388789, 298823, 413089, 413489, 410389, 406289, 398981, 423489, 424089, 302189, 412889, 392981, 415689, 340923, 310289, 400689, 392389, 460889, 415989, 407289, 408089, 405589, 418389, 403281, 411889, 366011, 407489, 297489, 424889, 408389, 444489, 414489, 268489, 413589, 288589, 299489, 412789, 305989, 420089, 401189, 422289, 413589, 457689, 367289, 124041, 437611, 161211, 379881, 420189, 302023, 342523, 385089, 307189, 474789, 367389, 418289, 377789, 373789, 401411, 397989, 405189, 315789, 372211, 415789, 422589, 425489, 404689, 415689, 417189, 219989, 413289, 371689, 281489, 417089, 405989, 408289, 397289, 424989, 198889, 409889, 427389, 424589, 222889, 409089, 325689, 438489, 295789, 428889, 408689, 417189, 349589, 365311, 392689, 409789, 395189, 424989, 259723, 388589, 423889, 407189, 419089, 408589, 350389, 390789, 398589, 406089, 387989, 402089, 427089, 180289, 403689, 414189, 412189, 431789, 413289, 225611, 386681, 406289, 275189, 387089, 399389, 405989, 402889, 407189, 489289, 275689, 413289, 394089, 462389, 408289, 323289, 335923, 410889, 411089, 410389, 413089, 416989, 278289, 401689, 460389, 330023, 416189, 195689, 372489, 309189, 391889, 205623, 307889, 407889, 422689, 415889, 317389, 407989, 411423, 337189, 342323, 334589, 405989, 415689, 431089, 407789, 408789, 420189, 422389, 394981, 413989, 409989, 419689, 399289, 398889, 425089, 408589, 372789, 402389, 171289, 409889, 414389, 486189, 407689, 326789, 380981, 415089, 428589, 486489, 374289, 166481, 474989, 412489, 393989, 419389, 385381, 404589, 410989, 416189, 410589, 422389, 419989, 394181, 241789, 412289, 400081, 419189, 418589, 421689, 378489, 258989, 415789, 306389, 421089, 416689, 402989, 400281, 461489, 404789, 393581, 419889, 416889, 360389, 420989, 397381, 432289, 402889, 422389, 405589, 423389, 428989, 421089, 435989, 334989, 423389, 413889, 412189, 397581, 413389, 418289, 407389, 496689, 407981, 309389, 412189, 327589, 418889, 410489, 418389, 445489, 422189, 408089, 390681, 424789, 455789, 234189, 281689, 390581, 426889, 415489, 418189, 392681, 405189, 412189, 412989, 254389, 416989, 425789, 284189, 423689, 438089, 347089, 328989, 410489, 425589, 420589, 439889, 372189, 413089, 422689, 420489, 417989, 422489, 428389, 269489, 263989, 408989, 430589, 409989, 282689, 274289, 422089, 423289, 419689, 365789, 427689, 424089, 247389, 499089, 428081, 408789, 410589, 470889, 415189, 413389, 394711, 421489, 419089, 421089, 409389, 424989, 395089, 295523, 479089, 394011, 490789, 361889, 227189, 270023, 454389, 416581, 393281, 429889, 376689, 361789, 365089, 303289, 242189, 241989, 420489, 419189, 462289, 406989, 178589, 412589, 432289, 414889, 416789, 425089, 413789, 366011, 419189, 266989, 498389, 419289, 260389, 417489, 447289, 454789, 406789, 388789, 386489, 250989, 390489, 434189, 291611, 313089, 394389, 379389, 412789, 408289, 419089, 260589, 302489, 457189, 396689, 273989, 409589, 390381, 422089, 443889, 257689, 473289, 454589, 369289, 332489, 241189, 465889, 501789, 380489, 356289, 456589, 360189, 421089, 423489, 339511, 261289, 469489, 436989, 457289, 443689, 422289, 381489, 380181, 435489, 456089, 454089, 281489, 424289, 306689, 410089, 440389, 474989, 434489, 458889, 395723, 420289, 210989, 423889, 368323, 411189, 434989, 441689, 413689, 437189, 398981, 372723, 458589, 424889, 361311, 261781, 429189, 353289, 420189, 381089, 437389, 394889, 346123, 412589, 431389, 176489, 418289, 424189, 372289, 428589, 421089, 303089, 420789, 420689, 343389, 428589, 411889, 251189, 406789, 433689, 362889, 173989, 423289, 416589, 420989, 436789, 326089, 406789, 427389, 412289, 276889, 309289, 310389, 326789, 485489, 322489, 409889, 476689, 415489, 226189, 414089, 424689, 453889, 340623, 319989, 399789, 412689, 346489, 429889, 428089, 405889, 423089, 411289, 467589, 411489, 432889, 414189, 385481, 430489, 270689, 248489, 422089, 501089, 421189, 266189, 421889, 347489, 421989, 433389, 334323, 197489, 401989, 414989, 339681, 449389, 383189, 417489, 419889, 401489, 192611, 232389, 419289, 427089, 380789, 362189, 437989, 372289, 417889, 408289, 383989, 409589, 401389, 420889, 406189, 420589, 233589, 399889, 371189, 387989, 373811, 405889, 419789, 301189, 412789, 413989, 472889, 419789, 426689, 349389, 198323, 412989, 283989, 422789, 392481, 417389, 416089, 431289, 398481, 249689, 417989, 401981, 197389, 366589, 415889, 295423, 413789, 423789, 236089, 302789, 424489, 415989, 415689, 360889, 409489, 412289, 217989, 420689, 451889, 360489, 414989, 382089, 347689, 415189, 420789, 389781, 420789, 350089, 387989, 416189, 343489, 372989, 439189, 283489, 382781, 386589, 387589, 384789, 406889, 398389, 403889, 399589, 419789, 404289, 372511, 264889, 413189, 391389, 386689, 387089, 409789, 321089, 375689, 413589, 407589, 385089, 405489, 402989, 416989, 387889, 491389, 381089, 422189, 419089, 415089, 423889, 353489, 412389, 397389, 336689, 415189, 400389, 429689, 409189, 402089, 391089, 402489, 192689, 333789, 395589, 383123, 229189, 349623, 411889, 403289, 353189, 414189, 334223, 399989, 423989, 347623, 400689, 408989, 410089, 395889, 409189, 386989, 425589, 253289, 431489, 402489, 406289, 287789, 408189, 410089, 393489, 333889, 404589, 258889, 414489, 404789, 462689, 416189, 253789, 235289, 278889, 402289, 351889, 279289, 401589, 204889, 403589, 412789, 258089, 327089, 415289, 319789, 392389, 312489, 444789, 398489, 434789, 421789, 430189, 262189, 406689, 399189, 346789, 410389, 411089, 333489, 289689, 346589, 337989, 397789, 392289, 398689, 400789, 418589, 394789, 400489, 404989, 289189, 414689, 418689, 401189, 421189, 407289, 433089, 412689, 419489, 458189, 417381, 367911, 482989, 398989, 365989, 407989, 416789, 407189, 431689, 407889, 404389, 342589, 407389, 491589, 404889, 405889, 409989, 413489, 398989, 409589, 432589, 396789, 414889, 407389, 402489, 453489, 332423, 403389, 399689, 468589, 412889, 403589, 253989, 464589, 415289, 442181, 404789, 400889, 489489, 414689, 410089, 414489, 492889, 415989, 379211, 412789, 418489, 413689, 369711, 180889, 283589, 413489, 429389, 500089, 336389, 412789, 421689, 423989, 432789, 385289, 421489, 501789, 405489, 407589, 400189, 417589, 418689, 224689, 425489, 413289, 421389, 301389, 420289, 421489, 299289, 386389, 415489, 170419, 217189, 418989, 416289, 407689, 417089, 417789, 374889, 410889, 416289, 180981, 392289, 388689, 281989, 433589, 356789, 326889, 350089, 416989, 406181, 424089, 246489, 415989, 420289, 420889, 399589, 376889, 341989, 361489, 417689, 278089, 206289, 347289, 387589, 276789, 255789, 414989, 211489, 328311, 409089, 418089, 423689, 471489, 448089, 228889, 419689, 480089, 420589, 425789, 287789, 433089, 340423, 280389, 423189, 255789, 421989, 498589, 425989, 459589, 426889, 285389, 335389, 430289, 207689, 427789, 431889, 398281, 425689, 445189, 429189, 211989, 427689, 343789, 306189, 417589, 418389, 460289, 425089, 415989, 381489, 259589, 359589, 282489, 416689, 243589, 426289, 309189, 418089, 434589, 378389, 182889, 422389, 421289, 426089, 428789, 427989, 424189, 390489, 424889, 425989, 438289, 432089, 297789, 416489, 442689, 329889, 433389, 422389, 427289, 426889, 366823, 232489, 431781, 399589, 173411, 367123, 374089, 127923, 279289, 408281, 435089, 361023, 281789, 439089, 462881, 437589, 412989, 281489, 374389, 481189, 323481, 411589, 335289, 332289, 425489, 402389, 179589, 437489, 397581, 409281, 462589, 395281, 424489, 404081, 462789, 433489, 450789, 418989, 424389, 393081, 413989, 418289, 413189, 401681, 421489, 303889, 426689, 240789, 436689, 397111, 448489, 421389, 249889, 428889, 425489, 400389, 437289, 406489, 357989, 411089, 401289, 333423, 419489, 408889, 415289, 422689, 447389, 417089, 427289, 417089, 314489, 451789, 409589, 496489, 177489, 185889, 432989, 426089, 399389, 381511, 325789, 368611, 307889, 376011, 425789, 386389, 492489, 475489, 304689, 423189, 351989, 422289, 268189, 316289, 386711, 306489, 334223, 404889, 433089, 447989, 419089, 250589, 252789, 398689, 415389, 416689, 416989, 295389, 417589, 302189, 423189, 399489, 439089, 385989, 436889, 411889, 327889, 404189, 438989, 207489, 410989, 412689, 417989, 411689, 424789, 391789, 334789, 410489, 239389, 417589, 248989, 386781, 328323, 415889, 399789, 423089, 415389, 369489, 499589, 414389, 437489, 396681, 412189, 216911, 410189, 380723, 269389, 227889, 254489, 480989, 384989, 254589, 336389, 363889, 412489, 466389, 501789, 170419, 421189, 467289, 456989, 368689, 423689, 291989, 454389, 341823, 465389, 343623, 421389, 341689, 284889, 446689, 423989, 427689, 430789, 262789, 321789, 345411, 423789, 311989, 442389, 393023, 395689, 409289, 424989, 501789, 457789, 355589, 409589, 418889, 406089, 434489, 413789, 431289, 403589, 368889, 394781, 428689, 424089, 436389, 413189, 424189, 410189, 455989, 414689, 243289, 357589, 427089, 411189, 425889, 398481, 350281, 499089, 349989, 304589, 421089, 438989, 414789, 434089, 431589, 364823, 424489, 417989, 357189, 331489, 381589, 418189, 260789, 420189, 422189, 328989, 438489, 417689, 477889, 419889, 221989, 199189, 269989, 334389, 473589, 419389, 417189, 413981, 375989, 415089, 432389, 425889, 301289, 399089, 386581, 418289, 263889, 373589, 382389, 417181, 402189, 417589, 348023, 423789, 399789, 440289, 342589, 435389, 416089, 439789, 454389, 458289, 413789, 425689, 415889, 407489, 437589, 407689, 386889, 417089, 405289, 412189, 393989, 364389, 276789, 413389, 286489, 416289, 418189, 316089, 479689, 221989, 415089, 406089, 423989, 209789, 423289, 433089, 401089, 437589, 404389, 411089, 407389, 446789, 355589, 407489, 403789, 428289, 354689, 423889, 412689, 404889, 425389, 428289, 414589, 173789, 329089, 220711, 456589, 492489, 309689, 377289, 477489, 314089, 206411] + }, + { + "label": "RF block", + "visible": false, + "values": [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154, 9197, 18159, 13115, 41120, 4254, 53966, 17129, 14957, 12469, 12882, 19875, 23547, 16325, 15238, 15452, 31817, 18210, 16237, 13815, 24070, 14163, 10748, 16292, 12787, 19559, 10597, 34781, 25859, 23121, 7331, 19298, 17056, 18788, 12009, 8997, 9280, 10990, 9825, 13690, 14547, 15443, 14758, 22429, 9324, 13396, 10915, 12615, 13307, 16842, 12533, 11312, 29347, 2923, 28796, 42332, 12953, 14401, 16151, 23973, 4730, 21716, 13116, 13175, 15085, 8140, 14046, 15629, 13231, 5612, 14571, 14929, 12812, 9048, 10826, 20129, 17258, 12673, 11513, 12391, 14423, 10741, 14543, 4797, 6770, 12516, 15056, 26071, 38770, 15137, 15072, 11241, 26828, 8765, 10555, 10704, 13486, 6364, 10951, 12683, 21652, 27201, 21344, 10776, 9748, 11037, 12370, 8567, 13685, 11766, 12085, 11494, 20165, 13118, 14030, 13022, 10399, 14657, 11485, 10530, 13011, 6136, 10941, 24564, 2983, 44046, 27024, 13288, 11442, 25304, 11719, 10889, 42292, 21241, 13750, 11650, 12963, 7752, 11368, 12729, 10642, 9786, 12557, 11922, 10954, 10880, 9807, 11606, 10332, 11490, 12266, 8847, 11958, 9329, 11618, 30498, 9096, 9656, 10880, 12137, 10590, 30171, 10776, 12029, 10048, 9194, 12699, 11935, 10320, 12246, 10999, 11670, 12919, 10448, 28090, 9996, 11446, 11869, 11452, 11130, 10617, 10938, 10938, 61633, 9401, 10986, 10264, 11382, 26443, 7246, 10959, 10865, 10461, 15205, 10010, 11370, 10761, 9628, 10072, 15113, 15277, 10752, 15445, 10415, 10409, 11365, 42807, 10732, 80687, 14568, 10607, 25736, 10835, 25227, 10372, 10690, 10861, 9204, 24356, 9578, 10690, 16420, 32922, 9966, 10328, 22516, 11073, 10370, 10319, 16053, 12519, 10850, 10016, 23430, 9967, 10409, 16565, 33216, 10086, 11852, 10717, 71528, 10854, 6473, 9864, 24531, 10169, 10465, 13817, 8117, 10114, 10539, 9383, 9575, 9905, 10607, 10809, 12302, 11300, 17273, 19981, 10379, 62047, 32661, 10668, 10740, 11887, 10168, 10328, 10606, 5848, 19699, 9904, 10606, 12471, 10735, 10454, 10221, 11269, 10282, 10788, 10518, 13610, 10157, 12402, 12469, 10341, 11117, 11692, 11407, 11290, 10950, 11411, 10684, 15902, 9235, 11594, 10388, 10673, 10287, 11358, 10456, 21224, 11029, 9757, 10623, 20290, 11303, 10606, 10576, 10914, 10215, 11150, 10688, 20300, 10648, 10158, 9969, 10490, 9674, 14900, 8394, 58012, 9555, 18938, 12074, 10625, 16410, 18293, 8646, 7452, 10486, 10598, 10851, 9883, 9527, 9921, 8487, 12350, 21204, 10475, 33939, 10793, 10449, 12448, 11840, 16981, 9941, 9714, 10921, 17966, 13494, 13501, 9559, 12461, 10527, 10273, 12408, 10142, 8618, 10065, 10490, 19855, 11973, 6992, 27078, 9865, 22933, 10190, 39964, 15056, 10890, 10469, 9225, 9722, 22231, 10448, 16940, 8739, 9933, 10792, 10162, 10820, 10476, 10596, 15300, 10848, 10490, 10626, 11052, 11152, 9908, 10688, 10853, 23939, 10974, 10706, 11293, 25292, 10575, 44141, 9329, 42453, 11111, 33703, 9989, 14744, 29684, 10627, 12450, 10102, 10804, 22365, 15455, 10235, 17927, 28090, 22636, 5696, 10830, 11452, 37616, 10548, 14079, 2381, 9319, 5708, 10278, 10270, 10173, 10438, 10466, 14781, 11824, 13649, 11169, 10106, 10054, 48407, 10727, 8452, 10180, 11032, 9142, 27478, 10124, 10562, 10836, 10135, 7096, 9831, 11865, 10439, 10077, 10337, 10278, 10402, 40924, 10160, 24221, 8787, 12698, 13555, 20043, 9006, 10211, 30486, 10615, 5012, 13470, 11561, 21404, 11943, 35820, 10150, 10799, 10569, 10388, 18464, 10494, 10739, 17119, 10382, 10994, 10169, 10365, 10862, 10219, 35420, 11482, 36677, 10085, 9303, 10751, 26201, 9832, 9444, 11268, 16820, 24669, 11580, 10429, 13545, 31487, 14811, 28689, 13605, 22274, 13142, 15556, 39192, 11083, 28305, 22002, 32055, 11237, 14968, 15304, 10818, 14371, 9237, 10504, 11672, 15811, 20320, 13030, 18281, 37483, 10853, 18766, 33670, 11700, 25359, 13903, 19952, 17043, 18835, 21038, 13206, 10850, 13772, 8348, 14495, 25290, 14003, 13966, 12454, 16773, 15792, 14666, 12615, 18555, 20326, 13386, 16211, 11108, 12505, 18943, 13578, 13475, 9963, 13037, 24033, 10640, 25696, 8173, 12725, 9708, 9863, 12975, 12783, 29488, 10613, 15552, 10566, 9981, 11013, 10682, 10087, 12383, 11656, 10325, 10872, 8027, 11261, 11077, 38056, 10047, 9527, 9601, 12561, 10987, 10731, 10944, 6680, 11525, 10922, 10432, 38982, 12574, 19619, 12819, 8162, 9543, 12403, 9836, 14314, 22537, 11423, 11359, 16214, 12020, 11313, 9979, 10532, 11140, 5538, 11040, 10342, 7274, 11035, 10156, 9986, 10486, 12454, 12438, 24463, 20432, 20455, 12397, 37736, 10196, 18212, 15145, 18863, 13024, 13364, 12974, 41227, 11856, 11346, 11326, 12760, 10202, 15894, 11309, 22422, 17922, 9380, 11075, 11609, 9989, 21795, 16305, 10791, 18100, 10980, 12215, 10666, 10339, 7981, 12100, 10235, 28922, 10339, 11453, 15440, 24216, 8614, 14903, 11618, 10720, 10714, 11399, 10649, 10249, 11125, 11523, 13787, 10415, 12882, 10920, 11001, 23505, 19807, 12172, 76180, 10338, 10975, 8062, 13561, 20564, 11107, 9966, 8921, 34621, 36878, 11835, 10960, 11871, 10982, 29514, 10178, 10481, 11149, 10573, 9197, 34702, 15114, 11222, 7482, 11016, 28924, 9036, 11100, 12007, 30205, 10454, 10890, 10902, 10595, 10095, 10696, 10249, 10609, 10740, 10824, 10277, 10679, 10296, 13965, 9912, 10483, 9972, 10735, 19105, 24162, 10498, 9856, 11457, 10418, 10479, 9695, 10405, 20038, 21024, 10611, 10964, 10095, 18471, 10126, 11042, 10546, 13961, 9864, 10287, 10254, 10350, 36948, 10205, 19478, 16141, 10222, 32500, 9865, 19020, 32054, 7968, 10325, 26167, 15826, 10497, 26223, 10784, 11040, 21312, 13074, 11326, 10699, 11514, 10271, 9270, 27080, 11929, 29848, 13399, 10618, 16773, 38775, 15158, 10308, 16630, 24280, 10359, 26577, 25968, 11063, 9358, 24236, 10131, 10633, 8785, 16274, 10153, 17928, 10168, 12024, 15155, 10751, 10514, 10726, 10694, 10684, 12918, 10318, 9723, 10353, 18212, 11901, 35670, 10645, 10501, 14751, 11704, 5960, 21709, 33016, 11319, 10692, 9730, 11579, 10545, 10898, 10450, 16733, 20856, 10557, 10411, 9420, 31288, 35500, 10552, 7849, 8744, 10903, 9795, 9018, 10362, 11398, 11504, 21077, 9900, 19523, 22921, 48955, 10100, 35563, 17163, 10109, 10710, 10407, 10174, 10338, 19927, 10088, 11713, 9719, 10242, 37731, 15195, 6232, 41049, 10615, 10017, 9755, 10709, 14637, 9291, 11864, 10109, 10156, 11304, 67519, 17390, 17379, 12079, 10161, 10612, 9842, 15579, 10903, 9928, 10148, 10154, 16966, 10889, 10372, 12307, 13177, 26663, 10878, 9647, 10531, 9319, 13014, 9437, 9204, 12344, 11695, 29491, 4829, 9900, 33272, 14803, 6452, 10605, 11949, 14380, 41594, 10764, 11066, 10315, 13599, 10388, 10160, 22538, 10492, 10394, 11021, 11273, 16408, 10459, 9505, 11608, 27802, 10337, 10946, 10642, 10364, 19852, 9766, 9477, 10783, 10463, 32639, 33506, 10877, 11257, 11148, 11070, 10769, 32854, 11405, 10836, 9867, 10488, 14866, 10453, 10822, 10211, 10304, 10483, 10395, 10455, 11100, 10595, 10385, 10249, 10315, 10299, 14743, 10506, 4196, 10680, 8481, 10569, 10217, 10535, 10788, 10380, 10104, 10496, 10774, 10578, 12092, 10172, 10273, 11082, 28496, 10138, 11213, 10182, 10541, 10214, 10813, 10209, 9657, 10418, 10325, 9225, 10075, 10889, 8608, 11322, 11055, 10799, 10054, 22351, 34451, 10954, 10801, 10028, 10797, 10584, 8069, 23265, 19284, 10490, 12889, 11179, 10694, 23407, 10668, 10530, 10576, 33861, 16659, 18867, 10082, 16290, 9883, 14526, 9639, 10930, 10400, 6394, 10245, 10304, 11994, 10994, 11345, 10426, 8470, 17899, 10053, 16420, 10516, 29232, 10200, 10599, 10119, 14293, 10478, 27110, 10359, 9926, 9912, 29435, 17805, 12276, 10674, 26997, 10445, 20195, 9146, 10524, 10816, 10555, 10744, 10242, 10180, 14829, 10046, 11402, 13681, 9995, 10387, 10157, 10482, 15997, 21537, 20617, 7234, 19940, 10347, 9837, 10492, 3567, 15063, 10527, 14404, 26219, 9845, 10367, 12283, 10012, 11008, 16150, 10090, 9801, 10182, 10385, 11210, 10227, 10945, 10796, 12408, 10596, 12523, 10445, 10863, 15001, 11714, 4158, 10011, 11102, 18453, 25567, 34427, 21636, 17312, 11486, 25894, 10305, 11143, 10014, 7083, 29212, 11225, 13217, 12442, 10534, 30505, 18992, 9916, 9305, 9562, 14432, 10474, 15954, 11336, 14433, 10782, 10858, 13947, 13731, 16533, 18216, 23681, 32935, 9827, 10190, 9891, 12630, 10233, 10130, 10387, 15376, 10256, 24143, 10237, 9739, 10317, 9752, 8255, 10923, 8741, 37789, 61374, 8664, 4220, 34907, 3366, 9820, 18920, 28985, 11698, 10181, 82710, 10549, 34749, 25408, 11746, 16455, 10624, 17395, 12460, 11048, 12144, 12643, 13238, 11049, 10607, 10713, 16579, 22372, 10607, 11766, 11282, 10549, 22312, 9792, 12057, 9784, 10705, 21263, 39010, 10601, 20597, 10461, 10502, 8825, 10079, 10800, 11227, 20574, 10297, 28465, 11264, 10799, 11484, 32910, 10132, 10895, 21699, 10646, 10735, 10696, 11264, 19742, 42988, 41859, 10492, 5759, 24954, 10411, 13437, 11267, 5603, 10173, 10822, 11230, 33464, 17149, 11761, 10849, 11071, 10266, 10318, 5839, 14954, 10101, 39692, 29152, 9676, 12924, 11540, 43420, 30908, 9929, 23278, 17192, 9964, 10193, 20560, 27021, 19244, 9997, 11196, 11353, 14331, 10630, 9783, 10959, 14011, 21597, 12489, 10930, 19611, 10617, 10366, 32400, 5912, 12172, 32577, 65364, 44139, 10069, 10473, 10503, 9310, 33098, 10077, 10394, 10412, 5522, 12512, 10444, 11968, 23134, 20539, 10636, 10680, 9865, 17915, 9652, 57471, 17323, 19811, 12337, 19754, 25944, 18475, 9532, 10535, 20382, 26345, 13869, 12280, 12403, 10090, 14846, 17309, 11379, 11821, 18237, 46284, 7399, 12253, 21048, 14545, 12262, 14172, 11900, 11608, 23811, 11756, 12709, 11665, 13314, 11359, 11199, 13162, 11013, 10641, 10930, 11373, 16875, 10709, 14663, 19210, 9117, 10354, 10345, 10785, 33407, 11203, 9776, 22824, 5670, 9550, 10557, 11541, 8667, 41163, 10187, 17357, 76115, 10894, 10300, 14510, 15094, 9959, 9200, 10324, 8811, 10727, 15676, 34492, 11302, 30983, 10239, 27184, 11148, 16012, 13382, 11702, 18726, 10832, 16952, 24133, 9454, 21152, 22064, 5202, 29716, 8219, 18975, 10078, 11633, 10604, 9357, 25145, 82471, 25294, 13270, 8653, 20891, 41040, 11945, 9080, 25991, 8592, 26568, 12760, 9918, 11163, 25627, 12672, 15235, 18263, 11658, 12806, 11580, 10176, 11538, 10923, 11015, 18276, 10587, 10847, 10852, 18896, 14635, 16942, 18271, 8292, 12197, 11126, 11489, 14929, 9764, 15179, 11765, 10865, 25110, 10109, 10387, 15412, 11745, 10938, 10866, 7458, 11852, 31513, 11403, 16621, 11869, 22140, 27762, 11317, 10083, 11296, 18886, 12088, 4649, 10649, 11756, 5362, 5696, 11160, 12697, 10587, 11287, 49254, 5111, 11307, 16226, 65648, 10693, 12976, 9795, 11685, 13300, 9676, 11079, 19515, 4971, 36232, 30848, 8851, 9364, 12046, 10543, 27251, 14449, 25057, 8742, 10756, 10119, 31794, 16824, 13457, 13126, 10940, 8487, 15164, 12277, 10026, 10669, 11707, 10301, 10134, 10264, 12246, 9538, 10608, 10708, 9828, 30769, 10272, 10700, 22730, 10375, 28088, 10679, 15887, 26494, 10750, 16367, 10320, 20659, 11089, 25920, 37391, 9229, 57506, 24371, 13704, 10908, 12191, 10632, 11670, 22268, 14633, 10035, 28198, 10394, 18725, 16048, 9974, 12317, 10831, 11404, 8516, 12843, 10178, 13677, 9834, 23288, 11986, 11347, 18648, 12240, 21040, 10354, 10543, 29142, 10722, 11426, 11068, 9953, 11366, 10677, 10497, 10617, 10630, 11202, 22069, 48435, 10150, 10683, 9589, 10529, 21533, 10302, 24630, 9491, 12154, 10609, 10864, 10744, 10824, 11051, 35643, 10335, 11128, 10196, 20262, 14029, 15512, 13132, 9473, 10776, 10227, 10858, 27460, 10466, 41882, 10425, 23124, 9776, 10710, 10243, 11306, 11631, 13932, 9667, 15904, 15014, 34062, 12569, 10702, 10223, 10575, 24485, 12828, 20228, 11740, 11350, 15787, 12331, 11897, 11918, 5419, 11540, 10408, 10647, 10595, 9036, 11470, 11221, 15296, 19651, 11423, 10007, 9515, 38820, 10686, 10398, 23090, 11000, 9523, 9228, 10795, 11570, 25015, 16290, 41501, 23156, 27076, 9705, 16633, 39615, 25068, 11360, 10211, 14392, 9340, 16150, 8181, 51944, 8740, 17771, 10974, 24164, 8383, 11886, 6533, 11492, 10738, 11183, 11084, 10903, 10390, 9487, 10620, 8266, 15542, 11094, 17072, 33639, 33150, 12483, 10196, 29392, 24209, 18940, 30223, 25634, 20366, 6509, 14943, 10926, 10030, 9480, 10221, 15497, 6424, 12117, 25062, 13167, 9658, 9925, 19563, 62188, 21058, 14014, 57943, 19077, 25315, 15032, 12432, 13616, 14913, 20394, 17053, 26546, 10478, 10214, 21465, 18236, 14091, 11012, 11873, 12159, 33008, 14540, 14730, 20518, 13484, 12526, 4889, 10978, 11327, 11275, 11315, 37227, 15152, 12142, 30949, 13920, 6760, 13238, 10143, 11176, 10785, 12044, 10015, 11509, 10305, 9929, 11989, 11969, 9381, 19884, 14021, 9348, 12366, 6139, 60031, 5686, 9360, 11195, 11103, 17782, 14637, 10345, 24660, 10742, 10857, 9383, 10755, 11377, 8993, 11301, 10398, 8455, 9976, 13778, 8067, 31746, 10800, 10741, 10798, 37306, 6794, 15761, 11289, 11595, 4846, 20598, 9148, 10764, 41269, 10303, 11103, 17525, 9367, 22586, 9782, 10147, 33394, 28569, 9935, 9319, 13227, 30809, 10949, 11866, 12566, 10833, 11049, 10057, 10110, 10675, 11593, 12021, 30957, 4385, 23884, 21501, 21241, 19901, 4683, 9416, 28303, 12191, 11174, 9041, 15090, 19681, 10345, 9568, 22790, 20433, 10896, 11544, 19006, 7436, 17652, 10867, 11300, 14826, 12256, 18901, 17356, 22603, 20761, 15085, 10008, 10169, 9754, 12484, 21462, 10322, 10221, 21330, 10370, 9100, 12219, 9615, 12862, 11684, 10562, 30345, 10522, 11059, 28976, 8969, 23416, 4984, 13203, 11497, 6010, 12975, 44056, 10758, 18000, 16477, 11233, 19186, 12322, 12033, 8707, 11488, 10317, 14374, 9960, 10525, 11512, 11073, 9890, 11719, 11539, 10378, 12021, 20131, 34812, 16470, 10299, 14957, 11583, 12118, 10190, 11986, 5592, 10248, 11855, 6832, 9332, 11067, 4082, 10369, 9916, 15017, 12934, 9081, 10595, 10432, 11759, 10559, 11043, 8917, 21134, 9891, 9176, 16130, 12942, 13627, 18725, 10904, 9808, 10271, 10536, 10638, 13854, 10695, 11433, 39161, 11455, 18960, 11107, 10703, 12723, 9257, 11431, 11105, 10333, 10313, 11585, 10344, 11084, 21966, 8377, 10323, 8185, 14299, 10609, 10551, 16646, 11337, 10546, 10707, 26303, 12953, 9294, 11267, 39151, 8228, 10602, 11245, 10260, 10439, 9924, 10518, 10226, 13153, 9727, 10631, 10293, 4908, 11351, 11699, 13297, 7873, 10887, 13199, 39299, 10164, 28920, 11162, 21162, 10873, 5283, 9938, 13808, 5140, 10517, 12483, 9389, 23219, 19894, 16043, 11175, 14779, 11053, 10940, 39710, 10974, 12795, 10458, 29754, 19573, 11346, 10526, 11079, 10434, 11672, 6137, 10845, 18903, 11224, 10704, 12516, 10495, 11055, 10604, 9788, 10452, 10533, 4945, 9983, 11643, 9712, 10519, 13844, 10913, 14131, 10514, 14742, 33770, 8857, 13931, 10485, 20982, 10189, 10240, 11140, 12490, 10792, 10299, 28767, 10669, 13604, 6395, 10977, 39186, 10903, 61691, 10745, 18824, 10159, 12396, 11054, 10595, 20240, 9738, 10219, 21439, 41329, 10739, 10896, 4868, 52815, 10708, 38900, 9872, 9994, 13546, 8304, 10149, 10501, 14794, 9865, 24487, 10105, 10997, 10480, 8867, 15620, 4849, 14141, 21448, 44760, 24356, 10123, 10512, 32705, 10711, 14130, 10830, 26961, 13539, 10216, 12642, 10823, 11040, 13619, 10147, 10247, 11415, 30393, 10969, 11854, 7609, 46668, 22548, 7873, 62534, 10747, 10471, 11411, 14595, 10810, 26857, 11315, 10359, 13682, 19665, 19345, 27815, 14945, 20679, 31038, 13784, 15296, 10509, 10744, 22472, 10520, 11555, 10757, 27673, 14992, 14989, 27100, 10319, 27530, 7593, 15409, 11668, 10774, 17530, 11036, 8222, 10799, 20249, 10742, 20896, 13897, 38765, 18303, 9745, 71755, 12680, 11783, 5892, 22802, 8486, 23485, 11273, 24528, 12647, 27395, 18613, 19047, 25991, 6369, 22035, 11269, 4850, 11819, 23594, 10413, 10210, 38584, 10776, 11590, 26886, 12407, 15941, 10203, 10543, 16827, 10406, 10801, 16961, 25091, 26117, 4995, 10669, 4570, 10934, 5509, 12342, 11069, 11221, 18032, 10606, 10294, 10794, 10149, 23535, 11605, 11509, 10267, 10945, 10808, 10208, 12462, 9539, 10996, 13746, 11135, 10701, 22650, 10277, 9871, 22744, 23044, 33427, 3378, 9747, 8703, 7656, 9463, 10656, 11297, 15888, 14886, 11302, 38639, 10594, 10537, 14643, 57349, 14269, 11499, 10223, 15088, 28919, 23684, 13888, 13690, 26912, 12774, 11234, 26520, 10459, 11919, 8800, 9204, 10845, 18581, 12632, 10618, 11108, 10805, 24695, 11472, 10718, 10299, 55165, 12039, 11745, 12596, 12705, 36938, 10675, 25627, 10441, 10320, 11116, 32508, 10810, 18654, 23086, 16685, 8342, 11231, 10819, 11306, 10918, 16246, 10979, 10863, 11223, 8547, 12869, 10174, 26564, 10143, 16311, 10658, 10181, 12059, 9562, 32135, 9438, 29761, 26396, 16018, 16535, 46584, 14336, 9155, 21595, 27259, 11287, 7579, 38688, 46567, 6178, 8256, 31900, 12278, 19151, 10862, 3608, 15766, 12738, 15914, 42111, 10020, 36021, 10692, 6690, 9883, 15079, 12033, 9900, 22825, 11361, 11951, 37286, 11418, 10924, 11337, 9619, 10213, 10856, 11048, 10842, 12414, 10325, 16869, 11143, 25523, 9572, 8037, 9731, 10596, 14328, 10393, 41055, 20795, 14812, 29254, 9532, 9682, 22098, 10576, 14922, 27530, 22068, 44823, 62466, 15851, 17035, 13790, 32455, 9763, 22771, 20480, 5260, 10708, 36714, 21263, 35770, 11534, 5466, 21040, 12474, 25403, 12246, 12780, 19804, 14025, 22915, 11714, 10546, 10914, 4907, 25442, 21807, 11633, 9574, 11884, 20814, 10725, 15213, 21476, 24079, 34650, 11473, 14708, 11460, 14527, 12063, 11321, 10635, 38457, 9976, 11387, 12442, 9942, 11507, 21903, 14923, 12090, 12044, 13137, 23724, 16638, 12050, 23906, 12763, 10095, 10450, 16574, 7953, 23314, 46235, 10924, 10452, 11349, 49136, 8569, 28080, 12395, 31054, 17199, 10749, 12401, 23741, 9983, 10240, 14952, 18745, 10093, 15763, 15947, 22766, 9734, 11323, 9103, 8183, 10813, 11526, 31744, 37984, 10665, 18484, 10234, 28322, 24927, 12733, 11218, 26552, 11835, 19255, 13685, 18189, 14281, 11213, 12967, 12791, 13413, 23402, 14537, 13631, 13160, 14190, 13652, 11060, 11685, 9787, 11534, 14020, 10163, 11664, 11130, 11526, 11963, 11541, 36500, 31777, 11087, 5208, 10415, 11008, 17780, 13966, 11527, 12402, 9959, 15587, 11744, 11524, 10972, 9728, 6301, 11682, 11987, 10687, 11419, 10401, 11515, 11320, 10253, 9305, 11693, 10882, 11733, 22243, 10735, 29551, 12129, 7360, 16884, 43866, 16754, 22618, 10169, 10098, 31603, 17397] + } + ] + }] +} From fbf42028ae4d55f2364c1e31f961733bf2ee56a8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 6 Jul 2017 18:51:04 +0200 Subject: [PATCH 002/281] squashed changes --- src/traces/parcoords/lines.js | 2 +- src/traces/table/attributes.js | 285 ++++++--- src/traces/table/calc.js | 19 +- src/traces/table/constants.js | 17 +- src/traces/table/defaults.js | 105 +--- src/traces/table/index.js | 1 - src/traces/table/plot.js | 42 +- src/traces/table/render.js | 523 ++++++++-------- test/image/mocks/table.json | 114 ++++ test/image/mocks/table_large.json | 204 ++++--- test/jasmine/tests/table_test.js | 972 ++++++++++++++++++++++++++++++ 11 files changed, 1699 insertions(+), 585 deletions(-) create mode 100644 test/image/mocks/table.json create mode 100644 test/jasmine/tests/table_test.js diff --git a/src/traces/parcoords/lines.js b/src/traces/parcoords/lines.js index 92776dabf0a..67805d3970e 100644 --- a/src/traces/parcoords/lines.js +++ b/src/traces/parcoords/lines.js @@ -106,7 +106,7 @@ function palette(unitToColor, context, opacity) { // but first it shifts the sample index by 0, 8 or 16 bits depending on rgbIndex [0..2] // with the end result that each line will be of a unique color, making it possible for the pick handler // to uniquely identify which line is hovered over (bijective mapping). -// The inverse, i.e. readPixel is invoked from 'parcoords.js' +// The inverse, i.e. readPixel is invoked from 'render.js' function calcPickColor(j, rgbIndex) { return (j >>> 8 * rgbIndex) % 256 / 255; } diff --git a/src/traces/table/attributes.js b/src/traces/table/attributes.js index 2ce56c23846..2d6cf9337ef 100644 --- a/src/traces/table/attributes.js +++ b/src/traces/table/attributes.js @@ -8,13 +8,9 @@ 'use strict'; -var colorAttributes = require('../../components/colorscale/color_attributes'); -var colorbarAttrs = require('../../components/colorbar/attributes'); -var colorscales = require('../../components/colorscale/scales'); -var axesAttrs = require('../../plots/cartesian/layout_attributes'); +var annAttrs = require('../../components/annotations/attributes'); var fontAttrs = require('../../plots/font_attributes'); -var extendDeep = require('../../lib/extend').extendDeep; var extendFlat = require('../../lib/extend').extendFlat; module.exports = { @@ -52,46 +48,132 @@ module.exports = { description: 'Sets the font for the `dimension` labels.' }), - dimensions: { - _isLinkedToArray: 'dimension', - label: { - valType: 'string', + labels: { + valType: 'data_array', + role: 'info', + dflt: [], + description: 'The shown name of the columns.' + }, + + columnwidth: { + valType: 'number', + arrayOk: true, + dflt: null, + role: 'style', + description: 'The width of cells.' + }, + + header: { + + values: { + valType: 'data_array', role: 'info', - description: 'The shown name of the dimension.' + dflt: [], + description: [ + 'Dimension values. `values[n]` represents the value of the `n`th point in the dataset,', + 'therefore the `values` vector for all dimensions must be the same (longer vectors', + 'will be truncated). Each value must be a finite number.' + ].join(' ') }, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - font: extendFlat({}, fontAttrs, { - description: 'Sets the font for the `dimension` values.' - }), - valueformat: { - valType: 'string', - dflt: '3s', - role: 'style', + + format: { + valType: 'data_array', + role: 'info', + dflt: [], description: [ - 'Sets the tick label formatting rule using d3 formatting mini-language', + 'Sets the cell value formatting rule using d3 formatting mini-language', 'which is similar to those of Python. See', 'https://github.com/d3/d3-format/blob/master/README.md#locale_format' - ].join(' ') + ] }, - visible: { - valType: 'boolean', - dflt: true, - role: 'info', - description: 'Shows the dimension when set to `true` (the default). Hides the dimension for `false`.' + + prefix: { + valType: 'string', + arrayOk: true, + dflt: null, + role: 'style', + description: 'Prefix for cell values.' }, - range: { - valType: 'info_array', - role: 'info', - items: [ - {valType: 'number'}, - {valType: 'number'} - ], - description: [ - 'The domain range for the purpose of coloring. Defaults to the `values` extent.', - 'Must be an array of `[fromValue, toValue]` with finite numbers as elements.' - ].join(' ') + + suffix: { + valType: 'string', + arrayOk: true, + dflt: null, + role: 'style', + description: 'Suffix for cell values.' + }, + + height: { + valType: 'number', + arrayOk: false, + dflt: 28, + role: 'style', + description: 'The height of cells.' + }, + + align: extendFlat({}, annAttrs.align, {arrayOk: true}), + valign: extendFlat({}, annAttrs.valign, {arrayOk: true}), + + line: { + width: { + valType: 'number', + arrayOk: true, + role: 'style' + }, + color: { + valType: 'color', + arrayOk: true, + role: 'style' + } }, + + fill: { + color: { + valType: 'color', + arrayOk: true, + role: 'style', + description: [ + 'Sets the cell fill color. It accepts either a specific color', + ' or an array of colors.' + ].join('') + } + }, + + font: { + family: { + valType: 'string', + arrayOk: true, + role: 'style', + noBlank: true, + strict: true, + description: [ + 'HTML font family - the typeface that will be applied by the web browser.', + 'The web browser will only be able to apply a font if it is available on the system', + 'which it operates. Provide multiple font families, separated by commas, to indicate', + 'the preference in which to apply fonts if they aren\'t available on the system.', + 'The plotly service (at https://plot.ly or on-premise) generates images on a server,', + 'where only a select number of', + 'fonts are installed and supported.', + 'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,', + '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,', + '*PT Sans Narrow*, *Raleway*, *Times New Roman*.' + ].join(' ') + }, + size: { + valType: 'number', + arrayOk: true, + role: 'style' + }, + color: { + valType: 'color', + arrayOk: true, + role: 'style' + } + } + }, + + cells: { + values: { valType: 'data_array', role: 'info', @@ -102,53 +184,100 @@ module.exports = { 'will be truncated). Each value must be a finite number.' ].join(' ') }, - description: 'The dimensions (variables) of the table view.' - }, - line: extendFlat({}, - - // the default autocolorscale is set to Viridis - autocolorscale therefore defaults to false too, - // to avoid being overridden by the blue-white-red autocolor palette - extendDeep( - {}, - colorAttributes('line'), - { - colorscale: extendDeep( - {}, - colorAttributes('line').colorscale, - {dflt: colorscales.Viridis} - ), - autocolorscale: extendDeep( - {}, - colorAttributes('line').autocolorscale, - { - dflt: false, - description: [ - 'Has an effect only if line.color` is set to a numerical array.', - 'Determines whether the colorscale is a default palette (`autocolorscale: true`)', - 'or the palette determined by `line.colorscale`.', - 'In case `colorscale` is unspecified or `autocolorscale` is true, the default ', - 'palette will be chosen according to whether numbers in the `color` array are', - 'all positive, all negative or mixed.', - 'The default value is false, so that `table` colorscale can default to `Viridis`.' - ].join(' ') - } - ) + format: { + valType: 'data_array', + role: 'info', + dflt: [], + description: [ + 'Sets the cell value formatting rule using d3 formatting mini-language', + 'which is similar to those of Python. See', + 'https://github.com/d3/d3-format/blob/master/README.md#locale_format' + ] + }, + + prefix: { + valType: 'string', + arrayOk: true, + dflt: null, + role: 'style', + description: 'Prefix for cell values.' + }, + suffix: { + valType: 'string', + arrayOk: true, + dflt: null, + role: 'style', + description: 'Suffix for cell values.' + }, + + height: { + valType: 'number', + arrayOk: false, + dflt: 20, + role: 'style', + description: 'The height of cells.' + }, + + align: extendFlat({}, annAttrs.align, {arrayOk: true}), + valign: extendFlat({}, annAttrs.valign, {arrayOk: true}), + + line: { + width: { + valType: 'number', + arrayOk: true, + role: 'style' + }, + color: { + valType: 'color', + arrayOk: true, + role: 'style' + } + }, + + fill: { + color: { + valType: 'color', + arrayOk: true, + role: 'style', + description: [ + 'Sets the cell fill color. It accepts either a specific color', + ' or an array of colors.' + ].join('') } - ), + }, - { - showscale: { - valType: 'boolean', - role: 'info', - dflt: false, + font: { + family: { + valType: 'string', + arrayOk: true, + role: 'style', + noBlank: true, + strict: true, description: [ - 'Has an effect only if `line.color` is set to a numerical array.', - 'Determines whether or not a colorbar is displayed.' + 'HTML font family - the typeface that will be applied by the web browser.', + 'The web browser will only be able to apply a font if it is available on the system', + 'which it operates. Provide multiple font families, separated by commas, to indicate', + 'the preference in which to apply fonts if they aren\'t available on the system.', + 'The plotly service (at https://plot.ly or on-premise) generates images on a server,', + 'where only a select number of', + 'fonts are installed and supported.', + 'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,', + '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,', + '*PT Sans Narrow*, *Raleway*, *Times New Roman*.' ].join(' ') }, - colorbar: colorbarAttrs + size: { + valType: 'number', + arrayOk: true, + role: 'style' + }, + color: { + valType: 'color', + arrayOk: true, + role: 'style' + } } - ) + } }; diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index dc8c55c352b..f28e3060eed 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -8,21 +8,6 @@ 'use strict'; -var hasColorscale = require('../../components/colorscale/has_colorscale'); -var calcColorscale = require('../../components/colorscale/calc'); -var Lib = require('../../lib'); - -module.exports = function calc(gd, trace) { - var cs = !!trace.line.colorscale && Lib.isArray(trace.line.color); - var color = cs ? trace.line.color : Array.apply(0, Array(trace.dimensions.reduce(function(p, n) {return Math.max(p, n.values.length);}, 0))).map(function() {return 0.5;}); - var cscale = cs ? trace.line.colorscale : [[0, trace.line.color], [1, trace.line.color]]; - - if(hasColorscale(trace, 'line')) { - calcColorscale(trace, trace.line.color, 'line', 'c'); - } - - return [{ - lineColor: color, - cscale: cscale - }]; +module.exports = function calc() { + return [{}]; }; diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index b3993c0128e..5958fd5753f 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -11,18 +11,11 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, + cellPad: 4, columnTitleOffset: 28, columnExtentOffset: 10, - bar: { - width: 4, // Visible width of the filter bar - capturewidth: 10, // Mouse-sensitive width for interaction (Fitts law) - fillcolor: 'magenta', // Color of the filter bar fill - fillopacity: 1, // Filter bar fill opacity - strokecolor: 'white', // Color of the filter bar side lines - strokeopacity: 1, // Filter bar side stroke opacity - strokewidth: 1, // Filter bar side stroke width in pixels - handleheight: 16, // Height of the filter bar vertical resize areas on top and bottom - handleopacity: 1, // Opacity of the filter bar vertical resize areas on top and bottom - handleoverlap: 0 // A larger than 0 value causes overlaps with the filter bar, represented as pixels.' - } + transitionEase: 'cubic-out', + transitionDuration: 100, + releaseTransitionEase: 'elastic', + releaseTransitionDuration: 300 }; diff --git a/src/traces/table/defaults.js b/src/traces/table/defaults.js index f459da69b52..5da803bd998 100644 --- a/src/traces/table/defaults.js +++ b/src/traces/table/defaults.js @@ -10,95 +10,46 @@ var Lib = require('../../lib'); var attributes = require('./attributes'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); -var colorscaleDefaults = require('../../components/colorscale/defaults'); -var maxDimensionCount = require('./constants').maxDimensionCount; - -function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { - - if(hasColorscale(traceIn, 'line')) { - coerce('line.colorscale'); - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); - } -} - -function dimensionsDefaults(traceIn, traceOut, fontDflt) { - var dimensionsIn = traceIn.dimensions || [], - dimensionsOut = traceOut.dimensions = []; - - var dimensionIn, dimensionOut, i; - var commonLength = Infinity; - - if(dimensionsIn.length > maxDimensionCount) { - Lib.log('table views support up to ' + maxDimensionCount + ' dimensions at the moment'); - dimensionsIn.splice(maxDimensionCount); - } - - function coerce(attr, dflt) { - return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); - } - - for(i = 0; i < dimensionsIn.length; i++) { - dimensionIn = dimensionsIn[i]; - dimensionOut = {}; - - if(!Lib.isPlainObject(dimensionIn)) { - continue; - } - - var values = coerce('values'); - var visible = coerce('visible', values.length > 0); - - if(visible) { - coerce('label'); - coerce('tickvals'); - coerce('ticktext'); - coerce('valueformat'); - coerce('range'); - Lib.coerceFont(coerce, 'font', fontDflt); - - commonLength = Math.min(commonLength, dimensionOut.values.length); - } - - dimensionOut._index = i; - dimensionsOut.push(dimensionOut); - } - - if(isFinite(commonLength)) { - for(i = 0; i < dimensionsOut.length; i++) { - dimensionOut = dimensionsOut[i]; - if(dimensionOut.visible && dimensionOut.values.length > commonLength) { - dimensionOut.values = dimensionOut.values.slice(0, commonLength); - } - } - } - - return dimensionsOut; -} module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { function coerce(attr, dflt) { return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); } - // make default font size 10px, - // scale linearly with global font size var fontDflt = { family: layout.font.family, - size: Math.round(layout.font.size * (10 / 12)), + size: layout.font.size, color: layout.font.color }; - var dimensions = dimensionsDefaults(traceIn, traceOut, fontDflt); - - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - coerce('domain.x'); coerce('domain.y'); - if(!Array.isArray(dimensions) || !dimensions.length) { - traceOut.visible = false; - } - - Lib.coerceFont(coerce, 'labelfont', fontDflt); + coerce('labels'); + + coerce('columnwidth'); + + coerce('cells.values'); + coerce('cells.format'); + coerce('cells.align'); + coerce('cells.valign'); + coerce('cells.prefix'); + coerce('cells.suffix'); + coerce('cells.height'); + coerce('cells.line.width'); + coerce('cells.line.color'); + coerce('cells.fill.color'); + Lib.coerceFont(coerce, 'cells.font', fontDflt); + + coerce('header.values'); + coerce('header.format'); + coerce('header.align'); + coerce('header.valign'); + coerce('header.prefix'); + coerce('header.suffix'); + coerce('header.height'); + coerce('header.line.width'); + coerce('header.line.color'); + coerce('header.fill.color'); + Lib.coerceFont(coerce, 'header.font', fontDflt); }; diff --git a/src/traces/table/index.js b/src/traces/table/index.js index bcdf85f12e9..16367c46537 100644 --- a/src/traces/table/index.js +++ b/src/traces/table/index.js @@ -14,7 +14,6 @@ Table.attributes = require('./attributes'); Table.supplyDefaults = require('./defaults'); Table.calc = require('./calc'); Table.plot = require('./plot'); -Table.colorbar = require('./colorbar'); Table.moduleType = 'trace'; Table.name = 'table'; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index eb10cebf018..797c0ae84d9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -16,14 +16,14 @@ module.exports = function plot(gd, cdTable) { var svg = fullLayout._paper; var root = fullLayout._paperdiv; - var gdDimensions = {}; - var gdDimensionsOriginalOrder = {}; + var gdColumns = {}; + var gdColumnsOriginalOrder = {}; var size = fullLayout._size; cdTable.forEach(function(d, i) { - gdDimensions[i] = gd.data[i].dimensions; - gdDimensionsOriginalOrder[i] = gd.data[i].dimensions.slice(); + gdColumns[i] = gd.data[i].header.values.map(function(d) {return d[0];}); + gdColumnsOriginalOrder[i] = gdColumns[i].slice(); }); var hover = function(eventData) { @@ -34,18 +34,12 @@ module.exports = function plot(gd, cdTable) { gd.emit('plotly_unhover', eventData); }; - var columnMoved = function(i, visibleIndices) { + var columnMoved = function(i, indices) { - // Have updated order data on `gd.data` and raise `Plotly.restyle` event - // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call - - function visible(dimension) {return !('visible' in dimension) || dimension.visible;} - - function newIdx(visibleIndices, orig, dim) { + function newIdx(indices, orig, dim) { var origIndex = orig.indexOf(dim); - var currentIndex = visibleIndices.indexOf(origIndex); + var currentIndex = indices.indexOf(origIndex); if(currentIndex === -1) { - // invisible dimensions initially go to the end currentIndex += orig.length; } return currentIndex; @@ -53,27 +47,15 @@ module.exports = function plot(gd, cdTable) { function sorter(orig) { return function sorter(d1, d2) { - var i1 = newIdx(visibleIndices, orig, d1); - var i2 = newIdx(visibleIndices, orig, d2); + var i1 = newIdx(indices, orig, d1); + var i2 = newIdx(indices, orig, d2); return i1 - i2; }; } - // drag&drop sorting of the visible dimensions - var orig = sorter(gdDimensionsOriginalOrder[i].filter(visible)); - gdDimensions[i].sort(orig); - - // invisible dimensions are not interpreted in the context of drag&drop sorting as an invisible dimension - // cannot be dragged; they're interspersed into their original positions by this subsequent merging step - gdDimensionsOriginalOrder[i].filter(function(d) {return !visible(d);}) - .sort(function(d) { - // subsequent splicing to be done left to right, otherwise indices may be incorrect - return gdDimensionsOriginalOrder[i].indexOf(d); - }) - .forEach(function(d) { - gdDimensions[i].splice(gdDimensions[i].indexOf(d), 1); // remove from the end - gdDimensions[i].splice(gdDimensionsOriginalOrder[i].indexOf(d), 0, d); // insert at original index - }); + // drag&drop sorting of the columns + var orig = sorter(gdColumnsOriginalOrder[i].slice()); + gdColumns[i].sort(orig); gd.emit('plotly_restyle'); }; diff --git a/src/traces/table/render.js b/src/traces/table/render.js index 4dad86ad8f9..9aa2ad71103 100644 --- a/src/traces/table/render.js +++ b/src/traces/table/render.js @@ -9,7 +9,6 @@ 'use strict'; var c = require('./constants'); -var Lib = require('../../lib'); var d3 = require('d3'); var Drawing = require('../../components/drawing'); @@ -17,97 +16,7 @@ function keyFun(d) {return d.key;} function repeat(d) {return [d];} -function visible(dimension) {return !('visible' in dimension) || dimension.visible;} - -function dimensionExtent(dimension) { - - var lo = dimension.range ? dimension.range[0] : d3.min(dimension.values); - var hi = dimension.range ? dimension.range[1] : d3.max(dimension.values); - - if(isNaN(lo) || !isFinite(lo)) { - lo = 0; - } - - if(isNaN(hi) || !isFinite(hi)) { - hi = 0; - } - - // avoid a degenerate (zero-width) domain - if(lo === hi) { - if(lo === void(0)) { - lo = 0; - hi = 1; - } else if(lo === 0) { - // no use to multiplying zero, so add/subtract in this case - lo -= 1; - hi += 1; - } else { - // this keeps the range in the order of magnitude of the data - lo *= 0.9; - hi *= 1.1; - } - } - - return [lo, hi]; -} - -function ordinalScaleSnap(scale, v) { - var i, a, prevDiff, prevValue, diff; - for(i = 0, a = scale.range(), prevDiff = Infinity, prevValue = a[0], diff = null; i < a.length; i++) { - if((diff = Math.abs(a[i] - v)) > prevDiff) { - return prevValue; - } - prevDiff = diff; - prevValue = a[i]; - } - return a[a.length - 1]; -} - -function domainScale(height, padding, dimension) { - var extent = dimensionExtent(dimension); - return dimension.tickvals ? - d3.scale.ordinal() - .domain(dimension.tickvals) - .range(dimension.tickvals - .map(function(d) {return (d - extent[0]) / (extent[1] - extent[0]);}) - .map(function(d) {return (height - padding + d * (padding - (height - padding)));})) : - d3.scale.linear() - .domain(extent) - .range([height - padding, padding]); -} - function unitScale(height, padding) {return d3.scale.linear().range([height - padding, padding]);} -function domainToUnitScale(dimension) {return d3.scale.linear().domain(dimensionExtent(dimension));} - -function ordinalScale(dimension) { - var extent = dimensionExtent(dimension); - return dimension.tickvals && d3.scale.ordinal() - .domain(dimension.tickvals) - .range(dimension.tickvals.map(function(d) {return (d - extent[0]) / (extent[1] - extent[0]);})); -} - -function unitToColorScale(cscale) { - - var colorStops = cscale.map(function(d) {return d[0];}); - var colorStrings = cscale.map(function(d) {return d[1];}); - var colorTuples = colorStrings.map(function(c) {return d3.rgb(c);}); - var prop = function(n) {return function(o) {return o[n];};}; - - // We can't use d3 color interpolation as we may have non-uniform color palette raster - // (various color stop distances). - var polylinearUnitScales = 'rgb'.split('').map(function(key) { - return d3.scale.linear() - .clamp(true) - .domain(colorStops) - .range(colorTuples.map(prop(key))); - }); - - return function(d) { - return polylinearUnitScales.map(function(s) { - return s(d); - }); - }; -} function unwrap(d) { return d[0]; // plotly data structure convention @@ -116,113 +25,119 @@ function unwrap(d) { function model(layout, d, i) { var cd0 = unwrap(d), trace = cd0.trace, - lineColor = cd0.lineColor, - cscale = cd0.cscale, - line = trace.line, domain = trace.domain, - dimensions = trace.dimensions, width = layout.width, - labelFont = trace.labelfont; + labels = trace.labels, + columnWidths = trace.columnwidth; - var lines = Lib.extendDeep({}, line, { - color: lineColor.map(domainToUnitScale({values: lineColor, range: [line.cmin, line.cmax]})), - blockLineCount: c.blockLineCount, - canvasOverdrag: c.overdrag * c.canvasPixelRatio - }); + var colCount = labels.length; var groupWidth = Math.floor(width * (domain.x[1] - domain.x[0])); var groupHeight = Math.floor(layout.height * (domain.y[1] - domain.y[0])); + columnWidths = trace.header.values.map(function(d, i) { + return Array.isArray(columnWidths) ? + columnWidths[Math.min(i, columnWidths.length - 1)] : + isFinite(columnWidths) && columnWidths !== null ? columnWidths : 1; + }); + + var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); + columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); + var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; var rowContentWidth = groupWidth; var rowHeight = groupHeight; return { key: i, - colCount: dimensions.filter(visible).length, - dimensions: dimensions, + colCount: colCount, tickDistance: c.tickDistance, - unitToColor: unitToColorScale(cscale), - lines: lines, - labelFont: labelFont, translateX: domain.x[0] * width, translateY: layout.height - domain.y[1] * layout.height, pad: pad, - canvasWidth: rowContentWidth * c.canvasPixelRatio + 2 * lines.canvasOverdrag, - canvasHeight: rowHeight * c.canvasPixelRatio, width: rowContentWidth, height: rowHeight, - canvasPixelRatio: c.canvasPixelRatio + columnWidths: columnWidths, + + cells: { + values: trace.cells.values, + valueFormat: trace.cells.format, + prefix: trace.cells.prefix, + suffix: trace.cells.suffix, + cellHeights: trace.cells.height, + align: trace.cells.align, + valign: trace.cells.valign, + font: trace.cells.font, + fillColor: trace.cells.fill.color, + lineWidth: trace.cells.line.width, + lineColor: trace.cells.line.color + }, + + headerCells: { + values: trace.header.values.map(repeat), + align: trace.header.align, + valign: trace.header.valign, + font: trace.header.font, + cellHeights: trace.cells.height, + fillColor: trace.header.fill.color, + lineWidth: trace.header.line.width, + lineColor: trace.header.line.color + } }; } function viewModel(model) { - var width = model.width; var height = model.height; - var dimensions = model.dimensions; - var canvasPixelRatio = model.canvasPixelRatio; - - var xScale = function(d) {return width * d / Math.max(1, model.colCount - 1);}; - var unitPad = c.verticalPadding / (height * canvasPixelRatio); - var unitPadScale = (1 - 2 * unitPad); - var paddedUnitScale = function(d) {return unitPad + unitPadScale * d;}; + var newXScale = function (d) { + return d.parent.columns.reduce(function(prev, next) {return next.xIndex < d.xIndex ? prev + next.columnWidth : prev}, 0); + } var viewModel = { key: model.key, - xScale: xScale, model: model }; var uniqueKeys = {}; - viewModel.dimensions = dimensions.filter(visible).map(function(dimension, i) { - var domainToUnit = domainToUnitScale(dimension); - var foundKey = uniqueKeys[dimension.label]; - uniqueKeys[dimension.label] = (foundKey || 0) + 1; - var key = dimension.label + (foundKey ? '__' + foundKey : ''); + viewModel.columns = model.headerCells.values.map(function(label, i) { + var foundKey = uniqueKeys[label]; + uniqueKeys[label] = (foundKey || 0) + 1; + var key = label + (foundKey ? '__' + foundKey : ''); return { key: key, - label: dimension.label, - valueFormat: dimension.valueformat, - tickvals: dimension.tickvals, - ticktext: dimension.ticktext, - font: dimension.font, - ordinal: !!dimension.tickvals, - scatter: c.scatter || dimension.scatter, + label: label, xIndex: i, - crossfilterDimensionIndex: i, - visibleIndex: dimension._index, height: height, - values: dimension.values, - paddedUnitValues: dimension.values.map(domainToUnit).map(paddedUnitScale), - xScale: xScale, - x: xScale(i), - canvasX: xScale(i) * canvasPixelRatio, + newXScale: newXScale, + x: undefined, // initialized below unitScale: unitScale(height, c.verticalPadding), - domainScale: domainScale(height, c.verticalPadding, dimension), - ordinalScale: ordinalScale(dimension), - domainToUnitScale: domainToUnit, filter: [0, 1], parent: viewModel, - model: model + model: model, + rowPitch: model.cells.cellHeights, + columnWidth: model.columnWidths[i] }; }); + viewModel.columns.forEach(function(dim) { + dim.x = newXScale(dim); + }); return viewModel; } -function lineLayerModel(vm) { - return c.layers.map(function(key) { - return { - key: key, - context: key === 'contextLineLayer', - pick: key === 'pickLineLayer', - viewModel: vm, - model: vm.model - }; - }); +function gridPick(spec, col, row) { + if(Array.isArray(spec)) { + const column = spec[Math.min(col, spec.length - 1)]; + if(Array.isArray(column)) { + return column[Math.min(row, column.length - 1)]; + } else { + return column; + } + } else { + return spec; + } } module.exports = function(root, svg, styledData, layout, callbacks) { @@ -231,17 +146,16 @@ module.exports = function(root, svg, styledData, layout, callbacks) { var linePickActive = true; var vm = styledData - .filter(function(d) { return unwrap(d).trace.visible; }) .map(model.bind(0, layout)) .map(viewModel); svg.style('background', 'rgba(255, 255, 255, 0)'); - var tableControlOverlay = svg.selectAll('.table') + var table = svg.selectAll('.table') .data(vm, keyFun); - tableControlOverlay.exit().remove(); + table.exit().remove(); - tableControlOverlay.enter() + table.enter() .append('g') .classed('table', true) .attr('overflow', 'visible') @@ -250,16 +164,16 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .style('left', 0) .style('overflow', 'visible') .style('shape-rendering', 'crispEdges') - .style('pointer-events', 'none'); + .style('pointer-events', 'all'); // todo restore 'none' - tableControlOverlay + table .attr('width', function(d) {return d.model.width + d.model.pad.l + d.model.pad.r;}) .attr('height', function(d) {return d.model.height + d.model.pad.t + d.model.pad.b;}) .attr('transform', function(d) { return 'translate(' + d.model.translateX + ',' + d.model.translateY + ')'; }); - var tableControlView = tableControlOverlay.selectAll('.tableControlView') + var tableControlView = table.selectAll('.tableControlView') .data(repeat, keyFun); tableControlView.enter() @@ -271,64 +185,14 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .attr('transform', function(d) {return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')';}); var yColumn = tableControlView.selectAll('.yColumn') - .data(function(vm) {return vm.dimensions;}, keyFun); - - function updatePanelLayouttable(yColumn, vm) { - var panels = vm.panels || (vm.panels = []); - var yColumns = yColumn.each(function(d) {return d;})[vm.key].map(function(e) {return e.__data__;}); - var panelCount = yColumns.length - 1; - var rowCount = 1; - for(var row = 0; row < rowCount; row++) { - for(var p = 0; p < panelCount; p++) { - var panel = panels[p + row * panelCount] || (panels[p + row * panelCount] = {}); - var dim1 = yColumns[p]; - var dim2 = yColumns[p + 1]; - panel.dim1 = dim1; - panel.dim2 = dim2; - panel.canvasX = dim1.canvasX; - panel.panelSizeX = dim2.canvasX - dim1.canvasX; - panel.panelSizeY = vm.model.canvasHeight / rowCount; - panel.y = row * panel.panelSizeY; - panel.canvasY = vm.model.canvasHeight - panel.y - panel.panelSizeY; - } - } - } - - function updatePanelLayoutScatter(yColumn, vm) { - var panels = vm.panels || (vm.panels = []); - var yColumns = yColumn.each(function(d) {return d;})[vm.key].map(function(e) {return e.__data__;}); - var panelCount = yColumns.length - 1; - var rowCount = panelCount; - for(var row = 0; row < panelCount; row++) { - for(var p = 0; p < panelCount; p++) { - var panel = panels[p + row * panelCount] || (panels[p + row * panelCount] = {}); - var dim1 = yColumns[p]; - var dim2 = yColumns[p + 1]; - panel.dim1 = yColumns[row + 1]; - panel.dim2 = dim2; - panel.canvasX = dim1.canvasX; - panel.panelSizeX = dim2.canvasX - dim1.canvasX; - panel.panelSizeY = vm.model.canvasHeight / rowCount; - panel.y = row * panel.panelSizeY; - panel.canvasY = vm.model.canvasHeight - panel.y - panel.panelSizeY; - } - } - } - - function updatePanelLayout(yColumn, vm) { - return (c.scatter ? updatePanelLayoutScatter : updatePanelLayouttable)(yColumn, vm); - } + .data(function(vm) {return vm.columns;}, keyFun); yColumn.enter() .append('g') .classed('yColumn', true); - tableControlView.each(function(vm) { - updatePanelLayout(yColumn, vm); - }); - yColumn - .attr('transform', function(d) {return 'translate(' + d.xScale(d.xIndex) + ', 0)';}); + .attr('transform', function(d) {return 'translate(' + d.newXScale(d) + ', 0)';}); yColumn .call(d3.behavior.drag() @@ -339,22 +203,26 @@ module.exports = function(root, svg, styledData, layout, callbacks) { if(domainBrushing) { return; } - d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag, d3.event.x)); - d.canvasX = d.x * d.model.canvasPixelRatio; + d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag - d.columnWidth, d3.event.x)); yColumn - .sort(function(a, b) {return a.x - b.x;}) + .sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}) .each(function(dd, i) { dd.xIndex = i; - dd.x = d === dd ? dd.x : dd.xScale(dd.xIndex); - dd.canvasX = dd.x * dd.model.canvasPixelRatio; + dd.x = d === dd ? dd.x : dd.newXScale(dd); }); - updatePanelLayout(yColumn, p); - yColumn.filter(function(dd) {return Math.abs(d.xIndex - dd.xIndex) !== 0;}) - .attr('transform', function(d) {return 'translate(' + d.xScale(d.xIndex) + ', 0)';}); - d3.select(this).attr('transform', 'translate(' + d.x + ', 0)'); - yColumn.each(function(dd, i, ii) {if(ii === d.parent.key) p.dimensions[i] = dd;}); + .transition() + .ease(c.transitionEase) + .duration(c.transitionDuration) + .attr('transform', function(d) {return 'translate(' + d.newXScale(d) + ', 0)';}); + d3.select(this) + .transition() + .ease(c.transitionEase) + .duration(c.transitionDuration) + .attr('transform', 'translate(' + d.x + ', -5)'); + yColumn.each(function(dd, i, ii) {if(ii === d.parent.key) p.columns[i] = dd;}); + this.parentNode.appendChild(this); }) .on('dragend', function(d) { var p = d.parent; @@ -364,15 +232,16 @@ module.exports = function(root, svg, styledData, layout, callbacks) { } return; } - d.x = d.xScale(d.xIndex); - d.canvasX = d.x * d.model.canvasPixelRatio; - updatePanelLayout(yColumn, p); + d.x = d.newXScale(d); d3.select(this) + .transition() + .ease(c.releaseTransitionEase, 1, .75) + .duration(c.releaseTransitionDuration) .attr('transform', function(d) {return 'translate(' + d.x + ', 0)';}); linePickActive = true; - if(callbacks && callbacks.columnsMoved) { - callbacks.columnsMoved(p.key, p.dimensions.map(function(dd) {return dd.crossfilterDimensionIndex;})); + if(callbacks && callbacks.columnMoved) { + callbacks.columnMoved(p.key, p.columns.map(function(dd) {return dd.xIndex;})); } }) ); @@ -387,88 +256,174 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .append('g') .classed('columnOverlays', true); - columnOverlays.selectAll('.column').remove(); - - var column = columnOverlays.selectAll('.column') - .data(repeat, keyFun); - - column.enter() - .append('g') - .classed('column', true); - - column - .selectAll('.domain, .tick>line') - .attr('fill', 'none') - .attr('stroke', 'black') - .attr('stroke-opacity', 0.25) - .attr('stroke-width', '1px'); - - column - .selectAll('text') - .style('text-shadow', '1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff') - .style('cursor', 'default') - .style('user-select', 'none'); - - var columnHeading = columnOverlays.selectAll('.columnHeading') - .data(repeat, keyFun); + var columnBlock = columnOverlays.selectAll('.columnBlock') + .data(function(d) { + var blockDataHeader = Object.assign( + {}, + d, + { + key: 'header', + yOffset: 0, + values: d.model.headerCells.values[d.xIndex], + dragHandle: true, + model: Object.assign( + {}, + d.model, + { + cells: d.model.headerCells + } + ) + } + ); + + return [ + blockDataHeader, + Object.assign( + {}, + d, + { + key: 'cells', + yOffset: d.rowPitch, + dragHandle: false, + values: d.model.cells.values[d.xIndex], + model: d.model + } + ) + ]; + }, keyFun); - columnHeading.enter() + columnBlock.enter() .append('g') - .classed('columnHeading', true); + .classed('columnBlock', true); - var columnTitle = columnHeading.selectAll('.columnTitle') - .data(repeat, keyFun); + columnBlock + .attr('transform', function(d) {return 'translate(0 ' + d.yOffset + ')';}) + .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : null;}) + //.style('user-select', 'none') + //.style('pointer-events', 'auto'); - columnTitle.enter() - .append('text') - .classed('columnTitle', true) - .attr('text-anchor', 'end') - .style('cursor', 'ew-resize') - .style('user-select', 'none') - .style('pointer-events', 'auto'); - - columnTitle - .attr('transform', 'translate(0,' + -c.columnTitleOffset + ')') - .text(function(d) {return d.label;}) - .each(function(d) {Drawing.font(columnTitle, d.model.labelFont);}); - - var columnCells = columnOverlays.selectAll('.columnCells') + var columnCells = columnBlock.selectAll('.columnCells') .data(repeat, keyFun); columnCells.enter() .append('g') .classed('columnCells', true); - columnCells.each(function(d) {Drawing.font(d3.select(this), d.font);}); + columnCells.exit() + .remove(); var columnCell = columnCells.selectAll('.columnCell') - .data(function(d) {return d.values.map(function(v, i) {return {key: i, dimension: d, model: d.model, value: v};});}, keyFun); + .data(function(d) {return d.values.map(function(v, i) {return {key: i, column: d, model: d.model, value: v};});}, keyFun); columnCell.enter() .append('g') .classed('columnCell', true); columnCell - .attr('transform', function(d, i) {return 'translate(' + 0 + ',' + i * 20 + ')';}); + .attr('transform', function(d, i) { + return 'translate(' + 0 + ',' + i * d.column.rowPitch + ')'; + }) + .each(function(d, i) { + var spec = d.model.cells.font; + var col = d.column.xIndex; + var font = { + size: gridPick(spec.size, col, i), + color: gridPick(spec.color, col, i), + family: gridPick(spec.family, col, i) + }; + Drawing.font(d3.select(this), font); + + d.rowNumber = i; + d.align = gridPick(d.model.cells.align, d.column.xIndex, i); + d.valign = gridPick(d.model.cells.valign, d.column.xIndex, i); + d.cellBorderWidth = gridPick(d.model.cells.lineWidth, d.column.xIndex, i) + d.font = font; + }); + + var cellRect = columnCell.selectAll('.cellRect') + .data(repeat, keyFun); + + cellRect.enter() + .append('rect') + .classed('cellRect', true); + + cellRect + .attr('width', function(d) {return d.column.columnWidth - d.cellBorderWidth;}) + .attr('height', function(d) {return d.column.rowPitch - d.cellBorderWidth;}) + .attr('transform', function(d) {return 'translate(' + 0 + ' ' + (-(d.column.rowPitch - c.cellPad)) + ')'}) + .attr('stroke', function(d) { + return gridPick(d.model.cells.lineColor, d.column.xIndex, d.rowNumber); + }) + .attr('stroke-width', function(d) {return d.cellBorderWidth;}) + .attr('fill', function(d) { + return gridPick(d.model.cells.fillColor, d.column.xIndex, d.rowNumber); + }); - var columnCellText = columnCell.selectAll('.columnCellText') + var cellLine = columnCell.selectAll('.cellLine') .data(repeat, keyFun); - columnCellText.enter() + cellLine.enter() + .append('path') + .classed('cellLine', true); + + cellLine + .attr('id', function(d) {return 'textpath' + d.column.xIndex;}) + .attr('d', function(d) { + var x1 = 0; + var x2 = d.column.columnWidth; + var y = d.column.rowPitch; + return d3.svg.line()([[x1, y], [x2, y]]); + }) + .attr('transform', function(d) {return 'translate(' + 0 + ' ' + (-(d.column.rowPitch - c.cellPad)) + ')'}); + + var cellText = columnCell.selectAll('.cellText') + .data(repeat, keyFun); + + cellText.enter() .append('text') - .classed('columnCellText', true) - .attr('alignment-baseline', 'middle') - .attr('text-anchor', 'end'); + .classed('cellText', true); + + cellText + .attr('dy', function(d) { + var rowPitch = d.column.rowPitch; + var fontSize = d.font.size; + return ({ + top: -rowPitch + fontSize, + middle: -rowPitch / 2 + fontSize * 0.2 + c.cellPad / 2, + bottom: -c.cellPad + })[d.valign]; + }) + .each(function(d) {Drawing.font(d3.select(this), d.font);}); + + var textPath = cellText.selectAll('.textPath') + .data(repeat, keyFun); - columnCellText + textPath.enter() + .append('textPath') + .classed('textPath', true); + + textPath + .attr('xlink:href', function(d) {return '#textpath' + d.column.xIndex;}) + .attr('text-anchor', function(d) { + return ({ + left: 'start', + right: 'end', + center: 'middle' + })[d.align]; + }) + .attr('startOffset', function(d) { + return ({ + left: c.cellPad, + right: d.column.columnWidth - c.cellPad, + center: '50%' + })[d.align]; + }) .text(function(d) { - const starSchema = d.dimension.ticktext && d.dimension.tickvals - if(starSchema) { - var lookup = {} - for(var i = 0; i < d.dimension.ticktext.length; i++) { - lookup[d.dimension.tickvals[i]] = d.dimension.ticktext[i] - } - } - return starSchema ? lookup[d.value] : d3.format(d.dimension.valueFormat)(d.value); + var dim = d.column.xIndex; + var row = d.rowNumber; + var prefix = gridPick(d.model.cells.prefix, dim, row) || ''; + var suffix = gridPick(d.model.cells.suffix, dim, row) || ''; + var valueFormat = gridPick(d.model.cells.valueFormat, dim, row); + return prefix + (valueFormat ? d3.format(valueFormat)(d.value) : d.value) + suffix; }); }; diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json new file mode 100644 index 00000000000..9d31b309095 --- /dev/null +++ b/test/image/mocks/table.json @@ -0,0 +1,114 @@ +{ + "layout": { + "width": 1200, + "height": 800, + "title": "Widget parameters and cost", + "font": { + "color": "blue", + "size": 200, + "family": "sans-serif" + }, + "margin": {"t": 106, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0.02, 0.97] + }, + + "columnwidth": [110, 60, 90, 90, 80, 70, 80, 60, 100, 70], + + "header": { + + "values": [ + ["Height"], + ["Width"], + ["Cylinder"], + ["Weight"], + ["Cost"], + ["Penalty"], + ["H/W"], + ["Min H/W"], + ["Diameter"], + ["RF block"] + ], + + "align": ["right", "center", "center", "right", "right", "right", "left", "right", "right", "right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "PT Sans Narrow", + "size": 16, + "color": "white" + } + }, + + "cells": { + + "values": [ + [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666], + [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000], + ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"], + [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797], + [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939], + [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778], + [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373], + [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666], + [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081], + [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154] + ], + + "format": [ + ".2s", + "#0x", + null, + [",.0f", ",.1f", ",.2f", ",.3f", ",.2f"], + "$,", + "_>5", + ",.1%", + ".3s", + ",.0f", + ",.0f" + ], + + "prefix": ["", "", "", "", "US ", ""], + "suffix": ["m", ""], + + "height": 24, + + "align": ["right", "center", "center", "right", "right", "right", "left", "right", "right", "right"], + "valign": "middle", + + "line": { + "color": [ + "grey" + ], + "width": 0.5 + }, + + "fill": { + "color": [ + ["#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7"] + ] + }, + + "font": { + "size": 12, + "color": ["black", "red", "black", "black"] + } + } + }] +} diff --git a/test/image/mocks/table_large.json b/test/image/mocks/table_large.json index 5a748795127..bce80a00235 100644 --- a/test/image/mocks/table_large.json +++ b/test/image/mocks/table_large.json @@ -1,94 +1,128 @@ { - "layout": { - "width": 1184, - "height": 400, - "title": "Widget parameters and cost", - "font": { - "color": "blue", - "size": 2, - "family": "sans-serif" + "layout": { + "width": 800, + "height": 800, + "title": "Widget parameters and cost", + "font": { + "color": "blue", + "size": 2, + "family": "sans-serif" + }, + "margin": {"t": 106, "r": 60, "b": 54, "l": 60} }, - "margin": {"t": 106, "r": 70, "b": 54, "l": 90} - }, - "data": [{ + "data": [{ - "type": "table", + "type": "table", - "line": { - "showscale": true, - "reversescale": true, - "colorscale": "Viridis", - "valueformat": ",.2r", - "cmin": -4000, - "cmax": -100 - }, + "domain": { + "x": [0.05, 0.95], + "y": [0.02, 0.97] + }, - "labelfont": { - "family": "PT Sans Narrow", - "size": 16, - "weight": "bold", - "color": "grey" - }, + "columnwidth": [110, 60, 90, 90, 80, 70, 80, 60, 100, 70], - "dimensions": [ - { - "constraintrange": [100000, 150000], - "label": "Height", - "valueformat": ".2s", - "values": [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 86600, 163400, 162600, 90000, 93100, 163000, 140500, 130000, 100700, 164500, 147700, 121700, 107500, 176600, 133600, 111100, 93100, 72400, 130100, 54500, 182600, 160300, 218100, 66500, 95800, 164800, 107200, 101600, 91100, 91100, 78100, 63300, 75700, 69600, 88500, 115800, 195700, 88900, 74800, 65400, 74900, 115300, 91400, 67800, 85300, 171300, 32000, 227900, 163200, 122899, 112300, 101500, 111199, 73300, 120800, 93100, 117200, 118500, 104800, 108500, 146500, 90300, 32000, 93000, 110700, 103500, 93300, 106300, 118500, 93000, 67600, 51400, 89000, 94000, 88200, 109600, 102100, 123600, 81900, 100000, 218100, 223200, 97300, 162100, 97400, 145800, 67400, 156500, 201900, 94300, 67800, 76100, 98300, 112400, 141800, 111400, 74700, 67300, 71100, 68900, 62100, 73800, 85500, 94400, 68300, 79400, 96300, 70400, 67300, 67300, 128400, 80800, 87600, 165900, 35900, 76200, 79000, 38900, 157200, 64400, 67700, 65700, 125800, 59300, 66100, 198700, 96100, 65600, 70300, 69200, 65500, 129300, 62600, 64200, 61800, 60800, 83100, 58800, 69600, 60400, 63500, 63500, 59300, 56600, 77200, 62900, 57300, 68000, 227900, 53099, 59100, 63099, 65900, 60500, 158100, 60199, 66600, 57699, 58900, 62699, 62000, 58600, 78700, 60700, 60400, 66000, 66000, 133300, 60800, 63200, 60400, 68400, 64600, 61400, 61900, 59000, 155600, 53500, 62000, 60599, 63700, 118500, 48000, 57400, 58200, 56800, 62300, 54500, 61300, 62200, 53200, 51600, 88500, 125100, 60800, 61500, 59200, 56300, 60800, 179300, 58300, 199500, 102100, 60800, 183200, 58800, 125000, 56900, 58600, 53700, 56100, 127600, 96100, 56700, 120500, 58600, 53600, 59000, 113800, 59000, 59200, 54500, 135700, 161200, 57300, 53000, 127000, 54600, 55300, 89700, 59400, 54900, 64700, 56200, 127100, 57000, 35400, 51800, 170100, 54000, 56700, 73600, 83200, 53000, 60500, 52699, 51600, 92100, 56600, 57400, 65500, 58400, 97600, 52900, 56700, 207600, 221900, 56500, 57600, 63900, 54700, 56900, 56000, 49700, 51600, 53400, 58500, 65000, 57100, 55900, 56100, 59800, 55300, 57699, 57600, 53200, 53900, 63000, 58400, 57500, 61200, 62699, 61000, 60199, 57600, 128800, 57699, 59900, 94200, 60900, 55100, 56300, 54100, 61400, 55000, 223100, 57699, 52200, 55300, 54000, 61000, 54800, 59500, 59000, 54400, 57800, 57100, 53200, 56300, 58300, 56100, 53900, 55100, 54100, 59500, 188900, 92300, 105500, 67100, 100000, 202500, 101800, 55900, 86800, 55300, 56700, 59400, 51400, 49000, 54600, 49400, 65300, 56800, 55599, 184500, 55000, 55000, 86900, 60100, 89700, 52500, 52500, 55500, 91700, 104600, 67500, 50700, 63300, 55400, 54500, 62600, 52699, 54100, 53400, 54800, 53200, 59900, 74500, 134800, 52400, 105300, 53700, 215200, 101700, 57200, 54400, 60300, 50800, 129400, 55100, 165700, 55000, 51700, 56000, 54000, 56500, 54500, 56000, 78600, 56300, 54700, 59600, 58300, 58800, 52400, 54500, 57100, 119100, 50100, 56500, 58900, 66500, 55599, 225400, 57699, 97200, 57000, 212900, 57300, 101600, 216500, 55400, 65800, 53000, 164200, 124600, 86300, 56000, 95200, 152700, 208299, 32000, 60400, 60700, 196600, 55000, 77200, 37500, 52000, 55300, 54100, 53500, 52800, 55100, 60100, 125000, 62400, 63700, 106900, 54300, 54100, 217500, 56400, 69700, 101000, 57500, 55100, 153500, 53700, 54700, 58099, 53900, 37000, 53200, 62000, 52100, 53900, 54500, 61600, 59700, 218200, 54700, 189200, 55599, 70600, 63700, 107100, 68800, 55700, 56400, 57400, 32000, 83200, 61200, 217900, 62100, 62400, 60900, 60700, 56300, 57600, 105399, 60000, 56700, 221200, 157700, 58200, 58099, 54700, 60900, 61300, 162600, 60900, 224600, 57699, 52699, 59600, 71200, 52100, 57500, 60500, 134900, 67200, 63700, 55000, 65199, 161600, 80300, 70000, 73300, 56200, 68400, 183700, 180100, 56400, 77600, 197800, 215799, 56600, 73300, 57500, 57500, 55199, 54800, 55900, 63300, 106400, 163200, 70800, 71900, 166000, 114100, 100900, 164300, 93600, 150000, 98200, 161400, 200400, 92600, 127600, 97600, 84400, 96600, 55599, 100500, 112000, 110000, 89800, 97700, 84200, 79600, 102400, 84800, 86900, 166600, 91300, 79600, 78100, 85800, 88200, 104200, 76600, 83300, 110800, 75600, 76100, 113800, 86400, 86800, 74800, 77100, 95200, 86900, 172300, 69700, 87500, 79600, 65300, 80800, 82400, 67100, 79400, 78500, 84800, 76100, 47200, 79400, 78200, 220300, 66100, 78300, 85900, 92100, 80800, 74500, 72800, 36200, 75800, 77400, 69600, 62600, 90700, 70700, 93100, 40400, 62600, 94400, 73600, 72000, 138200, 75400, 73300, 170700, 75500, 144500, 76600, 72000, 78200, 33200, 74100, 67900, 35300, 72000, 69900, 68600, 69400, 74300, 73400, 128400, 71800, 217399, 86500, 174200, 67800, 86500, 136800, 125399, 75200, 108000, 72700, 223900, 67300, 73600, 86500, 83800, 70900, 72900, 71300, 71800, 88600, 60300, 77200, 65300, 63300, 68900, 127100, 70700, 223600, 68700, 66000, 70800, 69000, 60599, 65700, 64200, 150700, 65000, 68700, 75800, 154200, 63300, 103400, 70200, 66400, 69200, 71000, 65700, 62300, 70100, 72200, 68700, 64600, 67600, 61800, 68100, 129200, 54900, 77600, 169700, 67100, 64100, 69300, 65700, 64600, 71800, 65199, 61800, 198400, 208800, 72100, 59800, 66200, 62900, 152500, 72200, 57600, 61300, 61900, 54900, 177200, 79500, 60800, 67000, 61100, 155600, 63400, 61500, 65100, 150000, 64500, 56800, 59600, 59000, 63000, 59000, 56700, 59000, 58400, 60700, 56700, 56900, 54900, 54800, 52200, 54700, 54800, 62000, 134700, 115700, 59700, 51500, 66900, 55599, 56400, 52900, 56800, 52900, 58200, 57699, 59100, 53200, 55800, 53300, 60400, 58200, 107500, 55500, 56800, 54400, 56100, 201400, 56600, 176200, 84400, 54100, 214700, 55800, 123699, 173700, 73600, 55199, 169200, 82600, 56500, 62300, 59100, 151900, 122700, 66700, 58200, 56400, 57400, 55000, 56000, 111900, 60400, 149700, 71700, 56600, 93800, 178700, 80900, 54700, 87700, 118900, 52300, 195900, 190200, 58000, 51300, 211300, 54500, 56600, 56900, 111800, 54900, 79400, 69700, 62800, 78600, 57600, 55199, 57000, 56600, 57200, 68600, 53800, 53900, 54900, 122500, 63500, 179300, 57800, 55700, 89400, 61800, 32000, 79000, 214100, 61400, 56000, 54900, 61900, 55100, 58800, 54400, 82600, 176300, 56600, 55100, 59100, 141700, 60100, 54500, 71700, 58900, 58800, 52100, 60000, 56900, 77700, 62600, 57900, 53300, 52400, 59800, 218900, 70700, 218200, 144700, 53300, 57200, 53900, 54000, 55400, 107700, 53800, 121300, 52400, 54600, 199500, 118200, 80900, 202900, 56600, 53400, 52100, 56600, 222600, 50300, 65100, 54200, 54600, 60199, 183700, 134800, 146300, 62500, 52600, 56500, 53099, 180700, 57800, 53500, 52000, 54300, 87300, 57699, 54300, 64400, 68500, 213299, 57300, 51800, 56300, 50000, 67200, 49500, 51100, 63500, 62400, 165500, 49300, 51200, 58099, 77700, 40800, 55000, 63500, 78000, 208000, 56900, 58099, 53900, 83600, 55599, 53800, 86300, 55100, 55700, 58400, 59100, 206600, 55000, 51100, 61600, 187000, 54400, 57699, 55700, 56800, 54000, 52200, 53700, 57100, 55100, 56600, 76700, 56400, 58700, 58200, 58900, 56300, 182300, 59500, 57200, 52300, 54600, 77100, 54300, 57400, 54200, 54200, 55100, 54600, 57400, 57500, 55900, 54900, 54400, 54400, 54600, 82300, 54400, 41600, 56500, 54000, 55900, 53400, 55100, 57300, 55199, 53500, 56300, 57500, 55800, 64600, 53900, 54100, 58500, 49700, 53400, 59500, 53700, 56900, 53700, 57000, 53800, 51100, 55900, 54700, 47900, 53500, 57400, 54700, 88600, 58400, 56900, 53200, 127200, 58900, 57400, 56600, 52600, 121800, 56900, 44700, 120600, 90300, 61300, 60700, 58900, 56800, 120300, 57600, 54700, 56800, 62600, 85700, 86700, 52400, 83900, 51800, 64500, 51100, 59200, 56100, 43000, 53700, 56000, 63600, 56900, 57800, 54100, 53700, 116199, 52200, 73800, 56100, 157600, 54400, 54600, 53300, 68400, 55100, 198900, 54500, 52800, 51600, 225100, 129100, 63800, 55400, 157100, 54300, 53800, 69400, 55700, 72100, 54600, 71900, 54300, 53800, 55700, 53900, 60900, 52300, 53000, 56300, 53400, 54300, 179100, 57500, 54300, 84000, 53300, 53500, 51500, 54300, 37700, 105600, 55100, 53600, 206700, 51700, 54200, 64900, 52600, 57699, 79900, 52500, 51300, 53900, 54100, 59300, 54100, 55800, 57100, 63800, 56800, 65900, 54400, 56900, 79000, 59300, 44200, 53099, 57500, 49300, 123600, 180700, 112500, 97500, 58600, 220400, 54000, 55300, 53500, 51900, 172200, 58600, 99300, 65900, 54800, 52900, 148300, 53099, 65300, 50500, 86100, 54500, 109600, 60400, 90200, 56500, 56500, 73100, 153500, 120900, 118300, 144300, 57100, 52500, 53400, 51300, 98900, 54800, 53400, 54600, 101100, 54500, 136800, 54700, 50500, 55599, 52200, 54000, 57699, 46900, 208800, 105399, 55500, 32100, 174200, 32599, 52100, 104700, 137900, 61300, 46100, 151600, 55700, 191100, 168600, 107500, 59500, 58300, 83100, 65400, 60100, 65300, 73500, 63900, 59600, 58700, 57800, 175200, 159100, 56100, 61600, 57800, 58000, 204800, 52500, 60800, 51200, 56900, 158200, 193900, 56200, 154800, 58500, 54100, 45400, 53500, 57000, 58900, 57600, 55100, 130399, 59800, 57400, 59600, 161700, 52600, 57800, 57600, 57400, 55900, 55500, 59600, 138800, 212200, 102300, 66700, 39800, 128400, 53300, 75600, 59000, 45300, 65100, 55700, 59100, 160900, 111500, 170700, 56600, 57500, 61000, 53300, 42900, 82100, 54700, 197200, 141700, 53800, 72400, 72800, 227900, 183900, 53700, 120700, 92600, 51800, 54100, 57100, 120700, 99900, 52600, 65300, 59900, 112899, 56800, 53300, 57200, 139700, 63500, 65800, 64600, 50500, 55700, 55900, 55800, 45800, 63800, 56400, 151500, 200100, 51100, 56100, 55599, 64500, 192300, 76100, 55300, 55199, 48000, 65800, 66300, 64400, 127100, 54300, 57000, 56100, 52000, 91000, 51800, 206800, 91900, 196200, 65199, 220500, 214899, 85700, 50800, 56000, 57699, 188500, 72100, 67200, 67000, 53000, 86100, 147100, 92600, 63500, 99800, 209400, 32000, 66500, 113699, 86800, 65100, 64000, 62400, 60300, 144700, 73100, 67200, 42100, 78400, 58600, 61800, 67900, 56500, 56400, 59700, 59000, 51900, 60100, 58300, 54900, 67800, 55700, 55599, 58400, 59800, 62400, 51300, 59800, 41700, 51400, 59700, 61700, 56500, 147400, 56500, 98300, 183500, 58200, 56200, 56800, 82700, 52900, 50700, 55700, 53500, 58500, 117100, 180400, 61500, 154900, 54900, 225000, 59900, 123300, 99300, 63000, 136000, 57300, 93900, 127000, 50800, 102700, 133500, 93200, 150900, 113300, 111000, 53300, 85600, 68800, 54000, 181900, 193000, 76500, 70500, 50900, 62100, 113600, 66700, 49800, 182900, 51300, 71000, 67100, 51800, 61300, 68500, 67500, 153900, 98200, 69700, 101100, 61700, 55700, 62800, 61100, 57600, 204200, 57400, 56400, 56800, 188400, 79500, 115600, 46300, 62300, 63200, 60500, 61200, 94900, 59400, 85900, 63800, 61100, 131300, 86500, 59400, 80800, 64100, 58000, 59100, 47300, 67400, 57500, 62400, 95200, 65600, 57600, 171100, 62300, 54100, 60900, 97200, 65000, 45800, 61200, 64300, 43300, 32700, 62100, 69500, 58400, 61600, 223700, 41200, 60800, 91500, 226800, 58200, 89200, 64800, 63200, 71900, 52400, 59600, 52000, 39700, 65600, 148900, 59600, 50000, 136800, 62900, 64100, 58900, 135400, 63099, 58600, 53200, 55599, 117800, 73300, 70900, 72100, 55100, 72400, 67200, 53600, 55000, 63800, 56000, 53600, 54000, 68900, 51200, 57500, 56700, 54700, 56100, 53700, 58200, 135500, 57300, 182200, 57900, 85200, 121100, 58600, 111300, 60199, 55300, 57500, 118400, 222000, 123200, 193400, 131300, 77300, 57800, 70300, 58400, 63099, 118900, 79200, 52800, 74600, 58600, 172100, 86500, 55400, 65300, 57500, 60100, 50000, 110200, 54400, 49600, 51900, 62100, 66100, 63000, 44900, 67200, 59400, 54800, 56200, 179700, 56600, 63900, 56900, 54900, 59800, 58500, 55100, 55000, 56100, 57100, 146400, 83200, 54500, 57600, 53600, 56600, 57200, 56200, 110200, 51700, 87300, 57200, 73700, 57000, 58600, 58700, 177800, 54400, 60599, 58000, 53000, 68400, 147200, 103600, 53900, 56100, 54700, 57699, 155400, 57400, 225799, 56100, 202000, 52100, 55900, 80100, 59300, 59000, 89200, 65300, 86100, 78400, 58900, 63500, 63900, 55000, 55599, 64700, 68200, 53200, 60900, 93600, 132900, 67000, 61400, 64600, 42600, 93500, 54800, 55900, 56100, 54900, 59600, 58800, 137400, 87500, 59300, 54400, 51500, 183200, 57200, 55900, 65000, 58000, 50500, 48700, 58600, 60500, 140700, 122500, 192500, 65300, 122600, 59600, 162700, 106700, 61300, 60599, 57699, 74400, 55100, 49600, 49800, 190300, 80200, 81600, 58000, 128100, 40300, 64900, 81300, 61900, 55199, 59900, 59100, 57000, 55800, 57600, 56300, 68800, 69300, 58800, 145700, 58600, 164700, 61000, 55700, 168000, 139200, 167700, 172000, 65600, 155200, 46200, 84200, 64000, 54000, 51600, 54200, 95000, 47200, 58900, 140400, 53400, 52400, 56500, 51500, 223800, 181600, 65800, 92700, 114800, 169200, 138500, 59300, 60300, 87100, 63600, 83000, 53600, 55300, 53600, 140500, 155100, 66700, 56000, 57699, 60900, 173700, 84700, 86100, 104700, 65700, 61300, 38600, 57500, 59000, 61100, 57100, 57000, 77500, 58800, 173800, 73600, 71200, 69400, 61200, 60400, 55100, 60599, 53800, 58500, 57400, 59200, 58099, 62600, 57699, 168800, 72600, 58800, 65400, 35800, 152500, 32000, 60100, 60300, 57200, 223900, 55900, 54200, 147200, 55700, 57300, 68800, 56800, 60100, 58200, 58600, 56100, 74800, 54500, 70600, 49400, 132700, 56700, 57300, 57000, 189800, 46300, 86100, 58700, 62500, 38900, 74000, 65500, 73200, 188900, 71000, 60199, 81700, 50100, 221900, 52500, 53099, 163500, 61000, 69000, 51800, 51200, 197600, 56600, 61600, 68800, 56900, 59700, 47800, 54600, 54800, 62200, 69300, 52300, 36000, 213600, 56600, 94200, 52500, 39100, 49600, 181000, 64200, 57300, 60100, 169800, 54400, 55400, 62600, 112700, 118500, 58000, 61100, 52600, 85800, 84400, 57600, 58800, 62200, 75200, 95900, 51800, 60100, 56500, 87300, 54300, 56300, 51500, 68300, 56700, 49100, 56800, 127700, 59400, 54100, 66900, 50900, 94900, 62900, 56700, 71300, 55700, 57600, 184300, 100500, 63000, 39000, 69400, 65100, 32000, 69300, 113500, 60000, 80100, 87600, 62100, 216000, 74700, 64300, 65500, 61700, 54100, 135300, 73100, 55100, 61500, 59200, 60900, 63600, 62200, 105800, 63500, 49500, 214600, 63400, 59900, 95600, 62000, 64000, 58099, 63300, 35500, 58700, 63300, 44200, 55599, 56000, 32000, 60199, 57000, 86100, 74700, 49600, 59100, 57400, 65400, 55900, 60700, 53200, 177300, 53200, 52100, 92700, 74300, 73900, 129600, 64500, 52699, 56000, 60800, 58300, 76400, 57000, 65500, 177100, 66800, 49900, 58900, 57300, 66700, 58200, 61600, 62100, 68200, 55199, 64300, 53500, 60199, 60700, 47600, 57000, 94400, 95200, 59600, 61200, 161400, 51800, 56900, 59000, 165500, 69500, 61800, 62600, 205200, 52600, 58800, 61100, 55599, 58600, 53900, 60400, 53400, 115399, 50100, 58700, 56300, 37900, 61800, 63400, 75100, 52400, 59800, 113300, 210700, 55800, 138900, 59600, 185300, 102700, 42100, 54900, 87200, 40900, 58200, 135400, 51700, 62500, 171300, 109000, 59800, 102700, 62600, 77800, 198400, 61200, 65400, 55100, 153700, 165900, 62000, 58600, 71000, 56500, 63099, 40900, 83200, 60599, 73800, 59800, 70900, 58500, 61300, 56300, 55100, 58000, 57800, 38000, 53500, 61800, 53800, 55500, 54300, 56000, 54700, 55700, 71500, 179800, 53500, 64100, 58400, 63700, 55500, 54600, 60800, 64300, 58800, 56600, 186600, 58200, 61500, 35100, 60100, 212399, 58600, 171800, 58300, 96700, 56900, 66400, 60300, 58500, 71300, 65100, 56300, 59600, 196000, 57800, 60000, 42600, 181600, 57300, 195500, 54200, 55400, 61500, 44500, 55000, 56300, 66700, 52699, 143500, 54400, 58400, 56300, 53300, 191900, 38000, 76000, 111000, 198900, 160900, 54500, 55400, 56100, 55000, 81500, 57100, 119400, 74200, 55700, 70200, 57600, 58600, 134700, 53000, 55100, 60199, 224100, 58000, 62500, 56500, 134200, 60300, 73800, 209400, 57000, 55900, 62200, 55900, 57500, 159200, 61200, 55300, 168000, 55700, 55300, 219200, 76600, 128800, 211000, 87500, 58600, 57500, 56300, 202600, 56200, 61100, 56800, 153900, 88400, 97400, 166600, 54900, 220000, 81800, 98600, 66900, 86500, 152300, 59100, 86400, 73100, 55000, 57100, 54800, 65500, 138200, 177700, 51600, 108699, 67000, 61500, 45500, 58500, 55400, 133800, 59200, 213100, 66600, 122100, 97100, 92100, 135300, 49600, 73000, 58200, 51900, 61400, 60700, 58099, 53300, 192600, 55800, 121500, 139700, 40100, 115700, 54300, 56000, 58400, 54400, 57699, 98800, 214800, 161400, 39300, 56900, 41700, 57000, 39600, 65600, 56600, 65900, 219100, 55800, 54300, 56300, 52600, 61100, 60800, 65500, 53700, 57100, 54800, 52500, 46500, 50900, 55199, 46300, 57100, 56300, 58900, 53500, 59800, 217399, 59300, 185900, 43300, 59000, 51700, 133000, 75300, 58000, 57699, 97800, 117400, 57200, 185500, 53800, 56700, 115600, 170200, 65900, 79000, 55199, 100000, 96700, 123699, 76700, 169400, 136700, 71400, 61000, 127400, 58800, 62400, 48400, 44200, 55599, 91600, 67000, 55599, 62800, 58000, 65600, 61700, 59300, 54300, 201700, 62699, 108400, 64100, 71100, 59900, 56300, 227900, 54100, 53900, 61700, 165200, 59100, 115800, 62400, 92400, 55599, 59500, 58800, 60500, 57400, 80700, 58500, 56500, 59800, 60400, 63300, 55199, 118900, 63500, 195000, 54700, 53099, 67100, 55700, 219200, 56900, 70300, 156000, 83600, 95100, 210200, 67000, 48000, 56700, 172100, 59400, 62800, 195400, 133800, 44800, 54900, 57300, 63000, 95000, 57600, 32000, 138600, 71000, 61200, 73500, 53400, 194800, 56900, 49200, 51900, 60300, 60900, 57000, 116100, 61300, 81000, 205000, 57800, 117000, 61300, 51800, 54300, 58600, 57800, 61500, 82400, 55900, 156600, 59300, 227800, 55000, 54400, 52000, 58900, 54100, 55599, 177500, 92500, 57100, 148600, 53400, 52200, 113200, 57300, 87100, 227100, 215200, 195700, 144300, 91500, 148700, 91100, 198200, 52600, 108500, 90700, 68600, 56500, 174600, 103400, 215600, 60500, 41600, 102899, 81100, 121300, 79200, 67400, 64400, 109400, 57000, 61400, 54800, 56300, 41500, 175700, 140300, 61000, 68200, 59700, 84600, 43300, 82600, 112300, 34900, 168200, 71700, 79800, 60800, 79500, 61700, 60800, 54800, 69300, 60100, 64100, 64500, 52100, 58600, 58900, 56200, 65500, 58700, 70400, 216700, 103400, 62699, 64600, 66600, 56300, 66300, 73800, 50500, 170100, 122000, 55300, 56000, 58099, 126500, 52200, 147000, 65900, 193200, 115300, 62600, 65900, 202300, 52800, 53900, 101000, 95000, 53700, 73300, 84400, 227900, 54300, 93200, 60500, 38400, 57300, 61400, 170400, 224500, 57100, 95000, 53400, 208900, 138800, 73200, 59600, 223600, 70400, 111900, 72900, 100500, 76000, 71600, 68000, 71100, 67700, 75900, 74200, 72800, 66500, 69400, 66200, 59400, 61000, 52300, 62900, 71200, 55400, 67000, 59300, 63200, 64500, 65100, 222600, 183400, 59600, 40400, 55599, 58500, 125000, 64700, 115399, 66400, 54500, 81700, 124400, 60500, 56300, 53900, 32000, 64200, 64800, 58300, 56800, 65000, 62800, 62300, 53200, 58300, 61300, 58600, 64400, 58099, 55700, 158400, 155100, 49700, 170000, 213500, 75600, 162300, 59900, 47000, 223600, 187300] - }, - { - "label": "Width", - "valueformat": "#0x", - "font": { - "color": "blue" + "header": { + + "values": [ + ["Height"], + ["Width"], + ["Cylinder"], + ["Weight"], + ["Cost"], + ["Penalty"], + ["H/W"], + ["Min H/W"], + ["Diameter"], + ["RF block"] + ], + + "align": ["center", "center", "center", "right", "right", "right", "left", "right"], + "valign": ["top", "bottom", "middle"], + + "line": { + "color": ["white", "white", "red", "white"], + "width": [0, 0, 0.5] + }, + + "fill": { + "color": ["black", "lightgrey"] + }, + + "font": { + "family": "PT Sans Narrow", + "size": 16, + "color": ["white", "grey"] + } }, - "range": [0, 700000], - "values": [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 436900, 373600, 268630, 439000, 381800, 491200, 402800, 381400, 485600, 600000, 372200, 394700, 383800, 401100, 356500, 313200, 487100, 490700, 432299, 530300, 521500, 456700, 333800, 343200, 394000, 328200, 487700, 383600, 317700, 324600, 482900, 515100, 500100, 562700, 486000, 453400, 352900, 331300, 496200, 469099, 472500, 354700, 507700, 509000, 439300, 525300, 347600, 379000, 432800, 378800, 383200, 523800, 600000, 313600, 497700, 411300, 420000, 381100, 342800, 385900, 268630, 495800, 488000, 446400, 397900, 373300, 385700, 396500, 475700, 510600, 586800, 596000, 407600, 439200, 440800, 393100, 274600, 291900, 509799, 432800, 303000, 530600, 515900, 376800, 377400, 553500, 433600, 270800, 288000, 488000, 306800, 418000, 456900, 526300, 524500, 524000, 418800, 442800, 443200, 497200, 427500, 510300, 476000, 382700, 472200, 380400, 472900, 541100, 528200, 441599, 374600, 414099, 437299, 272500, 550000, 417299, 443700, 268630, 545800, 403400, 534400, 557200, 545200, 537400, 464300, 571200, 589400, 564000, 466500, 514500, 433200, 293600, 550100, 466599, 450100, 557200, 489000, 512200, 445600, 531000, 504400, 459799, 528800, 579800, 352900, 520700, 532000, 477900, 395600, 478900, 461300, 481400, 507500, 487200, 522299, 496000, 499600, 485200, 491500, 548300, 526000, 489600, 444000, 500900, 527600, 533200, 450000, 566500, 486300, 500700, 534900, 493000, 481100, 482500, 490900, 510200, 584700, 560700, 492000, 474600, 495300, 594100, 433700, 522500, 513100, 507500, 488100, 506400, 510400, 482700, 500400, 532000, 477700, 369600, 491200, 499400, 489200, 509099, 513600, 479600, 507299, 547600, 415300, 485900, 410400, 507700, 546700, 503300, 503600, 547700, 509200, 522400, 319700, 517200, 473000, 506800, 511400, 559200, 537900, 515300, 487500, 519000, 361100, 270800, 519000, 518200, 508200, 503900, 516500, 508600, 504900, 506500, 505300, 522000, 507500, 521400, 504600, 521400, 418700, 516700, 508400, 515400, 387000, 522299, 557300, 516599, 510600, 383600, 514700, 516700, 515600, 528200, 491500, 517900, 505000, 430300, 425300, 517800, 512600, 511599, 511300, 501599, 519099, 359700, 522400, 510400, 501100, 524600, 516000, 513800, 503100, 517000, 511400, 513700, 504000, 506900, 517000, 535700, 572700, 497900, 501900, 512600, 513800, 515000, 520700, 295100, 509700, 522299, 338800, 521300, 517200, 519500, 520800, 509300, 520700, 356000, 523000, 513600, 525100, 515700, 510000, 528300, 565200, 509300, 515500, 526900, 514200, 522200, 518500, 557400, 565100, 530700, 511100, 538200, 483700, 588800, 285200, 569100, 520800, 406300, 278300, 569500, 513900, 289000, 519600, 513600, 526900, 525500, 530300, 502000, 480000, 518500, 513000, 516900, 507000, 534300, 520400, 488500, 536000, 518900, 519000, 509400, 535500, 533600, 384900, 542700, 517200, 535700, 520500, 517100, 538700, 525900, 524200, 517100, 523600, 512900, 542400, 306800, 544600, 516599, 582200, 519900, 510900, 427200, 521300, 525900, 438200, 523500, 480000, 519600, 325400, 523300, 525200, 526500, 516400, 523800, 525400, 518700, 530800, 526400, 524400, 566400, 519500, 519700, 518400, 580400, 520600, 567600, 585000, 519300, 524300, 520800, 520900, 533400, 529500, 583500, 531400, 450000, 557600, 420700, 402900, 524500, 518700, 521800, 316400, 497100, 518900, 504400, 539400, 507000, 339700, 493800, 496700, 517500, 523400, 524400, 526200, 311300, 519200, 327600, 520400, 524800, 526400, 519200, 485200, 361000, 519300, 574400, 330400, 511800, 511200, 592800, 520900, 390400, 322200, 524600, 513300, 542400, 517200, 527300, 512700, 516100, 570800, 508900, 523500, 543500, 513700, 519700, 469000, 557400, 515000, 511000, 382700, 521400, 497900, 571100, 514099, 461100, 505600, 563300, 509200, 446300, 458000, 518000, 316500, 525600, 515700, 468600, 516300, 515400, 499000, 487500, 486900, 519099, 270200, 290900, 518000, 509900, 519300, 517299, 468700, 582300, 517200, 461100, 558600, 490500, 499099, 507100, 517600, 535200, 512100, 375300, 506100, 502200, 519600, 559900, 531200, 508100, 553600, 510700, 538600, 525200, 286400, 581800, 534900, 503500, 345400, 428300, 539400, 552000, 523400, 516300, 514099, 519200, 515800, 508000, 500400, 374900, 529900, 527100, 600000, 309600, 583500, 600000, 376000, 473900, 484799, 419300, 287200, 596600, 464600, 398900, 383900, 487000, 431900, 490700, 600000, 381100, 515800, 381500, 540900, 539100, 416500, 428800, 439300, 441300, 496000, 550800, 414300, 422100, 598200, 387800, 561100, 364000, 359700, 523400, 455300, 600000, 380400, 424000, 458600, 382500, 401100, 425100, 550500, 436599, 493200, 393200, 437900, 401100, 386300, 432299, 444799, 428200, 368800, 415700, 369900, 413400, 413000, 482100, 436000, 368600, 369300, 401300, 400400, 418300, 432299, 278800, 436100, 411800, 431300, 551100, 406300, 541500, 404200, 547200, 437000, 390200, 417900, 415800, 460600, 434900, 442600, 309300, 452000, 272200, 459700, 423300, 414799, 468900, 429300, 436700, 427400, 438800, 421100, 421700, 434000, 470700, 474799, 521599, 414400, 307300, 416700, 579600, 432400, 566100, 416200, 432500, 483100, 373200, 494799, 507400, 489700, 440800, 389200, 436599, 418000, 446500, 450700, 445200, 594100, 443900, 489000, 493300, 448900, 449700, 406000, 437400, 278100, 453400, 509500, 433000, 431200, 308600, 507500, 452500, 524700, 451700, 468700, 423600, 447200, 472600, 418500, 466000, 457000, 442299, 455000, 458400, 463800, 450900, 452900, 544200, 456500, 521700, 490900, 457200, 502500, 499099, 446800, 597000, 440600, 478700, 428700, 556900, 498300, 442000, 437900, 419000, 486000, 490700, 463000, 505500, 496700, 486200, 528300, 434200, 502600, 502400, 477800, 470500, 533400, 520700, 508400, 346400, 498900, 511300, 486900, 499300, 508100, 545700, 458400, 524300, 504700, 497299, 454300, 501100, 499900, 497800, 506900, 494500, 501000, 515300, 515000, 505300, 520200, 524099, 502600, 483000, 413400, 562300, 511700, 523500, 478800, 514600, 511100, 505500, 505300, 519099, 499600, 506900, 510500, 519900, 512400, 520400, 504500, 500900, 433200, 515900, 500700, 517100, 508200, 505900, 498900, 274800, 523200, 518100, 434600, 491100, 439900, 508300, 338800, 513900, 464600, 524000, 511100, 565900, 503700, 331700, 484200, 533800, 530700, 519799, 544000, 513200, 466100, 484799, 537100, 541300, 513500, 515100, 495600, 580400, 514600, 517000, 519600, 552000, 538400, 399700, 448000, 522100, 503600, 353100, 511300, 515700, 487700, 421700, 509200, 600000, 422400, 523700, 526700, 513000, 521500, 516400, 518100, 513300, 516700, 524400, 499099, 517299, 428600, 514700, 540300, 507500, 517200, 464900, 519099, 512100, 537200, 440900, 507900, 522500, 514799, 513900, 523500, 510100, 525100, 548400, 361100, 512700, 518100, 524400, 588900, 527800, 528500, 341500, 500100, 510300, 516000, 504200, 502900, 424200, 506599, 502700, 511000, 512200, 524099, 595200, 415700, 460400, 361800, 519700, 514300, 527300, 516900, 512900, 532100, 514900, 312800, 510400, 515100, 518500, 383900, 269400, 547800, 515000, 515100, 514300, 518700, 316300, 508700, 503200, 512700, 511599, 515500, 506599, 384900, 362200, 527700, 527500, 515600, 510100, 289800, 517400, 510600, 531900, 513800, 530100, 517600, 522700, 522900, 525700, 376000, 520100, 512100, 513900, 512400, 528600, 521900, 498500, 530200, 514700, 494200, 315900, 527900, 514700, 521599, 521599, 526700, 516400, 507900, 542600, 518600, 521500, 523500, 459700, 513400, 517900, 515400, 521400, 512900, 517600, 522100, 274700, 520800, 511599, 517000, 428600, 520500, 519799, 522800, 526400, 506700, 514000, 513100, 517900, 520200, 517600, 583600, 526800, 524400, 523900, 515900, 523300, 498700, 524200, 519200, 517500, 525100, 549400, 526000, 517200, 516900, 520700, 521000, 521300, 525700, 527200, 519400, 518600, 516900, 519600, 517400, 496300, 527400, 322400, 518300, 519200, 518400, 523400, 523100, 516599, 516100, 517900, 512500, 514600, 519500, 514200, 517600, 520200, 519200, 515200, 520100, 517000, 519600, 509900, 520900, 519799, 519900, 518200, 512400, 517700, 526200, 516700, 519799, 519900, 382200, 518900, 520000, 518200, 488700, 523600, 522299, 522299, 521900, 295200, 511599, 499400, 526900, 572800, 478500, 570100, 520000, 516599, 530600, 509799, 526000, 512000, 491599, 530200, 581800, 525800, 529700, 522200, 598700, 517400, 508500, 510200, 428700, 522200, 507100, 517299, 527600, 534400, 526500, 520700, 486900, 526200, 525600, 514799, 510400, 514900, 529600, 520100, 330400, 520800, 401100, 520600, 516000, 525100, 388800, 404700, 525800, 526400, 480100, 525700, 515300, 391100, 518100, 431599, 527800, 430300, 517400, 518700, 523500, 512400, 514300, 516100, 517299, 508200, 520900, 527200, 296700, 514400, 520100, 289600, 513900, 528000, 522700, 527600, 308500, 415200, 522800, 527500, 402800, 521400, 523300, 518800, 521200, 522200, 547400, 525300, 522800, 518000, 524800, 518300, 518300, 534100, 518400, 530400, 512800, 520500, 524900, 522500, 520200, 537200, 307300, 517200, 527300, 514099, 557900, 521599, 525600, 492800, 533800, 359300, 522299, 546000, 514200, 401500, 475200, 523900, 394000, 517800, 525400, 517600, 382800, 513200, 414900, 519000, 517100, 525300, 421700, 515300, 453800, 522299, 525300, 522200, 297000, 402100, 440400, 462900, 517700, 514200, 522299, 526700, 382000, 513200, 519799, 521000, 436200, 516400, 490400, 514099, 526800, 510600, 513400, 509900, 518900, 512400, 500400, 521700, 517100, 390400, 589900, 327700, 517100, 499799, 565300, 522299, 589000, 495000, 519099, 502299, 433100, 413000, 540000, 503200, 563400, 521599, 553100, 511500, 503200, 558600, 510200, 499799, 510100, 308500, 410700, 518400, 522700, 532000, 502400, 386700, 512700, 538900, 522900, 516300, 396900, 545300, 517400, 393900, 495600, 529600, 552900, 516900, 519300, 521800, 495100, 513500, 583300, 516800, 516300, 526400, 550500, 526300, 517100, 516800, 510400, 525000, 526500, 518200, 414300, 548400, 395800, 447800, 419799, 530100, 532300, 493200, 522600, 373100, 445500, 530000, 520500, 560400, 440000, 297700, 524200, 526100, 518600, 528400, 400700, 503000, 508600, 545500, 555400, 520600, 494900, 473200, 521599, 471700, 509099, 526800, 510800, 525700, 516900, 498300, 595700, 526300, 520600, 525600, 519400, 380300, 514099, 506100, 524000, 321100, 522500, 520000, 520600, 529700, 521800, 510300, 520500, 385100, 522200, 518300, 577600, 588400, 536100, 513100, 518000, 419000, 480700, 392500, 515900, 517400, 353900, 520800, 448300, 511200, 502700, 518500, 512900, 521300, 519799, 535700, 512299, 407000, 517100, 322600, 518700, 297300, 366500, 600000, 515200, 516300, 490700, 408800, 525700, 504300, 509600, 521300, 481400, 359700, 371300, 511900, 504300, 451300, 467600, 507700, 532300, 470600, 516800, 590300, 522000, 526000, 463900, 455600, 518500, 406100, 475600, 529000, 547300, 529000, 531400, 517500, 527800, 526600, 459500, 494200, 500000, 487000, 469000, 511300, 511700, 508600, 504500, 519900, 521700, 522299, 400400, 511100, 513900, 513900, 511100, 408500, 498900, 490600, 559100, 514200, 505500, 506300, 503800, 516599, 524200, 510100, 510600, 505700, 395700, 523100, 506599, 542700, 512700, 366700, 511800, 386800, 397700, 511000, 404200, 518300, 499400, 520500, 511800, 555900, 465500, 268630, 582200, 305800, 500800, 518400, 472200, 512700, 483300, 405400, 573000, 465600, 516500, 476000, 472000, 546000, 496200, 503400, 414000, 516800, 514000, 520800, 523700, 502900, 513900, 515400, 318200, 511500, 469900, 379700, 515300, 504200, 506500, 495500, 523200, 297100, 508100, 525600, 522800, 321100, 507299, 423900, 536700, 394000, 527100, 506900, 515400, 447800, 509900, 490900, 508000, 493400, 523200, 429900, 486800, 522100, 505400, 517299, 506800, 448600, 489000, 496800, 504300, 486200, 500300, 525300, 278500, 501900, 512400, 510400, 530000, 511500, 370200, 507600, 504500, 373400, 485300, 497600, 504200, 501100, 505400, 587500, 373900, 511500, 492299, 560600, 506500, 421500, 506100, 509099, 509300, 508600, 511300, 515200, 376500, 499900, 558600, 500200, 514400, 293900, 470700, 407400, 490100, 375800, 406100, 506100, 520900, 514099, 415600, 506200, 581600, 435400, 512500, 432800, 504200, 513900, 529300, 506000, 507000, 518400, 520600, 515900, 512200, 508200, 517900, 497500, 497100, 523300, 506800, 471000, 500600, 269500, 508100, 512600, 584400, 505900, 425000, 501900, 513300, 526800, 584700, 472500, 287400, 573200, 510700, 492200, 517600, 506300, 502800, 509200, 514400, 508800, 520600, 518200, 515100, 340000, 510500, 521000, 517400, 516800, 519900, 476700, 357200, 514000, 404600, 519300, 514900, 501200, 521200, 559700, 503000, 514500, 518100, 515100, 458600, 519200, 518300, 530500, 501100, 520600, 503800, 521599, 527200, 519300, 534200, 433200, 521599, 512100, 510400, 518500, 511599, 516500, 505600, 594900, 528900, 407600, 510400, 425800, 517100, 508700, 516599, 543700, 520400, 506300, 511599, 523000, 554000, 332400, 379900, 511500, 525100, 513700, 516400, 513600, 503400, 510400, 511200, 352600, 515200, 524000, 382400, 521900, 536300, 445300, 427200, 508700, 523800, 518800, 538100, 470400, 511300, 520900, 518700, 516200, 520700, 526600, 367700, 362200, 507200, 528800, 508200, 380900, 372500, 520300, 521500, 517900, 464000, 525900, 522299, 345600, 597300, 549000, 507000, 508800, 569100, 513400, 511599, 539300, 519700, 517299, 519300, 507600, 523200, 493300, 465700, 577300, 538600, 589000, 460100, 325400, 440200, 552600, 537500, 514200, 528100, 474900, 460000, 463300, 401500, 340400, 340200, 518700, 517400, 560500, 505200, 276800, 510800, 530500, 513100, 515000, 523300, 512000, 510600, 517400, 365200, 596600, 517500, 358600, 515700, 545500, 553000, 505000, 487000, 484700, 349200, 488700, 532400, 436200, 411300, 492600, 477600, 511000, 506500, 517299, 358800, 400700, 555400, 494900, 372200, 507800, 511300, 520300, 542100, 355900, 571500, 552800, 467500, 430700, 339400, 564100, 600000, 478700, 454500, 554800, 458400, 519300, 521700, 484099, 359500, 567700, 535200, 555500, 541900, 520500, 479700, 501100, 533700, 554300, 552300, 379700, 522500, 404900, 508300, 538600, 573200, 532700, 557100, 565900, 518500, 309200, 522100, 538500, 509400, 533200, 539900, 511900, 535400, 519900, 542900, 556800, 523100, 505900, 382700, 527400, 451500, 518400, 479300, 535600, 493100, 516300, 510800, 529600, 274700, 516500, 522400, 470500, 526800, 519300, 401300, 519000, 518900, 441599, 526800, 510100, 349400, 505000, 531900, 461100, 272200, 521500, 514799, 519200, 535000, 424300, 505000, 525600, 510500, 375100, 407500, 408600, 425000, 583700, 420700, 508100, 574900, 513700, 324400, 512299, 522900, 552100, 510800, 418200, 498000, 510900, 444700, 528100, 526300, 504099, 521300, 509500, 565800, 509700, 531100, 512400, 506400, 528700, 368900, 346700, 520300, 599300, 519400, 364400, 520100, 445700, 520200, 531600, 504500, 295700, 500200, 513200, 460600, 547600, 481400, 515700, 518100, 499700, 337200, 330600, 517500, 525300, 479000, 460400, 536200, 470500, 516100, 506500, 482200, 507800, 499600, 519099, 504400, 518800, 331800, 498100, 469400, 486200, 518400, 504099, 518000, 399400, 511000, 512200, 571100, 518000, 524900, 447600, 368500, 511200, 382200, 521000, 513400, 515600, 514300, 529500, 519400, 347900, 516200, 522900, 295600, 464799, 514099, 465600, 512000, 522000, 334300, 401000, 522700, 514200, 513900, 459099, 507700, 510500, 316200, 518900, 550100, 458700, 513200, 480300, 445900, 513400, 519000, 510700, 519000, 448300, 486200, 514400, 441700, 471200, 537400, 381700, 503700, 484799, 485800, 483000, 505100, 496599, 502100, 497800, 518000, 502500, 517100, 363100, 511400, 489600, 484900, 485300, 508000, 419300, 473900, 511800, 505800, 483300, 503700, 501200, 515200, 486100, 589600, 479300, 520400, 517299, 513300, 522100, 451700, 510600, 495600, 434900, 513400, 498600, 527900, 507400, 500300, 489300, 500700, 290900, 432000, 493800, 553300, 327400, 519799, 510100, 501500, 451400, 512400, 504400, 498200, 522200, 517800, 498900, 507200, 508300, 494099, 507400, 485200, 523800, 351500, 529700, 500700, 504500, 386000, 506400, 508300, 491700, 432100, 502800, 357100, 512700, 503000, 560900, 514400, 352000, 333500, 377100, 500500, 450100, 377500, 499799, 303100, 501800, 511000, 356300, 425300, 513500, 418000, 490600, 410700, 543000, 496700, 533000, 520000, 528400, 360400, 504900, 497400, 445000, 508600, 509300, 431700, 387900, 444799, 436200, 496000, 490500, 496900, 499000, 516800, 493000, 498700, 503200, 387400, 512900, 516900, 499400, 519400, 505500, 531300, 510900, 517700, 556400, 538300, 512500, 581200, 497200, 464200, 506200, 515000, 505400, 529900, 506100, 502600, 440800, 505600, 589800, 503100, 504099, 508200, 511700, 497200, 507800, 530800, 495000, 513100, 505600, 500700, 551700, 502600, 501599, 497900, 566800, 511100, 501800, 352200, 562800, 513500, 563100, 503000, 499099, 587700, 512900, 508300, 512700, 591100, 514200, 523800, 511000, 516700, 511900, 514300, 279100, 381800, 511700, 527600, 598300, 434600, 511000, 519900, 522200, 531000, 483500, 519700, 600000, 503700, 505800, 498400, 515800, 516900, 322900, 523700, 511500, 519600, 399600, 518500, 519700, 397500, 484600, 513700, 268630, 315400, 517200, 514500, 505900, 515300, 516000, 473100, 509099, 514500, 301900, 490500, 486900, 380200, 531800, 455000, 425100, 448300, 515200, 527100, 522299, 344700, 514200, 518500, 519099, 497800, 475100, 440200, 459700, 515900, 376300, 304500, 445500, 485800, 375000, 354000, 513200, 309700, 472900, 507299, 516300, 521900, 569700, 546300, 327100, 517900, 578300, 518800, 524000, 386000, 531300, 510600, 378600, 521400, 354000, 520200, 596800, 524200, 557800, 525100, 383600, 433600, 528500, 305900, 526000, 530100, 519200, 523900, 543400, 527400, 310200, 525900, 442000, 404400, 515800, 516599, 558500, 523300, 514200, 479700, 357800, 457800, 380700, 514900, 341800, 524500, 407400, 516300, 532800, 476599, 281100, 520600, 519500, 524300, 527000, 526200, 522400, 488700, 523100, 524200, 536500, 530300, 396000, 514700, 540900, 428100, 531600, 520600, 525500, 525100, 537000, 330700, 552700, 497800, 318000, 537300, 472299, 298100, 377500, 529200, 533300, 531200, 380000, 537300, 583800, 535800, 511200, 379700, 472600, 579400, 444400, 509799, 433500, 430500, 523700, 500600, 277800, 535700, 518500, 530200, 560800, 516200, 522700, 525000, 561000, 531700, 549000, 517200, 522600, 514000, 512200, 516500, 511400, 522600, 519700, 402100, 524900, 339000, 534900, 541700, 546700, 519600, 348100, 527100, 523700, 498600, 535500, 504700, 456200, 509300, 499500, 503600, 517700, 507100, 513500, 520900, 545600, 515300, 525500, 515300, 412700, 550000, 507800, 594700, 275700, 284100, 531200, 524300, 497600, 526100, 424000, 513200, 406100, 520600, 524000, 484600, 590700, 573700, 402900, 521400, 450200, 520500, 366400, 414500, 531300, 404700, 504400, 503100, 531300, 546200, 517299, 348800, 351000, 496900, 513600, 514900, 515200, 393600, 515800, 400400, 521400, 497700, 537300, 484200, 535100, 510100, 426100, 502400, 537200, 305700, 509200, 510900, 516200, 509900, 523000, 490000, 433000, 508700, 337600, 515800, 347200, 507700, 498500, 514099, 498000, 521300, 513600, 467700, 597800, 512600, 535700, 517600, 510400, 361500, 508400, 550900, 367600, 326100, 352700, 579200, 483200, 352800, 434600, 462100, 510700, 564600, 600000, 268630, 519400, 565500, 555200, 466900, 521900, 390200, 552600, 512000, 563600, 513800, 519600, 439900, 383100, 544900, 522200, 525900, 529000, 361000, 420000, 490000, 522000, 410200, 540600, 563200, 493900, 507500, 523200, 600000, 556000, 453800, 507800, 517100, 504300, 532700, 512000, 529500, 501800, 467100, 515700, 526900, 522299, 534600, 511400, 522400, 508400, 554200, 512900, 341500, 455800, 525300, 509400, 524099, 519400, 471200, 597300, 448200, 402800, 519300, 537200, 513000, 532300, 529800, 535000, 522700, 516200, 455400, 429700, 479799, 516400, 359000, 518400, 520400, 427200, 536700, 515900, 576100, 518100, 320200, 297400, 368200, 432600, 571800, 517600, 515400, 534900, 474200, 513300, 530600, 524099, 399500, 497299, 507500, 516500, 362100, 471800, 480600, 538100, 500400, 515800, 518200, 522000, 498000, 538500, 440800, 533600, 514300, 538000, 552600, 556500, 512000, 523900, 514099, 505700, 535800, 505900, 485100, 515300, 503500, 510400, 492200, 462600, 375000, 511599, 384700, 514500, 516400, 414300, 577900, 320200, 513300, 504300, 522200, 308000, 521500, 531300, 499300, 535800, 502600, 509300, 505600, 545000, 453800, 505700, 502000, 526500, 452900, 522100, 510900, 503100, 523600, 526500, 512800, 272000, 427299, 365300, 554800, 590700, 407900, 475500, 575700, 412299, 351000] - }, - { - "label": "Cylinder", - "tickvals": [0, 0.5, 1, 2, 3], - "ticktext": ["A", "AB", "B", "Y", "Z"], - "values": [0, 0, 1, 0.5, 2, 3, 3, 0, 1, 1, 2, 2, 3, 0, 0, 1, 2, 2, 3, 3, 0, 1, 1, 2, 3, 3, 3, 0, 2, 3, 1, 0, 1, 3, 1, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 3, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2, 0, 3, 0, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0, 3, 1, 1, 3, 0, 0, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 3, 2, 0, 2, 2, 2, 0, 2, 2, 2, 3, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 3, 2, 0, 2, 0, 0, 3, 0, 2, 0, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 3, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 0, 2, 3, 3, 2, 2, 0, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 3, 2, 0, 2, 2, 0, 1, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 3, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 0, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 3, 0, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 2, 1, 0, 2, 0, 2, 3, 2, 0, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1] - }, - { - "label": "Weight", - "visible": true, - "valueformat": ",.2f", - "values": [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797, 377, 1327, 462, 1009, 166, 1415, 1118, 1063, 593, 498, 959, 1331, 1146, 645, 921, 1596, 663, 568, 492, 833, 630, 445, 504, 394, 647, 314, 1039, 829, 911, 282, 925, 681, 581, 506, 368, 373, 628, 538, 418, 419, 478, 884, 847, 369, 410, 344, 396, 501, 510, 379, 733, 1649, 239, 1035, 1839, 967, 514, 875, 794, 414, 664, 447, 839, 540, 636, 499, 1059, 743, 173, 473, 519, 465, 623, 726, 631, 521, 643, 323, 424, 472, 657, 510, 521, 661, 690, 497, 1664, 2162, 828, 1062, 479, 1452, 574, 604, 1069, 766, 268, 369, 755, 644, 811, 636, 363, 375, 359, 378, 336, 413, 680, 431, 361, 493, 761, 412, 386, 339, 628, 390, 648, 611, 323, 369, 555, 142, 2133, 653, 392, 597, 740, 345, 345, 1211, 600, 396, 369, 390, 481, 498, 371, 337, 316, 363, 676, 330, 353, 527, 352, 329, 341, 349, 334, 357, 501, 363, 1066, 284, 307, 338, 367, 327, 901, 330, 367, 311, 543, 370, 355, 318, 398, 335, 346, 382, 337, 807, 365, 349, 350, 415, 346, 330, 337, 330, 2201, 489, 338, 322, 349, 744, 239, 327, 327, 317, 763, 303, 343, 334, 293, 298, 472, 558, 331, 769, 321, 315, 342, 2161, 325, 1667, 493, 328, 878, 328, 737, 315, 325, 317, 529, 727, 390, 320, 953, 729, 300, 538, 663, 333, 320, 309, 596, 591, 325, 300, 709, 303, 312, 501, 737, 306, 360, 320, 1585, 324, 196, 294, 827, 305, 316, 415, 557, 302, 550, 332, 289, 730, 319, 324, 369, 335, 532, 422, 315, 1423, 1091, 320, 323, 358, 307, 314, 317, 218, 414, 299, 323, 371, 322, 314, 311, 338, 310, 324, 319, 674, 305, 366, 356, 316, 338, 352, 343, 339, 327, 497, 323, 780, 427, 346, 311, 319, 307, 343, 312, 1695, 329, 293, 316, 429, 341, 315, 548, 330, 307, 331, 321, 427, 319, 530, 516, 310, 344, 724, 479, 2748, 667, 977, 426, 696, 755, 944, 474, 331, 314, 319, 381, 294, 282, 302, 264, 370, 449, 314, 1029, 318, 312, 706, 349, 508, 297, 293, 322, 531, 480, 396, 286, 367, 315, 308, 365, 302, 467, 302, 313, 421, 351, 295, 792, 296, 651, 305, 1207, 501, 325, 311, 302, 290, 693, 312, 681, 474, 296, 321, 305, 322, 312, 317, 453, 322, 312, 550, 331, 334, 297, 560, 324, 812, 311, 320, 336, 533, 316, 1305, 502, 857, 329, 1089, 521, 495, 1025, 316, 373, 301, 935, 685, 547, 311, 622, 851, 880, 175, 331, 343, 1122, 314, 494, 211, 329, 228, 307, 306, 302, 312, 324, 549, 354, 390, 443, 305, 303, 1364, 320, 352, 412, 328, 522, 1509, 303, 314, 326, 304, 376, 297, 354, 305, 303, 309, 324, 543, 1231, 306, 865, 477, 388, 388, 603, 532, 310, 1249, 321, 162, 431, 346, 880, 355, 789, 320, 383, 317, 317, 571, 324, 321, 810, 1075, 329, 363, 310, 385, 322, 1005, 344, 1169, 526, 286, 328, 558, 295, 505, 339, 608, 526, 352, 312, 391, 933, 448, 590, 411, 463, 391, 697, 1113, 327, 604, 845, 1066, 330, 435, 750, 325, 709, 523, 315, 353, 882, 736, 456, 1111, 1050, 454, 955, 1728, 423, 796, 793, 1348, 761, 970, 668, 459, 386, 783, 276, 820, 708, 501, 764, 445, 492, 464, 496, 419, 967, 1243, 751, 472, 377, 419, 628, 480, 701, 368, 486, 949, 668, 720, 570, 425, 576, 352, 449, 427, 1551, 349, 478, 370, 327, 381, 379, 333, 403, 387, 378, 368, 450, 382, 376, 1184, 330, 349, 416, 435, 381, 362, 362, 426, 379, 372, 345, 841, 432, 952, 441, 238, 313, 437, 392, 763, 719, 376, 370, 679, 387, 531, 591, 352, 377, 174, 366, 340, 383, 361, 341, 335, 346, 392, 390, 731, 477, 861, 419, 1073, 337, 523, 972, 624, 404, 485, 398, 1249, 366, 371, 400, 419, 344, 823, 365, 506, 925, 305, 628, 357, 323, 489, 662, 354, 833, 353, 369, 352, 342, 493, 366, 329, 862, 333, 361, 816, 785, 500, 502, 368, 343, 349, 366, 340, 325, 359, 371, 403, 333, 385, 336, 352, 716, 424, 395, 1525, 338, 342, 504, 392, 808, 362, 327, 300, 1073, 1137, 376, 332, 363, 340, 876, 396, 319, 339, 330, 290, 1026, 452, 339, 286, 336, 873, 514, 339, 363, 883, 334, 324, 331, 324, 324, 326, 313, 324, 325, 332, 313, 321, 309, 692, 296, 312, 303, 333, 649, 697, 374, 294, 357, 313, 316, 294, 316, 422, 450, 321, 331, 302, 713, 303, 335, 321, 916, 350, 313, 307, 313, 1121, 312, 1299, 481, 306, 1072, 304, 622, 970, 310, 310, 980, 472, 317, 535, 328, 898, 661, 386, 335, 320, 337, 309, 293, 1362, 351, 876, 403, 319, 514, 1102, 456, 309, 498, 706, 305, 922, 1655, 330, 284, 915, 305, 319, 522, 546, 307, 502, 341, 358, 450, 324, 314, 322, 320, 321, 388, 307, 297, 310, 605, 358, 1048, 322, 315, 468, 350, 179, 1056, 1079, 342, 319, 345, 348, 314, 329, 311, 488, 775, 318, 312, 510, 884, 776, 313, 304, 488, 329, 294, 501, 315, 381, 348, 450, 299, 414, 481, 1377, 342, 1135, 637, 302, 322, 309, 305, 311, 696, 303, 486, 293, 308, 1131, 541, 295, 1198, 319, 301, 293, 321, 1268, 281, 361, 304, 306, 339, 1439, 618, 644, 359, 302, 319, 297, 690, 327, 299, 300, 305, 503, 326, 309, 367, 392, 964, 325, 291, 317, 281, 386, 282, 281, 366, 351, 906, 198, 294, 733, 442, 350, 315, 359, 435, 1220, 322, 330, 307, 434, 313, 304, 1111, 313, 313, 330, 336, 764, 312, 286, 348, 924, 309, 327, 317, 364, 423, 294, 337, 323, 313, 718, 676, 323, 335, 332, 332, 321, 1004, 340, 324, 296, 312, 512, 311, 324, 306, 308, 313, 310, 367, 330, 317, 311, 307, 308, 309, 451, 312, 169, 320, 462, 316, 304, 314, 324, 311, 303, 316, 324, 316, 364, 305, 307, 332, 628, 303, 336, 305, 318, 305, 323, 305, 289, 314, 309, 274, 302, 326, 469, 404, 331, 323, 301, 690, 755, 327, 322, 299, 470, 319, 246, 692, 551, 327, 369, 334, 321, 694, 322, 313, 319, 758, 494, 536, 300, 483, 295, 407, 289, 330, 314, 212, 306, 312, 360, 326, 335, 310, 461, 1065, 299, 1554, 316, 883, 306, 314, 302, 381, 313, 939, 310, 298, 295, 1040, 613, 365, 317, 842, 311, 427, 322, 315, 358, 313, 356, 307, 305, 727, 303, 343, 674, 300, 314, 303, 311, 694, 456, 434, 320, 422, 307, 293, 311, 149, 510, 314, 704, 1070, 294, 309, 368, 299, 328, 471, 300, 292, 305, 309, 336, 306, 323, 323, 367, 319, 374, 311, 324, 449, 345, 175, 300, 330, 390, 740, 1029, 644, 532, 339, 966, 307, 325, 301, 245, 916, 334, 463, 373, 313, 671, 678, 298, 315, 286, 820, 312, 535, 340, 464, 322, 323, 416, 595, 571, 596, 753, 725, 295, 304, 294, 451, 308, 303, 310, 506, 308, 744, 308, 289, 311, 293, 455, 327, 263, 1153, 1348, 473, 148, 1811, 134, 294, 577, 834, 349, 287, 1848, 316, 1058, 839, 759, 799, 323, 501, 372, 598, 366, 454, 383, 334, 324, 323, 696, 763, 318, 351, 334, 321, 1631, 295, 354, 292, 321, 741, 1141, 318, 722, 320, 311, 303, 302, 323, 335, 442, 310, 807, 338, 324, 341, 958, 301, 327, 458, 321, 319, 318, 337, 670, 1254, 1019, 340, 193, 740, 308, 413, 336, 203, 330, 321, 336, 966, 561, 1178, 323, 329, 582, 306, 202, 455, 305, 1161, 845, 341, 396, 428, 1298, 973, 300, 692, 519, 296, 306, 441, 759, 572, 299, 628, 340, 514, 320, 296, 326, 569, 823, 373, 618, 410, 317, 313, 712, 210, 363, 717, 1324, 1247, 297, 315, 315, 313, 1031, 354, 312, 312, 208, 374, 338, 361, 704, 433, 320, 319, 295, 528, 291, 1356, 520, 802, 369, 856, 954, 612, 286, 316, 440, 901, 413, 373, 375, 301, 462, 645, 414, 356, 554, 2389, 377, 371, 735, 458, 368, 400, 355, 345, 756, 377, 381, 275, 417, 337, 611, 390, 326, 319, 383, 338, 375, 329, 730, 416, 532, 312, 312, 326, 741, 396, 292, 480, 196, 288, 375, 347, 477, 969, 311, 535, 1560, 328, 312, 719, 459, 299, 324, 312, 505, 325, 547, 1029, 342, 908, 308, 999, 336, 568, 466, 353, 645, 324, 518, 722, 285, 613, 699, 610, 1555, 792, 683, 302, 676, 582, 290, 865, 1675, 559, 398, 271, 459, 1523, 366, 276, 882, 488, 562, 381, 295, 339, 543, 381, 623, 551, 367, 459, 348, 309, 350, 335, 328, 792, 320, 323, 324, 767, 443, 567, 380, 290, 362, 337, 345, 483, 560, 467, 356, 334, 749, 631, 321, 460, 356, 328, 329, 241, 366, 703, 346, 515, 362, 465, 841, 344, 304, 341, 560, 364, 355, 381, 357, 194, 176, 341, 386, 322, 342, 1393, 185, 341, 499, 3154, 324, 435, 542, 353, 402, 292, 334, 413, 179, 806, 892, 494, 281, 527, 332, 655, 724, 1253, 300, 326, 302, 701, 570, 408, 669, 360, 466, 795, 373, 301, 316, 355, 312, 303, 307, 434, 287, 321, 321, 300, 686, 306, 324, 716, 316, 875, 323, 479, 751, 326, 547, 371, 438, 329, 734, 1176, 495, 2745, 736, 421, 327, 436, 323, 353, 670, 442, 300, 595, 369, 727, 484, 352, 369, 325, 341, 266, 481, 306, 323, 294, 493, 365, 400, 382, 372, 540, 310, 317, 932, 321, 404, 328, 303, 340, 324, 313, 315, 318, 331, 729, 1063, 306, 322, 339, 317, 455, 312, 693, 332, 416, 320, 362, 322, 327, 331, 1044, 309, 337, 363, 426, 407, 613, 471, 337, 321, 308, 326, 976, 318, 1265, 314, 874, 294, 319, 366, 337, 343, 453, 322, 481, 447, 749, 370, 337, 308, 316, 516, 385, 426, 349, 416, 585, 373, 353, 360, 194, 419, 311, 318, 317, 287, 341, 335, 587, 551, 393, 303, 288, 1113, 322, 313, 863, 329, 285, 276, 327, 345, 769, 956, 1183, 866, 765, 309, 668, 1849, 516, 395, 363, 427, 293, 359, 260, 1235, 339, 465, 329, 725, 242, 361, 302, 347, 318, 337, 333, 325, 313, 544, 318, 304, 436, 332, 638, 741, 969, 362, 309, 909, 751, 721, 934, 535, 1328, 221, 459, 341, 302, 287, 306, 883, 222, 351, 769, 326, 292, 353, 412, 3017, 791, 401, 1250, 603, 839, 584, 358, 381, 465, 455, 495, 609, 313, 305, 1283, 680, 404, 325, 344, 356, 987, 453, 530, 606, 391, 364, 175, 327, 610, 341, 333, 794, 448, 351, 1603, 417, 283, 395, 540, 338, 319, 354, 302, 339, 364, 526, 347, 357, 542, 840, 416, 301, 370, 191, 1251, 174, 512, 338, 329, 828, 721, 309, 777, 319, 325, 325, 322, 341, 293, 336, 314, 321, 303, 408, 257, 955, 322, 323, 323, 1101, 227, 478, 336, 350, 175, 486, 313, 359, 1170, 346, 336, 500, 282, 910, 295, 303, 971, 1226, 335, 285, 653, 1002, 325, 353, 382, 323, 334, 289, 305, 316, 349, 430, 677, 160, 914, 453, 595, 419, 173, 281, 920, 364, 331, 502, 657, 421, 311, 360, 665, 636, 327, 346, 407, 632, 471, 326, 336, 749, 391, 557, 381, 478, 442, 469, 303, 310, 292, 379, 453, 274, 312, 673, 321, 516, 371, 288, 446, 352, 318, 617, 315, 329, 939, 646, 497, 178, 394, 409, 180, 390, 922, 380, 465, 495, 396, 835, 391, 362, 511, 346, 308, 565, 345, 314, 346, 333, 316, 355, 348, 427, 360, 415, 1113, 813, 321, 486, 349, 363, 363, 359, 181, 317, 356, 223, 294, 326, 146, 372, 307, 465, 402, 275, 324, 317, 359, 316, 336, 506, 782, 298, 283, 500, 401, 412, 631, 342, 296, 311, 327, 323, 422, 321, 354, 1106, 357, 399, 333, 322, 380, 298, 345, 340, 340, 310, 354, 307, 336, 470, 258, 315, 361, 473, 326, 553, 666, 1079, 318, 326, 848, 390, 516, 344, 1169, 449, 324, 340, 310, 320, 300, 326, 305, 498, 288, 324, 312, 174, 344, 354, 409, 260, 331, 494, 1185, 309, 835, 336, 801, 428, 190, 303, 446, 185, 321, 532, 286, 493, 746, 536, 336, 499, 340, 373, 1164, 336, 378, 313, 883, 728, 344, 322, 360, 315, 353, 203, 384, 426, 369, 328, 386, 321, 337, 318, 301, 319, 320, 175, 300, 349, 296, 315, 686, 323, 698, 315, 427, 1174, 506, 396, 321, 464, 309, 308, 338, 370, 327, 313, 941, 323, 384, 194, 333, 1186, 329, 1325, 325, 558, 311, 373, 335, 323, 977, 542, 311, 460, 1188, 324, 332, 184, 2534, 322, 1325, 300, 305, 383, 250, 307, 316, 417, 297, 1378, 305, 330, 316, 506, 717, 173, 426, 637, 1256, 803, 305, 314, 718, 317, 439, 324, 755, 411, 310, 386, 325, 331, 550, 302, 309, 341, 1055, 328, 355, 265, 1013, 477, 533, 1710, 322, 315, 346, 719, 324, 844, 342, 311, 700, 424, 419, 998, 442, 664, 1037, 446, 754, 369, 321, 864, 316, 346, 322, 847, 470, 490, 865, 310, 994, 322, 501, 361, 390, 661, 332, 344, 657, 431, 322, 440, 398, 1876, 732, 292, 1528, 380, 351, 209, 476, 467, 1304, 337, 925, 378, 769, 555, 551, 774, 227, 503, 334, 205, 351, 493, 368, 304, 1131, 320, 484, 800, 281, 549, 306, 316, 809, 310, 325, 529, 939, 836, 179, 321, 176, 326, 189, 370, 327, 351, 822, 317, 308, 321, 301, 494, 346, 355, 306, 326, 318, 302, 298, 287, 323, 316, 329, 320, 475, 306, 527, 902, 575, 1023, 309, 520, 273, 723, 341, 373, 334, 854, 534, 333, 1296, 312, 318, 525, 1259, 406, 441, 309, 498, 663, 706, 423, 631, 794, 452, 393, 766, 371, 356, 309, 265, 321, 542, 379, 317, 394, 325, 522, 346, 378, 308, 1310, 358, 457, 372, 698, 799, 319, 978, 310, 307, 339, 959, 328, 598, 491, 509, 463, 337, 328, 340, 326, 475, 330, 323, 337, 290, 375, 308, 747, 310, 736, 315, 303, 369, 536, 1075, 539, 717, 1493, 477, 513, 1314, 409, 494, 454, 881, 337, 278, 2065, 1757, 212, 458, 708, 363, 560, 326, 137, 598, 390, 785, 928, 301, 1965, 321, 232, 295, 751, 354, 307, 674, 343, 398, 1135, 336, 462, 343, 290, 306, 328, 329, 334, 410, 312, 659, 335, 976, 342, 449, 293, 324, 703, 313, 2091, 583, 731, 863, 337, 292, 1122, 320, 784, 1010, 885, 1148, 1264, 492, 644, 454, 1033, 294, 655, 574, 250, 320, 1056, 617, 1132, 344, 192, 611, 686, 732, 672, 382, 449, 500, 474, 350, 314, 324, 182, 856, 1291, 347, 327, 349, 1909, 536, 461, 641, 507, 1004, 369, 445, 344, 441, 356, 341, 315, 855, 315, 404, 370, 297, 339, 465, 732, 366, 349, 396, 918, 534, 359, 508, 380, 357, 388, 465, 257, 805, 975, 321, 315, 335, 1028, 458, 838, 372, 997, 571, 335, 372, 886, 299, 306, 498, 552, 303, 449, 478, 927, 280, 415, 301, 234, 324, 346, 1107, 1192, 321, 548, 305, 983, 763, 455, 337, 985, 372, 600, 476, 555, 429, 612, 387, 391, 394, 530, 429, 410, 387, 412, 395, 333, 348, 294, 350, 413, 308, 361, 334, 350, 361, 355, 1161, 1772, 334, 185, 313, 330, 603, 397, 469, 373, 302, 465, 493, 344, 325, 297, 185, 355, 362, 324, 334, 334, 349, 345, 305, 299, 349, 328, 357, 467, 319, 891, 570, 245, 1310, 1273, 472, 775, 318, 288, 1076, 1412] - }, - { - "label": "Cost", - "visible": true, - "valueformat": "$,", - "values": [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939, 24258, 62488, 27363, 61924, 12511, 106196, 24444, 7443, 9111, 12527, 50738, 9320, 12291, 17571, 9508, 11176, 9142, 7687, 6724, 11219, 17825, 6506, 6367, 4966, 8495, 3860, 12844, 10688, 13026, 4007, 57281, 9790, 7335, 13748, 5358, 5393, 4401, 3769, 5233, 5058, 6047, 6188, 11899, 5297, 5154, 4406, 5061, 7022, 6358, 4721, 7723, 16745, 2651, 14194, 100772, 10504, 7021, 6131, 16730, 2904, 8334, 5968, 5876, 7394, 4454, 6800, 18376, 5204, 2190, 6146, 7013, 6412, 4361, 5082, 8028, 6484, 4504, 3832, 5687, 6174, 4603, 6913, 3651, 4631, 4833, 6532, 97138, 21918, 5801, 7435, 13138, 14597, 6070, 19943, 7487, 5362, 3945, 4907, 5287, 7937, 9998, 7852, 4820, 9385, 4686, 4751, 8594, 5144, 4760, 5899, 4614, 30326, 5332, 5030, 4759, 4429, 17294, 5192, 4542, 9333, 2261, 4911, 34968, 2179, 34658, 16325, 4811, 4185, 9017, 4224, 4435, 14536, 7129, 4772, 4726, 4840, 3369, 7428, 4504, 4316, 4097, 4399, 4733, 4105, 4597, 3691, 4405, 4245, 4195, 4168, 4694, 4421, 3507, 4615, 14408, 3607, 3956, 4295, 4583, 4138, 11128, 4147, 4602, 3940, 5590, 4505, 4377, 4016, 5191, 4199, 4269, 4686, 4375, 9716, 8664, 4371, 4294, 9779, 4396, 4183, 4247, 4112, 129671, 3426, 4257, 4102, 4386, 8822, 3138, 4040, 4066, 3950, 12502, 3787, 4273, 4238, 3678, 3660, 6006, 7725, 4172, 12580, 4056, 3920, 4249, 35461, 4054, 108185, 6568, 4154, 11735, 4090, 8971, 3943, 4062, 3857, 5408, 8982, 5662, 3974, 6673, 18248, 3739, 3770, 8110, 4129, 4050, 3826, 8314, 9053, 4022, 3718, 8838, 3786, 3874, 6244, 18434, 3815, 4491, 3954, 39629, 4009, 2456, 3643, 10976, 3783, 3946, 5151, 3900, 3730, 3854, 7621, 3597, 7909, 3959, 4022, 4585, 4130, 6699, 27180, 3935, 89225, 14401, 3962, 4022, 4459, 3816, 3938, 3931, 3041, 26734, 3722, 4047, 4583, 3998, 3907, 3887, 4191, 3858, 4033, 3994, 11019, 3777, 4482, 4277, 3968, 4237, 4378, 4264, 4212, 4049, 7410, 4020, 12723, 12452, 4283, 3862, 3953, 3803, 4276, 3866, 18642, 4063, 3648, 3901, 27631, 4251, 3875, 3837, 4109, 3808, 4083, 3993, 27553, 3950, 3715, 3617, 3819, 7947, 11786, 3358, 44432, 38355, 6845, 9723, 4878, 11458, 6609, 3321, 4964, 3884, 3963, 8633, 3627, 3471, 3780, 3359, 4582, 28916, 3896, 12827, 3908, 3865, 4945, 4276, 6296, 3685, 3657, 3948, 6513, 6549, 4829, 3554, 4503, 3893, 3820, 4464, 3720, 3270, 3743, 3861, 27079, 4284, 4335, 9658, 3671, 7768, 3772, 15008, 6611, 4023, 3840, 3957, 3579, 8798, 3870, 9817, 3319, 3647, 3955, 3782, 3981, 3845, 3930, 5570, 3975, 3856, 3851, 4094, 4130, 3676, 5579, 4013, 17649, 3704, 3967, 4152, 34352, 3909, 16007, 3517, 56056, 4041, 14115, 3652, 6567, 13776, 3906, 4618, 3729, 6550, 8592, 12494, 3885, 13919, 10616, 12510, 2200, 4164, 4256, 13850, 3877, 11216, 1477, 7529, 3283, 3802, 3773, 3728, 3868, 4104, 7658, 4381, 4671, 6364, 3789, 3774, 16177, 3965, 9465, 5965, 4054, 5330, 15225, 3764, 3865, 4058, 3775, 3758, 3704, 4368, 3729, 3767, 3828, 4150, 3804, 15268, 3815, 11823, 3345, 4872, 4659, 7489, 3729, 3868, 29343, 3997, 2114, 5553, 4292, 12800, 4382, 19742, 4101, 8777, 3940, 3978, 7211, 4103, 3980, 12415, 12316, 4082, 8375, 3841, 8810, 4128, 11997, 4269, 15031, 3683, 3614, 4116, 35845, 3653, 3538, 4223, 8373, 33766, 4411, 3863, 4728, 11456, 5587, 38362, 5111, 29991, 4825, 10478, 13283, 4010, 38799, 11943, 14042, 4038, 5282, 12235, 4027, 11570, 5328, 3914, 4404, 6180, 10126, 10305, 23044, 12414, 6658, 6690, 17090, 5813, 10147, 5552, 14343, 11440, 9605, 8565, 6188, 5280, 5483, 3629, 5741, 8375, 6864, 5353, 6098, 6015, 5678, 6594, 5520, 15985, 8704, 5263, 5731, 5020, 5553, 13258, 6541, 4909, 5117, 6779, 61602, 6992, 8510, 3993, 5627, 4035, 4817, 6048, 5638, 10862, 4568, 6015, 5021, 4284, 5133, 5166, 4381, 5240, 5107, 5232, 4897, 7559, 5099, 5020, 15005, 4330, 4830, 11538, 5852, 5130, 4805, 4753, 9282, 4965, 4964, 4540, 21046, 5789, 15483, 5931, 2900, 4104, 5939, 10136, 12664, 9245, 4934, 4829, 9958, 5014, 8126, 4141, 4664, 5028, 2236, 4825, 4450, 6349, 4727, 4520, 4438, 4538, 5013, 4969, 9032, 29764, 12658, 5571, 12826, 4427, 6303, 6807, 8189, 5126, 6691, 5004, 15571, 4613, 4841, 5437, 5492, 4572, 13590, 4729, 31885, 9172, 3977, 4397, 4489, 4192, 30894, 17398, 4636, 12650, 4567, 4597, 4625, 4501, 8431, 4569, 4265, 10628, 4315, 4627, 13535, 10198, 3503, 6671, 4717, 4428, 4557, 4727, 4387, 4179, 4651, 4798, 4920, 4306, 4756, 4240, 4542, 8949, 27217, 5130, 100064, 4412, 4353, 3534, 4753, 45902, 4727, 4278, 3988, 13557, 14324, 4833, 4152, 4563, 4299, 10786, 10025, 3990, 4245, 4201, 3703, 12584, 5588, 4231, 4049, 4219, 10855, 3598, 4248, 4530, 10756, 4306, 4004, 4135, 4069, 4192, 4082, 3919, 4071, 4059, 4177, 3922, 3982, 3841, 11321, 3668, 3855, 3796, 4226, 8651, 8405, 8613, 3628, 4544, 3889, 3934, 3673, 3943, 27240, 28881, 4011, 4120, 3737, 40767, 3746, 4190, 4026, 9678, 8023, 3928, 3813, 3904, 13989, 3909, 22474, 5945, 3795, 14047, 3829, 8130, 12089, 4416, 3859, 23854, 5822, 3941, 34877, 4097, 6289, 8372, 4738, 4124, 3961, 4110, 3843, 3763, 22330, 4302, 10698, 5011, 3960, 6460, 13165, 5659, 3833, 6159, 8569, 3728, 12430, 17360, 4081, 3556, 12850, 3802, 3962, 5382, 7233, 3823, 5937, 4512, 4425, 5552, 4024, 3882, 3993, 3970, 3997, 4806, 3793, 3723, 3848, 7973, 4442, 12803, 4020, 3904, 6002, 4338, 2233, 17184, 14084, 4271, 3942, 7932, 4327, 3882, 4098, 3837, 5936, 10801, 3953, 3865, 3573, 10508, 19422, 3855, 4313, 3419, 4098, 3648, 3507, 3942, 5038, 4350, 28905, 3717, 26636, 31080, 16310, 4550, 14594, 8871, 3743, 4000, 3809, 3784, 3870, 15692, 3764, 7100, 3653, 3821, 13999, 7394, 4537, 14574, 3960, 3737, 3643, 3972, 8878, 3501, 4511, 3785, 3810, 4214, 92394, 8440, 8972, 4418, 3717, 3955, 3701, 10342, 4052, 3730, 3688, 3796, 6183, 4046, 3823, 4535, 4834, 13248, 4026, 3616, 3936, 3491, 4754, 3483, 3528, 4498, 4365, 11386, 2894, 3620, 18349, 5466, 2455, 3885, 4448, 5426, 14879, 3993, 4086, 3797, 5588, 3885, 3773, 18127, 3875, 3891, 4095, 4159, 11648, 3866, 3565, 4317, 12171, 3823, 4053, 3922, 8253, 27165, 3649, 7753, 4005, 3871, 17967, 44240, 3984, 4138, 4101, 4124, 3966, 12588, 4194, 4016, 3667, 3851, 11327, 3833, 4023, 3798, 3810, 3874, 3840, 8337, 4063, 3925, 3852, 3812, 3820, 3828, 5671, 3844, 2457, 3964, 3237, 3922, 3762, 3880, 4014, 3866, 3752, 3931, 4022, 3918, 4517, 3779, 3801, 4107, 15710, 3752, 4170, 3771, 3965, 3775, 4004, 3779, 3585, 3903, 3836, 3382, 3748, 4032, 3283, 5534, 4099, 3997, 3732, 8711, 18895, 4040, 3984, 3701, 7008, 3970, 3088, 8520, 6614, 4162, 4436, 4138, 3979, 8524, 4013, 3861, 3965, 18961, 6070, 6394, 3698, 5940, 3645, 4818, 3582, 4120, 3910, 2799, 3779, 3893, 4458, 4022, 4108, 3820, 3227, 10985, 3685, 22218, 3925, 10987, 3806, 3865, 3745, 22845, 3873, 12636, 3830, 3697, 3640, 14144, 8228, 4503, 3912, 10683, 3832, 27508, 4369, 3907, 4705, 3860, 4686, 3807, 3775, 11854, 3763, 4259, 10998, 3715, 3918, 3754, 3837, 10320, 29350, 28013, 4806, 27181, 3783, 3626, 3838, 2197, 6793, 3880, 11481, 28248, 3636, 3818, 4555, 3699, 4061, 5737, 3704, 3612, 3780, 3815, 4160, 3795, 3964, 4006, 4520, 3967, 4631, 3837, 4005, 5551, 4224, 2573, 3722, 4063, 25150, 8949, 12712, 7939, 6700, 4162, 13481, 3801, 3966, 3741, 3298, 11662, 4130, 6268, 4621, 3866, 16793, 9268, 3710, 4199, 3545, 8357, 3845, 7090, 4227, 5999, 3976, 3986, 5145, 8848, 7687, 7778, 9672, 18129, 3671, 3758, 3623, 6176, 3829, 3751, 3839, 6623, 3818, 9382, 3824, 3567, 3876, 3648, 3187, 4050, 3274, 14438, 33701, 3315, 2019, 17972, 1935, 3651, 7236, 10042, 4314, 3418, 46207, 3910, 13235, 11016, 5315, 12999, 4040, 6042, 4600, 6015, 4556, 10560, 4629, 4154, 4057, 4028, 10213, 10194, 3936, 4337, 4100, 4017, 17640, 3666, 4336, 3605, 3985, 10013, 13900, 3940, 9771, 4029, 3830, 6681, 3749, 4002, 4144, 28335, 3851, 9628, 4190, 4020, 4209, 11639, 3714, 4051, 29534, 4001, 3943, 3919, 4181, 8921, 15249, 25498, 4413, 2570, 9094, 3781, 5196, 4153, 2806, 4299, 3944, 4153, 11672, 7329, 13429, 3990, 4059, 5928, 3770, 2724, 5689, 3807, 14139, 10239, 7795, 4983, 10307, 16032, 12418, 3739, 8526, 6457, 3656, 3791, 28264, 8997, 7054, 3697, 6385, 4206, 7040, 3971, 3702, 4031, 8243, 47305, 4623, 6289, 26518, 3919, 3896, 17804, 2868, 4490, 17926, 86514, 14833, 3636, 3919, 3900, 4163, 13083, 4797, 3872, 3870, 2921, 4626, 4389, 4492, 8805, 27930, 3981, 3945, 3652, 6474, 3616, 84260, 6441, 11593, 4576, 12714, 13232, 12893, 3555, 3922, 28141, 12058, 5088, 4661, 4667, 3727, 5861, 9001, 5727, 4432, 6923, 39382, 6197, 4625, 16568, 5855, 4562, 4751, 4391, 4257, 9707, 4869, 4715, 17117, 5311, 4147, 6155, 4805, 4006, 3954, 8680, 4167, 23759, 4134, 11938, 26580, 3728, 3886, 3880, 4065, 18544, 9038, 3609, 30977, 2647, 3585, 8622, 4313, 3341, 60270, 3902, 6742, 101532, 4069, 3902, 11753, 5734, 3706, 7359, 3882, 5163, 4062, 7403, 12706, 4274, 11082, 3834, 13857, 4180, 7733, 6289, 4394, 8664, 4020, 6487, 8926, 3545, 7424, 8967, 7105, 15471, 8990, 15930, 3739, 4733, 4080, 3681, 11600, 109361, 35468, 4939, 3449, 29173, 88421, 4596, 3452, 11753, 4978, 36214, 4717, 3650, 4247, 34932, 4724, 9055, 6852, 4699, 6300, 4318, 3863, 4364, 4208, 4057, 11771, 3994, 3980, 3999, 11116, 5528, 7493, 24623, 3933, 4465, 4205, 4283, 6279, 5729, 5893, 4439, 4200, 9248, 4421, 4061, 5686, 4450, 4066, 4108, 3132, 4617, 17583, 4328, 6506, 4535, 30003, 48630, 4313, 3777, 4245, 6884, 4535, 3881, 8812, 4461, 2683, 2233, 4284, 4820, 4040, 4277, 16571, 2554, 4242, 6285, 51154, 4044, 5770, 3800, 4401, 5008, 3647, 4158, 26583, 2467, 20174, 10786, 3461, 3497, 7861, 4243, 16393, 11861, 76828, 4026, 4071, 3740, 17541, 7580, 5092, 4687, 4720, 3266, 13157, 4661, 3747, 3893, 4432, 3893, 3761, 3795, 9961, 3574, 4001, 3976, 3773, 17165, 3782, 4045, 9144, 3962, 50212, 4029, 5950, 8949, 4070, 7221, 8644, 28169, 4062, 8752, 15000, 15842, 44456, 9155, 5309, 4053, 10116, 4046, 4394, 8316, 5514, 3711, 38351, 8468, 10339, 6030, 8029, 4578, 4029, 4222, 3390, 6727, 3803, 20095, 3644, 31728, 4573, 9131, 24869, 4656, 40536, 3844, 3932, 12001, 3974, 9248, 4031, 3798, 4203, 4056, 3876, 3886, 3939, 4057, 9567, 26598, 3804, 4015, 7758, 3949, 29312, 3902, 8209, 7521, 5578, 3987, 4785, 3995, 4079, 4112, 12730, 3823, 4210, 8367, 27490, 4937, 8779, 6457, 7775, 3957, 3823, 4042, 22441, 3978, 15741, 3913, 12279, 3646, 3940, 5004, 4172, 4199, 5890, 4245, 5994, 5525, 18737, 4526, 4310, 3837, 3909, 33292, 4777, 27477, 4301, 5769, 8151, 4658, 4344, 4495, 2657, 5789, 3851, 3932, 3934, 3683, 4207, 4138, 8298, 6530, 8710, 3782, 3585, 13380, 3997, 3900, 49974, 4074, 3540, 3419, 4076, 4261, 9672, 6695, 14148, 50140, 9092, 3985, 9640, 42657, 33535, 8852, 8334, 5261, 3730, 22730, 3339, 76534, 4819, 28020, 4070, 8981, 2923, 4505, 4593, 4316, 3911, 4185, 4135, 4015, 3895, 5559, 3947, 4231, 5169, 4122, 8906, 18540, 11809, 4399, 3866, 11489, 9502, 10162, 11780, 34617, 14012, 2961, 5785, 4343, 3766, 3585, 3799, 14853, 2997, 4256, 9665, 19975, 3645, 8150, 26579, 49058, 11073, 4814, 31254, 7724, 11033, 8315, 4314, 4509, 5916, 28810, 5994, 15238, 3883, 3771, 13249, 9488, 4866, 3982, 4169, 4354, 12208, 5757, 12358, 7437, 4743, 4418, 2405, 4048, 10157, 4252, 4071, 19869, 5500, 4254, 11221, 5164, 4153, 4884, 3785, 4207, 3912, 4325, 3755, 4161, 8314, 3687, 4203, 4409, 5546, 22831, 5131, 3903, 4589, 2432, 80943, 2199, 3585, 4205, 4049, 12623, 11762, 3815, 9929, 3934, 4023, 4371, 3987, 4218, 3830, 4139, 3910, 4533, 3782, 5007, 3306, 23891, 3988, 4008, 4002, 13496, 3002, 5976, 4142, 4357, 2414, 30186, 4189, 4749, 13952, 4589, 4189, 5993, 3502, 13135, 3665, 3739, 11784, 28602, 4450, 3574, 10675, 13041, 4002, 4349, 4771, 4001, 4159, 3482, 3804, 3884, 4343, 9972, 16927, 2221, 12913, 29211, 7041, 27050, 2402, 3485, 11956, 4511, 4063, 3515, 9775, 27027, 3871, 8808, 8094, 8066, 4060, 4286, 26107, 7034, 28205, 4038, 4148, 12288, 5029, 6825, 24260, 30775, 28412, 5946, 3777, 3890, 3615, 4738, 29181, 16464, 3920, 8606, 4059, 5257, 4640, 3570, 6020, 4387, 3958, 40271, 3907, 4062, 12193, 4527, 31964, 2436, 4879, 9400, 2240, 4846, 59578, 8689, 28097, 6135, 9008, 12433, 5015, 4496, 3579, 4307, 3807, 8084, 4643, 3879, 4300, 4138, 4068, 4424, 4336, 6213, 4457, 26961, 14333, 13269, 4073, 6316, 4332, 4492, 8378, 4443, 2350, 4011, 4427, 2909, 3752, 3989, 1997, 8651, 3891, 5882, 5091, 3443, 4074, 3974, 4512, 3921, 4204, 5164, 10883, 3711, 3570, 6328, 5074, 5141, 8367, 4363, 3678, 3889, 4145, 4042, 5286, 3989, 4476, 13140, 4539, 25758, 4129, 4004, 4694, 3864, 4295, 4277, 4463, 3857, 4439, 3782, 4186, 30163, 3261, 3942, 5408, 6214, 4099, 3875, 9581, 15415, 3965, 4083, 10985, 4853, 3614, 4321, 14442, 3146, 4061, 4248, 3869, 4031, 3748, 4124, 3763, 7007, 3547, 4060, 3906, 2375, 4294, 4412, 5156, 3421, 4143, 6916, 14716, 3866, 10080, 4168, 11257, 6132, 2617, 3796, 5781, 2543, 4022, 7851, 3579, 31698, 10449, 7074, 4179, 6623, 4294, 4985, 14197, 4219, 4643, 3871, 10871, 10158, 4303, 4042, 4687, 3933, 4395, 2669, 5223, 26888, 4835, 4120, 4863, 4033, 4234, 3945, 3787, 4005, 4006, 2384, 3737, 4331, 3717, 3897, 11221, 3970, 11405, 3906, 5170, 26275, 5172, 4725, 4027, 29448, 3856, 3820, 4221, 4553, 4084, 3920, 12274, 4041, 4563, 2432, 4168, 14781, 4089, 84860, 4055, 6853, 3917, 4639, 4187, 4046, 15864, 3795, 3896, 29479, 14289, 4031, 4153, 2588, 41096, 4004, 28909, 3755, 3826, 4556, 3108, 3827, 3932, 4954, 3685, 14009, 3794, 4092, 3929, 5161, 10867, 2372, 5304, 7846, 14855, 10527, 3801, 3892, 17953, 3898, 5557, 4010, 8929, 5144, 3868, 4846, 4033, 4106, 7961, 3734, 3844, 4228, 14218, 4070, 4390, 3578, 64666, 30739, 9257, 42766, 3995, 3910, 4320, 11739, 4026, 10762, 4262, 3868, 21774, 27155, 26769, 13667, 5432, 8575, 13691, 5792, 12304, 8357, 3962, 12225, 3930, 4287, 3987, 10619, 5986, 6403, 11136, 3844, 13668, 4749, 6511, 4570, 5367, 9270, 4129, 5042, 6824, 27699, 3999, 28366, 4786, 30493, 10545, 3619, 38201, 4702, 4334, 2851, 30809, 3274, 21828, 4164, 12971, 4680, 9109, 6845, 6667, 9545, 3102, 31606, 4117, 3017, 4334, 31897, 8413, 3756, 13786, 3943, 7094, 9861, 17684, 7372, 3802, 3923, 13130, 3832, 4035, 6716, 13120, 10771, 2451, 3981, 2509, 4019, 2530, 4595, 4017, 4468, 12432, 3922, 3813, 3969, 3716, 31879, 4280, 4485, 3782, 4025, 3901, 3719, 18455, 3560, 3943, 19801, 4049, 3957, 30692, 3774, 3690, 12946, 43153, 12827, 3480, 3642, 3492, 5065, 4683, 8439, 4097, 5979, 7318, 4074, 27698, 3828, 3955, 7204, 80055, 4851, 11026, 3846, 6536, 41579, 8716, 5304, 9580, 9725, 10335, 8879, 9245, 8502, 4393, 7028, 3207, 3943, 6586, 4696, 3914, 9070, 4049, 33617, 4304, 8600, 3814, 81235, 4422, 6506, 4557, 7048, 19991, 3954, 13795, 3822, 3798, 4260, 11751, 4101, 7718, 31546, 6384, 3247, 4172, 4088, 4228, 4035, 5786, 4094, 3987, 4185, 3877, 4554, 3840, 8856, 17877, 11098, 3877, 3743, 4629, 5448, 14210, 5504, 17927, 15188, 5892, 6491, 15609, 4910, 8230, 29322, 11412, 4175, 3866, 34283, 101349, 2855, 3210, 17724, 4466, 6815, 4038, 1938, 8412, 4895, 12817, 23221, 3737, 32782, 3984, 3123, 3650, 12300, 4338, 3889, 8256, 4272, 5260, 14199, 4117, 6801, 4269, 3612, 3803, 4083, 4070, 4216, 5383, 3891, 9386, 4152, 13778, 7919, 3149, 3636, 4064, 11473, 3886, 34380, 6906, 11939, 10572, 7726, 3639, 58427, 3988, 5494, 13997, 12759, 69547, 82624, 6238, 9041, 5960, 13276, 3667, 7896, 6782, 3844, 3967, 12716, 7470, 14500, 4257, 2617, 7419, 4804, 8821, 4705, 4733, 28271, 6839, 30762, 4321, 3868, 3984, 2542, 11350, 13299, 4292, 4368, 4264, 27377, 8775, 5744, 7910, 12689, 12160, 4769, 5551, 4261, 5514, 4379, 4244, 3879, 21386, 4042, 9266, 4556, 3667, 4165, 29895, 11939, 4558, 4237, 4917, 13036, 6889, 4424, 32664, 4694, 8153, 9377, 5507, 3342, 10823, 62847, 3939, 3912, 4122, 66439, 3210, 10350, 4615, 12868, 7511, 4255, 4616, 12370, 3704, 3788, 6565, 6764, 3760, 5382, 5920, 13436, 16417, 5747, 3951, 2810, 4018, 4297, 24861, 15191, 3990, 6731, 3764, 13253, 9573, 10539, 4175, 13712, 4754, 7612, 10652, 6949, 5321, 4285, 4785, 4906, 4827, 33385, 5270, 5091, 4739, 5003, 4787, 4146, 4299, 3657, 4368, 5066, 3848, 4575, 4150, 4381, 4496, 4471, 14916, 29694, 4159, 2529, 3889, 4098, 8034, 4757, 6803, 4640, 3780, 5750, 7248, 4255, 3991, 3723, 2276, 4447, 4513, 4048, 4071, 4323, 4361, 4313, 3757, 3874, 4314, 4087, 4463, 30169, 3933, 11064, 8721, 3231, 14337, 15420, 5613, 10373, 4057, 3450, 14347, 15572] - }, - { - "label": "Penalty", - "valueformat": "_>5", - "values": [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778, 760, 4349, 891, 4228, 123, 10800, 1593, 467, 260, 226, 2940, 803, 689, 420, 422, 1229, 275, 198, 150, 423, 423, 134, 146, 89, 248, 55, 612, 401, 546, 52, 4208, 307, 194, 257, 91, 93, 178, 133, 99, 98, 131, 345, 461, 90, 96, 69, 91, 160, 148, 81, 274, 1332, 31, 667, 11733, 502, 163, 354, 480, 67, 252, 120, 303, 181, 162, 153, 1142, 251, 17, 131, 165, 135, 162, 222, 230, 154, 198, 58, 109, 132, 189, 159, 102, 167, 218, 147, 11969, 2288, 316, 467, 234, 1025, 169, 497, 435, 265, 49, 82, 252, 234, 372, 229, 79, 127, 76, 82, 105, 97, 207, 115, 75, 1014, 259, 95, 84, 68, 404, 91, 183, 273, 49, 82, 1378, 14, 5405, 769, 86, 168, 308, 67, 69, 818, 200, 87, 79, 86, 100, 174, 77, 66, 58, 74, 206, 62, 73, 129, 71, 63, 65, 67, 71, 72, 116, 76, 696, 46, 55, 66, 77, 61, 460, 62, 77, 55, 146, 77, 71, 58, 93, 64, 68, 82, 66, 364, 113, 69, 69, 145, 69, 62, 65, 62, 19984, 113, 65, 60, 69, 307, 33, 60, 60, 57, 676, 52, 67, 64, 49, 50, 129, 196, 63, 690, 59, 56, 66, 5409, 60, 13549, 146, 62, 466, 61, 305, 56, 60, 56, 138, 299, 102, 58, 406, 1019, 51, 137, 247, 63, 59, 54, 226, 257, 59, 51, 286, 52, 55, 143, 1039, 53, 73, 58, 4807, 59, 22, 49, 411, 52, 57, 98, 129, 51, 143, 90, 47, 284, 57, 59, 77, 63, 162, 849, 56, 8935, 711, 58, 59, 73, 53, 56, 57, 30, 822, 50, 59, 78, 59, 56, 55, 65, 54, 60, 58, 532, 52, 75, 71, 57, 65, 70, 67, 65, 60, 173, 59, 717, 203, 68, 55, 57, 53, 67, 55, 1579, 61, 49, 56, 877, 66, 56, 142, 62, 53, 62, 58, 873, 57, 132, 126, 54, 98, 622, 103, 9106, 1860, 454, 148, 206, 412, 423, 103, 77, 55, 57, 118, 49, 45, 52, 40, 77, 960, 56, 603, 57, 55, 225, 68, 146, 50, 49, 58, 159, 142, 88, 46, 76, 56, 54, 75, 51, 100, 51, 55, 842, 69, 59, 353, 49, 236, 52, 829, 150, 60, 54, 54, 47, 277, 55, 309, 104, 49, 58, 52, 59, 55, 57, 116, 58, 55, 143, 62, 63, 50, 151, 59, 515, 53, 58, 64, 1357, 56, 961, 117, 3664, 61, 696, 128, 147, 639, 56, 79, 51, 342, 268, 245, 55, 311, 413, 505, 17, 63, 67, 713, 55, 199, 17, 89, 34, 53, 53, 51, 55, 60, 192, 71, 84, 130, 52, 52, 1033, 58, 122, 113, 61, 134, 1110, 52, 55, 60, 52, 68, 50, 71, 52, 52, 54, 61, 139, 861, 53, 464, 105, 86, 84, 207, 125, 54, 3281, 58, 15, 108, 68, 523, 71, 1197, 59, 120, 57, 57, 187, 60, 58, 483, 696, 61, 109, 54, 121, 60, 563, 67, 797, 130, 47, 61, 1473, 49, 119, 65, 231, 1307, 71, 55, 85, 491, 114, 1705, 96, 1039, 86, 346, 690, 60, 1724, 462, 677, 61, 106, 664, 59, 590, 134, 56, 71, 355, 338, 168, 1600, 612, 141, 437, 1438, 111, 367, 283, 942, 412, 453, 259, 128, 92, 277, 45, 304, 278, 156, 269, 123, 136, 121, 148, 104, 1063, 676, 257, 125, 85, 105, 301, 142, 232, 85, 150, 4912, 226, 287, 135, 108, 147, 77, 123, 109, 1131, 72, 131, 84, 63, 88, 88, 66, 95, 89, 90, 81, 222, 88, 85, 808, 64, 76, 179, 115, 88, 78, 77, 236, 85, 83, 71, 1381, 113, 1075, 118, 31, 58, 117, 144, 653, 301, 84, 81, 315, 88, 207, 155, 74, 86, 17, 80, 68, 166, 77, 69, 67, 71, 89, 88, 303, 989, 509, 105, 642, 67, 153, 405, 231, 94, 147, 90, 889, 76, 81, 98, 104, 71, 773, 78, 1146, 413, 55, 178, 73, 61, 1077, 421, 74, 503, 73, 77, 73, 69, 255, 76, 63, 420, 65, 76, 752, 363, 112, 151, 78, 68, 72, 78, 67, 61, 75, 80, 91, 65, 84, 65, 72, 292, 847, 91, 11709, 67, 67, 110, 86, 2467, 77, 63, 54, 662, 742, 82, 63, 75, 66, 434, 144, 58, 65, 63, 48, 594, 115, 65, 53, 64, 433, 119, 65, 75, 438, 65, 59, 62, 60, 61, 60, 56, 60, 60, 63, 56, 58, 54, 561, 49, 55, 52, 64, 254, 271, 115, 48, 73, 55, 56, 49, 56, 853, 954, 59, 62, 51, 1951, 52, 64, 59, 430, 100, 56, 53, 55, 717, 55, 1725, 131, 53, 681, 53, 229, 536, 63, 54, 842, 126, 57, 1413, 61, 321, 252, 84, 63, 58, 63, 54, 50, 2153, 69, 432, 92, 57, 151, 677, 118, 54, 140, 279, 52, 519, 1391, 61, 46, 538, 53, 58, 135, 178, 53, 140, 69, 72, 115, 59, 56, 58, 58, 58, 85, 53, 50, 54, 218, 72, 618, 59, 56, 127, 69, 18, 1321, 688, 67, 57, 98, 69, 56, 61, 54, 133, 382, 57, 55, 120, 434, 1165, 55, 60, 108, 61, 49, 114, 56, 86, 69, 957, 50, 814, 1112, 1052, 70, 751, 257, 51, 59, 54, 52, 55, 392, 52, 160, 49, 53, 726, 181, 64, 806, 57, 51, 49, 58, 629, 45, 74, 52, 53, 65, 9789, 237, 263, 72, 51, 57, 50, 337, 60, 51, 50, 53, 143, 60, 54, 76, 87, 580, 60, 48, 57, 44, 84, 45, 45, 75, 70, 470, 26, 48, 1034, 110, 56, 56, 73, 108, 837, 59, 62, 53, 110, 55, 52, 1450, 55, 55, 62, 64, 426, 55, 46, 68, 509, 54, 60, 57, 107, 846, 49, 93, 59, 55, 992, 2282, 59, 63, 62, 62, 58, 577, 65, 59, 49, 55, 208, 54, 59, 53, 53, 55, 54, 109, 61, 57, 55, 53, 54, 54, 116, 55, 19, 58, 98, 56, 52, 56, 59, 55, 52, 56, 59, 56, 75, 52, 53, 62, 758, 52, 64, 52, 57, 52, 59, 52, 47, 56, 54, 42, 51, 60, 101, 101, 62, 59, 51, 274, 1101, 60, 58, 50, 155, 58, 34, 270, 169, 62, 76, 63, 58, 272, 59, 55, 57, 1092, 137, 159, 51, 132, 49, 92, 47, 62, 56, 26, 53, 55, 73, 60, 63, 54, 98, 564, 50, 3025, 56, 444, 53, 55, 52, 564, 55, 537, 54, 50, 49, 667, 228, 75, 57, 409, 54, 869, 63, 56, 76, 55, 75, 53, 52, 623, 52, 66, 534, 51, 56, 52, 54, 337, 989, 902, 72, 848, 53, 48, 55, 15, 157, 55, 586, 1108, 49, 54, 76, 50, 61, 125, 51, 48, 52, 54, 64, 53, 59, 59, 76, 58, 79, 54, 59, 114, 67, 21, 51, 61, 726, 306, 600, 234, 162, 65, 594, 53, 59, 51, 36, 485, 63, 131, 79, 55, 867, 285, 50, 60, 46, 330, 55, 171, 66, 126, 58, 59, 98, 247, 199, 210, 330, 1010, 49, 52, 48, 126, 54, 52, 54, 151, 53, 318, 53, 47, 55, 49, 95, 60, 39, 760, 3499, 103, 13, 1582, 12, 49, 190, 388, 69, 45, 6497, 56, 640, 418, 246, 757, 59, 140, 78, 174, 76, 172, 82, 63, 60, 59, 331, 352, 57, 69, 63, 58, 1417, 49, 70, 48, 58, 336, 732, 57, 319, 58, 54, 72, 52, 59, 63, 918, 54, 363, 64, 59, 66, 515, 51, 60, 1002, 58, 57, 57, 64, 270, 883, 1867, 68, 22, 309, 53, 97, 64, 25, 64, 58, 64, 523, 186, 826, 59, 61, 166, 53, 24, 118, 53, 758, 400, 95, 90, 158, 954, 549, 51, 271, 153, 49, 53, 914, 320, 185, 50, 193, 65, 164, 58, 50, 60, 217, 2632, 79, 187, 810, 57, 55, 976, 27, 74, 988, 8719, 865, 49, 56, 56, 59, 614, 77, 55, 55, 27, 79, 67, 74, 283, 897, 58, 57, 49, 157, 48, 7908, 153, 430, 77, 511, 575, 285, 46, 56, 904, 492, 96, 79, 80, 51, 123, 265, 108, 72, 175, 6523, 163, 78, 437, 122, 76, 88, 71, 67, 333, 83, 82, 326, 100, 64, 181, 86, 60, 57, 119, 64, 639, 62, 622, 806, 126, 55, 55, 60, 1051, 128, 48, 1104, 23, 47, 116, 68, 104, 4048, 55, 164, 11963, 61, 55, 605, 120, 50, 85, 55, 125, 60, 183, 600, 67, 464, 54, 631, 64, 199, 132, 71, 253, 59, 153, 295, 46, 210, 284, 233, 1168, 369, 390, 51, 204, 156, 48, 454, 13920, 1427, 90, 42, 967, 9234, 76, 43, 469, 117, 1506, 82, 49, 65, 1401, 82, 262, 172, 78, 131, 68, 54, 69, 64, 61, 438, 58, 59, 59, 395, 112, 192, 700, 51, 74, 64, 67, 137, 155, 125, 72, 63, 318, 173, 59, 120, 72, 61, 61, 34, 77, 941, 68, 152, 75, 1036, 2493, 67, 52, 66, 177, 75, 68, 120, 72, 23, 17, 66, 85, 59, 67, 1079, 21, 66, 143, 11880, 59, 113, 134, 71, 92, 48, 63, 812, 20, 1241, 446, 111, 45, 195, 64, 778, 609, 7556, 54, 60, 51, 944, 195, 95, 214, 77, 100, 716, 79, 51, 56, 72, 55, 52, 53, 155, 47, 58, 58, 51, 897, 53, 60, 297, 57, 2646, 59, 130, 313, 60, 178, 115, 911, 61, 300, 801, 317, 9038, 308, 102, 60, 158, 59, 70, 255, 111, 51, 1691, 112, 345, 133, 101, 77, 60, 66, 41, 147, 53, 449, 49, 1156, 76, 131, 717, 79, 1595, 54, 57, 507, 58, 134, 60, 52, 65, 60, 55, 56, 57, 61, 315, 2179, 53, 59, 94, 57, 987, 55, 266, 89, 105, 58, 78, 59, 61, 62, 613, 54, 65, 109, 870, 93, 248, 138, 94, 58, 53, 60, 785, 57, 911, 56, 491, 49, 57, 83, 64, 66, 120, 61, 132, 113, 1080, 77, 66, 54, 56, 1274, 84, 868, 69, 109, 217, 79, 70, 74, 23, 110, 55, 57, 57, 48, 65, 63, 223, 169, 123, 52, 47, 692, 58, 56, 2946, 61, 46, 43, 60, 67, 339, 407, 779, 2965, 325, 56, 298, 6838, 1303, 125, 108, 103, 49, 585, 39, 6512, 75, 852, 61, 298, 32, 74, 66, 68, 57, 64, 63, 59, 55, 145, 57, 58, 105, 62, 259, 1056, 528, 73, 54, 476, 325, 335, 501, 1382, 903, 29, 121, 67, 52, 47, 53, 846, 30, 69, 339, 438, 48, 103, 812, 10805, 400, 89, 3049, 211, 419, 223, 71, 80, 125, 938, 137, 693, 55, 52, 820, 294, 91, 59, 66, 71, 553, 118, 235, 207, 85, 74, 19, 60, 416, 66, 62, 1242, 113, 69, 1218, 98, 54, 88, 136, 65, 57, 70, 51, 65, 108, 129, 67, 72, 145, 710, 98, 53, 78, 21, 7564, 17, 120, 65, 61, 500, 611, 54, 350, 57, 60, 64, 58, 65, 50, 63, 56, 66, 52, 93, 38, 1462, 59, 59, 59, 684, 30, 130, 63, 69, 19, 1015, 59, 77, 762, 71, 64, 139, 45, 552, 49, 52, 529, 3101, 67, 46, 501, 592, 59, 70, 83, 59, 63, 46, 53, 56, 69, 153, 885, 16, 541, 981, 196, 841, 18, 45, 498, 75, 61, 115, 302, 836, 55, 114, 248, 233, 60, 68, 780, 225, 860, 60, 64, 649, 89, 175, 668, 1088, 925, 127, 52, 55, 48, 82, 979, 293, 55, 263, 59, 130, 78, 47, 121, 70, 57, 1886, 56, 61, 519, 172, 1172, 19, 88, 137, 18, 86, 4092, 118, 859, 139, 127, 489, 89, 74, 116, 68, 53, 210, 72, 55, 68, 63, 58, 71, 69, 123, 73, 842, 723, 775, 59, 139, 69, 74, 109, 73, 19, 58, 72, 29, 50, 59, 13, 115, 54, 124, 93, 43, 60, 57, 74, 56, 64, 126, 388, 50, 46, 144, 92, 97, 238, 67, 49, 55, 61, 59, 102, 58, 72, 679, 73, 763, 63, 59, 81, 52, 67, 66, 68, 54, 71, 53, 64, 1041, 38, 56, 92, 133, 60, 144, 294, 1454, 57, 60, 422, 86, 121, 67, 775, 93, 60, 66, 54, 58, 51, 61, 52, 159, 47, 60, 55, 18, 67, 71, 96, 40, 62, 156, 798, 54, 390, 64, 412, 121, 22, 52, 116, 21, 59, 195, 46, 1153, 356, 171, 64, 149, 66, 84, 762, 64, 80, 55, 441, 337, 67, 59, 76, 56, 71, 24, 90, 815, 80, 61, 85, 59, 65, 57, 51, 58, 58, 18, 51, 69, 50, 56, 551, 59, 572, 56, 102, 1107, 126, 87, 59, 983, 54, 53, 65, 77, 61, 56, 523, 59, 82, 21, 63, 802, 61, 8238, 60, 175, 55, 79, 64, 59, 1136, 134, 55, 994, 788, 59, 63, 21, 7677, 59, 1377, 51, 53, 81, 35, 53, 57, 96, 50, 932, 53, 61, 56, 126, 371, 18, 103, 229, 875, 382, 53, 56, 993, 56, 111, 59, 316, 96, 54, 85, 60, 62, 203, 51, 54, 66, 679, 61, 71, 42, 4768, 1085, 289, 4911, 59, 56, 68, 608, 59, 412, 66, 55, 604, 842, 817, 619, 110, 258, 642, 117, 668, 110, 58, 484, 57, 68, 58, 410, 127, 142, 437, 54, 617, 71, 147, 75, 95, 280, 62, 80, 216, 879, 59, 926, 88, 4185, 356, 48, 4600, 81, 69, 27, 1094, 100, 1870, 64, 548, 81, 328, 174, 170, 339, 31, 1122, 63, 28, 70, 1173, 111, 52, 719, 58, 160, 362, 352, 183, 53, 56, 781, 54, 60, 161, 562, 408, 19, 58, 20, 60, 21, 78, 60, 71, 486, 57, 53, 58, 51, 1170, 68, 72, 53, 60, 57, 51, 377, 46, 58, 439, 61, 58, 1085, 53, 129, 538, 1842, 598, 55, 126, 43, 201, 72, 113, 62, 339, 177, 62, 1294, 55, 57, 172, 7283, 91, 176, 54, 147, 1940, 282, 102, 288, 355, 167, 125, 328, 113, 71, 78, 39, 58, 164, 81, 56, 128, 60, 1299, 68, 116, 53, 7338, 72, 136, 78, 237, 1244, 57, 618, 54, 53, 66, 519, 61, 209, 1141, 148, 98, 64, 61, 65, 60, 126, 61, 59, 64, 51, 78, 54, 310, 336, 388, 56, 52, 77, 141, 691, 143, 929, 1094, 129, 151, 960, 93, 272, 989, 455, 64, 49, 4784, 12101, 27, 96, 959, 74, 176, 60, 12, 230, 87, 724, 1656, 51, 4285, 58, 32, 49, 659, 70, 54, 256, 67, 94, 736, 63, 146, 66, 48, 53, 61, 61, 64, 100, 55, 284, 63, 616, 97, 92, 48, 60, 583, 55, 5038, 189, 627, 420, 93, 48, 3879, 58, 289, 644, 522, 5278, 7955, 139, 266, 122, 622, 49, 240, 182, 46, 58, 623, 213, 745, 67, 22, 209, 216, 299, 207, 83, 899, 155, 1094, 69, 55, 59, 21, 440, 828, 68, 64, 68, 4618, 334, 121, 232, 511, 565, 79, 113, 67, 111, 71, 66, 56, 1396, 57, 134, 77, 49, 65, 1026, 632, 76, 68, 89, 549, 166, 72, 1224, 82, 104, 131, 120, 39, 394, 4543, 58, 56, 63, 5089, 98, 398, 78, 581, 194, 64, 78, 500, 50, 53, 148, 172, 52, 112, 129, 577, 286, 108, 53, 30, 59, 68, 987, 823, 58, 169, 52, 590, 333, 172, 64, 616, 80, 207, 181, 176, 104, 172, 85, 87, 87, 1255, 104, 95, 84, 95, 87, 63, 68, 49, 69, 96, 54, 75, 63, 70, 74, 72, 786, 3447, 63, 21, 55, 62, 219, 88, 148, 79, 52, 122, 167, 67, 59, 50, 19, 72, 74, 60, 62, 65, 69, 67, 52, 52, 69, 61, 72, 1047, 57, 451, 238, 35, 934, 908, 124, 364, 58, 46, 698, 1102] - }, - { - "label": "H/W", - "valueformat": ",.1%", - "font": {"family": "monospace", size: 10}, - "values": [0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3471,0.4373,0.4575,0.106,0.568,0.2164,0.2366,0.3269,0.3503,0.2102,0.106,0.349,0.2887,0.3282,0.2623,0.2514,0.3849,0.4355,0.2245,0.273,0.2763,0.2245,0.2229,0.2021,0.394,0.4183,0.3022,0.4758,0.3389,0.2964,0.1157,0.2767,0.2982,0.1634,0.3805,0.282,0.2266,0.2335,0.4048,0.4518,0.4244,0.4931,0.3975,0.3376,0.1572,0.2424,0.4214,0.4037,0.3976,0.2394,0.4163,0.4412,0.354,0.354,0.3156,0.1511,0.2696,0.2559,0.2709,0.4223,0.4888,0.2403,0.3769,0.3182,0.3028,0.2626,0.238,0.2774,0.1221,0.4055,0.456,0.3534,0.2872,0.2698,0.2924,0.2902,0.3572,0.4176,0.5192,0.5446,0.3186,0.3452,0.3526,0.2835,0.1725,0.1683,0.4279,0.3328,0.0849,0.3074,0.4186,0.2147,0.28,0.4077,0.3662,0.1143,0.0861,0.3937,0.239,0.3419,0.3586,0.4139,0.3827,0.4126,0.3441,0.3755,0.3721,0.4283,0.3654,0.4365,0.3905,0.2883,0.4039,0.301,0.3766,0.4707,0.4609,0.3743,0.2462,0.3333,0.3497,0.1066,0.5141,0.3411,0.3647,0.2297,0.3886,0.339,0.4667,0.4915,0.4194,0.4781,0.3982,0.3725,0.4933,0.4984,0.3962,0.4453,0.3677,0.1643,0.4875,0.4024,0.3883,0.4964,0.4059,0.4534,0.376,0.4706,0.4409,0.3963,0.4695,0.5232,0.2757,0.4578,0.4747,0.4099,0.1677,0.4258,0.4022,0.4183,0.4416,0.4267,0.3642,0.4358,0.433,0.4275,0.4326,0.4856,0.464,0.431,0.3653,0.4402,0.4672,0.4672,0.384,0.4332,0.4255,0.4375,0.4745,0.4246,0.4165,0.4211,0.429,0.4512,0.4291,0.5072,0.43,0.414,0.4316,0.4756,0.3857,0.4651,0.4549,0.4507,0.4258,0.4519,0.4491,0.4205,0.4472,0.4804,0.3892,0.2445,0.4304,0.4379,0.43,0.4528,0.4528,0.3003,0.449,0.3481,0.3132,0.4251,0.2272,0.4489,0.4217,0.4464,0.445,0.494,0.4531,0.3948,0.2236,0.4605,0.3525,0.4482,0.4578,0.5002,0.4241,0.4563,0.4283,0.4645,0.2254,0.1096,0.4617,0.4652,0.3812,0.4493,0.4612,0.4189,0.4455,0.4516,0.4406,0.4658,0.3804,0.4644,0.4692,0.4696,0.2486,0.4627,0.4517,0.4418,0.3038,0.4693,0.4968,0.4639,0.459,0.2915,0.4581,0.4593,0.4501,0.4698,0.3939,0.465,0.4483,0.2227,0.2034,0.4613,0.455,0.4477,0.4566,0.4447,0.4631,0.31,0.4708,0.457,0.4426,0.4596,0.4589,0.4579,0.447,0.4572,0.4561,0.456,0.4464,0.4537,0.4631,0.4727,0.5143,0.4404,0.4407,0.4499,0.4528,0.4548,0.4631,0.1663,0.452,0.4624,0.2446,0.4604,0.4621,0.4632,0.4667,0.4479,0.4657,0.1329,0.4653,0.4614,0.4698,0.4617,0.449,0.4735,0.5057,0.4503,0.4611,0.4691,0.4571,0.469,0.4622,0.4991,0.509,0.4768,0.456,0.4841,0.4242,0.3999,0.1929,0.4636,0.4537,0.3063,0.0758,0.4677,0.458,0.2022,0.4643,0.4569,0.4675,0.4741,0.4813,0.4474,0.4306,0.4532,0.4562,0.4613,0.3225,0.4793,0.4654,0.4016,0.4759,0.4292,0.4665,0.4569,0.48,0.4419,0.2803,0.4752,0.4665,0.4724,0.4651,0.4626,0.4761,0.4732,0.4701,0.4637,0.4688,0.4597,0.4825,0.2323,0.4098,0.4642,0.4769,0.4662,0.2957,0.3255,0.4641,0.4715,0.3779,0.4727,0.3506,0.4645,0.1597,0.4683,0.4735,0.4705,0.4624,0.4673,0.4709,0.4627,0.4522,0.4701,0.4697,0.5068,0.4612,0.4609,0.466,0.5259,0.4635,0.4485,0.5349,0.4628,0.4654,0.4543,0.4653,0.308,0.4718,0.4863,0.4744,0.2371,0.5003,0.3191,0.1864,0.4691,0.4529,0.4688,0.1522,0.3725,0.4326,0.4484,0.4442,0.3543,0.1314,0.4618,0.4363,0.4568,0.3268,0.4694,0.449,0.2738,0.4672,0.2723,0.4663,0.4713,0.4736,0.4641,0.4251,0.236,0.4569,0.5107,0.2235,0.4575,0.4571,0.3753,0.4645,0.3207,0.2212,0.4671,0.4582,0.3889,0.4635,0.4726,0.4546,0.4622,0.5338,0.4557,0.4615,0.4914,0.4598,0.4652,0.4074,0.4977,0.2968,0.4563,0.1935,0.4658,0.4273,0.5074,0.407,0.3923,0.4499,0.5069,0.4518,0.4143,0.3748,0.4568,0.0986,0.4635,0.4533,0.4077,0.4556,0.4591,0.4414,0.3821,0.4269,0.4624,0.049,0.1332,0.4598,0.4518,0.4646,0.4564,0.4074,0.4197,0.4563,0.2365,0.5009,0.4378,0.4395,0.4359,0.4655,0.4777,0.4516,0.2404,0.4389,0.4385,0.4646,0.4947,0.3696,0.4278,0.4836,0.4374,0.4824,0.4568,0.1027,0.4017,0.4785,0.4259,0.1476,0.2125,0.4828,0.4787,0.4659,0.4588,0.4589,0.4644,0.4599,0.4447,0.394,0.2117,0.4591,0.4552,0.434,0.1955,0.4826,0.4357,0.2824,0.3239,0.3866,0.2579,0.0868,0.504,0.337,0.3013,0.2995,0.3904,0.3763,0.3902,0.488,0.2711,0.426,0.2838,0.4567,0.4595,0.3141,0.344,0.3524,0.2747,0.4047,0.4712,0.3362,0.3363,0.51,0.2836,0.4845,0.2807,0.2489,0.4478,0.3792,0.4862,0.294,0.3372,0.3838,0.3054,0.3059,0.3382,0.3782,0.3669,0.4057,0.3136,0.3726,0.3203,0.3039,0.3652,0.3654,0.3497,0.284,0.3396,0.3227,0.334,0.3348,0.2618,0.3699,0.2903,0.2834,0.3092,0.3196,0.3438,0.3595,0.2426,0.3603,0.3344,0.3617,0.4885,0.3156,0.4708,0.3111,0.5068,0.3744,0.2958,0.3443,0.3438,0.3224,0.3595,0.3693,0.1386,0.3765,0.1277,0.3831,0.3513,0.3366,0.4357,0.3552,0.3688,0.3921,0.3668,0.3512,0.3531,0.3646,0.3964,0.4014,0.3932,0.3426,0.0899,0.3302,0.4054,0.3646,0.4796,0.2794,0.3071,0.4079,0.2652,0.4221,0.2835,0.4224,0.3672,0.3027,0.3528,0.3471,0.3736,0.3794,0.3734,0.5055,0.3836,0.4118,0.428,0.3856,0.3808,0.2789,0.3667,0.0545,0.3847,0.4435,0.3622,0.3622,0.248,0.4418,0.3883,0.374,0.3867,0.4,0.3478,0.293,0.4093,0.3151,0.3958,0.3906,0.3731,0.384,0.3927,0.4015,0.3808,0.3807,0.4755,0.3919,0.4541,0.4291,0.3891,0.3733,0.4442,0.3692,0.4273,0.3735,0.4146,0.3594,0.4912,0.4337,0.3702,0.3727,0.3572,0.2876,0.2819,0.3909,0.4457,0.4305,0.4233,0.3758,0.362,0.445,0.4411,0.4159,0.4156,0.3562,0.4412,0.4476,0.2794,0.4378,0.3557,0.4235,0.4378,0.443,0.3957,0.3939,0.4675,0.4451,0.4383,0.3913,0.4421,0.4432,0.4388,0.4485,0.4338,0.4443,0.4584,0.4601,0.4505,0.468,0.4694,0.4478,0.421,0.2787,0.4466,0.452,0.472,0.4119,0.459,0.4547,0.4526,0.4485,0.4662,0.4414,0.4492,0.4514,0.4667,0.4566,0.4671,0.4441,0.4427,0.3257,0.4604,0.4439,0.4627,0.4521,0.3045,0.4423,0.0986,0.4388,0.464,0.2199,0.4353,0.3162,0.3346,0.2652,0.4587,0.2954,0.4414,0.4546,0.5036,0.4446,0.1798,0.3615,0.4671,0.4725,0.4634,0.4866,0.4582,0.4101,0.3729,0.4767,0.3916,0.4418,0.4585,0.4018,0.4017,0.4337,0.4623,0.4319,0.4331,0.4861,0.2038,0.2578,0.4641,0.4523,0.1418,0.4568,0.4591,0.4308,0.3099,0.4543,0.5206,0.3527,0.4609,0.4481,0.4554,0.4663,0.4594,0.4615,0.4561,0.4481,0.4706,0.4452,0.4624,0.3061,0.4512,0.361,0.4497,0.4615,0.3755,0.4573,0.4801,0.4582,0.2268,0.4465,0.4665,0.4599,0.452,0.4684,0.4513,0.4707,0.4658,0.1848,0.4561,0.463,0.4653,0.4472,0.4677,0.474,0.2698,0.4412,0.4515,0.4639,0.4442,0.446,0.3465,0.444,0.4448,0.4577,0.4598,0.4643,0.3763,0.345,0.2422,0.2171,0.4664,0.4571,0.4734,0.4629,0.4575,0.4244,0.4611,0.1915,0.458,0.4605,0.319,0.2657,0.1885,0.3449,0.4584,0.4617,0.4622,0.4621,0.0937,0.4584,0.4381,0.4585,0.457,0.4553,0.3229,0.2501,0.2159,0.4652,0.4749,0.4591,0.457,0.1091,0.4596,0.4571,0.4799,0.4595,0.4428,0.4599,0.4684,0.4585,0.4572,0.1627,0.4628,0.4603,0.4576,0.4624,0.4614,0.4724,0.4474,0.4667,0.4523,0.3287,0.2666,0.4767,0.4566,0.4439,0.4808,0.4717,0.4529,0.4299,0.3346,0.4617,0.4634,0.4696,0.3761,0.4578,0.4641,0.4291,0.4663,0.4572,0.4592,0.463,0.0681,0.4658,0.4605,0.4554,0.2416,0.4661,0.4621,0.4671,0.4696,0.4527,0.4618,0.4594,0.4608,0.4651,0.461,0.5069,0.4704,0.4657,0.4657,0.457,0.467,0.3164,0.4647,0.462,0.4652,0.4705,0.4723,0.4717,0.4598,0.4627,0.4665,0.4659,0.4667,0.4683,0.4697,0.4635,0.4637,0.4625,0.4652,0.4628,0.414,0.473,0.2808,0.4618,0.4652,0.4625,0.47,0.468,0.4593,0.4609,0.4644,0.4562,0.4571,0.4637,0.4496,0.4637,0.4661,0.4607,0.4655,0.4667,0.4575,0.4659,0.453,0.4672,0.4628,0.4661,0.4671,0.4565,0.463,0.4783,0.4632,0.4624,0.4652,0.2936,0.4605,0.4631,0.465,0.3615,0.4647,0.4649,0.4657,0.4693,0.1734,0.4547,0.4547,0.4063,0.4825,0.4172,0.5094,0.4611,0.4598,0.4103,0.4522,0.4713,0.4552,0.429,0.4445,0.4951,0.4734,0.4458,0.4704,0.5342,0.4663,0.4493,0.4541,0.3857,0.4685,0.4511,0.4537,0.4707,0.4766,0.4724,0.467,0.3707,0.474,0.4518,0.4587,0.3528,0.4605,0.475,0.4668,0.262,0.4657,0.2022,0.4661,0.4632,0.4735,0.1637,0.2756,0.462,0.471,0.323,0.4714,0.4615,0.3217,0.4624,0.3595,0.4732,0.3584,0.4631,0.4649,0.4678,0.4585,0.4534,0.4638,0.4643,0.4519,0.4675,0.4729,0.1176,0.4569,0.4658,0.2056,0.4606,0.4745,0.4712,0.4733,0.2708,0.3096,0.4677,0.4739,0.1961,0.4697,0.4691,0.4539,0.4686,0.4645,0.4675,0.4728,0.4715,0.4641,0.4707,0.459,0.4642,0.4783,0.4613,0.4666,0.456,0.4546,0.4705,0.4656,0.4412,0.4779,0.2631,0.4641,0.4698,0.4648,0.4343,0.3409,0.4131,0.3953,0.4752,0.1389,0.4683,0.4907,0.4607,0.3496,0.303,0.4653,0.2947,0.4519,0.4706,0.4647,0.2345,0.4601,0.3496,0.4685,0.431,0.4708,0.3121,0.4549,0.3636,0.4658,0.4688,0.4491,0.1435,0.2812,0.3221,0.3186,0.4606,0.4617,0.4689,0.4754,0.2831,0.4584,0.4664,0.4664,0.3351,0.4619,0.3536,0.4594,0.4763,0.455,0.4612,0.4559,0.4612,0.4655,0.2916,0.4163,0.4616,0.3583,0.4157,0.2951,0.465,0.3951,0.4274,0.461,0.5429,0.3434,0.4634,0.3112,0.2645,0.3055,0.4805,0.4449,0.4803,0.4562,0.493,0.4462,0.4297,0.4947,0.4506,0.4411,0.4523,0.1333,0.2516,0.4623,0.4611,0.4742,0.4444,0.1819,0.4602,0.4781,0.4717,0.4594,0.2387,0.3514,0.4612,0.2391,0.4371,0.4755,0.5075,0.4634,0.4623,0.4629,0.4375,0.4584,0.4529,0.457,0.4589,0.4668,0.3888,0.4737,0.4593,0.4592,0.453,0.4691,0.471,0.4586,0.2755,0.3362,0.2935,0.3811,0.38,0.4017,0.479,0.4176,0.4636,0.3278,0.3804,0.4743,0.4614,0.3995,0.3285,0.127,0.4676,0.4686,0.4576,0.4751,0.3578,0.4209,0.4539,0.3483,0.4137,0.4668,0.4225,0.4004,0.2937,0.2878,0.4554,0.4061,0.4182,0.4739,0.4628,0.4412,0.475,0.4264,0.468,0.4603,0.4595,0.2674,0.4573,0.4528,0.4668,0.1814,0.459,0.4542,0.456,0.4792,0.4661,0.4544,0.4647,0.3393,0.4584,0.4619,0.4261,0.3883,0.485,0.457,0.4624,0.3545,0.2884,0.3164,0.4606,0.4622,0.3059,0.455,0.382,0.4468,0.3756,0.4642,0.4559,0.4652,0.4678,0.4447,0.4605,0.2002,0.4252,0.1264,0.4535,0.0768,0.1516,0.5143,0.4644,0.4603,0.433,0.2203,0.4536,0.4371,0.4426,0.4683,0.3953,0.2126,0.2787,0.4484,0.4045,0.2419,0.4356,0.4412,0.4186,0.3838,0.4517,0.5263,0.4596,0.4657,0.3192,0.3825,0.4513,0.364,0.3972,0.4704,0.4855,0.4611,0.4749,0.4611,0.4681,0.4676,0.4076,0.4341,0.4417,0.4321,0.4012,0.4556,0.4561,0.4502,0.4447,0.4575,0.4704,0.4625,0.3587,0.4597,0.4542,0.4522,0.4546,0.2611,0.4424,0.3923,0.3756,0.456,0.4493,0.4495,0.4211,0.4637,0.4735,0.4544,0.4571,0.4472,0.2786,0.3427,0.4451,0.3878,0.4578,0.1417,0.4519,0.2635,0.2984,0.448,0.2682,0.461,0.4055,0.3935,0.461,0.4532,0.332,0.1754,0.4313,0.1925,0.3898,0.4651,0.3866,0.4439,0.4293,0.2235,0.38,0.3891,0.446,0.4251,0.4099,0.4324,0.4295,0.4536,0.2311,0.4655,0.443,0.4537,0.4719,0.4416,0.4454,0.4479,0.1643,0.4133,0.4002,0.2786,0.4536,0.4485,0.4437,0.4344,0.4656,0.0929,0.4507,0.4692,0.466,0.1327,0.4278,0.3083,0.4904,0.3317,0.4639,0.4464,0.4542,0.3529,0.4505,0.405,0.4442,0.4323,0.3919,0.3434,0.4274,0.4413,0.4413,0.4593,0.4477,0.4013,0.4216,0.4393,0.4419,0.391,0.4347,0.4677,0.1074,0.4396,0.4583,0.4495,0.4328,0.4465,0.3244,0.4464,0.4402,0.3301,0.4526,0.4355,0.4347,0.4427,0.4438,0.3638,0.3327,0.4507,0.4008,0.3338,0.4483,0.3323,0.4413,0.4459,0.4374,0.4562,0.4517,0.4632,0.3368,0.4343,0.4097,0.4406,0.4644,0.1571,0.4078,0.3433,0.4312,0.2404,0.343,0.4475,0.4677,0.4585,0.2978,0.4329,0.5107,0.3633,0.4574,0.3604,0.437,0.4603,0.4743,0.4422,0.451,0.4648,0.4666,0.447,0.461,0.4507,0.4612,0.4428,0.441,0.4696,0.4486,0.3355,0.4433,0.0873,0.4502,0.4274,0.4633,0.4473,0.3137,0.4417,0.458,0.4693,0.4663,0.2505,0.1642,0.3798,0.3794,0.4149,0.4598,0.436,0.4444,0.4461,0.3955,0.4296,0.4678,0.4436,0.4565,0.1679,0.424,0.4656,0.4521,0.4593,0.4598,0.4267,0.247,0.4596,0.355,0.4674,0.4528,0.4351,0.4582,0.5148,0.4358,0.4551,0.4633,0.4589,0.2789,0.4626,0.4544,0.4736,0.4462,0.4608,0.4453,0.4665,0.4722,0.4632,0.4771,0.2868,0.4384,0.4576,0.4528,0.4649,0.455,0.4593,0.4494,0.4847,0.4772,0.3203,0.4532,0.3521,0.4601,0.4501,0.4579,0.3659,0.466,0.4457,0.4536,0.47,0.4856,0.1852,0.2763,0.4576,0.469,0.459,0.4587,0.3582,0.446,0.2846,0.4551,0.1506,0.4631,0.4681,0.3023,0.4626,0.4773,0.3561,0.3619,0.4226,0.4454,0.4599,0.4746,0.4065,0.4563,0.4653,0.454,0.448,0.4675,0.4657,0.2741,0.2293,0.4402,0.4674,0.4436,0.3383,0.279,0.4655,0.4656,0.4618,0.4091,0.4663,0.4635,0.2082,0.5098,0.4897,0.4526,0.4573,0.3859,0.4562,0.4557,0.4743,0.4617,0.4668,0.4706,0.449,0.4627,0.3526,0.3432,0.3848,0.4733,0.4664,0.4005,0.1627,0.3335,0.4913,0.4769,0.4565,0.4537,0.4198,0.4104,0.4135,0.2112,0.2602,0.2586,0.4607,0.3893,0.5202,0.4403,0.1955,0.4489,0.4753,0.4532,0.4559,0.4663,0.4562,0.453,0.4611,0.2964,0.5273,0.4587,0.2129,0.4571,0.3808,0.492,0.4493,0.319,0.3455,0.1815,0.3167,0.4668,0.281,0.3651,0.4084,0.4136,0.457,0.4549,0.4631,0.2638,0.3535,0.4965,0.3545,0.3188,0.4554,0.4548,0.4688,0.3183,0.1743,0.5057,0.4601,0.3527,0.2615,0.2009,0.5048,0.5397,0.3916,0.3909,0.4718,0.4048,0.464,0.4681,0.3436,0.2044,0.501,0.4792,0.4978,0.481,0.3468,0.395,0.415,0.429,0.4886,0.491,0.3411,0.465,0.3459,0.4472,0.4815,0.5162,0.4552,0.4983,0.3921,0.4449,0.238,0.4527,0.4773,0.449,0.4781,0.4793,0.4581,0.4769,0.4625,0.4837,0.4987,0.4605,0.4482,0.2139,0.4548,0.3927,0.453,0.4435,0.3831,0.4611,0.4562,0.4505,0.4724,0.0508,0.4606,0.4682,0.3233,0.4711,0.462,0.3325,0.4622,0.4588,0.3834,0.4682,0.454,0.2746,0.4505,0.4613,0.4117,0.1395,0.4648,0.4575,0.4622,0.3452,0.378,0.4189,0.4669,0.448,0.3362,0.3335,0.3431,0.3518,0.3948,0.3497,0.4479,0.4932,0.4636,0.1025,0.4598,0.4698,0.3886,0.4498,0.3492,0.4462,0.4597,0.2471,0.4715,0.4647,0.4353,0.4644,0.4498,0.518,0.4551,0.4763,0.4502,0.4371,0.4764,0.3329,0.1331,0.4637,0.5051,0.4669,0.3253,0.4705,0.2647,0.456,0.4743,0.4444,0.1259,0.4458,0.4578,0.398,0.4349,0.3629,0.4577,0.457,0.4471,0.2514,0.2462,0.4599,0.4665,0.4168,0.3852,0.4403,0.4187,0.456,0.45,0.3949,0.4535,0.4433,0.4676,0.4361,0.4621,0.2827,0.4413,0.3417,0.4268,0.4643,0.4372,0.4671,0.3045,0.4481,0.4555,0.4998,0.4623,0.4673,0.2633,0.268,0.4482,0.3432,0.4516,0.4483,0.4836,0.445,0.416,0.4594,0.2678,0.4286,0.4608,0.0796,0.3901,0.4498,0.4001,0.4503,0.4679,0.199,0.3279,0.4676,0.4527,0.4547,0.3982,0.4441,0.4483,0.2104,0.4554,0.5006,0.2441,0.4498,0.4204,0.3503,0.4514,0.455,0.4526,0.4557,0.4128,0.4275,0.4511,0.3975,0.4156,0.4814,0.3497,0.4435,0.4278,0.3997,0.4083,0.4555,0.4375,0.4447,0.4324,0.4621,0.4418,0.4639,0.1858,0.4582,0.4375,0.3922,0.411,0.4341,0.2897,0.4094,0.4591,0.4498,0.4225,0.4454,0.4248,0.4582,0.4206,0.4125,0.4125,0.4705,0.4584,0.456,0.4554,0.3935,0.449,0.4335,0.3667,0.4582,0.4343,0.4744,0.4472,0.4396,0.4417,0.4437,0.1965,0.3368,0.4342,0.4921,0.166,0.468,0.4532,0.4425,0.2859,0.4429,0.4426,0.4356,0.317,0.4652,0.4401,0.4461,0.4527,0.4355,0.4535,0.4248,0.4704,0.2361,0.4796,0.442,0.4482,0.3481,0.4446,0.4449,0.4166,0.3797,0.443,0.2438,0.302,0.4472,0.422,0.4548,0.1667,0.2308,0.335,0.4456,0.3629,0.3366,0.4416,0.1677,0.4501,0.4485,0.185,0.3163,0.4537,0.3153,0.428,0.3329,0.3446,0.4355,0.4676,0.4649,0.3747,0.1945,0.4429,0.4388,0.374,0.4521,0.4462,0.3908,0.3047,0.3842,0.3624,0.4362,0.4196,0.4384,0.4377,0.4605,0.4379,0.4407,0.4454,0.3494,0.4594,0.4551,0.4456,0.4639,0.4512,0.4753,0.4562,0.462,0.4849,0.3585,0.459,0.5171,0.4388,0.4005,0.4507,0.4604,0.4446,0.4656,0.4473,0.446,0.2542,0.4474,0.5283,0.468,0.444,0.2958,0.4531,0.3254,0.4495,0.4341,0.4381,0.4467,0.4453,0.4422,0.4804,0.4375,0.4453,0.4383,0.3708,0.4533,0.4418,0.3096,0.3812,0.4562,0.3676,0.4488,0.4437,0.5262,0.4684,0.4533,0.4564,0.5244,0.4615,0.3803,0.4566,0.4583,0.4556,0.461,0.0872,0.3438,0.4357,0.4166,0.3994,0.2737,0.4565,0.4645,0.4661,0.476,0.402,0.4626,0.4806,0.4295,0.4501,0.4282,0.4582,0.4583,0.1882,0.4707,0.4564,0.4594,0.1755,0.4605,0.4572,0.341,0.3504,0.4534,0.1948,0.106,0.4602,0.4586,0.4437,0.4594,0.4585,0.3139,0.4479,0.4592,0.1339,0.4348,0.4316,0.161,0.4552,0.3262,0.2141,0.3608,0.4566,0.4696,0.466,0.1421,0.458,0.4574,0.4623,0.3439,0.3867,0.3428,0.2931,0.461,0.1563,0.2227,0.3469,0.4189,0.2885,0.2017,0.4541,0.2233,0.3998,0.4523,0.4592,0.4671,0.5042,0.4081,0.1494,0.4663,0.4696,0.4518,0.4625,0.3405,0.4728,0.4552,0.2448,0.4622,0.1409,0.4536,0.4747,0.4271,0.4657,0.3898,0.334,0.3606,0.4703,0.254,0.4646,0.4694,0.4611,0.4706,0.3508,0.4716,0.1887,0.3862,0.4019,0.2887,0.4615,0.4606,0.5001,0.4689,0.4565,0.3809,0.143,0.2964,0.3414,0.458,0.3001,0.4675,0.3678,0.4507,0.4762,0.4107,0.062,0.4648,0.4652,0.468,0.4744,0.4651,0.4616,0.4232,0.4694,0.4671,0.4817,0.4778,0.3495,0.4638,0.4857,0.3818,0.4745,0.4643,0.4666,0.4716,0.4772,0.1133,0.4934,0.3119,0.2747,0.4783,0.4206,0.1651,0.3022,0.4712,0.4756,0.4334,0.2626,0.4801,0.3983,0.482,0.4545,0.2641,0.3024,0.5135,0.3654,0.4546,0.3335,0.3338,0.4,0.4239,0.1084,0.399,0.4471,0.4692,0.4334,0.4574,0.4603,0.4766,0.5168,0.4761,0.4574,0.4502,0.467,0.4512,0.4542,0.4509,0.4497,0.4633,0.4654,0.2004,0.4622,0.2306,0.4708,0.4706,0.4868,0.4633,0.1202,0.473,0.4698,0.4369,0.3703,0.4456,0.3404,0.4469,0.4071,0.448,0.4582,0.4483,0.453,0.4635,0.4649,0.4568,0.469,0.4555,0.3523,0.4867,0.4526,0.4758,0.2122,0.0891,0.4765,0.4712,0.4305,0.4704,0.2048,0.4563,0.3358,0.3646,0.4404,0.3895,0.3805,0.5067,0.3549,0.4647,0.2781,0.4611,0.3036,0.2191,0.3975,0.3599,0.4495,0.4458,0.4683,0.4512,0.4597,0.3168,0.2124,0.4259,0.4524,0.4414,0.4618,0.1988,0.4589,0.3512,0.4695,0.4374,0.4764,0.4272,0.419,0.4488,0.3451,0.2974,0.4794,0.1887,0.4479,0.4591,0.4619,0.4513,0.4652,0.4285,0.3506,0.4528,0.181,0.4565,0.1194,0.4527,0.4441,0.4621,0.4391,0.4672,0.458,0.2902,0.5053,0.4555,0.3871,0.4642,0.4582,0.2483,0.4511,0.4638,0.1405,0.1109,0.157,0.4349,0.3917,0.2041,0.3435,0.2639,0.4581,0.4561,0.5093,0.2,0.4629,0.3909,0.4518,0.2513,0.4614,0.3486,0.4497,0.4309,0.4423,0.4346,0.4522,0.3755,0.2737,0.4879,0.4608,0.4711,0.4727,0.3195,0.2443,0.3497,0.461,0.342,0.4809,0.4786,0.4506,0.4249,0.4109,0.5651,0.3878,0.3821,0.428,0.4563,0.4248,0.471,0.4512,0.4747,0.4325,0.407,0.4516,0.4624,0.4702,0.476,0.4525,0.4662,0.4429,0.4955,0.4425,0.1248,0.3524,0.4626,0.4448,0.4575,0.4631,0.4049,0.5235,0.3977,0.2327,0.3973,0.4819,0.457,0.4742,0.4033,0.4828,0.3757,0.4503,0.2622,0.3144,0.4172,0.4505,0.1567,0.4656,0.4665,0.3262,0.4417,0.4622,0.5028,0.4337,0.0923,0.2431,0.275,0.3721,0.5334,0.4603,0.454,0.3645,0.2497,0.4562,0.4356,0.4707,0.1906,0.3585,0.4343,0.4569,0.1385,0.4014,0.3687,0.4652,0.3999,0.4398,0.4466,0.454,0.4269,0.4708,0.3649,0.4594,0.4415,0.4715,0.4832,0.4903,0.4526,0.4629,0.4618,0.4428,0.4646,0.4505,0.4181,0.456,0.4403,0.4459,0.4271,0.24,0.1916,0.452,0.3443,0.4589,0.4579,0.2893,0.5132,0.2048,0.4469,0.4498,0.4405,0.1836,0.461,0.475,0.4454,0.5038,0.4384,0.4445,0.4473,0.4882,0.3888,0.4429,0.4397,0.4733,0.3946,0.4608,0.4523,0.4387,0.4655,0.4708,0.3544,0.1169,0.3776,0.1953,0.3413,0.5151,0.2456,0.4156,0.5287,0.1887,0.1637] - }, - { - "label": "Min H/W", - "values": [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, 42910, 126039, 135736, 46100, 54920, 113880, 100220, 91860, 52140, 104500, 110480, 82230, 69120, 136490, 97950, 79780, 44390, 23330, 86870, 1469, 130450, 114629, 184720, 32180, 56400, 131980, 58430, 63240, 59330, 58640, 29810, 11790, 25690, 13330, 39900, 70460, 160410, 55770, 25179, 18490, 27650, 79830, 40630, 16900, 41369, 118770, -2760, 190000, 119920, 85020, 73980, 49120, 51200, 41940, 71030, 51970, 75200, 80390, 70520, 69910, 119636, 40720, -16800, 48360, 70910, 66170, 54730, 66650, 70930, 41940, 8919, -8201, 48240, 50080, 44120, 70290, 74640, 94410, 30920, 56720, 187800, 170140, 45710, 124420, 59660, 90450, 24040, 129420, 173100, 45500, 37120, 34300, 52610, 59770, 89350, 59000, 32820, 23020, 26780, 19180, 19350, 22770, 37900, 56130, 21080, 41360, 49010, 16290, 14480, 23140, 90940, 39390, 43869, 138650, -19100, 34470, 34630, 12036, 102620, 24060, 14260, 9980, 71280, 5559, 19670, 141580, 37160, 9199, 23650, 17750, 22180, 99940, 7589, 17540, 16790, 5080, 34200, 7580, 25040, 7300, 13060, 17520, 6419, -1381, 41910, 10830, 4100, 20210, 188340, 5209, 12970, 14960, 15149, 11780, 105870, 10600, 16640, 9179, 9750, 7869, 9400, 9640, 34300, 10610, 7640, 12680, 21000, 76650, 12170, 13130, 6909, 19100, 16490, 13150, 12810, 7980, 97129, -2571, 12800, 13140, 14170, 59090, 4630, 5150, 6889, 6050, 13490, 3860, 10260, 13930, 3160, -1600, 40730, 88140, 11680, 11560, 10280, 5390, 9440, 131340, 7570, 144740, 60570, 12210, 142160, 8029, 70330, 6570, 8240, -1070, 5180, 75360, 64130, 4979, 73200, 7920, 2460, 3080, 60010, 7470, 10450, 2600, 99590, 134120, 5400, 1179, 76180, 4209, 3650, 38840, 8910, 4250, 14170, 3999, 76350, 4860, -15060, -341, 128230, 2330, 5859, 22060, 44500, 770, 4769, 1039, 539, 53740, 5130, 5729, 13939, 5580, 48450, 1110, 6199, 164570, 179370, 4720, 6339, 12740, 3569, 6740, 4089, 13730, -641, 2360, 8390, 12540, 5500, 4519, 5790, 8100, 4159, 6329, 7200, 2510, 2199, 9430, 1130, 7710, 11010, 11439, 9619, 8699, 5529, 99290, 6729, 7670, 60320, 8769, 3379, 4350, 2020, 10470, 2929, 187500, 5399, 839, 2790, 2430, 9999, 1970, 2979, 8070, 2849, 5110, 5679, 979, 4449, 2559, -410, 829, 3989, 279, 11130, 130020, 63780, 48590, 15020, 59370, 174670, 44850, 4510, 57900, 3340, 5340, 6710, -1150, -4031, 4400, 1400, 13450, 5500, 3909, 133800, 1570, 2959, 38050, 6499, 37810, 599, 1560, 1949, 38340, 66110, 13230, -1020, 9730, 3350, 2790, 8729, 109, 1679, 1690, 2440, 1910, 5659, 43820, 80340, 739, 47080, 1709, 164110, 58980, 5069, 1810, 16480, -1550, 81400, 3139, 133160, 2669, -821, 3349, 2360, 4120, 1960, 4129, 25520, 3660, 2260, 2959, 6350, 6830, 559, -3540, 5040, 62340, -8401, 4570, 6469, 14420, 3509, 172060, 4749, 38850, 3860, 167900, 1540, 59530, 176210, 2949, 13930, 819, 132560, 74890, 34410, 5559, 41260, 102000, 174330, -17380, 10730, 8950, 144260, 2560, 24580, 6370, 80, 22540, 2060, 1019, 160, 3180, 11580, 88900, 10470, 6260, 73860, 3119, 2980, 158220, 4309, 30660, 68780, 5040, 3770, 99260, 1980, 1970, 6829, 2289, -20080, 2310, 9650, -2251, 2529, 2530, 14700, 3959, 166700, 3599, 150930, 3459, 20810, 6590, 55690, 22690, 5139, 69, 6480, -12630, 37400, 9400, 186250, 9540, 10830, 14040, 9070, 4760, 7700, 56650, 11310, 4790, 194180, 128610, 6400, 7109, 2769, 9170, 14430, 104370, 9179, 178490, 1839, 3649, 9690, 20490, 339, 3980, 9289, 97370, 16590, 13480, 3039, 9209, 108480, 29490, 14640, 22230, 2340, 15880, 155060, 121920, 2909, 27250, 163260, 172970, 2660, 18100, 5159, 5870, 3790, 2880, 4320, 12500, 56360, 125710, 17810, 19190, 106000, 83140, 42550, 104300, 56000, 102609, 49720, 119469, 171680, 32940, 81140, 57710, 46010, 47900, 12410, 51430, 52000, 71890, 38220, 59550, 30110, 25690, 60750, 41920, 42970, 122470, 41700, 24520, 36670, 43590, 28380, 65420, 20490, 46900, 74830, 23260, 30570, 53800, 48360, 44400, 28940, 38850, 55090, 44390, 117250, 26040, 38180, 40279, 21509, 40690, 43770, 23870, 34920, 35680, 47920, 34530, 10209, 38060, 36900, 172090, 22500, 41440, 48970, 51970, 40759, 32670, 29570, 8320, 32190, 36220, 26469, 7490, 50070, 16550, 52680, -14320, 18900, 55380, 31810, 30419, 92140, 31910, 29040, 139770, 30299, 117280, 30630, 29670, 36720, -13690, 31170, 24230, -7440, 28120, 27790, 26429, 26000, 27230, 25920, 76240, 30360, 186670, 44830, 116240, 24560, 29890, 95180, 82150, 26890, 70680, 23220, 173160, 18330, 29520, 47580, 40140, 29100, 28250, 26230, 27280, 29190, 15910, 28300, 15970, 18410, 23929, 86500, 26960, 195790, 23360, 15049, 27500, 25880, 29740, 14950, 18950, 98230, 19830, 21830, 33440, 109480, 16040, 61550, 23600, 20700, 24970, 25500, 19860, 15920, 25010, 26910, 14280, 18950, 15430, 12709, 22380, 78950, 4990, 32920, 110000, 23040, 16230, 26429, 10009, 14770, 27599, 21410, 19900, 149800, 159730, 25800, 9250, 16530, 14280, 99670, 28780, 7340, 11060, 14120, 7850, 123859, 27430, 9960, 32360, 11210, 104469, 14710, 11570, 14290, 95429, 18660, 4369, 9129, 9270, 17570, 8890, 6709, 9220, 7710, 11250, 6599, 5370, 3400, 4270, 179, 2290, 4540, 13700, 93360, 59470, 8529, -851, 19020, 4139, 5289, 2350, 6269, 990, 8240, 7010, 8050, 1210, 4560, 1259, 9949, 8110, 64180, 3909, 6729, 2690, 5280, 150810, 6709, 148720, 32080, 2289, 171240, 6690, 79710, 122870, 39720, 3809, 122739, 30200, 5390, 5709, 8730, 118730, 74280, 13320, 5130, 4419, 3000, 3679, 9389, 63420, 6690, 95570, 20350, 5090, 44240, 120660, 29440, 2999, 35740, 63700, -1540, 155930, 145400, 5790, 939, 175990, 3370, 5030, 8129, 69630, 3980, 19400, 27460, 10430, 25930, 6300, 3050, 5360, 4789, 5870, 16930, 1360, 3990, 3170, 79640, 12030, 125269, 7050, 3980, 42910, 9890, -19210, 25280, 170010, 10610, 3749, 3420, 10510, 2749, 7790, 1890, 27759, 140190, 5329, 3289, 6660, 82810, 7319, 1650, 37550, 8889, 7769, 499, 9579, 6610, 35280, 11940, 7629, 2200, 1180, 7390, 159380, 29129, 172160, 108520, 1330, 5769, 1170, 2310, 4110, 54490, 2309, 90020, 1360, 3090, 147650, 79810, 53960, 148120, 5100, 1890, 669, 4730, 190970, -570, 14780, 2929, 3439, 8649, 133040, 96310, 110079, 9729, -151, 4940, 2090, 151720, 6060, 2439, -1190, 2919, 34290, 5939, 2029, 12110, 15930, 175700, 5290, 589, 4910, -1241, 14340, -2690, 1250, 10480, 10930, 116080, 17710, -1590, 6629, 25540, -11360, 2330, 11860, 27210, 153740, 5040, 5950, 1549, 37630, 4259, 2010, 34760, 2959, 4410, 6640, 6889, 179130, 2920, -60, 9899, 144140, 2350, 5719, 3420, 4159, 3330, 799, 2390, 5310, 3079, 4840, 18340, 3719, 6260, 5810, 7309, 3969, 132430, 7079, 5280, 549, 2090, 22160, 1699, 5679, 2509, 2129, 2999, 2469, 4830, 4780, 3960, 3040, 2710, 2440, 2859, 32670, 1659, 9360, 4670, 2080, 4059, 1059, 2789, 5639, 3589, 1709, 5050, 6039, 3850, 13180, 2140, 2079, 6579, -1821, 1389, 7799, 1739, 5910, 1610, 5020, 1809, -721, 4659, 2929, -4720, 1829, 5420, 2709, 50380, 6510, 4900, 1380, 78330, 6539, 5170, 4370, 409, 92280, 5740, -5240, 67910, 33020, 13450, 3690, 6899, 5139, 67240, 6620, 2099, 5599, 13440, 32679, 28520, -180, 30930, -421, 4630, -641, 8349, 5080, 129, 1480, 5289, 11870, 4140, 4360, 1450, 1629, 67510, -421, 21240, 4620, 106560, 2909, 1640, 1290, 35360, 3020, 158790, 2440, 1200, -911, 186220, 88630, 11220, 2760, 109090, 1729, 2269, 30290, 3889, 28940, 1820, 28870, 2559, 1930, 3350, 2659, 9469, 690, 1270, 5479, 1309, 1579, 149430, 6060, 2289, 55039, 1910, 699, -770, 1540, 6850, 64080, 2819, 850, 166420, -441, 1869, 13020, 480, 5479, 25160, -31, -981, 2100, 1620, 7470, 2270, 2390, 5259, 10760, 5520, 13850, 1910, 4650, 26980, 5580, 13470, 1379, 4770, -2110, 67810, 128539, 59940, 48220, 5219, 184470, 1770, 699, 2079, 11750, 124680, 6210, 59900, 14120, 2260, 1140, 110020, 1779, 23809, -1401, 34390, 1970, 67430, 8870, 44820, 4270, 3970, 20880, 123800, 80690, 74260, 98010, 5329, 1080, 1170, -1370, 60700, 3479, 1419, 2499, 57480, 2859, 87760, 3290, -2181, 4539, 859, 3010, 5810, -4340, 158760, 53230, 3790, -6940, 115210, -171, 389, 54720, 81370, 9070, -12800, 102100, 3790, 140870, 125290, 66200, 5500, 7980, 26760, 13240, 4789, 14150, 23180, 8039, 8580, 8720, 6790, 144350, 118030, 4259, 9330, 4600, 7759, 166130, 1229, 6909, -1090, 5270, 118510, 139370, 4460, 115410, 8939, 1140, -9890, 1809, 5070, 6720, 8089, 3749, 72070, 8120, 5770, 6959, 106649, -31, 6090, 5920, 6360, 3400, 2849, 7780, 97370, 157360, 62720, 21920, -2180, 75390, 69, 26280, 6740, 7990, 20550, 2700, 7050, 104860, 67500, 140930, 4179, 4890, 9140, 459, 2829, 31800, 3839, 142650, 86160, 1739, 22910, 25480, 175740, 136730, 2790, 68020, 41520, -771, 2410, 7269, 61130, 47270, 539, 12740, 7960, 74870, 5390, 2690, 4800, 107590, 11250, 13799, 12540, -2471, 3520, 4869, 3750, 7290, 11580, 4570, 93740, 141260, -2510, 4790, 3800, 22599, 144230, 36850, 3710, 3459, 12609, 13720, 21469, 13280, 76830, 2449, 5709, 3969, 19, 37430, 569, 166100, 40190, 163939, 13330, 190770, 178250, 25700, -721, 4369, 8630, 147620, 19530, 16770, 16040, 869, 37960, 111130, 55470, 12310, 49370, 164270, -14760, 15730, 60470, 39740, 13420, 4970, 10200, 7700, 98310, 27540, 15350, 1490, 30840, 5699, 7070, 15000, 3360, 4649, 6919, 6340, 5950, 10680, 8300, 6199, 20900, 4570, 4429, 7540, 9350, 10410, -871, 7570, 1659, 289, 8310, 10310, 5390, 106550, 6610, 49240, 127590, 6780, 5649, 6169, 32320, 1240, -1721, 4690, 2439, 7929, 77530, 128090, 10840, 100630, 3630, 188329, 8720, 84620, 59530, 11900, 95580, 5470, 43960, 74950, -381, 47110, 86950, 66336, 92680, 82720, 60920, 1459, 38380, 17530, 5669, 141360, 135700, 29940, 18850, 3299, 14900, 59000, 17080, -541, 141500, -381, 19600, 15020, -571, 11010, 17110, 15960, 122080, 47050, 22710, 63130, 10169, 5280, 12150, 11550, 5280, 174490, 6590, 3839, 4519, 156290, 28769, 73210, -7371, 22900, 10490, 9810, 9660, 50119, 8410, 36810, 13000, 11760, 78980, 43510, 10720, 28590, 13560, 6270, 8420, 2440, 18500, 7820, 11970, 46580, 15570, 5070, 143250, 12110, 2859, 9860, 44200, 13850, 8780, 10440, 13850, 5960, -15830, 12340, 19080, 8290, 11060, 164950, 3810, 9650, 42270, 170740, 7550, 47050, 14190, 12290, 20970, 1540, 8470, 479, 2050, 15610, 93040, 9579, -1440, 107410, 15830, 23360, 9890, 97820, 22490, 7990, 1110, 4190, 76240, 22679, 12740, 28560, 3850, 29120, 16780, 2210, 2070, 13200, 5299, 1759, 1940, 17310, -20, 6679, 4910, 4949, 6390, 1370, 7520, 88400, 7240, 155250, 7090, 33940, 62660, 8009, 68800, 10009, 3970, 4819, 59930, 174750, 94460, 136080, 80230, 28080, 6040, 19670, 8119, 12180, 67460, 28320, 739, 22780, 7090, 138100, 35450, 3299, 13560, 5820, 8109, 2330, 74480, 3000, 9140, -31, 10610, 15980, 10880, -11070, 16900, 7950, 2989, 4690, 133840, 4680, 12070, 3850, 4790, 7740, 8119, 2940, 2280, 4170, 3679, 103080, 31040, 3290, 6560, 1750, 5440, 5550, 5639, 50710, -1191, 46540, 6160, 31120, 5290, 7730, 7040, 123430, 2360, 9969, 6840, 699, 13000, 113960, 65610, 2749, 3590, 3329, 6059, 104040, 7060, 174760, 4980, 166740, 579, 3500, 41860, 7109, 5370, 44670, 22580, 35230, 26020, 7019, 9689, 16860, 3870, 3509, 12830, 16580, 1130, 8240, 56830, 96679, 16279, 8519, 13779, 4509, 56250, 2770, 3750, 4310, 8500, 7010, 6570, 102840, 27770, 4400, 3700, 619, 126290, 5859, 4740, 11070, 6030, -1230, -3230, 7840, 8179, 91370, 75930, 134770, 11439, 63700, 13590, 130160, 62680, 6040, 6850, 6279, 21589, 7609, 3599, 3469, 150150, 46160, 47580, 6130, 76360, -15750, 14380, 53620, 10820, 2150, 8590, 7600, 4670, 4599, 6539, 4560, 32280, 9640, 7049, 109840, 7030, 110150, 5699, 5200, 119300, 90730, 132780, 123130, 12360, 111580, 5070, 34940, 16240, 2900, 949, 2470, 59120, 7129, 3359, 90910, 16180, 1620, 5370, -530, 169590, 146010, 8650, 37420, 68050, 126130, 104560, 2890, 300, 39230, 18150, 27519, 7760, 3370, 1429, 92090, 119149, 9929, 2479, 2150, 6709, 121649, 36730, 35990, 51330, 10270, 6070, 629, 5249, 18510, 10270, 3240, -320, 24230, 3089, 117210, 21750, 40279, 17190, 7349, 9460, 1779, 6609, 2610, 4960, 5409, 4910, 2419, 10290, 7109, 130530, 19860, 13650, 13560, -12130, 98940, -17310, 8470, 9220, 4239, 196430, 4250, 1960, 100150, 3020, 5370, 28670, 4899, 8210, 14040, 5920, 5090, 39860, 3999, 17410, 3290, 105480, 4550, 5820, 5080, 136300, 3870, 35600, 6140, 11450, 1390, 33250, 24640, 30700, 130530, 28929, 9389, 24210, -1271, 189460, 1270, 809, 108290, 9919, 27180, 1999, 109, 153130, 3790, 8969, 18390, 4769, 8749, -8780, 3630, 1690, 10960, 18660, -570, -890, 178930, 4570, 34270, 560, 2660, -2411, 136430, 12180, 4140, 9649, 140230, 4380, 4079, 16540, 57939, 70360, 6430, 9289, 2630, 52080, 51340, 5849, 6270, 14300, 29160, 42280, 4750, 8489, 5850, 39080, 3519, 6339, -410, 17860, 4819, 15920, 6989, 80760, 10780, 2259, 16490, -900, 54960, 11800, 5480, 14190, 3900, 5109, 139540, 63650, 11880, 779, 17300, 13759, -19560, 17870, 60550, 8060, 45310, 35980, 9810, 186439, 28220, 12890, 18940, 10500, 1900, 101870, 33000, 2829, 10080, 7810, 14990, 12830, 11150, 74180, 11610, -5510, 168730, 12080, 11870, 51010, 10660, 12100, 7029, 11399, -9330, 10080, 11860, 29, 8480, 2259, -6170, 9830, 8520, 37520, 26400, -911, 9440, 7189, 15620, 4100, 10450, 1490, 140990, 2060, 3139, 44210, 25770, 23100, 87670, 17110, 1519, 5420, 12470, 7930, 26280, 5479, 16890, 118140, 18870, -2140, 7170, 5970, 14490, 13030, 10540, 12540, 24710, 3859, 14440, 709, 9459, 10670, -1331, 6929, 65310, 52000, 10220, 5870, 128660, -181, 5890, 8850, 120360, 18260, 11359, 12780, 152980, 819, 8909, 10380, 4769, 9190, 3159, 11880, 1019, 80250, -2871, 8630, 5849, -701, 11160, 12569, 25930, 9190, 9520, 77590, 159430, 5500, 82810, 8159, 150100, 69350, 4390, 4850, 42190, 3150, 8220, 105090, 1519, 11399, 135670, 66470, 8450, 60900, 13540, 36730, 144100, 11530, 12100, 3100, 100860, 129860, 11510, 8860, 26500, 5639, 12170, -2270, 44410, 16120, 30179, 10200, 21850, 8809, 11399, 4620, 5800, 8129, 7480, -741, 2209, 10109, 3860, 3560, 3750, 2869, 3609, 3930, 15860, 125970, 2250, 5980, 8679, 17280, 4880, 3100, 10260, 11310, 8189, 6340, 142520, 7639, 2520, -15210, 9689, 161580, 7429, 122080, 7520, 43620, 7400, 15089, 9739, 8429, 16130, 14840, 6140, 9810, 139320, 6690, 9819, 7380, 125320, 5950, 139190, 3900, 5490, 2730, -6791, 4170, 5029, 7589, 1279, 91120, 3300, 6729, 5110, 1869, 163990, -181, 24830, 58240, 139070, 117440, 3400, 3409, 3880, 1900, 33150, 5130, 59400, 23830, 5120, 20360, 6019, 6909, 102410, 629, 3950, 8239, 184140, 6149, 10530, 16750, 85740, 8930, 46936, 177860, 5280, 4449, 11610, 4369, 5900, 111890, 10290, 3850, 137810, 6650, 6610, 181180, 23420, 83300, 168490, 42670, 7079, 4789, 4069, 168130, 4780, 9250, 4890, 104120, 40890, 53380, 120630, 3310, 182369, 51350, 54050, 18320, 49000, 116900, 7780, 55430, 25810, 4270, 5470, 2610, 8530, 83570, 144990, -191, 50870, 15120, 9100, 6899, 5369, 4339, 95940, 7060, 177700, 14580, 62420, 44680, 36320, 82790, 11240, 29640, 5350, 21309, 8799, 7690, 6179, 909, 138260, 3059, 90480, 87110, -4101, 75260, 2719, 4339, 2549, 2070, 6279, 50830, 179020, 115620, 1230, 5409, 7520, 4549, -1141, 13970, 3320, 18240, 190990, 3740, 2349, 3870, -101, 8480, 8560, 16630, 1389, 4679, 1150, -531, 6899, -571, 1109, 3489, 3940, 4239, 6350, 989, 6099, 184330, 4029, 136120, 11500, 5270, 4470, 103190, 37550, 5079, 4369, 44680, 79400, 3469, 127120, 219, 5580, 77630, 122940, 7959, 34560, 4220, 56650, 53650, 71330, 26640, 141620, 83130, 19550, 7979, 71320, 7180, 10129, -4100, -11900, 2429, 36700, 15280, 3340, 11399, 6780, 13950, 10560, 7040, 2330, 161490, 10209, 74500, 10610, 16930, 5230, 4339, 193090, 1389, 1530, 11840, 111649, 8630, 70180, 11470, 42450, 5239, 7730, 8089, 9149, 5310, 26140, 6969, 3950, 8270, 19130, 8300, 4419, 59429, 35930, 166590, 1579, 669, 17340, 3090, 176800, 5580, 29690, 103940, 31200, 46640, 151130, 9630, 7710, 4560, 127080, 7350, 26160, 153950, 80670, 4330, 4460, 6990, 9869, 40380, 5870, -2880, 103500, 21309, 9840, 22010, 1879, 155440, 5320, 9159, -240, 10530, 7170, 8580, 62590, 10290, 38390, 154760, 4079, 86430, 10380, 709, 2680, 7610, 5500, 12500, 39100, 5030, 122840, 7719, 193080, 4229, 4550, 590, 9099, 1969, 4239, 130730, 32719, 5840, 95030, 1640, 1160, 77050, 6460, 32010, 190340, 182590, 160430, 86380, 43179, 113420, 47640, 151990, 1530, 52040, 30700, 41736, 4560, 118050, 47880, 168909, 8310, 2580, 47640, 29900, 64940, 27820, 15440, 20410, 71090, 2509, 9179, 2210, 3400, 5400, 133700, 91300, 8799, 27180, 5639, 28280, -6090, 31850, 59980, -25100, 112600, 26320, 29020, 9090, 29070, 8429, 9599, 1850, 19120, 13390, 12529, 11810, -130, 5140, 7759, 3960, 14660, 3279, 19110, 182550, 57820, 10169, 13660, 14190, 4360, 19180, 14070, 5679, 129820, 70070, 1580, 4700, 4869, 73520, -1301, 94730, 14280, 147660, 72330, 14620, 14260, 166400, 959, 1859, 58280, 41330, 2109, 15690, 32590, 195880, 24560, 56380, 17240, -18780, 5540, 9860, 116910, 177079, 5770, 41940, 990, 168950, 89070, 22450, 7950, 187390, 23220, 63840, 19090, 50460, 24420, 19780, 15800, 21300, 13850, 31820, 20840, 21370, 12700, 14140, 10550, 8199, 8609, 890, 12330, 17620, 4809, 18490, 7769, 12850, 13460, 15880, 176340, 145900, 8440, 1930, 4149, 6859, 83570, 6909, 83379, 15069, 4069, 29480, 93600, 8350, 3169, 3969, -21580, 13939, 13870, 7739, 2300, 19620, 12230, 12100, 549, 13010, 9090, 7509, 14090, 5739, 3050, 107120, 127899, 6969, 133470, 158020, 16530, 121510, 12350, -10570, 182369, 152200] - }, - { - "label": "Diameter", - "values": [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081, 319366, 124041, 455411, 280876, 147711, 368624, 315981, 203423, 170419, 318081, 237211, 321023, 258211, 260481, 341011, 429823, 273989, 296489, 285589, 302889, 235581, 214989, 388889, 392489, 334089, 432089, 423289, 358489, 235589, 244989, 223823, 229989, 389489, 262681, 219489, 226389, 312723, 344923, 401889, 464489, 387789, 283223, 254689, 233089, 397989, 370889, 374289, 256489, 409489, 410789, 294711, 380711, 203011, 280789, 288211, 234211, 284989, 353623, 479081, 143423, 399489, 313089, 249823, 282889, 172623, 287689, 170419, 325623, 389789, 348189, 299689, 275089, 215523, 226323, 377489, 412389, 416623, 497789, 309389, 340989, 270623, 294889, 104423, 121723, 339623, 334589, 132823, 386011, 345723, 206623, 256481, 408911, 289011, 149881, 117823, 317823, 208589, 319789, 286723, 428089, 426289, 425789, 320589, 321881, 344989, 398989, 306581, 412089, 305823, 284489, 373989, 282189, 302723, 442889, 429989, 343389, 253681, 315889, 267123, 174289, 379823, 319089, 345489, 170419, 447589, 305189, 436189, 387023, 446989, 439189, 366089, 472989, 491189, 465789, 368289, 416289, 263023, 195389, 451889, 368389, 351889, 458989, 318823, 413989, 347389, 360823, 406189, 361589, 430589, 481589, 254689, 422489, 361823, 379689, 297389, 380689, 363089, 383189, 409289, 388989, 424089, 397789, 401389, 386989, 346911, 450089, 427789, 391389, 345789, 402689, 429389, 434989, 351789, 468289, 365381, 402489, 436689, 372081, 382889, 384289, 392689, 411989, 440111, 390523, 393789, 376389, 397089, 495889, 335489, 424289, 414889, 409289, 389889, 408189, 412189, 384489, 402189, 433789, 379489, 271389, 392989, 401189, 390989, 410889, 415389, 381389, 409089, 449389, 317089, 387689, 312189, 409489, 448489, 405089, 405389, 449489, 364611, 424189, 221489, 418989, 302823, 408589, 413189, 389023, 439689, 417089, 389289, 420789, 262889, 172589, 420789, 419989, 409989, 405689, 418289, 410389, 406689, 408289, 407089, 423789, 409289, 423189, 406389, 423189, 320489, 418489, 410189, 417189, 216823, 424089, 387123, 395681, 412389, 239011, 416489, 418489, 417389, 429989, 393289, 419689, 406789, 332089, 327089, 419589, 414389, 413389, 413089, 403389, 420889, 261489, 424189, 412189, 402889, 426389, 417789, 415589, 404889, 418789, 413189, 415489, 405789, 408689, 418789, 437489, 474489, 399689, 403689, 414389, 415589, 416789, 422489, 196889, 411489, 424089, 217881, 423089, 418989, 421289, 422589, 411089, 422489, 211411, 424789, 415389, 426889, 417489, 411789, 430089, 395023, 411089, 417289, 428689, 415989, 423989, 420289, 387223, 394923, 432489, 390181, 439989, 313523, 490589, 115023, 398923, 399881, 236123, 180089, 399323, 343723, 190789, 421389, 415389, 405981, 427289, 432089, 403789, 381789, 420289, 414789, 418689, 408789, 436089, 422189, 318323, 437789, 420689, 420789, 411189, 437289, 435389, 286689, 444489, 418989, 437489, 422289, 418889, 440489, 427689, 354023, 418889, 425389, 414689, 444189, 208589, 446389, 418389, 483989, 421689, 412689, 328989, 423089, 427689, 339989, 425289, 381789, 421389, 227189, 353123, 426989, 428289, 418189, 425589, 427189, 420489, 432589, 428189, 426189, 396223, 421289, 421489, 420189, 435811, 422389, 446681, 486789, 421089, 426089, 422589, 422689, 435189, 359323, 485289, 433189, 351789, 387423, 322489, 304689, 426289, 420489, 423589, 146223, 398889, 397981, 406189, 418481, 408789, 241489, 395589, 398489, 419289, 425189, 426189, 405281, 141123, 398281, 229389, 422189, 426589, 428189, 420989, 386989, 262789, 421089, 476189, 232189, 413589, 412989, 494589, 422689, 269481, 223989, 426389, 368711, 397811, 418989, 429089, 414489, 417889, 426211, 410689, 425289, 445289, 415489, 421489, 370789, 387223, 416789, 412789, 284489, 351223, 399689, 472889, 415889, 290923, 407389, 393123, 410989, 348089, 359789, 419789, 218289, 427389, 417489, 370389, 395381, 417189, 400789, 389289, 388689, 420889, 171989, 146311, 419789, 388981, 421089, 396381, 370489, 484089, 418989, 362889, 388423, 392289, 400889, 408889, 419389, 365023, 413889, 277089, 407889, 403989, 421389, 461689, 432989, 409889, 455389, 412489, 440389, 426989, 188189, 483589, 436689, 405289, 247189, 330089, 441189, 453789, 425189, 418089, 415889, 374611, 417589, 409789, 330223, 276689, 408981, 406181, 501789, 211389, 413323, 455411, 277789, 375689, 314623, 274711, 188989, 452011, 366389, 300689, 285689, 316823, 333689, 320523, 501789, 282889, 345623, 283289, 442689, 440889, 318289, 330589, 341089, 271123, 325823, 452589, 316089, 323889, 477281, 289589, 390923, 265789, 261489, 353223, 310711, 501789, 210223, 325789, 288423, 284289, 302889, 326889, 380323, 338389, 394989, 294989, 339689, 302889, 288089, 334089, 346589, 329989, 270589, 317489, 271689, 315189, 314789, 383889, 337789, 270389, 248381, 303089, 302189, 320089, 334089, 134211, 337889, 313589, 333089, 452889, 308089, 443289, 305989, 448989, 338789, 291989, 296981, 317589, 362389, 336689, 344389, 211089, 353789, 173989, 289523, 325089, 316589, 370689, 331089, 338489, 329189, 340589, 322889, 323489, 335789, 372489, 376589, 423389, 316189, 209089, 318489, 481389, 334189, 467889, 246023, 334289, 384889, 274989, 396589, 409189, 391489, 342589, 290989, 338389, 319789, 348289, 352489, 346989, 449511, 345689, 318823, 395089, 350689, 351489, 285081, 339189, 179889, 355189, 411289, 334789, 332989, 210389, 409289, 354289, 426489, 353489, 370489, 325389, 348989, 302423, 320289, 367789, 358789, 344089, 356789, 360189, 365589, 352689, 354689, 445989, 358289, 423489, 392689, 358989, 404289, 400889, 348589, 498789, 342389, 380489, 258523, 458689, 353711, 343789, 339689, 320789, 387789, 392489, 364789, 407289, 398489, 387989, 430089, 313281, 404389, 404189, 379589, 372289, 435189, 422489, 410189, 248189, 400689, 413089, 316723, 401089, 409889, 447489, 360189, 426089, 406489, 399089, 356089, 402889, 401689, 399589, 408689, 396289, 402789, 417089, 416789, 407089, 421989, 425889, 404389, 384789, 315189, 464089, 390781, 425289, 380589, 416389, 412889, 407289, 407089, 420889, 401389, 408689, 412289, 421689, 367811, 422189, 406289, 402689, 288611, 394981, 402489, 418889, 409989, 407689, 400689, 176589, 424989, 419889, 336389, 392889, 341689, 410089, 240589, 415689, 343681, 425789, 412889, 467689, 405489, 161523, 385989, 435589, 432489, 421589, 445789, 414989, 367889, 386589, 438889, 443089, 415289, 416889, 397389, 482189, 416389, 418789, 421389, 453789, 440189, 301489, 303411, 423889, 405389, 254889, 413089, 417489, 343111, 323489, 410989, 501789, 324189, 425489, 428489, 414789, 423289, 418189, 419889, 415089, 418489, 426189, 400889, 419089, 330389, 416489, 442089, 409289, 418989, 366689, 420889, 413889, 438989, 342689, 409689, 424289, 393881, 415689, 425289, 411889, 426889, 450189, 262889, 414489, 419889, 354223, 490689, 429589, 430289, 243289, 329923, 412089, 417789, 334023, 404689, 325989, 408389, 404489, 412789, 413989, 425889, 496989, 317489, 362189, 263589, 421489, 416089, 429089, 418689, 414689, 411181, 416689, 214589, 412189, 416889, 420289, 285689, 171189, 449589, 416789, 416889, 416089, 420489, 146123, 410489, 404989, 414489, 413389, 417289, 408389, 286689, 263989, 429489, 429289, 417389, 411889, 191589, 419189, 412389, 433689, 415589, 431889, 419389, 424489, 424689, 427489, 277789, 421889, 413889, 415689, 414189, 430389, 423689, 400289, 431989, 416489, 395989, 217689, 429689, 416489, 423389, 351423, 428489, 418189, 409689, 444389, 420389, 423289, 425289, 361489, 415189, 419689, 417189, 423189, 414689, 419389, 423889, 176489, 422589, 413389, 418789, 330389, 422289, 421589, 424589, 405481, 408489, 415789, 392181, 419689, 421989, 419389, 485389, 428589, 426189, 425689, 417689, 425089, 400489, 425989, 420989, 419289, 426889, 428481, 427789, 418989, 418689, 422489, 422789, 423089, 404781, 428989, 421189, 420389, 418689, 421389, 419189, 398089, 429189, 224189, 420089, 349023, 420189, 425189, 424889, 418389, 417889, 419689, 414289, 416389, 421289, 415989, 419389, 421989, 420989, 416989, 421889, 418789, 421389, 411689, 422689, 421589, 421689, 419989, 414189, 419489, 427989, 418489, 421589, 349723, 283989, 420689, 421789, 419989, 390489, 425389, 424089, 424089, 423689, 196989, 413389, 401189, 428689, 474589, 380289, 471889, 421789, 418389, 432389, 411589, 427789, 413789, 393389, 431989, 483589, 427589, 431489, 423989, 500489, 419189, 410289, 411989, 330489, 423989, 408889, 419089, 429389, 436189, 428289, 350523, 342311, 427989, 355423, 416589, 412189, 416689, 431389, 421889, 232189, 422589, 302889, 422389, 417789, 426889, 290589, 306489, 427589, 428189, 381889, 427489, 417089, 292889, 419889, 333389, 429589, 332089, 419189, 420489, 425289, 414189, 416089, 417889, 419089, 409989, 422689, 428989, 198489, 416189, 421889, 191389, 415689, 429789, 424489, 429389, 210289, 316989, 424589, 429289, 281881, 423189, 425089, 420589, 422989, 423989, 449189, 427089, 424589, 419789, 426589, 420089, 420089, 435889, 420189, 432189, 414589, 422289, 426689, 424289, 421989, 438989, 209089, 418989, 429089, 415889, 459689, 423389, 427389, 394589, 435589, 261089, 424089, 447789, 415989, 303289, 376989, 425689, 295789, 419589, 427189, 419389, 284589, 414989, 316689, 420789, 372511, 427089, 323489, 417089, 355589, 424089, 427089, 423989, 198789, 303889, 342189, 364689, 419489, 415989, 424089, 428489, 283789, 414989, 421589, 422789, 337989, 418189, 392189, 415889, 428589, 412389, 415189, 339723, 420689, 414189, 402189, 423489, 346923, 292189, 445311, 229489, 418889, 401589, 467089, 424089, 490789, 396789, 420889, 404089, 334889, 242823, 441789, 404989, 465189, 423389, 408511, 413289, 382281, 460389, 411989, 401589, 411889, 210289, 312489, 420189, 424489, 433789, 404189, 242111, 414489, 440689, 424689, 418089, 298689, 447089, 419189, 295689, 397389, 431389, 431981, 418689, 421089, 423589, 396889, 415289, 485089, 418589, 418089, 428189, 452289, 428089, 418889, 418589, 412189, 426789, 428289, 419989, 316089, 450189, 297589, 349589, 321589, 431889, 434089, 394989, 424389, 274889, 347289, 431789, 422289, 462189, 341789, 153111, 425989, 427889, 374011, 430189, 302489, 404789, 410389, 447289, 457189, 399681, 396689, 352281, 423389, 373489, 410889, 428589, 412589, 427489, 418689, 400089, 497489, 428089, 422389, 381011, 421189, 282089, 415889, 407889, 425789, 222889, 377911, 421789, 376011, 431489, 423589, 412089, 422289, 286889, 423989, 420089, 479389, 490189, 437889, 414889, 419789, 320789, 382489, 294289, 417689, 419189, 255689, 422589, 350089, 412989, 404489, 420289, 414689, 423089, 421589, 437489, 414089, 308789, 418889, 224389, 420489, 199089, 268289, 479081, 416989, 418089, 392489, 310589, 427489, 406089, 411389, 423089, 383189, 261489, 273089, 413689, 406089, 353089, 369389, 409489, 411381, 372389, 418589, 492089, 423789, 427789, 365689, 357389, 420289, 307889, 377389, 430789, 402711, 430789, 433189, 419289, 406881, 428389, 361289, 395989, 401789, 388789, 298823, 413089, 413489, 410389, 406289, 398981, 423489, 424089, 302189, 412889, 392981, 415689, 340923, 310289, 400689, 392389, 460889, 415989, 407289, 408089, 405589, 418389, 403281, 411889, 366011, 407489, 297489, 424889, 408389, 444489, 414489, 268489, 413589, 288589, 299489, 412789, 305989, 420089, 401189, 422289, 413589, 457689, 367289, 124041, 437611, 161211, 379881, 420189, 302023, 342523, 385089, 307189, 474789, 367389, 418289, 377789, 373789, 401411, 397989, 405189, 315789, 372211, 415789, 422589, 425489, 404689, 415689, 417189, 219989, 413289, 371689, 281489, 417089, 405989, 408289, 397289, 424989, 198889, 409889, 427389, 424589, 222889, 409089, 325689, 438489, 295789, 428889, 408689, 417189, 349589, 365311, 392689, 409789, 395189, 424989, 259723, 388589, 423889, 407189, 419089, 408589, 350389, 390789, 398589, 406089, 387989, 402089, 427089, 180289, 403689, 414189, 412189, 431789, 413289, 225611, 386681, 406289, 275189, 387089, 399389, 405989, 402889, 407189, 489289, 275689, 413289, 394089, 462389, 408289, 323289, 335923, 410889, 411089, 410389, 413089, 416989, 278289, 401689, 460389, 330023, 416189, 195689, 372489, 309189, 391889, 205623, 307889, 407889, 422689, 415889, 317389, 407989, 411423, 337189, 342323, 334589, 405989, 415689, 431089, 407789, 408789, 420189, 422389, 394981, 413989, 409989, 419689, 399289, 398889, 425089, 408589, 372789, 402389, 171289, 409889, 414389, 486189, 407689, 326789, 380981, 415089, 428589, 486489, 374289, 166481, 474989, 412489, 393989, 419389, 385381, 404589, 410989, 416189, 410589, 422389, 419989, 394181, 241789, 412289, 400081, 419189, 418589, 421689, 378489, 258989, 415789, 306389, 421089, 416689, 402989, 400281, 461489, 404789, 393581, 419889, 416889, 360389, 420989, 397381, 432289, 402889, 422389, 405589, 423389, 428989, 421089, 435989, 334989, 423389, 413889, 412189, 397581, 413389, 418289, 407389, 496689, 407981, 309389, 412189, 327589, 418889, 410489, 418389, 445489, 422189, 408089, 390681, 424789, 455789, 234189, 281689, 390581, 426889, 415489, 418189, 392681, 405189, 412189, 412989, 254389, 416989, 425789, 284189, 423689, 438089, 347089, 328989, 410489, 425589, 420589, 439889, 372189, 413089, 422689, 420489, 417989, 422489, 428389, 269489, 263989, 408989, 430589, 409989, 282689, 274289, 422089, 423289, 419689, 365789, 427689, 424089, 247389, 499089, 428081, 408789, 410589, 470889, 415189, 413389, 394711, 421489, 419089, 421089, 409389, 424989, 395089, 295523, 479089, 394011, 490789, 361889, 227189, 270023, 454389, 416581, 393281, 429889, 376689, 361789, 365089, 303289, 242189, 241989, 420489, 419189, 462289, 406989, 178589, 412589, 432289, 414889, 416789, 425089, 413789, 366011, 419189, 266989, 498389, 419289, 260389, 417489, 447289, 454789, 406789, 388789, 386489, 250989, 390489, 434189, 291611, 313089, 394389, 379389, 412789, 408289, 419089, 260589, 302489, 457189, 396689, 273989, 409589, 390381, 422089, 443889, 257689, 473289, 454589, 369289, 332489, 241189, 465889, 501789, 380489, 356289, 456589, 360189, 421089, 423489, 339511, 261289, 469489, 436989, 457289, 443689, 422289, 381489, 380181, 435489, 456089, 454089, 281489, 424289, 306689, 410089, 440389, 474989, 434489, 458889, 395723, 420289, 210989, 423889, 368323, 411189, 434989, 441689, 413689, 437189, 398981, 372723, 458589, 424889, 361311, 261781, 429189, 353289, 420189, 381089, 437389, 394889, 346123, 412589, 431389, 176489, 418289, 424189, 372289, 428589, 421089, 303089, 420789, 420689, 343389, 428589, 411889, 251189, 406789, 433689, 362889, 173989, 423289, 416589, 420989, 436789, 326089, 406789, 427389, 412289, 276889, 309289, 310389, 326789, 485489, 322489, 409889, 476689, 415489, 226189, 414089, 424689, 453889, 340623, 319989, 399789, 412689, 346489, 429889, 428089, 405889, 423089, 411289, 467589, 411489, 432889, 414189, 385481, 430489, 270689, 248489, 422089, 501089, 421189, 266189, 421889, 347489, 421989, 433389, 334323, 197489, 401989, 414989, 339681, 449389, 383189, 417489, 419889, 401489, 192611, 232389, 419289, 427089, 380789, 362189, 437989, 372289, 417889, 408289, 383989, 409589, 401389, 420889, 406189, 420589, 233589, 399889, 371189, 387989, 373811, 405889, 419789, 301189, 412789, 413989, 472889, 419789, 426689, 349389, 198323, 412989, 283989, 422789, 392481, 417389, 416089, 431289, 398481, 249689, 417989, 401981, 197389, 366589, 415889, 295423, 413789, 423789, 236089, 302789, 424489, 415989, 415689, 360889, 409489, 412289, 217989, 420689, 451889, 360489, 414989, 382089, 347689, 415189, 420789, 389781, 420789, 350089, 387989, 416189, 343489, 372989, 439189, 283489, 382781, 386589, 387589, 384789, 406889, 398389, 403889, 399589, 419789, 404289, 372511, 264889, 413189, 391389, 386689, 387089, 409789, 321089, 375689, 413589, 407589, 385089, 405489, 402989, 416989, 387889, 491389, 381089, 422189, 419089, 415089, 423889, 353489, 412389, 397389, 336689, 415189, 400389, 429689, 409189, 402089, 391089, 402489, 192689, 333789, 395589, 383123, 229189, 349623, 411889, 403289, 353189, 414189, 334223, 399989, 423989, 347623, 400689, 408989, 410089, 395889, 409189, 386989, 425589, 253289, 431489, 402489, 406289, 287789, 408189, 410089, 393489, 333889, 404589, 258889, 414489, 404789, 462689, 416189, 253789, 235289, 278889, 402289, 351889, 279289, 401589, 204889, 403589, 412789, 258089, 327089, 415289, 319789, 392389, 312489, 444789, 398489, 434789, 421789, 430189, 262189, 406689, 399189, 346789, 410389, 411089, 333489, 289689, 346589, 337989, 397789, 392289, 398689, 400789, 418589, 394789, 400489, 404989, 289189, 414689, 418689, 401189, 421189, 407289, 433089, 412689, 419489, 458189, 417381, 367911, 482989, 398989, 365989, 407989, 416789, 407189, 431689, 407889, 404389, 342589, 407389, 491589, 404889, 405889, 409989, 413489, 398989, 409589, 432589, 396789, 414889, 407389, 402489, 453489, 332423, 403389, 399689, 468589, 412889, 403589, 253989, 464589, 415289, 442181, 404789, 400889, 489489, 414689, 410089, 414489, 492889, 415989, 379211, 412789, 418489, 413689, 369711, 180889, 283589, 413489, 429389, 500089, 336389, 412789, 421689, 423989, 432789, 385289, 421489, 501789, 405489, 407589, 400189, 417589, 418689, 224689, 425489, 413289, 421389, 301389, 420289, 421489, 299289, 386389, 415489, 170419, 217189, 418989, 416289, 407689, 417089, 417789, 374889, 410889, 416289, 180981, 392289, 388689, 281989, 433589, 356789, 326889, 350089, 416989, 406181, 424089, 246489, 415989, 420289, 420889, 399589, 376889, 341989, 361489, 417689, 278089, 206289, 347289, 387589, 276789, 255789, 414989, 211489, 328311, 409089, 418089, 423689, 471489, 448089, 228889, 419689, 480089, 420589, 425789, 287789, 433089, 340423, 280389, 423189, 255789, 421989, 498589, 425989, 459589, 426889, 285389, 335389, 430289, 207689, 427789, 431889, 398281, 425689, 445189, 429189, 211989, 427689, 343789, 306189, 417589, 418389, 460289, 425089, 415989, 381489, 259589, 359589, 282489, 416689, 243589, 426289, 309189, 418089, 434589, 378389, 182889, 422389, 421289, 426089, 428789, 427989, 424189, 390489, 424889, 425989, 438289, 432089, 297789, 416489, 442689, 329889, 433389, 422389, 427289, 426889, 366823, 232489, 431781, 399589, 173411, 367123, 374089, 127923, 279289, 408281, 435089, 361023, 281789, 439089, 462881, 437589, 412989, 281489, 374389, 481189, 323481, 411589, 335289, 332289, 425489, 402389, 179589, 437489, 397581, 409281, 462589, 395281, 424489, 404081, 462789, 433489, 450789, 418989, 424389, 393081, 413989, 418289, 413189, 401681, 421489, 303889, 426689, 240789, 436689, 397111, 448489, 421389, 249889, 428889, 425489, 400389, 437289, 406489, 357989, 411089, 401289, 333423, 419489, 408889, 415289, 422689, 447389, 417089, 427289, 417089, 314489, 451789, 409589, 496489, 177489, 185889, 432989, 426089, 399389, 381511, 325789, 368611, 307889, 376011, 425789, 386389, 492489, 475489, 304689, 423189, 351989, 422289, 268189, 316289, 386711, 306489, 334223, 404889, 433089, 447989, 419089, 250589, 252789, 398689, 415389, 416689, 416989, 295389, 417589, 302189, 423189, 399489, 439089, 385989, 436889, 411889, 327889, 404189, 438989, 207489, 410989, 412689, 417989, 411689, 424789, 391789, 334789, 410489, 239389, 417589, 248989, 386781, 328323, 415889, 399789, 423089, 415389, 369489, 499589, 414389, 437489, 396681, 412189, 216911, 410189, 380723, 269389, 227889, 254489, 480989, 384989, 254589, 336389, 363889, 412489, 466389, 501789, 170419, 421189, 467289, 456989, 368689, 423689, 291989, 454389, 341823, 465389, 343623, 421389, 341689, 284889, 446689, 423989, 427689, 430789, 262789, 321789, 345411, 423789, 311989, 442389, 393023, 395689, 409289, 424989, 501789, 457789, 355589, 409589, 418889, 406089, 434489, 413789, 431289, 403589, 368889, 394781, 428689, 424089, 436389, 413189, 424189, 410189, 455989, 414689, 243289, 357589, 427089, 411189, 425889, 398481, 350281, 499089, 349989, 304589, 421089, 438989, 414789, 434089, 431589, 364823, 424489, 417989, 357189, 331489, 381589, 418189, 260789, 420189, 422189, 328989, 438489, 417689, 477889, 419889, 221989, 199189, 269989, 334389, 473589, 419389, 417189, 413981, 375989, 415089, 432389, 425889, 301289, 399089, 386581, 418289, 263889, 373589, 382389, 417181, 402189, 417589, 348023, 423789, 399789, 440289, 342589, 435389, 416089, 439789, 454389, 458289, 413789, 425689, 415889, 407489, 437589, 407689, 386889, 417089, 405289, 412189, 393989, 364389, 276789, 413389, 286489, 416289, 418189, 316089, 479689, 221989, 415089, 406089, 423989, 209789, 423289, 433089, 401089, 437589, 404389, 411089, 407389, 446789, 355589, 407489, 403789, 428289, 354689, 423889, 412689, 404889, 425389, 428289, 414589, 173789, 329089, 220711, 456589, 492489, 309689, 377289, 477489, 314089, 206411] - }, - { - "label": "RF block", - "visible": false, - "values": [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154, 9197, 18159, 13115, 41120, 4254, 53966, 17129, 14957, 12469, 12882, 19875, 23547, 16325, 15238, 15452, 31817, 18210, 16237, 13815, 24070, 14163, 10748, 16292, 12787, 19559, 10597, 34781, 25859, 23121, 7331, 19298, 17056, 18788, 12009, 8997, 9280, 10990, 9825, 13690, 14547, 15443, 14758, 22429, 9324, 13396, 10915, 12615, 13307, 16842, 12533, 11312, 29347, 2923, 28796, 42332, 12953, 14401, 16151, 23973, 4730, 21716, 13116, 13175, 15085, 8140, 14046, 15629, 13231, 5612, 14571, 14929, 12812, 9048, 10826, 20129, 17258, 12673, 11513, 12391, 14423, 10741, 14543, 4797, 6770, 12516, 15056, 26071, 38770, 15137, 15072, 11241, 26828, 8765, 10555, 10704, 13486, 6364, 10951, 12683, 21652, 27201, 21344, 10776, 9748, 11037, 12370, 8567, 13685, 11766, 12085, 11494, 20165, 13118, 14030, 13022, 10399, 14657, 11485, 10530, 13011, 6136, 10941, 24564, 2983, 44046, 27024, 13288, 11442, 25304, 11719, 10889, 42292, 21241, 13750, 11650, 12963, 7752, 11368, 12729, 10642, 9786, 12557, 11922, 10954, 10880, 9807, 11606, 10332, 11490, 12266, 8847, 11958, 9329, 11618, 30498, 9096, 9656, 10880, 12137, 10590, 30171, 10776, 12029, 10048, 9194, 12699, 11935, 10320, 12246, 10999, 11670, 12919, 10448, 28090, 9996, 11446, 11869, 11452, 11130, 10617, 10938, 10938, 61633, 9401, 10986, 10264, 11382, 26443, 7246, 10959, 10865, 10461, 15205, 10010, 11370, 10761, 9628, 10072, 15113, 15277, 10752, 15445, 10415, 10409, 11365, 42807, 10732, 80687, 14568, 10607, 25736, 10835, 25227, 10372, 10690, 10861, 9204, 24356, 9578, 10690, 16420, 32922, 9966, 10328, 22516, 11073, 10370, 10319, 16053, 12519, 10850, 10016, 23430, 9967, 10409, 16565, 33216, 10086, 11852, 10717, 71528, 10854, 6473, 9864, 24531, 10169, 10465, 13817, 8117, 10114, 10539, 9383, 9575, 9905, 10607, 10809, 12302, 11300, 17273, 19981, 10379, 62047, 32661, 10668, 10740, 11887, 10168, 10328, 10606, 5848, 19699, 9904, 10606, 12471, 10735, 10454, 10221, 11269, 10282, 10788, 10518, 13610, 10157, 12402, 12469, 10341, 11117, 11692, 11407, 11290, 10950, 11411, 10684, 15902, 9235, 11594, 10388, 10673, 10287, 11358, 10456, 21224, 11029, 9757, 10623, 20290, 11303, 10606, 10576, 10914, 10215, 11150, 10688, 20300, 10648, 10158, 9969, 10490, 9674, 14900, 8394, 58012, 9555, 18938, 12074, 10625, 16410, 18293, 8646, 7452, 10486, 10598, 10851, 9883, 9527, 9921, 8487, 12350, 21204, 10475, 33939, 10793, 10449, 12448, 11840, 16981, 9941, 9714, 10921, 17966, 13494, 13501, 9559, 12461, 10527, 10273, 12408, 10142, 8618, 10065, 10490, 19855, 11973, 6992, 27078, 9865, 22933, 10190, 39964, 15056, 10890, 10469, 9225, 9722, 22231, 10448, 16940, 8739, 9933, 10792, 10162, 10820, 10476, 10596, 15300, 10848, 10490, 10626, 11052, 11152, 9908, 10688, 10853, 23939, 10974, 10706, 11293, 25292, 10575, 44141, 9329, 42453, 11111, 33703, 9989, 14744, 29684, 10627, 12450, 10102, 10804, 22365, 15455, 10235, 17927, 28090, 22636, 5696, 10830, 11452, 37616, 10548, 14079, 2381, 9319, 5708, 10278, 10270, 10173, 10438, 10466, 14781, 11824, 13649, 11169, 10106, 10054, 48407, 10727, 8452, 10180, 11032, 9142, 27478, 10124, 10562, 10836, 10135, 7096, 9831, 11865, 10439, 10077, 10337, 10278, 10402, 40924, 10160, 24221, 8787, 12698, 13555, 20043, 9006, 10211, 30486, 10615, 5012, 13470, 11561, 21404, 11943, 35820, 10150, 10799, 10569, 10388, 18464, 10494, 10739, 17119, 10382, 10994, 10169, 10365, 10862, 10219, 35420, 11482, 36677, 10085, 9303, 10751, 26201, 9832, 9444, 11268, 16820, 24669, 11580, 10429, 13545, 31487, 14811, 28689, 13605, 22274, 13142, 15556, 39192, 11083, 28305, 22002, 32055, 11237, 14968, 15304, 10818, 14371, 9237, 10504, 11672, 15811, 20320, 13030, 18281, 37483, 10853, 18766, 33670, 11700, 25359, 13903, 19952, 17043, 18835, 21038, 13206, 10850, 13772, 8348, 14495, 25290, 14003, 13966, 12454, 16773, 15792, 14666, 12615, 18555, 20326, 13386, 16211, 11108, 12505, 18943, 13578, 13475, 9963, 13037, 24033, 10640, 25696, 8173, 12725, 9708, 9863, 12975, 12783, 29488, 10613, 15552, 10566, 9981, 11013, 10682, 10087, 12383, 11656, 10325, 10872, 8027, 11261, 11077, 38056, 10047, 9527, 9601, 12561, 10987, 10731, 10944, 6680, 11525, 10922, 10432, 38982, 12574, 19619, 12819, 8162, 9543, 12403, 9836, 14314, 22537, 11423, 11359, 16214, 12020, 11313, 9979, 10532, 11140, 5538, 11040, 10342, 7274, 11035, 10156, 9986, 10486, 12454, 12438, 24463, 20432, 20455, 12397, 37736, 10196, 18212, 15145, 18863, 13024, 13364, 12974, 41227, 11856, 11346, 11326, 12760, 10202, 15894, 11309, 22422, 17922, 9380, 11075, 11609, 9989, 21795, 16305, 10791, 18100, 10980, 12215, 10666, 10339, 7981, 12100, 10235, 28922, 10339, 11453, 15440, 24216, 8614, 14903, 11618, 10720, 10714, 11399, 10649, 10249, 11125, 11523, 13787, 10415, 12882, 10920, 11001, 23505, 19807, 12172, 76180, 10338, 10975, 8062, 13561, 20564, 11107, 9966, 8921, 34621, 36878, 11835, 10960, 11871, 10982, 29514, 10178, 10481, 11149, 10573, 9197, 34702, 15114, 11222, 7482, 11016, 28924, 9036, 11100, 12007, 30205, 10454, 10890, 10902, 10595, 10095, 10696, 10249, 10609, 10740, 10824, 10277, 10679, 10296, 13965, 9912, 10483, 9972, 10735, 19105, 24162, 10498, 9856, 11457, 10418, 10479, 9695, 10405, 20038, 21024, 10611, 10964, 10095, 18471, 10126, 11042, 10546, 13961, 9864, 10287, 10254, 10350, 36948, 10205, 19478, 16141, 10222, 32500, 9865, 19020, 32054, 7968, 10325, 26167, 15826, 10497, 26223, 10784, 11040, 21312, 13074, 11326, 10699, 11514, 10271, 9270, 27080, 11929, 29848, 13399, 10618, 16773, 38775, 15158, 10308, 16630, 24280, 10359, 26577, 25968, 11063, 9358, 24236, 10131, 10633, 8785, 16274, 10153, 17928, 10168, 12024, 15155, 10751, 10514, 10726, 10694, 10684, 12918, 10318, 9723, 10353, 18212, 11901, 35670, 10645, 10501, 14751, 11704, 5960, 21709, 33016, 11319, 10692, 9730, 11579, 10545, 10898, 10450, 16733, 20856, 10557, 10411, 9420, 31288, 35500, 10552, 7849, 8744, 10903, 9795, 9018, 10362, 11398, 11504, 21077, 9900, 19523, 22921, 48955, 10100, 35563, 17163, 10109, 10710, 10407, 10174, 10338, 19927, 10088, 11713, 9719, 10242, 37731, 15195, 6232, 41049, 10615, 10017, 9755, 10709, 14637, 9291, 11864, 10109, 10156, 11304, 67519, 17390, 17379, 12079, 10161, 10612, 9842, 15579, 10903, 9928, 10148, 10154, 16966, 10889, 10372, 12307, 13177, 26663, 10878, 9647, 10531, 9319, 13014, 9437, 9204, 12344, 11695, 29491, 4829, 9900, 33272, 14803, 6452, 10605, 11949, 14380, 41594, 10764, 11066, 10315, 13599, 10388, 10160, 22538, 10492, 10394, 11021, 11273, 16408, 10459, 9505, 11608, 27802, 10337, 10946, 10642, 10364, 19852, 9766, 9477, 10783, 10463, 32639, 33506, 10877, 11257, 11148, 11070, 10769, 32854, 11405, 10836, 9867, 10488, 14866, 10453, 10822, 10211, 10304, 10483, 10395, 10455, 11100, 10595, 10385, 10249, 10315, 10299, 14743, 10506, 4196, 10680, 8481, 10569, 10217, 10535, 10788, 10380, 10104, 10496, 10774, 10578, 12092, 10172, 10273, 11082, 28496, 10138, 11213, 10182, 10541, 10214, 10813, 10209, 9657, 10418, 10325, 9225, 10075, 10889, 8608, 11322, 11055, 10799, 10054, 22351, 34451, 10954, 10801, 10028, 10797, 10584, 8069, 23265, 19284, 10490, 12889, 11179, 10694, 23407, 10668, 10530, 10576, 33861, 16659, 18867, 10082, 16290, 9883, 14526, 9639, 10930, 10400, 6394, 10245, 10304, 11994, 10994, 11345, 10426, 8470, 17899, 10053, 16420, 10516, 29232, 10200, 10599, 10119, 14293, 10478, 27110, 10359, 9926, 9912, 29435, 17805, 12276, 10674, 26997, 10445, 20195, 9146, 10524, 10816, 10555, 10744, 10242, 10180, 14829, 10046, 11402, 13681, 9995, 10387, 10157, 10482, 15997, 21537, 20617, 7234, 19940, 10347, 9837, 10492, 3567, 15063, 10527, 14404, 26219, 9845, 10367, 12283, 10012, 11008, 16150, 10090, 9801, 10182, 10385, 11210, 10227, 10945, 10796, 12408, 10596, 12523, 10445, 10863, 15001, 11714, 4158, 10011, 11102, 18453, 25567, 34427, 21636, 17312, 11486, 25894, 10305, 11143, 10014, 7083, 29212, 11225, 13217, 12442, 10534, 30505, 18992, 9916, 9305, 9562, 14432, 10474, 15954, 11336, 14433, 10782, 10858, 13947, 13731, 16533, 18216, 23681, 32935, 9827, 10190, 9891, 12630, 10233, 10130, 10387, 15376, 10256, 24143, 10237, 9739, 10317, 9752, 8255, 10923, 8741, 37789, 61374, 8664, 4220, 34907, 3366, 9820, 18920, 28985, 11698, 10181, 82710, 10549, 34749, 25408, 11746, 16455, 10624, 17395, 12460, 11048, 12144, 12643, 13238, 11049, 10607, 10713, 16579, 22372, 10607, 11766, 11282, 10549, 22312, 9792, 12057, 9784, 10705, 21263, 39010, 10601, 20597, 10461, 10502, 8825, 10079, 10800, 11227, 20574, 10297, 28465, 11264, 10799, 11484, 32910, 10132, 10895, 21699, 10646, 10735, 10696, 11264, 19742, 42988, 41859, 10492, 5759, 24954, 10411, 13437, 11267, 5603, 10173, 10822, 11230, 33464, 17149, 11761, 10849, 11071, 10266, 10318, 5839, 14954, 10101, 39692, 29152, 9676, 12924, 11540, 43420, 30908, 9929, 23278, 17192, 9964, 10193, 20560, 27021, 19244, 9997, 11196, 11353, 14331, 10630, 9783, 10959, 14011, 21597, 12489, 10930, 19611, 10617, 10366, 32400, 5912, 12172, 32577, 65364, 44139, 10069, 10473, 10503, 9310, 33098, 10077, 10394, 10412, 5522, 12512, 10444, 11968, 23134, 20539, 10636, 10680, 9865, 17915, 9652, 57471, 17323, 19811, 12337, 19754, 25944, 18475, 9532, 10535, 20382, 26345, 13869, 12280, 12403, 10090, 14846, 17309, 11379, 11821, 18237, 46284, 7399, 12253, 21048, 14545, 12262, 14172, 11900, 11608, 23811, 11756, 12709, 11665, 13314, 11359, 11199, 13162, 11013, 10641, 10930, 11373, 16875, 10709, 14663, 19210, 9117, 10354, 10345, 10785, 33407, 11203, 9776, 22824, 5670, 9550, 10557, 11541, 8667, 41163, 10187, 17357, 76115, 10894, 10300, 14510, 15094, 9959, 9200, 10324, 8811, 10727, 15676, 34492, 11302, 30983, 10239, 27184, 11148, 16012, 13382, 11702, 18726, 10832, 16952, 24133, 9454, 21152, 22064, 5202, 29716, 8219, 18975, 10078, 11633, 10604, 9357, 25145, 82471, 25294, 13270, 8653, 20891, 41040, 11945, 9080, 25991, 8592, 26568, 12760, 9918, 11163, 25627, 12672, 15235, 18263, 11658, 12806, 11580, 10176, 11538, 10923, 11015, 18276, 10587, 10847, 10852, 18896, 14635, 16942, 18271, 8292, 12197, 11126, 11489, 14929, 9764, 15179, 11765, 10865, 25110, 10109, 10387, 15412, 11745, 10938, 10866, 7458, 11852, 31513, 11403, 16621, 11869, 22140, 27762, 11317, 10083, 11296, 18886, 12088, 4649, 10649, 11756, 5362, 5696, 11160, 12697, 10587, 11287, 49254, 5111, 11307, 16226, 65648, 10693, 12976, 9795, 11685, 13300, 9676, 11079, 19515, 4971, 36232, 30848, 8851, 9364, 12046, 10543, 27251, 14449, 25057, 8742, 10756, 10119, 31794, 16824, 13457, 13126, 10940, 8487, 15164, 12277, 10026, 10669, 11707, 10301, 10134, 10264, 12246, 9538, 10608, 10708, 9828, 30769, 10272, 10700, 22730, 10375, 28088, 10679, 15887, 26494, 10750, 16367, 10320, 20659, 11089, 25920, 37391, 9229, 57506, 24371, 13704, 10908, 12191, 10632, 11670, 22268, 14633, 10035, 28198, 10394, 18725, 16048, 9974, 12317, 10831, 11404, 8516, 12843, 10178, 13677, 9834, 23288, 11986, 11347, 18648, 12240, 21040, 10354, 10543, 29142, 10722, 11426, 11068, 9953, 11366, 10677, 10497, 10617, 10630, 11202, 22069, 48435, 10150, 10683, 9589, 10529, 21533, 10302, 24630, 9491, 12154, 10609, 10864, 10744, 10824, 11051, 35643, 10335, 11128, 10196, 20262, 14029, 15512, 13132, 9473, 10776, 10227, 10858, 27460, 10466, 41882, 10425, 23124, 9776, 10710, 10243, 11306, 11631, 13932, 9667, 15904, 15014, 34062, 12569, 10702, 10223, 10575, 24485, 12828, 20228, 11740, 11350, 15787, 12331, 11897, 11918, 5419, 11540, 10408, 10647, 10595, 9036, 11470, 11221, 15296, 19651, 11423, 10007, 9515, 38820, 10686, 10398, 23090, 11000, 9523, 9228, 10795, 11570, 25015, 16290, 41501, 23156, 27076, 9705, 16633, 39615, 25068, 11360, 10211, 14392, 9340, 16150, 8181, 51944, 8740, 17771, 10974, 24164, 8383, 11886, 6533, 11492, 10738, 11183, 11084, 10903, 10390, 9487, 10620, 8266, 15542, 11094, 17072, 33639, 33150, 12483, 10196, 29392, 24209, 18940, 30223, 25634, 20366, 6509, 14943, 10926, 10030, 9480, 10221, 15497, 6424, 12117, 25062, 13167, 9658, 9925, 19563, 62188, 21058, 14014, 57943, 19077, 25315, 15032, 12432, 13616, 14913, 20394, 17053, 26546, 10478, 10214, 21465, 18236, 14091, 11012, 11873, 12159, 33008, 14540, 14730, 20518, 13484, 12526, 4889, 10978, 11327, 11275, 11315, 37227, 15152, 12142, 30949, 13920, 6760, 13238, 10143, 11176, 10785, 12044, 10015, 11509, 10305, 9929, 11989, 11969, 9381, 19884, 14021, 9348, 12366, 6139, 60031, 5686, 9360, 11195, 11103, 17782, 14637, 10345, 24660, 10742, 10857, 9383, 10755, 11377, 8993, 11301, 10398, 8455, 9976, 13778, 8067, 31746, 10800, 10741, 10798, 37306, 6794, 15761, 11289, 11595, 4846, 20598, 9148, 10764, 41269, 10303, 11103, 17525, 9367, 22586, 9782, 10147, 33394, 28569, 9935, 9319, 13227, 30809, 10949, 11866, 12566, 10833, 11049, 10057, 10110, 10675, 11593, 12021, 30957, 4385, 23884, 21501, 21241, 19901, 4683, 9416, 28303, 12191, 11174, 9041, 15090, 19681, 10345, 9568, 22790, 20433, 10896, 11544, 19006, 7436, 17652, 10867, 11300, 14826, 12256, 18901, 17356, 22603, 20761, 15085, 10008, 10169, 9754, 12484, 21462, 10322, 10221, 21330, 10370, 9100, 12219, 9615, 12862, 11684, 10562, 30345, 10522, 11059, 28976, 8969, 23416, 4984, 13203, 11497, 6010, 12975, 44056, 10758, 18000, 16477, 11233, 19186, 12322, 12033, 8707, 11488, 10317, 14374, 9960, 10525, 11512, 11073, 9890, 11719, 11539, 10378, 12021, 20131, 34812, 16470, 10299, 14957, 11583, 12118, 10190, 11986, 5592, 10248, 11855, 6832, 9332, 11067, 4082, 10369, 9916, 15017, 12934, 9081, 10595, 10432, 11759, 10559, 11043, 8917, 21134, 9891, 9176, 16130, 12942, 13627, 18725, 10904, 9808, 10271, 10536, 10638, 13854, 10695, 11433, 39161, 11455, 18960, 11107, 10703, 12723, 9257, 11431, 11105, 10333, 10313, 11585, 10344, 11084, 21966, 8377, 10323, 8185, 14299, 10609, 10551, 16646, 11337, 10546, 10707, 26303, 12953, 9294, 11267, 39151, 8228, 10602, 11245, 10260, 10439, 9924, 10518, 10226, 13153, 9727, 10631, 10293, 4908, 11351, 11699, 13297, 7873, 10887, 13199, 39299, 10164, 28920, 11162, 21162, 10873, 5283, 9938, 13808, 5140, 10517, 12483, 9389, 23219, 19894, 16043, 11175, 14779, 11053, 10940, 39710, 10974, 12795, 10458, 29754, 19573, 11346, 10526, 11079, 10434, 11672, 6137, 10845, 18903, 11224, 10704, 12516, 10495, 11055, 10604, 9788, 10452, 10533, 4945, 9983, 11643, 9712, 10519, 13844, 10913, 14131, 10514, 14742, 33770, 8857, 13931, 10485, 20982, 10189, 10240, 11140, 12490, 10792, 10299, 28767, 10669, 13604, 6395, 10977, 39186, 10903, 61691, 10745, 18824, 10159, 12396, 11054, 10595, 20240, 9738, 10219, 21439, 41329, 10739, 10896, 4868, 52815, 10708, 38900, 9872, 9994, 13546, 8304, 10149, 10501, 14794, 9865, 24487, 10105, 10997, 10480, 8867, 15620, 4849, 14141, 21448, 44760, 24356, 10123, 10512, 32705, 10711, 14130, 10830, 26961, 13539, 10216, 12642, 10823, 11040, 13619, 10147, 10247, 11415, 30393, 10969, 11854, 7609, 46668, 22548, 7873, 62534, 10747, 10471, 11411, 14595, 10810, 26857, 11315, 10359, 13682, 19665, 19345, 27815, 14945, 20679, 31038, 13784, 15296, 10509, 10744, 22472, 10520, 11555, 10757, 27673, 14992, 14989, 27100, 10319, 27530, 7593, 15409, 11668, 10774, 17530, 11036, 8222, 10799, 20249, 10742, 20896, 13897, 38765, 18303, 9745, 71755, 12680, 11783, 5892, 22802, 8486, 23485, 11273, 24528, 12647, 27395, 18613, 19047, 25991, 6369, 22035, 11269, 4850, 11819, 23594, 10413, 10210, 38584, 10776, 11590, 26886, 12407, 15941, 10203, 10543, 16827, 10406, 10801, 16961, 25091, 26117, 4995, 10669, 4570, 10934, 5509, 12342, 11069, 11221, 18032, 10606, 10294, 10794, 10149, 23535, 11605, 11509, 10267, 10945, 10808, 10208, 12462, 9539, 10996, 13746, 11135, 10701, 22650, 10277, 9871, 22744, 23044, 33427, 3378, 9747, 8703, 7656, 9463, 10656, 11297, 15888, 14886, 11302, 38639, 10594, 10537, 14643, 57349, 14269, 11499, 10223, 15088, 28919, 23684, 13888, 13690, 26912, 12774, 11234, 26520, 10459, 11919, 8800, 9204, 10845, 18581, 12632, 10618, 11108, 10805, 24695, 11472, 10718, 10299, 55165, 12039, 11745, 12596, 12705, 36938, 10675, 25627, 10441, 10320, 11116, 32508, 10810, 18654, 23086, 16685, 8342, 11231, 10819, 11306, 10918, 16246, 10979, 10863, 11223, 8547, 12869, 10174, 26564, 10143, 16311, 10658, 10181, 12059, 9562, 32135, 9438, 29761, 26396, 16018, 16535, 46584, 14336, 9155, 21595, 27259, 11287, 7579, 38688, 46567, 6178, 8256, 31900, 12278, 19151, 10862, 3608, 15766, 12738, 15914, 42111, 10020, 36021, 10692, 6690, 9883, 15079, 12033, 9900, 22825, 11361, 11951, 37286, 11418, 10924, 11337, 9619, 10213, 10856, 11048, 10842, 12414, 10325, 16869, 11143, 25523, 9572, 8037, 9731, 10596, 14328, 10393, 41055, 20795, 14812, 29254, 9532, 9682, 22098, 10576, 14922, 27530, 22068, 44823, 62466, 15851, 17035, 13790, 32455, 9763, 22771, 20480, 5260, 10708, 36714, 21263, 35770, 11534, 5466, 21040, 12474, 25403, 12246, 12780, 19804, 14025, 22915, 11714, 10546, 10914, 4907, 25442, 21807, 11633, 9574, 11884, 20814, 10725, 15213, 21476, 24079, 34650, 11473, 14708, 11460, 14527, 12063, 11321, 10635, 38457, 9976, 11387, 12442, 9942, 11507, 21903, 14923, 12090, 12044, 13137, 23724, 16638, 12050, 23906, 12763, 10095, 10450, 16574, 7953, 23314, 46235, 10924, 10452, 11349, 49136, 8569, 28080, 12395, 31054, 17199, 10749, 12401, 23741, 9983, 10240, 14952, 18745, 10093, 15763, 15947, 22766, 9734, 11323, 9103, 8183, 10813, 11526, 31744, 37984, 10665, 18484, 10234, 28322, 24927, 12733, 11218, 26552, 11835, 19255, 13685, 18189, 14281, 11213, 12967, 12791, 13413, 23402, 14537, 13631, 13160, 14190, 13652, 11060, 11685, 9787, 11534, 14020, 10163, 11664, 11130, 11526, 11963, 11541, 36500, 31777, 11087, 5208, 10415, 11008, 17780, 13966, 11527, 12402, 9959, 15587, 11744, 11524, 10972, 9728, 6301, 11682, 11987, 10687, 11419, 10401, 11515, 11320, 10253, 9305, 11693, 10882, 11733, 22243, 10735, 29551, 12129, 7360, 16884, 43866, 16754, 22618, 10169, 10098, 31603, 17397] - } - ] - }] + + "cells": { + + "values": [ + [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666], + [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000], + ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"], + [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797], + [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939], + [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778], + [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373], + [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666], + [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081], + [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154] + ], + + "format": [ + ".2s", + "#0x", + null, + [",.0f", ",.1f", ",.2f", ",.3f", ",.2f"], + "$,", + "_>5", + ",.1%", + null, + null, + null + ], + + "prefix": ["", "", "", "", "US ", ""], + "suffix": ["m", ""], + + "height": 20, + + "align": ["center", "center", "center", "right", "right", "right", "left", "right"], + "valign": ["top", "bottom", "middle"], + + "line": { + "color": [ + ["grey"] + ], + "width": 0.5 + }, + + "fill": { + "showscale": true, + "reversescale": true, + "colorscale": "Viridis", + "valueformat": ",.2r", + "cmin": -4000, + "cmax": -100, + "color": [ + ["#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9"] + ] + }, + + "font": { + "color": [ + ["rgb(214,235,14)", "rgb(24,251,11)", "rgb(109,103,67)", "rgb(152,192,23)", "rgb(80,207,160)", "rgb(84,134,44)", "rgb(222,105,214)", "rgb(76,181,63)", "rgb(110,173,82)", "rgb(144,56,245)", "rgb(48,196,142)", "rgb(190,102,179)", "rgb(115,83,61)", "rgb(54,231,74)", "rgb(235,105,39)", "rgb(1,128,246)", "rgb(205,58,176)", "rgb(34,128,113)", "rgb(222,81,3)", "rgb(18,252,69)"], + ["rgb(107,128,223)", "rgb(95,62,207)", "rgb(110,65,159)", "rgb(17,249,0)", "rgb(184,189,240)", "rgb(234,55,166)", "rgb(254,75,119)", "rgb(215,70,114)", "rgb(102,160,80)", "rgb(7,190,174)", "rgb(177,25,224)", "rgb(237,181,164)", "rgb(122,240,243)", "rgb(54,245,219)", "rgb(65,30,43)", "rgb(67,161,153)", "rgb(77,77,169)", "rgb(11,144,192)", "rgb(27,193,182)", "rgb(176,134,145)"], + ["rgb(214,204,7)", "rgb(228,251,163)", "rgb(22,8,80)", "rgb(129,125,180)", "rgb(229,211,97)", "rgb(14,77,169)", "rgb(31,68,23)", "rgb(219,106,81)", "rgb(113,123,241)", "rgb(113,228,139)", "rgb(115,124,86)", "rgb(185,227,179)", "rgb(126,218,33)", "rgb(83,39,227)", "rgb(43,40,158)", "rgb(244,77,12)", "rgb(19,15,168)", "rgb(212,66,245)", "rgb(175,76,103)", "rgb(250,61,197)"], + "red", + ["magenta", "blue"], + ["rgb(47,249,84)", "rgb(186,219,118)", "rgb(116,107,204)", "rgb(255,6,79)", "rgb(157,34,21)", "rgb(90,61,107)", "rgb(12,195,215)", "rgb(16,22,219)", "rgb(111,207,137)", "rgb(106,15,130)", "rgb(156,131,30)", "rgb(178,28,31)", "rgb(90,192,19)", "rgb(188,146,244)", "rgb(83,1,104)", "rgb(74,206,15)", "rgb(200,23,125)", "rgb(94,68,55)", "rgb(25,43,18)", "rgb(72,79,254)"] + ], + "size": [20, [16, 12]], + "family": ["monospace",["serif", "sans-serif"]] + } + } + }] } diff --git a/test/jasmine/tests/table_test.js b/test/jasmine/tests/table_test.js new file mode 100644 index 00000000000..b95c05c25d2 --- /dev/null +++ b/test/jasmine/tests/table_test.js @@ -0,0 +1,972 @@ +var Plotly = require('@lib/index'); +var Lib = require('@src/lib'); +var d3 = require('d3'); +var Plots = require('@src/plots/plots'); +var Table = require('@src/traces/table'); +var attributes = require('@src/traces/table/attributes'); + +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); +var mouseEvent = require('../assets/mouse_event'); + +// mock with two dimensions (one panel); special case, e.g. left and right panel is obv. the same +var mock2 = require('@mocks/table_2.json'); + +// mock with one dimension (zero panels); special case, as no panel can be rendered +var mock1 = require('@mocks/table_1.json'); + +// mock with zero dimensions; special case, as no dimension can be rendered +var mock0 = Lib.extendDeep({}, mock1); +mock0.data[0].dimensions = []; + +var mock = require('@mocks/table_large.json'); + +var lineStart = 30; +var lineCount = 10; + +describe('table initialization tests', function() { + + 'use strict'; + + describe('table global defaults', function() { + + it('should not coerce trace opacity', function() { + var gd = Lib.extendDeep({}, mock1); + + Plots.supplyDefaults(gd); + + expect(gd._fullData[0].opacity).toBeUndefined(); + }); + + it('should use global font as label, tick and range font defaults', function() { + var gd = Lib.extendDeep({}, mock1); + gd.layout.font = { + family: 'Gravitas', + size: 20, + color: 'blue' + }; + + Plots.supplyDefaults(gd); + + var expected = { + family: 'Gravitas', + size: 17, + color: 'blue' + }; + + expect(gd._fullData[0].labelfont).toEqual(expected); + expect(gd._fullData[0].tickfont).toEqual(expected); + expect(gd._fullData[0].rangefont).toEqual(expected); + }); + }); + + describe('table defaults', function() { + + function _supply(traceIn) { + var traceOut = { visible: true }, + defaultColor = '#444', + layout = { font: Plots.layoutAttributes.font }; + + Table.supplyDefaults(traceIn, traceOut, defaultColor, layout); + + return traceOut; + } + + it('\'line\' specification should yield a default color', function() { + var fullTrace = _supply({}); + expect(fullTrace.line.color).toEqual('#444'); + }); + + it('\'colorscale\' should assume a default value if the \'color\' array is specified', function() { + var fullTrace = _supply({ + line: { + color: [35, 63, 21, 42] + }, + dimensions: [ + {values: [321, 534, 542, 674]}, + {values: [562, 124, 942, 189]}, + {values: [287, 183, 385, 884]}, + {values: [113, 489, 731, 454]} + ] + }); + expect(fullTrace.line).toEqual({ + color: [35, 63, 21, 42], + colorscale: attributes.line.colorscale.dflt, + cauto: true, + autocolorscale: false, + reversescale: false, + showscale: false + }); + }); + + it('\'domain\' specification should have a default', function() { + var fullTrace = _supply({}); + expect(fullTrace.domain).toEqual({x: [0, 1], y: [0, 1]}); + }); + + it('\'dimension\' specification should have a default of an empty array', function() { + var fullTrace = _supply({}); + expect(fullTrace.dimensions).toEqual([]); + }); + + it('\'dimension\' should be used with default values where attributes are not provided', function() { + var fullTrace = _supply({ + dimensions: [{ + values: [1], + alienProperty: 'Alpha Centauri' + }] + }); + expect(fullTrace.dimensions).toEqual([{values: [1], visible: true, valueformat: '3s', _index: 0}]); + }); + + it('\'dimension.visible\' should be set to false, and other props just passed through if \'values\' is not provided', function() { + var fullTrace = _supply({ + dimensions: [{ + alienProperty: 'Alpha Centauri' + }] + }); + expect(fullTrace.dimensions).toEqual([{visible: false, values: [], _index: 0}]); + }); + + it('\'dimension.visible\' should be set to false, and other props just passed through if \'values\' is an empty array', function() { + var fullTrace = _supply({ + dimensions: [{ + values: [], + alienProperty: 'Alpha Centauri' + }] + }); + expect(fullTrace.dimensions).toEqual([{visible: false, values: [], _index: 0}]); + }); + + it('\'dimension.visible\' should be set to false, and other props just passed through if \'values\' is not an array', function() { + var fullTrace = _supply({ + dimensions: [{ + values: null, + alienProperty: 'Alpha Centauri' + }] + }); + expect(fullTrace.dimensions).toEqual([{visible: false, values: [], _index: 0}]); + }); + + it('\'dimension.values\' should get truncated to a common shortest length', function() { + var fullTrace = _supply({dimensions: [ + {values: [321, 534, 542, 674]}, + {values: [562, 124, 942]}, + {values: [], visible: true}, + {values: [1, 2], visible: false} // shouldn't be truncated to as false + ]}); + expect(fullTrace.dimensions).toEqual([ + {values: [], visible: true, valueformat: '3s', _index: 0}, + {values: [], visible: true, valueformat: '3s', _index: 1}, + {values: [], visible: true, valueformat: '3s', _index: 2}, + {values: [1, 2], visible: false, _index: 3} + ]); + }); + }); + + describe('table calc', function() { + + function _calc(trace) { + var gd = { data: [trace] }; + + Plots.supplyDefaults(gd); + + var fullTrace = gd._fullData[0]; + Table.calc(gd, fullTrace); + return fullTrace; + } + + var base = { type: 'table' }; + + it('\'colorscale\' should assume a default value if the \'color\' array is specified', function() { + + var fullTrace = _calc(Lib.extendDeep({}, base, { + line: { + color: [35, 63, 21, 42] + }, + dimensions: [ + {values: [321, 534, 542, 674]}, + {values: [562, 124, 942, 189]}, + {values: [287, 183, 385, 884]}, + {values: [113, 489, 731, 454]} + ] + })); + + expect(fullTrace.line).toEqual({ + color: [35, 63, 21, 42], + colorscale: attributes.line.colorscale.dflt, + cauto: true, + cmin: 21, + cmax: 63, + autocolorscale: false, + reversescale: false, + showscale: false + }); + }); + + it('use a singular \'color\' if it is not an array', function() { + + var fullTrace = _calc(Lib.extendDeep({}, base, { + line: { + color: '#444' + }, + dimensions: [ + {values: [321, 534, 542, 674]}, + {values: [562, 124, 942, 189]} + ] + })); + + expect(fullTrace.line).toEqual({ + color: '#444' + }); + }); + + it('use a singular \'color\' even if a \'colorscale\' is supplied as \'color\' is not an array', function() { + + var fullTrace = _calc(Lib.extendDeep({}, base, { + line: { + color: '#444', + colorscale: 'Jet' + }, + dimensions: [ + {values: [321, 534, 542, 674]}, + {values: [562, 124, 942, 189]} + ] + })); + + expect(fullTrace.line).toEqual({ + color: '#444' + }); + }); + }); +}); + +describe('@noCI table', function() { + + beforeAll(function() { + mock.data[0].dimensions.forEach(function(d) { + d.values = d.values.slice(lineStart, lineStart + lineCount); + }); + mock.data[0].line.color = mock.data[0].line.color.slice(lineStart, lineStart + lineCount); + }); + + afterEach(destroyGraphDiv); + + describe('edge cases', function() { + + it('Works fine with one panel only', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(2); + expect(document.querySelectorAll('.axis').length).toEqual(2); + expect(gd.data[0].dimensions[0].visible).not.toBeDefined(); + expect(gd.data[0].dimensions[0].range).not.toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([200, 700]); + expect(gd.data[0].dimensions[1].range).toBeDefined(); + expect(gd.data[0].dimensions[1].range).toEqual([0, 700000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + done(); + }); + }); + + it('Do something sensible if there is no panel i.e. dimension count is less than 2', function(done) { + + var mockCopy = Lib.extendDeep({}, mock1); + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(1); + expect(document.querySelectorAll('.axis').length).toEqual(1); // sole axis still shows up + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].visible).not.toBeDefined(); + expect(gd.data[0].dimensions[0].range).not.toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([200, 700]); + + done(); + }); + }); + + it('Does not error with zero dimensions', function(done) { + + var mockCopy = Lib.extendDeep({}, mock0); + var gd = createGraphDiv(); + + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(0); + expect(document.querySelectorAll('.axis').length).toEqual(0); + done(); + }); + }); + + it('Works with duplicate dimension labels', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + + mockCopy.layout.width = 320; + mockCopy.data[0].dimensions[1].label = mockCopy.data[0].dimensions[0].label; + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(2); + expect(document.querySelectorAll('.axis').length).toEqual(2); + done(); + }); + }); + + it('Works with a single line; also, use a longer color array than the number of lines', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + var dim, i, j; + + mockCopy.layout.width = 320; + for(i = 0; i < mockCopy.data[0].dimensions.length; i++) { + dim = mockCopy.data[0].dimensions[i]; + delete dim.constraintrange; + dim.range = [1, 2]; + dim.values = []; + for(j = 0; j < 1; j++) { + dim.values[j] = 1 + Math.random(); + } + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(2); + expect(document.querySelectorAll('.axis').length).toEqual(2); + expect(gd.data[0].dimensions[0].values.length).toEqual(1); + done(); + }); + }); + + it('Does not raise an error with zero lines and no specified range', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + var dim, i; + + mockCopy.layout.width = 320; + for(i = 0; i < mockCopy.data[0].dimensions.length; i++) { + dim = mockCopy.data[0].dimensions[i]; + delete dim.range; + delete dim.constraintrange; + dim.values = []; + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(2); + expect(document.querySelectorAll('.axis').length).toEqual(0); + expect(gd.data[0].dimensions[0].values.length).toEqual(0); + done(); + }); + }); + + it('Works with non-finite `values` elements', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + var dim, i, j; + var values = [[0, 1, 2, 3, 4], [Infinity, NaN, void(0), null, 1]]; + + mockCopy.layout.width = 320; + for(i = 0; i < values.length; i++) { + dim = mockCopy.data[0].dimensions[i]; + delete dim.range; + delete dim.constraintrange; + dim.values = []; + for(j = 0; j < values[0].length; j++) { + dim.values[j] = values[i][j]; + } + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(2); + expect(document.querySelectorAll('.axis').length).toEqual(2); + expect(gd.data[0].dimensions[0].values.length).toEqual(values[0].length); + done(); + }); + }); + + it('Works with 60 dimensions', function(done) { + + var mockCopy = Lib.extendDeep({}, mock1); + var newDimension, i, j; + + mockCopy.layout.width = 1680; + mockCopy.data[0].dimensions = []; + for(i = 0; i < 60; i++) { + newDimension = Lib.extendDeep({}, mock1.data[0].dimensions[0]); + newDimension.id = 'S' + i; + newDimension.label = 'S' + i; + delete newDimension.constraintrange; + newDimension.range = [1, 2]; + newDimension.values = []; + for(j = 0; j < 100; j++) { + newDimension.values[j] = 1 + Math.random(); + } + mockCopy.data[0].dimensions[i] = newDimension; + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(60); + expect(document.querySelectorAll('.axis').length).toEqual(60); + done(); + }); + }); + + it('Truncates 60+ dimensions to 60', function(done) { + + var mockCopy = Lib.extendDeep({}, mock1); + var newDimension, i, j; + + mockCopy.layout.width = 1680; + for(i = 0; i < 70; i++) { + newDimension = Lib.extendDeep({}, mock1.data[0].dimensions[0]); + newDimension.id = 'S' + i; + newDimension.label = 'S' + i; + delete newDimension.constraintrange; + newDimension.range = [0, 999]; + for(j = 0; j < 10; j++) { + newDimension.values[j] = Math.floor(1000 * Math.random()); + } + mockCopy.data[0].dimensions[i] = newDimension; + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(60); + expect(document.querySelectorAll('.axis').length).toEqual(60); + done(); + }); + }); + + it('Truncates dimension values to the shortest array, retaining only 3 lines', function(done) { + + var mockCopy = Lib.extendDeep({}, mock1); + var newDimension, i, j; + + mockCopy.layout.width = 1680; + for(i = 0; i < 60; i++) { + newDimension = Lib.extendDeep({}, mock1.data[0].dimensions[0]); + newDimension.id = 'S' + i; + newDimension.label = 'S' + i; + delete newDimension.constraintrange; + newDimension.range = [0, 999]; + newDimension.values = []; + for(j = 0; j < 65 - i; j++) { + newDimension.values[j] = Math.floor(1000 * Math.random()); + } + mockCopy.data[0].dimensions[i] = newDimension; + } + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(60); + expect(document.querySelectorAll('.axis').length).toEqual(60); + done(); + }); + }); + + it('Skip dimensions which are not plain objects or whose `values` is not an array', function(done) { + + var mockCopy = Lib.extendDeep({}, mock1); + var newDimension, i, j; + + mockCopy.layout.width = 680; + mockCopy.data[0].dimensions = []; + for(i = 0; i < 5; i++) { + newDimension = Lib.extendDeep({}, mock1.data[0].dimensions[0]); + newDimension.id = 'S' + i; + newDimension.label = 'S' + i; + delete newDimension.constraintrange; + newDimension.range = [1, 2]; + newDimension.values = []; + for(j = 0; j < 100; j++) { + newDimension.values[j] = 1 + Math.random(); + } + mockCopy.data[0].dimensions[i] = newDimension; + } + + mockCopy.data[0].dimensions[0] = 'This is not a plain object'; + mockCopy.data[0].dimensions[1].values = 'This is not an array'; + + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(5); // it's still five, but ... + expect(document.querySelectorAll('.axis').length).toEqual(3); // only 3 axes shown + done(); + }); + }); + + + }); + + describe('basic use', function() { + var mockCopy, + gd; + + beforeEach(function(done) { + mockCopy = Lib.extendDeep({}, mock); + mockCopy.data[0].domain = { + x: [0.1, 0.9], + y: [0.05, 0.85] + }; + gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); + }); + + it('`Plotly.plot` should have proper fields on `gd.data` on initial rendering', function() { + + expect(gd.data.length).toEqual(1); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(document.querySelectorAll('.axis').length).toEqual(10); // one dimension is `visible: false` + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].visible).not.toBeDefined(); + expect(gd.data[0].dimensions[4].visible).toEqual(true); + expect(gd.data[0].dimensions[5].visible).toEqual(false); + expect(gd.data[0].dimensions[0].range).not.toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].range).toBeDefined(); + expect(gd.data[0].dimensions[1].range).toEqual([0, 700000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + }); + + it('Calling `Plotly.plot` again should add the new table', function(done) { + + var reversedMockCopy = Lib.extendDeep({}, mockCopy); + reversedMockCopy.data[0].dimensions = reversedMockCopy.data[0].dimensions.slice().reverse(); + reversedMockCopy.data[0].dimensions.forEach(function(d) {d.id = 'R_' + d.id;}); + reversedMockCopy.data[0].dimensions.forEach(function(d) {d.label = 'R_' + d.label;}); + + Plotly.plot(gd, reversedMockCopy.data, reversedMockCopy.layout).then(function() { + + expect(gd.data.length).toEqual(2); + + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + expect(gd.data[1].dimensions.length).toEqual(11); + expect(gd.data[1].line.cmin).toEqual(-4000); + expect(gd.data[1].dimensions[10].constraintrange).toBeDefined(); + expect(gd.data[1].dimensions[10].constraintrange).toEqual([100000, 150000]); + expect(gd.data[1].dimensions[1].constraintrange).not.toBeDefined(); + + expect(document.querySelectorAll('.axis').length).toEqual(20); // one dimension is `visible: false` + + done(); + }); + + }); + + it('Calling `Plotly.restyle` with a string path should amend the preexisting table', function(done) { + + expect(gd.data.length).toEqual(1); + + Plotly.restyle(gd, 'line.colorscale', 'Viridis').then(function() { + + expect(gd.data.length).toEqual(1); + + expect(gd.data[0].line.colorscale).toEqual('Viridis'); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + done(); + }); + + }); + + it('Calling `Plotly.restyle` for a dimension should amend the preexisting dimension', function(done) { + + function restyleDimension(key, setterValue) { + + // array values need to be wrapped in an array; unwrapping here for value comparison + var value = Lib.isArray(setterValue) ? setterValue[0] : setterValue; + + return function() { + return Plotly.restyle(gd, 'dimensions[2].' + key, setterValue).then(function() { + expect(gd.data[0].dimensions[2][key]).toEqual(value, 'for dimension attribute \'' + key + '\''); + }); + }; + } + + restyleDimension('label', 'new label')() + .then(restyleDimension('tickvals', [[0, 0.1, 0.4, 1, 2]])) + .then(restyleDimension('ticktext', [['alpha', 'gamma', 'beta', 'omega', 'epsilon']])) + .then(restyleDimension('valueformat', '4s')) + .then(restyleDimension('range', [[0, 2]])) + .then(restyleDimension('constraintrange', [[0, 1]])) + .then(restyleDimension('values', [[0, 0.1, 0.4, 1, 2, 0, 0.1, 0.4, 1, 2]])) + .then(restyleDimension('visible', false)) + .then(done); + }); + + it('Calling `Plotly.restyle` with an object should amend the preexisting table', function(done) { + + var newStyle = Lib.extendDeep({}, mockCopy.data[0].line); + newStyle.colorscale = 'Viridis'; + newStyle.reversescale = false; + + Plotly.restyle(gd, {line: newStyle}).then(function() { + + expect(gd.data.length).toEqual(1); + + expect(gd.data[0].line.colorscale).toEqual('Viridis'); + expect(gd.data[0].line.reversescale).toEqual(false); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + done(); + }); + + + }); + + it('Should emit a \'plotly_restyle\' event', function(done) { + + var tester = (function() { + + var eventCalled = false; + + return { + set: function(d) {eventCalled = d;}, + get: function() {return eventCalled;} + }; + })(); + + gd.on('plotly_restyle', function() { + tester.set(true); + }); + + expect(tester.get()).toBe(false); + Plotly.restyle(gd, 'line.colorscale', 'Viridis') + .then(window.setTimeout(function() { + expect(tester.get()).toBe(true); + done(); + }, 0)); + + }); + + it('Should emit a \'plotly_hover\' event', function(done) { + + function testMaker() { + + var eventCalled = false; + + return { + set: function() {eventCalled = eventCalled || true;}, + get: function() {return eventCalled;} + }; + } + + var hoverTester = testMaker(); + var unhoverTester = testMaker(); + + gd.on('plotly_hover', function(d) { + hoverTester.set({hover: d}); + }); + + gd.on('plotly_unhover', function(d) { + unhoverTester.set({unhover: d}); + }); + + expect(hoverTester.get()).toBe(false); + expect(unhoverTester.get()).toBe(false); + + mouseEvent('mousemove', 324, 216); + mouseEvent('mouseover', 324, 216); + mouseEvent('mousemove', 315, 218); + mouseEvent('mouseover', 315, 218); + + window.setTimeout(function() { + + expect(hoverTester.get()).toBe(true); + + mouseEvent('mousemove', 329, 153); + mouseEvent('mouseover', 329, 153); + + window.setTimeout(function() { + + expect(unhoverTester.get()).toBe(true); + done(); + }, 20); + + }, 20); + + }); + + it('Calling `Plotly.relayout` with string should amend the preexisting table', function(done) { + + expect(gd.layout.width).toEqual(1184); + + Plotly.relayout(gd, 'width', 500).then(function() { + + expect(gd.data.length).toEqual(1); + + expect(gd.layout.width).toEqual(500); + expect(gd.data[0].line.colorscale).toEqual('Jet'); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + done(); + }); + + }); + + it('Calling `Plotly.relayout`with object should amend the preexisting table', function(done) { + + expect(gd.layout.width).toEqual(1184); + + Plotly.relayout(gd, {width: 500}).then(function() { + + expect(gd.data.length).toEqual(1); + + expect(gd.layout.width).toEqual(500); + expect(gd.data[0].line.colorscale).toEqual('Jet'); + expect(gd.data[0].dimensions.length).toEqual(11); + expect(gd.data[0].line.cmin).toEqual(-4000); + expect(gd.data[0].dimensions[0].constraintrange).toBeDefined(); + expect(gd.data[0].dimensions[0].constraintrange).toEqual([100000, 150000]); + expect(gd.data[0].dimensions[1].constraintrange).not.toBeDefined(); + + done(); + }); + + }); + + }); + + describe('Lifecycle methods', function() { + + it('Plotly.deleteTraces with one trace removes the plot', function(done) { + + var gd = createGraphDiv(); + var mockCopy = Lib.extendDeep({}, mock); + + mockCopy.data[0].line.showscale = false; + + Plotly.plot(gd, mockCopy).then(function() { + + expect(gd.data.length).toEqual(1); + + Plotly.deleteTraces(gd, 0).then(function() { + expect(d3.selectAll('.table-line-layers').node()).toEqual(null); + expect(gd.data.length).toEqual(0); + done(); + }); + }); + }); + + it('Plotly.deleteTraces with two traces removes the deleted plot', function(done) { + + var gd = createGraphDiv(); + var mockCopy = Lib.extendDeep({}, mock); + var mockCopy2 = Lib.extendDeep({}, mock); + mockCopy2.data[0].dimensions.splice(3, 4); + mockCopy.data[0].line.showscale = false; + + Plotly.plot(gd, mockCopy) + .then(function() { + expect(gd.data.length).toEqual(1); + expect(document.querySelectorAll('.yAxis').length).toEqual(10); + return Plotly.plot(gd, mockCopy2); + }) + .then(function() { + expect(gd.data.length).toEqual(2); + expect(document.querySelectorAll('.yAxis').length).toEqual(10 + 7); + return Plotly.deleteTraces(gd, [0]); + }) + .then(function() { + expect(document.querySelectorAll('.table-line-layers').length).toEqual(1); + expect(document.querySelectorAll('.yAxis').length).toEqual(7); + expect(gd.data.length).toEqual(1); + return Plotly.deleteTraces(gd, 0); + }) + .then(function() { + expect(document.querySelectorAll('.table-line-layers').length).toEqual(0); + expect(document.querySelectorAll('.yAxis').length).toEqual(0); + expect(gd.data.length).toEqual(0); + done(); + }); + }); + + it('Calling `Plotly.restyle` with zero panels left should erase lines', function(done) { + + var mockCopy = Lib.extendDeep({}, mock2); + var gd = createGraphDiv(); + Plotly.plot(gd, mockCopy.data, mockCopy.layout); + + function restyleDimension(key, dimIndex, setterValue) { + var value = Lib.isArray(setterValue) ? setterValue[0] : setterValue; + return function() { + return Plotly.restyle(gd, 'dimensions[' + dimIndex + '].' + key, setterValue).then(function() { + expect(gd.data[0].dimensions[dimIndex][key]).toEqual(value, 'for dimension attribute \'' + key + '\''); + }); + }; + } + + restyleDimension('values', 1, [[]])() + .then(function() { + d3.selectAll('.table-lines').each(function(d) { + var imageArray = d.lineLayer.readPixels(0, 0, d.model.canvasWidth, d.model.canvasHeight); + var foundPixel = false; + var i = 0; + do { + foundPixel = foundPixel || imageArray[i++] !== 0; + } while(!foundPixel && i < imageArray.length); + expect(foundPixel).toEqual(false); + }); + done(); + }); + }); + + describe('Having two datasets', function() { + + it('Two subsequent calls to Plotly.plot should create two table rows', function(done) { + + var gd = createGraphDiv(); + var mockCopy = Lib.extendDeep({}, mock); + var mockCopy2 = Lib.extendDeep({}, mock); + mockCopy.data[0].domain = {x: [0, 0.45]}; + mockCopy2.data[0].domain = {x: [0.55, 1]}; + mockCopy2.data[0].dimensions.splice(3, 4); + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(0); + + Plotly.plot(gd, mockCopy) + .then(function() { + + expect(1).toEqual(1); + expect(document.querySelectorAll('.table-line-layers').length).toEqual(1); + expect(gd.data.length).toEqual(1); + + return Plotly.plot(gd, mockCopy2); + }) + .then(function() { + + expect(1).toEqual(1); + expect(document.querySelectorAll('.table-line-layers').length).toEqual(2); + expect(gd.data.length).toEqual(2); + + done(); + }); + }); + + it('Plotly.addTraces should add a new table row', function(done) { + + var gd = createGraphDiv(); + var mockCopy = Lib.extendDeep({}, mock); + var mockCopy2 = Lib.extendDeep({}, mock); + mockCopy.data[0].domain = {y: [0, 0.35]}; + mockCopy2.data[0].domain = {y: [0.65, 1]}; + mockCopy2.data[0].dimensions.splice(3, 4); + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(0); + + Plotly.plot(gd, mockCopy) + .then(function() { + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(1); + expect(gd.data.length).toEqual(1); + + return Plotly.addTraces(gd, [mockCopy2.data[0]]); + }) + .then(function() { + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(2); + expect(gd.data.length).toEqual(2); + + done(); + }); + + }); + + it('Plotly.restyle should update the existing table row', function(done) { + + var gd = createGraphDiv(); + var mockCopy = Lib.extendDeep({}, mock); + var mockCopy2 = Lib.extendDeep({}, mock); + + delete mockCopy.data[0].dimensions[0].constraintrange; + delete mockCopy2.data[0].dimensions[0].constraintrange; + + // in this example, the brush range doesn't change... + mockCopy.data[0].dimensions[2].constraintrange = [0, 2]; + mockCopy2.data[0].dimensions[2].constraintrange = [0, 2]; + + // .. but what's inside the brush does: + function numberUpdater(v) { + switch(v) { + case 0.5: return 2.5; + default: return v; + } + } + + // shuffle around categorical values + mockCopy2.data[0].dimensions[2].ticktext = ['A', 'B', 'Y', 'AB', 'Z']; + mockCopy2.data[0].dimensions[2].tickvals = [0, 1, 2, 2.5, 3]; + mockCopy2.data[0].dimensions[2].values = mockCopy2.data[0].dimensions[2].values.map(numberUpdater); + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(0); + + Plotly.plot(gd, mockCopy) + .then(function() { + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(1); + expect(gd.data.length).toEqual(1); + + return Plotly.restyle(gd, { + // wrap the `dimensions` array + dimensions: [mockCopy2.data[0].dimensions] + }); + }) + .then(function() { + + expect(document.querySelectorAll('.table-line-layers').length).toEqual(1); + expect(gd.data.length).toEqual(1); + + done(); + }); + + }); + }); + }); +}); From 2644014f929681a2c6794efcb22a8b58bc0dce4b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 17 Jul 2017 03:59:22 +0200 Subject: [PATCH 003/281] squashed changes --- src/traces/table/constants.js | 4 +- src/traces/table/render.js | 304 +++++++++++++++++++++--------- test/image/mocks/table.json | 80 ++++---- test/image/mocks/table_large.json | 2 +- 4 files changed, 264 insertions(+), 126 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 5958fd5753f..0a71c25f1fc 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -12,10 +12,12 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, cellPad: 4, + uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, transitionEase: 'cubic-out', transitionDuration: 100, releaseTransitionEase: 'elastic', - releaseTransitionDuration: 300 + releaseTransitionDuration: 300, + clipView: false }; diff --git a/src/traces/table/render.js b/src/traces/table/render.js index 9aa2ad71103..906e208cf12 100644 --- a/src/traces/table/render.js +++ b/src/traces/table/render.js @@ -16,8 +16,6 @@ function keyFun(d) {return d.key;} function repeat(d) {return [d];} -function unitScale(height, padding) {return d3.scale.linear().range([height - padding, padding]);} - function unwrap(d) { return d[0]; // plotly data structure convention } @@ -46,19 +44,23 @@ function model(layout, d, i) { var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; var rowContentWidth = groupWidth; - var rowHeight = groupHeight; + + var rowCount = Math.ceil((groupHeight + c.uplift) / trace.cells.height); + var panelHeight = rowCount * trace.cells.height; return { key: i, colCount: colCount, - tickDistance: c.tickDistance, translateX: domain.x[0] * width, translateY: layout.height - domain.y[1] * layout.height, pad: pad, width: rowContentWidth, - height: rowHeight, + height: groupHeight, columnWidths: columnWidths, + panelHeight: panelHeight, + rowsPerPanel: rowCount, + cells: { values: trace.cells.values, valueFormat: trace.cells.format, @@ -78,7 +80,7 @@ function model(layout, d, i) { align: trace.header.align, valign: trace.header.valign, font: trace.header.font, - cellHeights: trace.cells.height, + cellHeights: trace.header.height, fillColor: trace.header.fill.color, lineWidth: trace.header.line.width, lineColor: trace.header.line.color @@ -90,13 +92,14 @@ function viewModel(model) { var height = model.height; - var newXScale = function (d) { + var xScale = function (d) { return d.parent.columns.reduce(function(prev, next) {return next.xIndex < d.xIndex ? prev + next.columnWidth : prev}, 0); } var viewModel = { key: model.key, - model: model + model: model, + scrollY: 0 // this'll be mutated on vertical scroll, initially 0 }; var uniqueKeys = {}; @@ -110,19 +113,17 @@ function viewModel(model) { label: label, xIndex: i, height: height, - newXScale: newXScale, + xScale: xScale, x: undefined, // initialized below - unitScale: unitScale(height, c.verticalPadding), - filter: [0, 1], parent: viewModel, model: model, - rowPitch: model.cells.cellHeights, - columnWidth: model.columnWidths[i] + columnWidth: model.columnWidths[i], + viewModel: viewModel }; }); - viewModel.columns.forEach(function(dim) { - dim.x = newXScale(dim); + viewModel.columns.forEach(function(col) { + col.x = xScale(col); }); return viewModel; } @@ -142,9 +143,6 @@ function gridPick(spec, col, row) { module.exports = function(root, svg, styledData, layout, callbacks) { - var domainBrushing = false; - var linePickActive = true; - var vm = styledData .map(model.bind(0, layout)) .map(viewModel); @@ -182,7 +180,8 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .style('box-sizing', 'content-box'); tableControlView - .attr('transform', function(d) {return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')';}); + .attr('transform', function(d) {return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')';}) + .attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); var yColumn = tableControlView.selectAll('.yColumn') .data(function(vm) {return vm.columns;}, keyFun); @@ -192,54 +191,45 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .classed('yColumn', true); yColumn - .attr('transform', function(d) {return 'translate(' + d.newXScale(d) + ', 0)';}); + .attr('transform', function(d) {return 'translate(' + d.xScale(d) + ', 0)';}); + + function easeColumn(elem, d, y) { + d3.select(elem) + .transition() + .ease(c.releaseTransitionEase, 1, .75) + .duration(c.releaseTransitionDuration) + .attr('transform', 'translate(' + d.x + ' ' + y + ')'); + } yColumn + .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.xIndex + ')';}) .call(d3.behavior.drag() - .origin(function(d) {return d;}) + .origin(function(d) { + easeColumn(this, d, -c.uplift); + this.parentNode.appendChild(this); + return d; + }) .on('drag', function(d) { - var p = d.parent; - linePickActive = false; - if(domainBrushing) { - return; - } d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag - d.columnWidth, d3.event.x)); - yColumn - .sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}) - .each(function(dd, i) { - dd.xIndex = i; - dd.x = d === dd ? dd.x : dd.newXScale(dd); - }); + var newOrder = yColumn.data().sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}); + newOrder.forEach(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd); + }) - yColumn.filter(function(dd) {return Math.abs(d.xIndex - dd.xIndex) !== 0;}) + yColumn.filter(function(dd) {return d !== dd;}) .transition() .ease(c.transitionEase) .duration(c.transitionDuration) - .attr('transform', function(d) {return 'translate(' + d.newXScale(d) + ', 0)';}); + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); d3.select(this) - .transition() - .ease(c.transitionEase) - .duration(c.transitionDuration) - .attr('transform', 'translate(' + d.x + ', -5)'); - yColumn.each(function(dd, i, ii) {if(ii === d.parent.key) p.columns[i] = dd;}); - this.parentNode.appendChild(this); + .transition().duration(0) // this just cancels the easeColumn easing in .origin + .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); }) .on('dragend', function(d) { var p = d.parent; - if(domainBrushing) { - if(domainBrushing === 'ending') { - domainBrushing = false; - } - return; - } - d.x = d.newXScale(d); - d3.select(this) - .transition() - .ease(c.releaseTransitionEase, 1, .75) - .duration(c.releaseTransitionDuration) - .attr('transform', function(d) {return 'translate(' + d.x + ', 0)';}); - linePickActive = true; - + d.x = d.xScale(d); + easeColumn(this, d, 0); if(callbacks && callbacks.columnMoved) { callbacks.columnMoved(p.key, p.columns.map(function(dd) {return dd.xIndex;})); } @@ -249,23 +239,21 @@ module.exports = function(root, svg, styledData, layout, callbacks) { yColumn.exit() .remove(); - var columnOverlays = yColumn.selectAll('.columnOverlays') - .data(repeat, keyFun); - - columnOverlays.enter() - .append('g') - .classed('columnOverlays', true); - - var columnBlock = columnOverlays.selectAll('.columnBlock') + var columnBlock = yColumn.selectAll('.columnBlock') .data(function(d) { + var scrollY = d.viewModel.scrollY; + var rowFrom = Math.floor(scrollY / d.model.panelHeight) * d.model.rowsPerPanel; var blockDataHeader = Object.assign( {}, d, { key: 'header', yOffset: 0, + anchor: 0, values: d.model.headerCells.values[d.xIndex], + rowPitch: d.model.headerCells.cellHeights, dragHandle: true, + rowBlockOffset: 0, model: Object.assign( {}, d.model, @@ -276,31 +264,162 @@ module.exports = function(root, svg, styledData, layout, callbacks) { } ); - return [ - blockDataHeader, + var result = [ + Object.assign( + {}, + d, + { + key: 'cells1', + type: 'cells', + anchor: 0, + yOffset: d.model.cells.cellHeights, + dragHandle: false, + values: d.model.cells.values[d.xIndex], + rowPitch: d.model.cells.cellHeights, + rowBlockOffset: 0, + model: d.model + } + ), Object.assign( {}, d, { - key: 'cells', - yOffset: d.rowPitch, + key: 'cells2', + anchor: d.model.panelHeight, + type: 'cells', + yOffset: d.model.cells.cellHeights, dragHandle: false, values: d.model.cells.values[d.xIndex], + rowPitch: d.model.cells.cellHeights, + rowBlockOffset: 1, model: d.model } - ) + ), + blockDataHeader ]; + + return result; }, keyFun); columnBlock.enter() .append('g') - .classed('columnBlock', true); + .classed('columnBlock', true) + .style('user-select', 'none'); + + var cellsColumnBlock = columnBlock.filter(function(d) {return d.type === 'cells';}); columnBlock - .attr('transform', function(d) {return 'translate(0 ' + d.yOffset + ')';}) - .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : null;}) - //.style('user-select', 'none') - //.style('pointer-events', 'auto'); + .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) + .attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + + cellsColumnBlock + .call(d3.behavior.drag() + .origin(function(d) { + d3.event.stopPropagation(); + return d; + }) + .on('drag', function() { + var gpd = this.parentElement.parentElement.parentElement.__data__; // fixme reach vm more appropriately + gpd.scrollY -= d3.event.dy; + cellsColumnBlock + .attr('transform', function(d) { + var bottom = (d.model.cells.values[0].length + 1) * d.model.cells.cellHeights - d.model.panelHeight + c.uplift; + gpd.scrollY = Math.min(bottom, Math.max(0, gpd.scrollY)); + var blockY = gpd.scrollY; + var anchorChanged = false; + + if(d.anchor - blockY + d.model.panelHeight < 0) { + d.anchor += 2 * d.model.panelHeight; + anchorChanged = true; + } else if(d.anchor - blockY > d.model.panelHeight) { + d.anchor -= 2 * d.model.panelHeight; + anchorChanged = true; + } + + if(anchorChanged) { + window.setTimeout(function() { + // setTimeout might lag rendering but yields a smoother scroll + renderColumnBlocks(columnBlock.filter(function(dd) {return dd.key === d.key;})); + }); + } + + var yTranslate = d.anchor - blockY + d.yOffset; + + return 'translate(0 ' + yTranslate + ')'; + + }); + }) + .on('dragend', function(d) { + }) + ); + + renderColumnBlocks(columnBlock); + + var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') + .data(repeat, keyFun); + + scrollAreaClip.enter() + .append(c.clipView ? 'g' : 'clipPath') + .classed('scrollAreaClip', true); + + scrollAreaClip + .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) + + var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') + .data(repeat, keyFun); + + scrollAreaClipRect.enter() + .append('rect') + .classed('scrollAreaClipRect', true); + + scrollAreaClipRect + .attr('width', function(d) {return d.model.width + 2 * c.overdrag;}) + .attr('height', function(d) {return d.model.height + d.model.headerCells.cellHeights + c.uplift;}) + .attr('x', -c.overdrag) + .attr('y', function(d) {return -(d.model.headerCells.cellHeights + c.uplift);}) + .attr('stroke', 'orange') + .attr('stroke-width', 2) + .attr('fill', 'none') + .style('pointer-events', 'stroke'); + + var columnBoundary = yColumn.selectAll('.columnBoundary') + .data(repeat, keyFun); + + columnBoundary.enter() + .append('g') + .classed('columnBoundary', true); + + var columnBoundaryClippath = yColumn.selectAll('.columnBoundaryClippath') + .data(repeat, keyFun); + + // SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference + columnBoundaryClippath.enter() + .append(c.clipView ? 'g' : 'clipPath') + .classed('columnBoundaryClippath', true); + + columnBoundaryClippath + .attr('id', function(d) {return 'columnBoundaryClippath_' + d.xIndex;}); + + var columnBoundaryRect = columnBoundaryClippath.selectAll('.columnBoundaryRect') + .data(repeat, keyFun); + + columnBoundaryRect.enter() + .append('rect') + .classed('columnBoundaryRect', true); + + columnBoundaryRect + .attr('y', function(d) {return -d.model.headerCells.cellHeights + 0*c.uplift;}) + .attr('width', function(d) {return d.columnWidth;}) + .attr('height', function(d) {return d.height + d.model.headerCells.cellHeights + c.uplift;}) + .attr('fill', 'none') + .attr('stroke', 'magenta') + .attr('stroke-width', 2) + .style('pointer-events', 'stroke'); +}; + +function renderColumnBlocks(columnBlock) { + + // this is performance critical code as scrolling calls it on every revolver switch var columnCells = columnBlock.selectAll('.columnCells') .data(repeat, keyFun); @@ -313,12 +432,19 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .remove(); var columnCell = columnCells.selectAll('.columnCell') - .data(function(d) {return d.values.map(function(v, i) {return {key: i, column: d, model: d.model, value: v};});}, keyFun); + .data(function(d) { + var rowFrom = Math.round(d.anchor / d.model.cells.cellHeights); + var rowTo = rowFrom + (rowFrom >= 0 ? d.model.rowsPerPanel : 0); + + return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: i, column: d, model: d.model, value: v};}); + }, keyFun); columnCell.enter() .append('g') .classed('columnCell', true); + columnCell.exit().remove(); + columnCell .attr('transform', function(d, i) { return 'translate(' + 0 + ',' + i * d.column.rowPitch + ')'; @@ -348,13 +474,13 @@ module.exports = function(root, svg, styledData, layout, callbacks) { .classed('cellRect', true); cellRect - .attr('width', function(d) {return d.column.columnWidth - d.cellBorderWidth;}) - .attr('height', function(d) {return d.column.rowPitch - d.cellBorderWidth;}) - .attr('transform', function(d) {return 'translate(' + 0 + ' ' + (-(d.column.rowPitch - c.cellPad)) + ')'}) + .attr('width', function(d) {return d.column.columnWidth;}) + .attr('height', function(d) {return d.column.rowPitch;}) + .attr('transform', function(d) {return 'translate(0 -' + d.column.rowPitch + ')'}) + .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { return gridPick(d.model.cells.lineColor, d.column.xIndex, d.rowNumber); }) - .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('fill', function(d) { return gridPick(d.model.cells.fillColor, d.column.xIndex, d.rowNumber); }); @@ -374,7 +500,7 @@ module.exports = function(root, svg, styledData, layout, callbacks) { var y = d.column.rowPitch; return d3.svg.line()([[x1, y], [x2, y]]); }) - .attr('transform', function(d) {return 'translate(' + 0 + ' ' + (-(d.column.rowPitch - c.cellPad)) + ')'}); + .attr('transform', function(d) {return 'translate(0 -' + d.column.rowPitch + ')'}); var cellText = columnCell.selectAll('.cellText') .data(repeat, keyFun); @@ -386,10 +512,9 @@ module.exports = function(root, svg, styledData, layout, callbacks) { cellText .attr('dy', function(d) { var rowPitch = d.column.rowPitch; - var fontSize = d.font.size; return ({ - top: -rowPitch + fontSize, - middle: -rowPitch / 2 + fontSize * 0.2 + c.cellPad / 2, + top: -rowPitch + c.cellPad, + middle: -rowPitch / 2, bottom: -c.cellPad })[d.valign]; }) @@ -418,12 +543,19 @@ module.exports = function(root, svg, styledData, layout, callbacks) { center: '50%' })[d.align]; }) + .attr('alignment-baseline', function(d) { + return ({ + top: "hanging", + middle: "central", + bottom: "alphabetic" + })[d.valign]; + }) .text(function(d) { - var dim = d.column.xIndex; + var col = d.column.xIndex; var row = d.rowNumber; - var prefix = gridPick(d.model.cells.prefix, dim, row) || ''; - var suffix = gridPick(d.model.cells.suffix, dim, row) || ''; - var valueFormat = gridPick(d.model.cells.valueFormat, dim, row); + var prefix = gridPick(d.model.cells.prefix, col, row) || ''; + var suffix = gridPick(d.model.cells.suffix, col, row) || ''; + var valueFormat = gridPick(d.model.cells.valueFormat, col, row); return prefix + (valueFormat ? d3.format(valueFormat)(d.value) : d.value) + suffix; }); -}; +} \ No newline at end of file diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json index 9d31b309095..978b16af419 100644 --- a/test/image/mocks/table.json +++ b/test/image/mocks/table.json @@ -1,13 +1,8 @@ { "layout": { - "width": 1200, - "height": 800, + "width": 1000, + "height": 300, "title": "Widget parameters and cost", - "font": { - "color": "blue", - "size": 200, - "family": "sans-serif" - }, "margin": {"t": 106, "r": 60, "b": 54, "l": 60} }, @@ -17,27 +12,30 @@ "domain": { "x": [0.05, 0.95], - "y": [0.02, 0.97] + "y": [0.06, 0.89] }, - "columnwidth": [110, 60, 90, 90, 80, 70, 80, 60, 100, 70], + "columnwidth": [50, 90, 70, 60, 90, 80, 70, 80, 60, 100, 70], "header": { + "height": 50, + "values": [ - ["Height"], - ["Width"], - ["Cylinder"], - ["Weight"], - ["Cost"], - ["Penalty"], - ["H/W"], - ["Min H/W"], - ["Diameter"], - ["RF block"] + "Index", + "Cylinder", + "Height", + "Width", + "Weight", + "Cost", + "Penalty", + "H/W", + "Min", + "Diameter", + "RF block" ], - "align": ["right", "center", "center", "right", "right", "right", "left", "right", "right", "right"], + "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], "valign": "middle", "line": { @@ -50,7 +48,7 @@ }, "font": { - "family": "PT Sans Narrow", + "family": "Arial", "size": 16, "color": "white" } @@ -59,22 +57,26 @@ "cells": { "values": [ - [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666], - [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000], - ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"], - [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797], - [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939], - [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778], - [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373], - [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666], - [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081], - [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154] + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19], + + ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), + [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666].slice(0, 20), + [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000].slice(0, 20), + [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797].slice(0, 20), + [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939].slice(0, 20), + [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778].slice(0, 20), + [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373].slice(0, 20), + [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666].slice(0, 20), + [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081].slice(0, 20), + [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154].slice(0, 20), + ], "format": [ + null, + null, ".2s", "#0x", - null, [",.0f", ",.1f", ",.2f", ",.3f", ",.2f"], "$,", "_>5", @@ -84,30 +86,32 @@ ",.0f" ], - "prefix": ["", "", "", "", "US ", ""], - "suffix": ["m", ""], + "prefix": ["", "", "", "", "", "US ", ""], + "suffix": ["", "", "m", ""], "height": 24, - "align": ["right", "center", "center", "right", "right", "right", "left", "right", "right", "right"], - "valign": "middle", + "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], + "valign": ["middle", "top", "bottom", "middle"], "line": { "color": [ "grey" ], - "width": 0.5 + "width": 1 }, "fill": { "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"], ["#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7", "#f7fbff", "#deebf7"] ] }, "font": { + "family": "verdana", "size": 12, - "color": ["black", "red", "black", "black"] + "color": ["black", "red", "black"] } } }] diff --git a/test/image/mocks/table_large.json b/test/image/mocks/table_large.json index bce80a00235..e3233ce7718 100644 --- a/test/image/mocks/table_large.json +++ b/test/image/mocks/table_large.json @@ -50,7 +50,7 @@ }, "font": { - "family": "PT Sans Narrow", + "family": "\"PT Sans Narrow\"", "size": 16, "color": ["white", "grey"] } From 9b5cc10dabe9b253aff517520ab6f9a7a3d1fcea Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 24 Jul 2017 21:03:19 +0200 Subject: [PATCH 004/281] squashed changes --- src/lib/gup.js | 34 ++ src/traces/parcoords/lines.js | 2 +- src/traces/table/attributes.js | 28 +- src/traces/table/base_plot.js | 2 - src/traces/table/calc.js | 76 +++- src/traces/table/colorbar.js | 51 --- src/traces/table/defaults.js | 15 +- src/traces/table/plot.js | 458 +++++++++++++++++++++--- src/traces/table/render.js | 561 ------------------------------ test/image/mocks/table.json | 59 ++-- test/image/mocks/table_large.json | 128 ------- 11 files changed, 564 insertions(+), 850 deletions(-) create mode 100644 src/lib/gup.js delete mode 100644 src/traces/table/colorbar.js delete mode 100644 src/traces/table/render.js delete mode 100644 test/image/mocks/table_large.json diff --git a/src/lib/gup.js b/src/lib/gup.js new file mode 100644 index 00000000000..1090252c7f3 --- /dev/null +++ b/src/lib/gup.js @@ -0,0 +1,34 @@ +/** +* Copyright 2012-2017, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var identity = require('./identity'); + +function wrap(d) {return [d];} + +module.exports = { + + // The D3 data binding concept and the General Update Pattern promotes the idea of + // traversing into the scenegraph by using the `.data(fun, keyFun)` call. + // The `fun` is most often a `repeat`, ie. the elements beneath a `` element need + // access to the same data, or a `descend`, which fans a scenegraph node into a bunch of + // of elements, e.g. points, lines, rows, requiring an array as input. + // The role of the `keyFun` is to identify what elements are being entered/exited/updated, + // otherwise D3 reverts to using a plain index which would screw up `transition`s. + keyFun: function(d) {return d.key;}, + repeat: wrap, + descend: identity, + + // Plotly.js uses a convention of storing the actual contents of the `calcData` as the + // element zero of a container array. These helpers are just used for clarity as a + // newcomer to the codebase may not know what the `[0]` is, and whether there can be further + // elements (not atm). + wrap: wrap, + unwrap: function(d) {return d[0];} +}; diff --git a/src/traces/parcoords/lines.js b/src/traces/parcoords/lines.js index 67805d3970e..92776dabf0a 100644 --- a/src/traces/parcoords/lines.js +++ b/src/traces/parcoords/lines.js @@ -106,7 +106,7 @@ function palette(unitToColor, context, opacity) { // but first it shifts the sample index by 0, 8 or 16 bits depending on rgbIndex [0..2] // with the end result that each line will be of a unique color, making it possible for the pick handler // to uniquely identify which line is hovered over (bijective mapping). -// The inverse, i.e. readPixel is invoked from 'render.js' +// The inverse, i.e. readPixel is invoked from 'parcoords.js' function calcPickColor(j, rgbIndex) { return (j >>> 8 * rgbIndex) % 256 / 255; } diff --git a/src/traces/table/attributes.js b/src/traces/table/attributes.js index 2d6cf9337ef..0dc975c2282 100644 --- a/src/traces/table/attributes.js +++ b/src/traces/table/attributes.js @@ -10,7 +10,6 @@ var annAttrs = require('../../components/annotations/attributes'); var fontAttrs = require('../../plots/font_attributes'); - var extendFlat = require('../../lib/extend').extendFlat; module.exports = { @@ -44,17 +43,6 @@ module.exports = { } }, - labelfont: extendFlat({}, fontAttrs, { - description: 'Sets the font for the `dimension` labels.' - }), - - labels: { - valType: 'data_array', - role: 'info', - dflt: [], - description: 'The shown name of the columns.' - }, - columnwidth: { valType: 'number', arrayOk: true, @@ -63,6 +51,16 @@ module.exports = { description: 'The width of cells.' }, + columnorder: { + valType: 'data_array', + role: 'info', + description: [ + 'Specifies the rendered order of the data columns; for example, a value `2` at position `0`', + 'means that column index `0` in the data will be rendered as the', + 'third column, as columns have an index base of zero.' + ].join(' ') + }, + header: { values: { @@ -84,7 +82,7 @@ module.exports = { 'Sets the cell value formatting rule using d3 formatting mini-language', 'which is similar to those of Python. See', 'https://github.com/d3/d3-format/blob/master/README.md#locale_format' - ] + ].join(' ') }, prefix: { @@ -105,7 +103,6 @@ module.exports = { height: { valType: 'number', - arrayOk: false, dflt: 28, role: 'style', description: 'The height of cells.' @@ -193,7 +190,7 @@ module.exports = { 'Sets the cell value formatting rule using d3 formatting mini-language', 'which is similar to those of Python. See', 'https://github.com/d3/d3-format/blob/master/README.md#locale_format' - ] + ].join(' ') }, prefix: { @@ -214,7 +211,6 @@ module.exports = { height: { valType: 'number', - arrayOk: false, dflt: 20, role: 'style', description: 'The height of cells.' diff --git a/src/traces/table/base_plot.js b/src/traces/table/base_plot.js index e98c443179e..901128aa9b7 100644 --- a/src/traces/table/base_plot.js +++ b/src/traces/table/base_plot.js @@ -27,7 +27,5 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) if(hadTable && !hasTable) { oldFullLayout._paperdiv.selectAll('.table').remove(); - oldFullLayout._paperdiv.selectAll('.table').remove(); - oldFullLayout._glimages.selectAll('*').remove(); } }; diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index f28e3060eed..a981d7143be 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -8,6 +8,78 @@ 'use strict'; -module.exports = function calc() { - return [{}]; +var c = require('./constants'); +var wrap = require('../../lib/gup').wrap; + +module.exports = function calc(gd, trace) { + + var domain = trace.domain; + var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); + var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); + + var columnWidths = trace.header.values.map(function(d, i) { + return Array.isArray(trace.columnwidth) ? + trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : + isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; + }); + + var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); + columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); + + var headerRows = trace.header.values[0].length; + var headerHeight = headerRows * trace.header.height; + var scrollHeight = groupHeight - headerHeight; + var rowCount = Math.ceil((scrollHeight + c.uplift) / trace.cells.height); + + var uniqueKeys = {}; + + var columnOrder = trace._fullInput.columnorder; + + var calcdata = { + key: trace.index, + translateX: domain.x[0] * gd._fullLayout._size.w, + translateY: gd._fullLayout._size.h - domain.y[1] * gd._fullLayout._size.h, + size: gd._fullLayout._size, + width: groupWidth, + height: groupHeight, + columnWidths: columnWidths, + columnOrder: columnOrder, // will be mutated on column move + panelHeight: rowCount * trace.cells.height, + rowsPerPanel: rowCount, + headerHeight: headerHeight, + scrollHeight: scrollHeight, + scrollY: 0, // will be mutated on scroll + cells: trace.cells, + headerCells: trace.header, + columns: trace.header.values.map(function(label, i) { + var foundKey = uniqueKeys[label]; + uniqueKeys[label] = (foundKey || 0) + 1; + var key = label + (foundKey ? '__' + foundKey : ''); + return { + key: key, + label: label, + specIndex: i, + xIndex: columnOrder[i], + xScale: xScale, + x: undefined, // initialized below + calcdata: undefined, // initialized below + columnWidth: columnWidths[i] + }; + }), + + // these two are being phased out in favor of the new `columnOrder` attribute + gdColumns: trace.header.values.map(function(d) {return d[0];}), + gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}) + }; + + calcdata.columns.forEach(function(col) { + col.calcdata = calcdata; + col.x = xScale(col); + }); + + return wrap(calcdata); }; + +var xScale = function (d) { + return d.calcdata.columns.reduce(function(prev, next) {return next.xIndex < d.xIndex ? prev + next.columnWidth : prev}, 0); +} diff --git a/src/traces/table/colorbar.js b/src/traces/table/colorbar.js deleted file mode 100644 index c4a8e54c69a..00000000000 --- a/src/traces/table/colorbar.js +++ /dev/null @@ -1,51 +0,0 @@ -/** -* Copyright 2012-2017, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = require('fast-isnumeric'); - -var Lib = require('../../lib'); -var Plots = require('../../plots/plots'); -var Colorscale = require('../../components/colorscale'); -var drawColorbar = require('../../components/colorbar/draw'); - -module.exports = function colorbar(gd, cd) { - var trace = cd[0].trace, - line = trace.line, - cbId = 'cb' + trace.uid; - - gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); - - if((line === undefined) || !line.showscale) { - Plots.autoMargin(gd, cbId); - return; - } - - var vals = line.color, - cmin = line.cmin, - cmax = line.cmax; - - if(!isNumeric(cmin)) cmin = Lib.aggNums(Math.min, null, vals); - if(!isNumeric(cmax)) cmax = Lib.aggNums(Math.max, null, vals); - - var cb = cd[0].t.cb = drawColorbar(gd, cbId); - var sclFunc = Colorscale.makeColorScaleFunc( - Colorscale.extractScale( - line.colorscale, - cmin, - cmax - ), - { noNumericCheck: true } - ); - - cb.fillcolor(sclFunc) - .filllevels({start: cmin, end: cmax, size: (cmax - cmin) / 254}) - .options(line.colorbar)(); -}; diff --git a/src/traces/table/defaults.js b/src/traces/table/defaults.js index 5da803bd998..2ae1ee8ae26 100644 --- a/src/traces/table/defaults.js +++ b/src/traces/table/defaults.js @@ -11,6 +11,18 @@ var Lib = require('../../lib'); var attributes = require('./attributes'); +function defaultColumnOrder(traceIn, coerce) { + var specifiedColumnOrder = traceIn.columnorder || []; + var commonLength = traceIn.header.values.length; + var truncated = specifiedColumnOrder.slice(0, commonLength); + var sorted = truncated.slice().sort(function(a, b) {return a - b;}); + var oneStepped = truncated.map(function(d) {return sorted.indexOf(d);}); + for(var i = oneStepped.length; i < commonLength; i++) { + oneStepped.push(i); + } + coerce('columnorder', oneStepped); +}; + module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { function coerce(attr, dflt) { return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); @@ -25,9 +37,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('domain.x'); coerce('domain.y'); - coerce('labels'); - coerce('columnwidth'); + defaultColumnOrder(traceIn, coerce); coerce('cells.values'); coerce('cells.format'); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 797c0ae84d9..f527825123e 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -8,75 +8,419 @@ 'use strict'; -var table = require('./render'); +var c = require('./constants'); +var d3 = require('d3'); +var gup = require('../../lib/gup'); +var Drawing = require('../../components/drawing'); +var extendFlat = require('../../lib/extend').extendFlat; -module.exports = function plot(gd, cdTable) { +module.exports = function plot(gd, calcdata) { - var fullLayout = gd._fullLayout; - var svg = fullLayout._paper; - var root = fullLayout._paperdiv; + var table = gd._fullLayout._paper.selectAll('.table') + .data(calcdata.map(gup.unwrap), gup.keyFun); - var gdColumns = {}; - var gdColumnsOriginalOrder = {}; + table.exit().remove(); - var size = fullLayout._size; + table.enter() + .append('g') + .classed('table', true) + .attr('overflow', 'visible') + .style('box-sizing', 'content-box') + .style('position', 'absolute') + .style('left', 0) + .style('overflow', 'visible') + .style('shape-rendering', 'crispEdges') + .style('pointer-events', 'all'); // todo restore 'none' - cdTable.forEach(function(d, i) { - gdColumns[i] = gd.data[i].header.values.map(function(d) {return d[0];}); - gdColumnsOriginalOrder[i] = gdColumns[i].slice(); - }); + table + .attr('width', function(d) {return d.width + d.size.l + d.size.r;}) + .attr('height', function(d) {return d.height + d.size.t + d.size.b;}) + .attr('transform', function(d) { + return 'translate(' + d.translateX + ',' + d.translateY + ')'; + }); + + var tableControlView = table.selectAll('.tableControlView') + .data(gup.repeat, gup.keyFun); + + tableControlView.enter() + .append('g') + .classed('tableControlView', true) + .style('box-sizing', 'content-box'); + + tableControlView + .attr('transform', function(d) {return 'translate(' + d.size.l + ',' + d.size.t + ')';}) + .attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); + + var yColumn = tableControlView.selectAll('.yColumn') + .data(function(vm) {return vm.columns;}, gup.keyFun); + + yColumn.enter() + .append('g') + .classed('yColumn', true); + + yColumn + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); + + yColumn + .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) + .call(d3.behavior.drag() + .origin(function(d) { + easeColumn(this, d, -c.uplift); + this.parentNode.appendChild(this); + return d; + }) + .on('drag', function(d) { + d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); + var newOrder = yColumn.data().sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}); + newOrder.forEach(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd); + }) + + yColumn.filter(function(dd) {return d !== dd;}) + .transition() + .ease(c.transitionEase) + .duration(c.transitionDuration) + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); + d3.select(this) + .transition().duration(0) // this just cancels the easeColumn easing in .origin + .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); + }) + .on('dragend', function(d) { + var p = d.calcdata; + d.x = d.xScale(d); + easeColumn(this, d, 0); + columnMoved(gd, calcdata, p.key, p.columns.map(function(dd) {return dd.xIndex;})); + }) + ); + + yColumn.exit() + .remove(); + + var columnBlock = yColumn.selectAll('.columnBlock') + .data(function(d) { + var headerPanel = extendFlat({}, d, { + key: 'header', + type: 'header', + yOffset: 0, + anchor: 0, + values: d.calcdata.headerCells.values[d.specIndex], + rowPitch: d.calcdata.headerCells.height, + dragHandle: true, + rowBlockOffset: 0, + calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) + }); + var revolverPanel1 = extendFlat({}, d, { + key: 'cells1', + type: 'cells', + anchor: 0, // will be mutated on scroll; points to current place + yOffset: d.calcdata.headerHeight, + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowPitch: d.calcdata.cells.height, + rowBlockOffset: 0, + calcdata: d.calcdata + }); + var revolverPanel2 = extendFlat({}, d, { + key: 'cells2', + anchor: d.calcdata.panelHeight, // will be mutated on scroll; points to current place + type: 'cells', + yOffset: d.calcdata.headerHeight, + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowPitch: d.calcdata.cells.height, + rowBlockOffset: 1, + calcdata: d.calcdata + }); + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + }, gup.keyFun); + + columnBlock.enter() + .append('g') + .classed('columnBlock', true) + .style('user-select', 'none'); + + var cellsColumnBlock = columnBlock.filter(function(d) {return d.type === 'cells';}); + + columnBlock + .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) + .attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + + cellsColumnBlock + .call(d3.behavior.drag() + .origin(function(d) { + d3.event.stopPropagation(); + return d; + }) + .on('drag', function(d) { + var calcdata = d.calcdata; + calcdata.scrollY -= d3.event.dy; + var anchorChanged = false; + cellsColumnBlock + .attr('transform', function(d) { + var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; + calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); + var blockY = calcdata.scrollY; + + if(d.anchor - blockY + d.calcdata.panelHeight < 0) { + d.anchor += 2 * d.calcdata.panelHeight; + anchorChanged = true; + } else if(d.anchor - blockY > d.calcdata.panelHeight) { + d.anchor -= 2 * d.calcdata.panelHeight; + anchorChanged = true; + } + + var yTranslate = d.anchor - blockY + d.yOffset; + + return 'translate(0 ' + yTranslate + ')'; + + }); + if(anchorChanged) { + window.clearTimeout(d.currentRepaint); + d.currentRepaint = window.setTimeout(function() { + // setTimeout might lag rendering but yields a smoother scroll + renderColumnBlocks(columnBlock); + }); + } + }) + .on('dragend', function(d) { + }) + ); + + renderColumnBlocks(columnBlock); // initial render + + var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') + .data(gup.repeat, gup.keyFun); + + scrollAreaClip.enter() + .append(c.clipView ? 'g' : 'clipPath') + .classed('scrollAreaClip', true); + + scrollAreaClip + .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) + + var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') + .data(gup.repeat, gup.keyFun); + + scrollAreaClipRect.enter() + .append('rect') + .classed('scrollAreaClipRect', true) + .attr('x', -c.overdrag) + .attr('y', -c.uplift) + .attr('stroke', 'orange') + .attr('stroke-width', 2) + .attr('fill', 'none') + .style('pointer-events', 'stroke'); + + scrollAreaClipRect + .attr('width', function(d) {return d.width + 2 * c.overdrag;}) + .attr('height', function(d) {return d.height + c.uplift;}); + + var columnBoundary = yColumn.selectAll('.columnBoundary') + .data(gup.repeat, gup.keyFun); + + columnBoundary.enter() + .append('g') + .classed('columnBoundary', true); + + var columnBoundaryClippath = yColumn.selectAll('.columnBoundaryClippath') + .data(gup.repeat, gup.keyFun); + + // SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference + columnBoundaryClippath.enter() + .append(c.clipView ? 'g' : 'clipPath') + .classed('columnBoundaryClippath', true); + + columnBoundaryClippath + .attr('id', function(d) {return 'columnBoundaryClippath_' + d.specIndex;}); - var hover = function(eventData) { - gd.emit('plotly_hover', eventData); - }; + var columnBoundaryRect = columnBoundaryClippath.selectAll('.columnBoundaryRect') + .data(gup.repeat, gup.keyFun); - var unhover = function(eventData) { - gd.emit('plotly_unhover', eventData); - }; + columnBoundaryRect.enter() + .append('rect') + .classed('columnBoundaryRect', true) + .attr('fill', 'none') + .attr('stroke', 'magenta') + .attr('stroke-width', 2) + .style('pointer-events', 'stroke'); - var columnMoved = function(i, indices) { + columnBoundaryRect + .attr('width', function(d) {return d.columnWidth;}) + .attr('height', function(d) {return d.calcdata.height + c.uplift;}); +}; + +function columnMoved(gd, calcdata, i, indices) { + + var o = calcdata[i][0].gdColumnsOriginalOrder; + calcdata[i][0].gdColumns.sort(function (a, b) { + return indices[o.indexOf(a)] - indices[o.indexOf(b)]; + }); - function newIdx(indices, orig, dim) { - var origIndex = orig.indexOf(dim); - var currentIndex = indices.indexOf(origIndex); - if(currentIndex === -1) { - currentIndex += orig.length; - } - return currentIndex; + calcdata[i][0].columnorder = indices; + + gd.emit('plotly_restyle'); +} + +function gridPick(spec, col, row) { + if(Array.isArray(spec)) { + const column = spec[Math.min(col, spec.length - 1)]; + if(Array.isArray(column)) { + return column[Math.min(row, column.length - 1)]; + } else { + return column; } + } else { + return spec; + } +} + +function easeColumn(elem, d, y) { + d3.select(elem) + .transition() + .ease(c.releaseTransitionEase, 1, .75) + .duration(c.releaseTransitionDuration) + .attr('transform', 'translate(' + d.x + ' ' + y + ')'); +} + +function renderColumnBlocks(columnBlock) { + + // this is performance critical code as scrolling calls it on every revolver switch + // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization + + var columnCells = columnBlock.selectAll('.columnCells') + .data(gup.repeat, gup.keyFun); + + columnCells.enter() + .append('g') + .classed('columnCells', true); + + columnCells.exit() + .remove(); + + var columnCell = columnCells.selectAll('.columnCell') + .data(function(d) { + var rowFrom = Math.round(d.anchor / d.calcdata.cells.height); + var rowTo = rowFrom + (rowFrom >= 0 ? d.calcdata.rowsPerPanel : 0); + + return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: rowFrom + i, column: d, calcdata: d.calcdata, value: v};}); + }, gup.keyFun); + + columnCell.enter() + .append('g') + .classed('columnCell', true); + + columnCell.exit().remove(); - function sorter(orig) { - return function sorter(d1, d2) { - var i1 = newIdx(indices, orig, d1); - var i2 = newIdx(indices, orig, d2); - return i1 - i2; + columnCell + .attr('transform', function(d, i) { + return 'translate(' + 0 + ' ' + i * d.column.rowPitch + ')'; + }) + .each(function(d, i) { + var spec = d.calcdata.cells.font; + var col = d.column.specIndex; + var font = { + size: gridPick(spec.size, col, i), + color: gridPick(spec.color, col, i), + family: gridPick(spec.family, col, i) }; - } + Drawing.font(d3.select(this), font); + + d.rowNumber = d.key; + d.align = gridPick(d.calcdata.cells.align, col, i); + d.valign = gridPick(d.calcdata.cells.valign, col, i); + d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i) + d.font = font; + }); + + var cellRect = columnCell.selectAll('.cellRect') + .data(gup.repeat, gup.keyFun); + + cellRect.enter() + .append('rect') + .classed('cellRect', true); + + cellRect + .attr('width', function(d) {return d.column.columnWidth;}) + .attr('height', function(d) {return d.column.rowPitch;}) + .attr('stroke-width', function(d) {return d.cellBorderWidth;}) + .attr('stroke', function(d) { + return gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); + }) + .attr('fill', function(d) { + return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); + }); + + var cellLine = columnCell.selectAll('.cellLine') + .data(gup.repeat, gup.keyFun); + + cellLine.enter() + .append('path') + .classed('cellLine', true); + + cellLine + .attr('id', function(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex;}) + .attr('d', function(d) { + var x1 = 0; + var x2 = d.column.columnWidth; + var y = d.column.rowPitch; + return d3.svg.line()([[x1, y], [x2, y]]); + }); + + var cellText = columnCell.selectAll('.cellText') + .data(gup.repeat, gup.keyFun); + + cellText.enter() + .append('text') + .classed('cellText', true); + + cellText + .attr('dy', function(d) { + var rowPitch = d.column.rowPitch; + return ({ + top: -rowPitch + c.cellPad, + middle: -rowPitch / 2, + bottom: -c.cellPad + })[d.valign]; + }) + .each(function(d) {Drawing.font(d3.select(this), d.font);}); + + var textPath = cellText.selectAll('.textPath') + .data(gup.repeat, gup.keyFun); + + textPath.enter() + .append('textPath') + .classed('textPath', true); - // drag&drop sorting of the columns - var orig = sorter(gdColumnsOriginalOrder[i].slice()); - gdColumns[i].sort(orig); - - gd.emit('plotly_restyle'); - }; - - table( - root, - svg, - cdTable, - { - width: size.w, - height: size.h, - margin: { - t: size.t, - r: size.r, - b: size.b, - l: size.l - } - }, - { - hover: hover, - unhover: unhover, - columnMoved: columnMoved + textPath + .attr('xlink:href', function(d) {return '#textpath_' + d.column.key + '_' + d.column.specIndex;}) + .attr('text-anchor', function(d) { + return ({ + left: 'start', + right: 'end', + center: 'middle' + })[d.align]; + }) + .attr('startOffset', function(d) { + return ({ + left: c.cellPad, + right: d.column.columnWidth - c.cellPad, + center: '50%' + })[d.align]; + }) + .attr('alignment-baseline', function(d) { + return ({ + top: "hanging", + middle: "central", + bottom: "alphabetic" + })[d.valign]; + }) + .text(function(d) { + var col = d.column.specIndex; + var row = d.rowNumber; + var prefix = gridPick(d.calcdata.cells.prefix, col, row) || ''; + var suffix = gridPick(d.calcdata.cells.suffix, col, row) || ''; + var format = gridPick(d.calcdata.cells.format, col, row) || ''; + return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; }); }; diff --git a/src/traces/table/render.js b/src/traces/table/render.js deleted file mode 100644 index 906e208cf12..00000000000 --- a/src/traces/table/render.js +++ /dev/null @@ -1,561 +0,0 @@ -/** -* Copyright 2012-2017, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var c = require('./constants'); -var d3 = require('d3'); -var Drawing = require('../../components/drawing'); - -function keyFun(d) {return d.key;} - -function repeat(d) {return [d];} - -function unwrap(d) { - return d[0]; // plotly data structure convention -} - -function model(layout, d, i) { - var cd0 = unwrap(d), - trace = cd0.trace, - domain = trace.domain, - width = layout.width, - labels = trace.labels, - columnWidths = trace.columnwidth; - - var colCount = labels.length; - - var groupWidth = Math.floor(width * (domain.x[1] - domain.x[0])); - var groupHeight = Math.floor(layout.height * (domain.y[1] - domain.y[0])); - - columnWidths = trace.header.values.map(function(d, i) { - return Array.isArray(columnWidths) ? - columnWidths[Math.min(i, columnWidths.length - 1)] : - isFinite(columnWidths) && columnWidths !== null ? columnWidths : 1; - }); - - var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); - columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - - var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; - var rowContentWidth = groupWidth; - - var rowCount = Math.ceil((groupHeight + c.uplift) / trace.cells.height); - var panelHeight = rowCount * trace.cells.height; - - return { - key: i, - colCount: colCount, - translateX: domain.x[0] * width, - translateY: layout.height - domain.y[1] * layout.height, - pad: pad, - width: rowContentWidth, - height: groupHeight, - columnWidths: columnWidths, - - panelHeight: panelHeight, - rowsPerPanel: rowCount, - - cells: { - values: trace.cells.values, - valueFormat: trace.cells.format, - prefix: trace.cells.prefix, - suffix: trace.cells.suffix, - cellHeights: trace.cells.height, - align: trace.cells.align, - valign: trace.cells.valign, - font: trace.cells.font, - fillColor: trace.cells.fill.color, - lineWidth: trace.cells.line.width, - lineColor: trace.cells.line.color - }, - - headerCells: { - values: trace.header.values.map(repeat), - align: trace.header.align, - valign: trace.header.valign, - font: trace.header.font, - cellHeights: trace.header.height, - fillColor: trace.header.fill.color, - lineWidth: trace.header.line.width, - lineColor: trace.header.line.color - } - }; -} - -function viewModel(model) { - - var height = model.height; - - var xScale = function (d) { - return d.parent.columns.reduce(function(prev, next) {return next.xIndex < d.xIndex ? prev + next.columnWidth : prev}, 0); - } - - var viewModel = { - key: model.key, - model: model, - scrollY: 0 // this'll be mutated on vertical scroll, initially 0 - }; - - var uniqueKeys = {}; - - viewModel.columns = model.headerCells.values.map(function(label, i) { - var foundKey = uniqueKeys[label]; - uniqueKeys[label] = (foundKey || 0) + 1; - var key = label + (foundKey ? '__' + foundKey : ''); - return { - key: key, - label: label, - xIndex: i, - height: height, - xScale: xScale, - x: undefined, // initialized below - parent: viewModel, - model: model, - columnWidth: model.columnWidths[i], - viewModel: viewModel - }; - }); - - viewModel.columns.forEach(function(col) { - col.x = xScale(col); - }); - return viewModel; -} - -function gridPick(spec, col, row) { - if(Array.isArray(spec)) { - const column = spec[Math.min(col, spec.length - 1)]; - if(Array.isArray(column)) { - return column[Math.min(row, column.length - 1)]; - } else { - return column; - } - } else { - return spec; - } -} - -module.exports = function(root, svg, styledData, layout, callbacks) { - - var vm = styledData - .map(model.bind(0, layout)) - .map(viewModel); - - svg.style('background', 'rgba(255, 255, 255, 0)'); - var table = svg.selectAll('.table') - .data(vm, keyFun); - - table.exit().remove(); - - table.enter() - .append('g') - .classed('table', true) - .attr('overflow', 'visible') - .style('box-sizing', 'content-box') - .style('position', 'absolute') - .style('left', 0) - .style('overflow', 'visible') - .style('shape-rendering', 'crispEdges') - .style('pointer-events', 'all'); // todo restore 'none' - - table - .attr('width', function(d) {return d.model.width + d.model.pad.l + d.model.pad.r;}) - .attr('height', function(d) {return d.model.height + d.model.pad.t + d.model.pad.b;}) - .attr('transform', function(d) { - return 'translate(' + d.model.translateX + ',' + d.model.translateY + ')'; - }); - - var tableControlView = table.selectAll('.tableControlView') - .data(repeat, keyFun); - - tableControlView.enter() - .append('g') - .classed('tableControlView', true) - .style('box-sizing', 'content-box'); - - tableControlView - .attr('transform', function(d) {return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')';}) - .attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); - - var yColumn = tableControlView.selectAll('.yColumn') - .data(function(vm) {return vm.columns;}, keyFun); - - yColumn.enter() - .append('g') - .classed('yColumn', true); - - yColumn - .attr('transform', function(d) {return 'translate(' + d.xScale(d) + ', 0)';}); - - function easeColumn(elem, d, y) { - d3.select(elem) - .transition() - .ease(c.releaseTransitionEase, 1, .75) - .duration(c.releaseTransitionDuration) - .attr('transform', 'translate(' + d.x + ' ' + y + ')'); - } - - yColumn - .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.xIndex + ')';}) - .call(d3.behavior.drag() - .origin(function(d) { - easeColumn(this, d, -c.uplift); - this.parentNode.appendChild(this); - return d; - }) - .on('drag', function(d) { - d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag - d.columnWidth, d3.event.x)); - var newOrder = yColumn.data().sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}); - newOrder.forEach(function(dd, i) { - dd.xIndex = i; - dd.x = d === dd ? dd.x : dd.xScale(dd); - }) - - yColumn.filter(function(dd) {return d !== dd;}) - .transition() - .ease(c.transitionEase) - .duration(c.transitionDuration) - .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - d3.select(this) - .transition().duration(0) // this just cancels the easeColumn easing in .origin - .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); - }) - .on('dragend', function(d) { - var p = d.parent; - d.x = d.xScale(d); - easeColumn(this, d, 0); - if(callbacks && callbacks.columnMoved) { - callbacks.columnMoved(p.key, p.columns.map(function(dd) {return dd.xIndex;})); - } - }) - ); - - yColumn.exit() - .remove(); - - var columnBlock = yColumn.selectAll('.columnBlock') - .data(function(d) { - var scrollY = d.viewModel.scrollY; - var rowFrom = Math.floor(scrollY / d.model.panelHeight) * d.model.rowsPerPanel; - var blockDataHeader = Object.assign( - {}, - d, - { - key: 'header', - yOffset: 0, - anchor: 0, - values: d.model.headerCells.values[d.xIndex], - rowPitch: d.model.headerCells.cellHeights, - dragHandle: true, - rowBlockOffset: 0, - model: Object.assign( - {}, - d.model, - { - cells: d.model.headerCells - } - ) - } - ); - - var result = [ - Object.assign( - {}, - d, - { - key: 'cells1', - type: 'cells', - anchor: 0, - yOffset: d.model.cells.cellHeights, - dragHandle: false, - values: d.model.cells.values[d.xIndex], - rowPitch: d.model.cells.cellHeights, - rowBlockOffset: 0, - model: d.model - } - ), - Object.assign( - {}, - d, - { - key: 'cells2', - anchor: d.model.panelHeight, - type: 'cells', - yOffset: d.model.cells.cellHeights, - dragHandle: false, - values: d.model.cells.values[d.xIndex], - rowPitch: d.model.cells.cellHeights, - rowBlockOffset: 1, - model: d.model - } - ), - blockDataHeader - ]; - - return result; - }, keyFun); - - columnBlock.enter() - .append('g') - .classed('columnBlock', true) - .style('user-select', 'none'); - - var cellsColumnBlock = columnBlock.filter(function(d) {return d.type === 'cells';}); - - columnBlock - .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) - .attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); - - cellsColumnBlock - .call(d3.behavior.drag() - .origin(function(d) { - d3.event.stopPropagation(); - return d; - }) - .on('drag', function() { - var gpd = this.parentElement.parentElement.parentElement.__data__; // fixme reach vm more appropriately - gpd.scrollY -= d3.event.dy; - cellsColumnBlock - .attr('transform', function(d) { - var bottom = (d.model.cells.values[0].length + 1) * d.model.cells.cellHeights - d.model.panelHeight + c.uplift; - gpd.scrollY = Math.min(bottom, Math.max(0, gpd.scrollY)); - var blockY = gpd.scrollY; - var anchorChanged = false; - - if(d.anchor - blockY + d.model.panelHeight < 0) { - d.anchor += 2 * d.model.panelHeight; - anchorChanged = true; - } else if(d.anchor - blockY > d.model.panelHeight) { - d.anchor -= 2 * d.model.panelHeight; - anchorChanged = true; - } - - if(anchorChanged) { - window.setTimeout(function() { - // setTimeout might lag rendering but yields a smoother scroll - renderColumnBlocks(columnBlock.filter(function(dd) {return dd.key === d.key;})); - }); - } - - var yTranslate = d.anchor - blockY + d.yOffset; - - return 'translate(0 ' + yTranslate + ')'; - - }); - }) - .on('dragend', function(d) { - }) - ); - - renderColumnBlocks(columnBlock); - - var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') - .data(repeat, keyFun); - - scrollAreaClip.enter() - .append(c.clipView ? 'g' : 'clipPath') - .classed('scrollAreaClip', true); - - scrollAreaClip - .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) - - var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') - .data(repeat, keyFun); - - scrollAreaClipRect.enter() - .append('rect') - .classed('scrollAreaClipRect', true); - - scrollAreaClipRect - .attr('width', function(d) {return d.model.width + 2 * c.overdrag;}) - .attr('height', function(d) {return d.model.height + d.model.headerCells.cellHeights + c.uplift;}) - .attr('x', -c.overdrag) - .attr('y', function(d) {return -(d.model.headerCells.cellHeights + c.uplift);}) - .attr('stroke', 'orange') - .attr('stroke-width', 2) - .attr('fill', 'none') - .style('pointer-events', 'stroke'); - - var columnBoundary = yColumn.selectAll('.columnBoundary') - .data(repeat, keyFun); - - columnBoundary.enter() - .append('g') - .classed('columnBoundary', true); - - var columnBoundaryClippath = yColumn.selectAll('.columnBoundaryClippath') - .data(repeat, keyFun); - - // SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference - columnBoundaryClippath.enter() - .append(c.clipView ? 'g' : 'clipPath') - .classed('columnBoundaryClippath', true); - - columnBoundaryClippath - .attr('id', function(d) {return 'columnBoundaryClippath_' + d.xIndex;}); - - var columnBoundaryRect = columnBoundaryClippath.selectAll('.columnBoundaryRect') - .data(repeat, keyFun); - - columnBoundaryRect.enter() - .append('rect') - .classed('columnBoundaryRect', true); - - columnBoundaryRect - .attr('y', function(d) {return -d.model.headerCells.cellHeights + 0*c.uplift;}) - .attr('width', function(d) {return d.columnWidth;}) - .attr('height', function(d) {return d.height + d.model.headerCells.cellHeights + c.uplift;}) - .attr('fill', 'none') - .attr('stroke', 'magenta') - .attr('stroke-width', 2) - .style('pointer-events', 'stroke'); -}; - -function renderColumnBlocks(columnBlock) { - - // this is performance critical code as scrolling calls it on every revolver switch - - var columnCells = columnBlock.selectAll('.columnCells') - .data(repeat, keyFun); - - columnCells.enter() - .append('g') - .classed('columnCells', true); - - columnCells.exit() - .remove(); - - var columnCell = columnCells.selectAll('.columnCell') - .data(function(d) { - var rowFrom = Math.round(d.anchor / d.model.cells.cellHeights); - var rowTo = rowFrom + (rowFrom >= 0 ? d.model.rowsPerPanel : 0); - - return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: i, column: d, model: d.model, value: v};}); - }, keyFun); - - columnCell.enter() - .append('g') - .classed('columnCell', true); - - columnCell.exit().remove(); - - columnCell - .attr('transform', function(d, i) { - return 'translate(' + 0 + ',' + i * d.column.rowPitch + ')'; - }) - .each(function(d, i) { - var spec = d.model.cells.font; - var col = d.column.xIndex; - var font = { - size: gridPick(spec.size, col, i), - color: gridPick(spec.color, col, i), - family: gridPick(spec.family, col, i) - }; - Drawing.font(d3.select(this), font); - - d.rowNumber = i; - d.align = gridPick(d.model.cells.align, d.column.xIndex, i); - d.valign = gridPick(d.model.cells.valign, d.column.xIndex, i); - d.cellBorderWidth = gridPick(d.model.cells.lineWidth, d.column.xIndex, i) - d.font = font; - }); - - var cellRect = columnCell.selectAll('.cellRect') - .data(repeat, keyFun); - - cellRect.enter() - .append('rect') - .classed('cellRect', true); - - cellRect - .attr('width', function(d) {return d.column.columnWidth;}) - .attr('height', function(d) {return d.column.rowPitch;}) - .attr('transform', function(d) {return 'translate(0 -' + d.column.rowPitch + ')'}) - .attr('stroke-width', function(d) {return d.cellBorderWidth;}) - .attr('stroke', function(d) { - return gridPick(d.model.cells.lineColor, d.column.xIndex, d.rowNumber); - }) - .attr('fill', function(d) { - return gridPick(d.model.cells.fillColor, d.column.xIndex, d.rowNumber); - }); - - var cellLine = columnCell.selectAll('.cellLine') - .data(repeat, keyFun); - - cellLine.enter() - .append('path') - .classed('cellLine', true); - - cellLine - .attr('id', function(d) {return 'textpath' + d.column.xIndex;}) - .attr('d', function(d) { - var x1 = 0; - var x2 = d.column.columnWidth; - var y = d.column.rowPitch; - return d3.svg.line()([[x1, y], [x2, y]]); - }) - .attr('transform', function(d) {return 'translate(0 -' + d.column.rowPitch + ')'}); - - var cellText = columnCell.selectAll('.cellText') - .data(repeat, keyFun); - - cellText.enter() - .append('text') - .classed('cellText', true); - - cellText - .attr('dy', function(d) { - var rowPitch = d.column.rowPitch; - return ({ - top: -rowPitch + c.cellPad, - middle: -rowPitch / 2, - bottom: -c.cellPad - })[d.valign]; - }) - .each(function(d) {Drawing.font(d3.select(this), d.font);}); - - var textPath = cellText.selectAll('.textPath') - .data(repeat, keyFun); - - textPath.enter() - .append('textPath') - .classed('textPath', true); - - textPath - .attr('xlink:href', function(d) {return '#textpath' + d.column.xIndex;}) - .attr('text-anchor', function(d) { - return ({ - left: 'start', - right: 'end', - center: 'middle' - })[d.align]; - }) - .attr('startOffset', function(d) { - return ({ - left: c.cellPad, - right: d.column.columnWidth - c.cellPad, - center: '50%' - })[d.align]; - }) - .attr('alignment-baseline', function(d) { - return ({ - top: "hanging", - middle: "central", - bottom: "alphabetic" - })[d.valign]; - }) - .text(function(d) { - var col = d.column.xIndex; - var row = d.rowNumber; - var prefix = gridPick(d.model.cells.prefix, col, row) || ''; - var suffix = gridPick(d.model.cells.suffix, col, row) || ''; - var valueFormat = gridPick(d.model.cells.valueFormat, col, row); - return prefix + (valueFormat ? d3.format(valueFormat)(d.value) : d.value) + suffix; - }); -} \ No newline at end of file diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json index 978b16af419..3be5713e0dd 100644 --- a/test/image/mocks/table.json +++ b/test/image/mocks/table.json @@ -3,7 +3,7 @@ "width": 1000, "height": 300, "title": "Widget parameters and cost", - "margin": {"t": 106, "r": 60, "b": 54, "l": 60} + "margin": {"t": 80, "r": 60, "b": 54, "l": 60} }, "data": [{ @@ -12,27 +12,28 @@ "domain": { "x": [0.05, 0.95], - "y": [0.06, 0.89] + "y": [0, 1] }, "columnwidth": [50, 90, 70, 60, 90, 80, 70, 80, 60, 100, 70], + "columnorder": [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10], "header": { - "height": 50, + "height": 20, "values": [ - "Index", - "Cylinder", - "Height", - "Width", - "Weight", - "Cost", - "Penalty", - "H/W", - "Min", - "Diameter", - "RF block" + ["Index" , "#"], + ["Cylinder", "class"], + ["Height" , "m"], + ["Width" , "mm"], + ["Weight" , "kg"], + ["Cost" , "USD"], + ["Penalty" , "USD"], + ["H/W" , "ratio"], + ["Min" , "mm"], + ["Diameter", "mm"], + ["RF block", "m"] ], "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], @@ -57,19 +58,17 @@ "cells": { "values": [ - [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19], - - ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), - [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666].slice(0, 20), - [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000].slice(0, 20), - [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797].slice(0, 20), - [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939].slice(0, 20), - [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778].slice(0, 20), - [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373].slice(0, 20), - [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666].slice(0, 20), - [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081].slice(0, 20), - [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154].slice(0, 20), - + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20), + ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), + [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666].slice(0, 20), + [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000].slice(0, 20), + [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797].slice(0, 20), + [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939].slice(0, 20), + [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778].slice(0, 20), + [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373].slice(0, 20), + [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666].slice(0, 20), + [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081].slice(0, 20), + [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154].slice(0, 20), ], "format": [ @@ -86,10 +85,10 @@ ",.0f" ], - "prefix": ["", "", "", "", "", "US ", ""], - "suffix": ["", "", "m", ""], + "prefix": ["#", "", "", "", "", "US ", ""], + "suffix": ["", " class", "m", ""], - "height": 24, + "height": 27, "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], "valign": ["middle", "top", "bottom", "middle"], diff --git a/test/image/mocks/table_large.json b/test/image/mocks/table_large.json deleted file mode 100644 index e3233ce7718..00000000000 --- a/test/image/mocks/table_large.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "layout": { - "width": 800, - "height": 800, - "title": "Widget parameters and cost", - "font": { - "color": "blue", - "size": 2, - "family": "sans-serif" - }, - "margin": {"t": 106, "r": 60, "b": 54, "l": 60} - }, - - "data": [{ - - "type": "table", - - "domain": { - "x": [0.05, 0.95], - "y": [0.02, 0.97] - }, - - "columnwidth": [110, 60, 90, 90, 80, 70, 80, 60, 100, 70], - - "header": { - - "values": [ - ["Height"], - ["Width"], - ["Cylinder"], - ["Weight"], - ["Cost"], - ["Penalty"], - ["H/W"], - ["Min H/W"], - ["Diameter"], - ["RF block"] - ], - - "align": ["center", "center", "center", "right", "right", "right", "left", "right"], - "valign": ["top", "bottom", "middle"], - - "line": { - "color": ["white", "white", "red", "white"], - "width": [0, 0, 0.5] - }, - - "fill": { - "color": ["black", "lightgrey"] - }, - - "font": { - "family": "\"PT Sans Narrow\"", - "size": 16, - "color": ["white", "grey"] - } - }, - - "cells": { - - "values": [ - [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666], - [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000], - ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"], - [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797], - [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939], - [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778], - [0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373, 0.4575, 0.106, 0.568, 0.2164, 0.2366, 0.3269, 0.3471, 0.4373], - [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666], - [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081], - [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154] - ], - - "format": [ - ".2s", - "#0x", - null, - [",.0f", ",.1f", ",.2f", ",.3f", ",.2f"], - "$,", - "_>5", - ",.1%", - null, - null, - null - ], - - "prefix": ["", "", "", "", "US ", ""], - "suffix": ["m", ""], - - "height": 20, - - "align": ["center", "center", "center", "right", "right", "right", "left", "right"], - "valign": ["top", "bottom", "middle"], - - "line": { - "color": [ - ["grey"] - ], - "width": 0.5 - }, - - "fill": { - "showscale": true, - "reversescale": true, - "colorscale": "Viridis", - "valueformat": ",.2r", - "cmin": -4000, - "cmax": -100, - "color": [ - ["#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9","#e0f3f8", "#abd9e9"] - ] - }, - - "font": { - "color": [ - ["rgb(214,235,14)", "rgb(24,251,11)", "rgb(109,103,67)", "rgb(152,192,23)", "rgb(80,207,160)", "rgb(84,134,44)", "rgb(222,105,214)", "rgb(76,181,63)", "rgb(110,173,82)", "rgb(144,56,245)", "rgb(48,196,142)", "rgb(190,102,179)", "rgb(115,83,61)", "rgb(54,231,74)", "rgb(235,105,39)", "rgb(1,128,246)", "rgb(205,58,176)", "rgb(34,128,113)", "rgb(222,81,3)", "rgb(18,252,69)"], - ["rgb(107,128,223)", "rgb(95,62,207)", "rgb(110,65,159)", "rgb(17,249,0)", "rgb(184,189,240)", "rgb(234,55,166)", "rgb(254,75,119)", "rgb(215,70,114)", "rgb(102,160,80)", "rgb(7,190,174)", "rgb(177,25,224)", "rgb(237,181,164)", "rgb(122,240,243)", "rgb(54,245,219)", "rgb(65,30,43)", "rgb(67,161,153)", "rgb(77,77,169)", "rgb(11,144,192)", "rgb(27,193,182)", "rgb(176,134,145)"], - ["rgb(214,204,7)", "rgb(228,251,163)", "rgb(22,8,80)", "rgb(129,125,180)", "rgb(229,211,97)", "rgb(14,77,169)", "rgb(31,68,23)", "rgb(219,106,81)", "rgb(113,123,241)", "rgb(113,228,139)", "rgb(115,124,86)", "rgb(185,227,179)", "rgb(126,218,33)", "rgb(83,39,227)", "rgb(43,40,158)", "rgb(244,77,12)", "rgb(19,15,168)", "rgb(212,66,245)", "rgb(175,76,103)", "rgb(250,61,197)"], - "red", - ["magenta", "blue"], - ["rgb(47,249,84)", "rgb(186,219,118)", "rgb(116,107,204)", "rgb(255,6,79)", "rgb(157,34,21)", "rgb(90,61,107)", "rgb(12,195,215)", "rgb(16,22,219)", "rgb(111,207,137)", "rgb(106,15,130)", "rgb(156,131,30)", "rgb(178,28,31)", "rgb(90,192,19)", "rgb(188,146,244)", "rgb(83,1,104)", "rgb(74,206,15)", "rgb(200,23,125)", "rgb(94,68,55)", "rgb(25,43,18)", "rgb(72,79,254)"] - ], - "size": [20, [16, 12]], - "family": ["monospace",["serif", "sans-serif"]] - } - } - }] -} From 0ed234f5bc49d05d27610f61435dc4385b39ca53 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 16 Aug 2017 13:45:53 +0200 Subject: [PATCH 005/281] heterogeneous row height --- src/traces/parcoords/parcoords.js | 1 - test/image/mocks/table_one_column.json | 86 ++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 test/image/mocks/table_one_column.json diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index 237ea08e384..4027c1ea7d2 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -89,7 +89,6 @@ function ordinalScale(dimension) { } function unitToColorScale(cscale) { - var colorStops = cscale.map(function(d) {return d[0];}); var colorStrings = cscale.map(function(d) {return d[1];}); var colorTuples = colorStrings.map(function(c) {return d3.rgb(c);}); diff --git a/test/image/mocks/table_one_column.json b/test/image/mocks/table_one_column.json new file mode 100644 index 00000000000..aa946d1cbd3 --- /dev/null +++ b/test/image/mocks/table_one_column.json @@ -0,0 +1,86 @@ +{ + "layout": { + "width": 1000, + "height": 300, + "title": "Widget parameters and cost", + "margin": {"t": 80, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [50], + "columnorder": [0], + + "header": { + + "height": 20, + + "values": [ + ["Index" , "#"], + ], + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 16, + "color": "white" + } + }, + + "cells": { + + "values": [ + [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20) + ], + + "format": [ + null + ], + + "prefix": ["#"], + "suffix": [""], + + "height": 27, + + "align": ["right"], + "valign": ["middle"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fill": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "verdana", + "size": 12, + "color": ["black"] + } + } + }] +} From 90268f66a988271af2d8c6944471e224eefed033 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 21 Aug 2017 14:36:48 +0200 Subject: [PATCH 006/281] attach key suffix unconditionally --- src/traces/table/calc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index a981d7143be..5a87f40fe33 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -54,7 +54,7 @@ module.exports = function calc(gd, trace) { columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; - var key = label + (foundKey ? '__' + foundKey : ''); + var key = label + '__' + uniqueKeys[label]; return { key: key, label: label, From 875560f8dca0dae8c6b8dac24ecf9a4f1822395a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 21 Aug 2017 17:22:03 +0200 Subject: [PATCH 007/281] panelHeight, rowsPerPanel removed from calc.js --- src/traces/table/calc.js | 3 --- src/traces/table/plot.js | 19 +++++++++++-------- test/image/mocks/table_one_column.json | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 5a87f40fe33..99f1d8fd03c 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -29,7 +29,6 @@ module.exports = function calc(gd, trace) { var headerRows = trace.header.values[0].length; var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; - var rowCount = Math.ceil((scrollHeight + c.uplift) / trace.cells.height); var uniqueKeys = {}; @@ -44,8 +43,6 @@ module.exports = function calc(gd, trace) { height: groupHeight, columnWidths: columnWidths, columnOrder: columnOrder, // will be mutated on column move - panelHeight: rowCount * trace.cells.height, - rowsPerPanel: rowCount, headerHeight: headerHeight, scrollHeight: scrollHeight, scrollY: 0, // will be mutated on scroll diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f527825123e..38ad65b79f6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -123,7 +123,7 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: d.calcdata.panelHeight, // will be mutated on scroll; points to current place + anchor: Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) * d.calcdata.cells.height, // will be mutated on scroll; points to current place type: 'cells', yOffset: d.calcdata.headerHeight, dragHandle: false, @@ -161,12 +161,12 @@ module.exports = function plot(gd, calcdata) { var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; - - if(d.anchor - blockY + d.calcdata.panelHeight < 0) { - d.anchor += 2 * d.calcdata.panelHeight; + var panelHeight = Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) * d.calcdata.cells.height; + if(blockY - d.anchor > panelHeight) { + d.anchor += 2 * panelHeight; anchorChanged = true; - } else if(d.anchor - blockY > d.calcdata.panelHeight) { - d.anchor -= 2 * d.calcdata.panelHeight; + } else if(d.anchor - blockY > panelHeight) { + d.anchor -= 2 * panelHeight; anchorChanged = true; } @@ -178,7 +178,8 @@ module.exports = function plot(gd, calcdata) { if(anchorChanged) { window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function() { - // setTimeout might lag rendering but yields a smoother scroll + // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes + // some repaints invisible ie. wasteful (DOM work blocks the main thread) renderColumnBlocks(columnBlock); }); } @@ -301,7 +302,7 @@ function renderColumnBlocks(columnBlock) { var columnCell = columnCells.selectAll('.columnCell') .data(function(d) { var rowFrom = Math.round(d.anchor / d.calcdata.cells.height); - var rowTo = rowFrom + (rowFrom >= 0 ? d.calcdata.rowsPerPanel : 0); + var rowTo = rowFrom + (rowFrom >= 0 ? Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) : 0); return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: rowFrom + i, column: d, calcdata: d.calcdata, value: v};}); }, gup.keyFun); @@ -314,6 +315,8 @@ function renderColumnBlocks(columnBlock) { columnCell .attr('transform', function(d, i) { + console.log(i) + //debugger return 'translate(' + 0 + ' ' + i * d.column.rowPitch + ')'; }) .each(function(d, i) { diff --git a/test/image/mocks/table_one_column.json b/test/image/mocks/table_one_column.json index aa946d1cbd3..c0c066ee772 100644 --- a/test/image/mocks/table_one_column.json +++ b/test/image/mocks/table_one_column.json @@ -1,9 +1,9 @@ { "layout": { "width": 1000, - "height": 300, + "height": 600, "title": "Widget parameters and cost", - "margin": {"t": 80, "r": 60, "b": 54, "l": 60} + "margin": {"t": 380, "r": 60, "b": 54, "l": 60} }, "data": [{ @@ -23,7 +23,7 @@ "height": 20, "values": [ - ["Index" , "#"], + ["Index" , "#"] ], "align": ["right"], From ce87db74302e0afe75ba9b139404f26a785acefd Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 21 Aug 2017 18:59:09 +0200 Subject: [PATCH 008/281] prep for row-based anchor calculation --- src/traces/table/calc.js | 10 ++++++++++ src/traces/table/plot.js | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 99f1d8fd03c..80af15aa8df 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -29,6 +29,14 @@ module.exports = function calc(gd, trace) { var headerRows = trace.header.values[0].length; var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); + + var rowAnchors = []; + var acc = 0; + for(var i = 0; i < rowHeights.length; i++) { + rowAnchors.push(acc); + acc += rowHeights[i]; + } var uniqueKeys = {}; @@ -48,6 +56,8 @@ module.exports = function calc(gd, trace) { scrollY: 0, // will be mutated on scroll cells: trace.cells, headerCells: trace.header, + rowHeights: rowHeights, + rowAnchors: rowAnchors, columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 38ad65b79f6..550e5516775 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -123,7 +123,7 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) * d.calcdata.cells.height, // will be mutated on scroll; points to current place + anchor: effectiveHeightOfPanelA(d), // will be mutated on scroll; points to current place type: 'cells', yOffset: d.calcdata.headerHeight, dragHandle: false, @@ -161,7 +161,7 @@ module.exports = function plot(gd, calcdata) { var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; - var panelHeight = Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) * d.calcdata.cells.height; + var panelHeight = effectiveHeightOfPanel(d); if(blockY - d.anchor > panelHeight) { d.anchor += 2 * panelHeight; anchorChanged = true; @@ -251,6 +251,18 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; +function rowCountOfPanel(d) { + return Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height); +} + +function effectiveHeightOfPanel(d) { + return rowCountOfPanel(d) * d.calcdata.cells.height; +} + +function effectiveHeightOfPanelA(d) { + return effectiveHeightOfPanel(d); +} + function columnMoved(gd, calcdata, i, indices) { var o = calcdata[i][0].gdColumnsOriginalOrder; @@ -302,7 +314,7 @@ function renderColumnBlocks(columnBlock) { var columnCell = columnCells.selectAll('.columnCell') .data(function(d) { var rowFrom = Math.round(d.anchor / d.calcdata.cells.height); - var rowTo = rowFrom + (rowFrom >= 0 ? Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height) : 0); + var rowTo = rowFrom + (rowFrom >= 0 ? rowCountOfPanel(d) : 0); return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: rowFrom + i, column: d, calcdata: d.calcdata, value: v};}); }, gup.keyFun); From 6ff00f7b8cf22dd2554b620b3206a37614769c90 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 21 Aug 2017 21:23:00 +0200 Subject: [PATCH 009/281] from-to reads from anchor map --- src/traces/table/calc.js | 22 ++++++++++++++++++++++ src/traces/table/plot.js | 15 ++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 80af15aa8df..983ac3b02b5 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -29,6 +29,7 @@ module.exports = function calc(gd, trace) { var headerRows = trace.header.values[0].length; var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; + var minimumFillHeight = scrollHeight + c.uplift; var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); var rowAnchors = []; @@ -38,6 +39,25 @@ module.exports = function calc(gd, trace) { acc += rowHeights[i]; } + var anchorToRowBlock = {}; + var currentRowHeight; + var currentAnchor = 0; + var currentBlockHeight = 0; + var currentBlock = []; + for(i = 0; i < rowHeights.length; i++) { + currentRowHeight = rowHeights[i]; + currentBlockHeight += currentRowHeight; + currentBlock.push({ + rowIndex: i + }); + if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { + anchorToRowBlock[currentAnchor] = currentBlock; + currentBlock = []; + currentAnchor += currentBlockHeight; + currentBlockHeight = 0; + } + } + var uniqueKeys = {}; var columnOrder = trace._fullInput.columnorder; @@ -53,6 +73,8 @@ module.exports = function calc(gd, trace) { columnOrder: columnOrder, // will be mutated on column move headerHeight: headerHeight, scrollHeight: scrollHeight, + minimumFillHeight: minimumFillHeight, + anchorToRowBlock: anchorToRowBlock, scrollY: 0, // will be mutated on scroll cells: trace.cells, headerCells: trace.header, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 550e5516775..5b9e1528060 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -252,7 +252,7 @@ module.exports = function plot(gd, calcdata) { }; function rowCountOfPanel(d) { - return Math.ceil((d.calcdata.scrollHeight + c.uplift) / d.calcdata.cells.height); + return Math.ceil((d.calcdata.minimumFillHeight) / d.calcdata.cells.height); } function effectiveHeightOfPanel(d) { @@ -296,6 +296,13 @@ function easeColumn(elem, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } +function rowFromTo(d) { + var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; + var rowFrom = rowBlock ? rowBlock[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.length : 0; + return [rowFrom, rowTo]; +} + function renderColumnBlocks(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch @@ -313,10 +320,8 @@ function renderColumnBlocks(columnBlock) { var columnCell = columnCells.selectAll('.columnCell') .data(function(d) { - var rowFrom = Math.round(d.anchor / d.calcdata.cells.height); - var rowTo = rowFrom + (rowFrom >= 0 ? rowCountOfPanel(d) : 0); - - return d.values.slice(rowFrom, rowTo).map(function(v, i) {return {key: rowFrom + i, column: d, calcdata: d.calcdata, value: v};}); + var fromTo = rowFromTo(d); + return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) {return {key: fromTo[0] + i, column: d, calcdata: d.calcdata, value: v};}); }, gup.keyFun); columnCell.enter() From 95a66c97453daa5ba6708b8d23ab677c13911094 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 21 Aug 2017 21:26:03 +0200 Subject: [PATCH 010/281] row block is now an object --- src/traces/table/calc.js | 6 +++--- src/traces/table/plot.js | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 983ac3b02b5..988996cb5f1 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -43,16 +43,16 @@ module.exports = function calc(gd, trace) { var currentRowHeight; var currentAnchor = 0; var currentBlockHeight = 0; - var currentBlock = []; + var currentBlock = {rows: []}; for(i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; currentBlockHeight += currentRowHeight; - currentBlock.push({ + currentBlock.rows.push({ rowIndex: i }); if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; - currentBlock = []; + currentBlock = {rows: []}; currentAnchor += currentBlockHeight; currentBlockHeight = 0; } diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5b9e1528060..be9e5a6efda 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -263,6 +263,13 @@ function effectiveHeightOfPanelA(d) { return effectiveHeightOfPanel(d); } +function rowFromTo(d) { + var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; + var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; + return [rowFrom, rowTo]; +} + function columnMoved(gd, calcdata, i, indices) { var o = calcdata[i][0].gdColumnsOriginalOrder; @@ -296,13 +303,6 @@ function easeColumn(elem, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } -function rowFromTo(d) { - var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; - var rowFrom = rowBlock ? rowBlock[0].rowIndex : 0; - var rowTo = rowBlock ? rowFrom + rowBlock.length : 0; - return [rowFrom, rowTo]; -} - function renderColumnBlocks(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch From af697c11befc32d1993aa727e45cfa4304eb9d20 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 02:03:32 +0200 Subject: [PATCH 011/281] scroll with no d.anchor overshoot issue --- src/traces/table/calc.js | 12 ++++++++++-- src/traces/table/plot.js | 8 +++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 988996cb5f1..d055124e594 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -39,11 +39,18 @@ module.exports = function calc(gd, trace) { acc += rowHeights[i]; } + var makeIdentity = function() { + return { + totalHeight: 0, + rows: [] + }; + } + var anchorToRowBlock = {}; var currentRowHeight; var currentAnchor = 0; var currentBlockHeight = 0; - var currentBlock = {rows: []}; + var currentBlock = makeIdentity(); for(i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; currentBlockHeight += currentRowHeight; @@ -52,7 +59,8 @@ module.exports = function calc(gd, trace) { }); if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; - currentBlock = {rows: []}; + currentBlock.totalHeight = currentBlockHeight; + currentBlock = makeIdentity(); currentAnchor += currentBlockHeight; currentBlockHeight = 0; } diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index be9e5a6efda..be6fa5737d5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -162,7 +162,7 @@ module.exports = function plot(gd, calcdata) { calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; var panelHeight = effectiveHeightOfPanel(d); - if(blockY - d.anchor > panelHeight) { + if(blockY - d.anchor > panelHeight && d.anchor + 2 * panelHeight < 540) { d.anchor += 2 * panelHeight; anchorChanged = true; } else if(d.anchor - blockY > panelHeight) { @@ -256,11 +256,13 @@ function rowCountOfPanel(d) { } function effectiveHeightOfPanel(d) { - return rowCountOfPanel(d) * d.calcdata.cells.height; + var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; + if(!rowBlock) debugger + return rowBlock ? rowBlock.totalHeight : NaN; } function effectiveHeightOfPanelA(d) { - return effectiveHeightOfPanel(d); + return rowCountOfPanel(d) * d.calcdata.cells.height; } function rowFromTo(d) { From cecbc1775a7528793928d07b814f8bedc5979c2a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 02:40:24 +0200 Subject: [PATCH 012/281] on the brink of eliminating more legacy --- src/traces/table/plot.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index be6fa5737d5..f2e85a1842d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -132,6 +132,8 @@ module.exports = function plot(gd, calcdata) { rowBlockOffset: 1, calcdata: d.calcdata }); + revolverPanel1.otherPanel = revolverPanel2; + revolverPanel2.otherPanel = revolverPanel1; return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); @@ -161,12 +163,17 @@ module.exports = function plot(gd, calcdata) { var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; - var panelHeight = effectiveHeightOfPanel(d); - if(blockY - d.anchor > panelHeight && d.anchor + 2 * panelHeight < 540) { - d.anchor += 2 * panelHeight; + var jumpOld = 2 * effectiveHeightOfPanel(d) + var selfHeight = d.calcdata.anchorToRowBlock[d.anchor].totalHeight; + var otherHeight = d.calcdata.anchorToRowBlock[d.otherPanel.anchor].totalHeight; + var jump = selfHeight + otherHeight; + if(jump !== jumpOld) debugger + //if(d.anchor + 2 * panelHeight >= 540) debugger + if(blockY - d.anchor > otherHeight && d.anchor + jump < 540) { + d.anchor += jump; anchorChanged = true; - } else if(d.anchor - blockY > panelHeight) { - d.anchor -= 2 * panelHeight; + } else if(d.anchor - blockY > otherHeight) { + d.anchor -= jump; anchorChanged = true; } @@ -256,9 +263,7 @@ function rowCountOfPanel(d) { } function effectiveHeightOfPanel(d) { - var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; - if(!rowBlock) debugger - return rowBlock ? rowBlock.totalHeight : NaN; + return d.calcdata.anchorToRowBlock[d.anchor].totalHeight; } function effectiveHeightOfPanelA(d) { From 7c41679478f48a9a65ff394834eb22794c41ab1e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 02:44:37 +0200 Subject: [PATCH 013/281] removing one thing --- src/traces/table/plot.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f2e85a1842d..99e5a239fd3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -123,7 +123,7 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: effectiveHeightOfPanelA(d), // will be mutated on scroll; points to current place + anchor: d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place type: 'cells', yOffset: d.calcdata.headerHeight, dragHandle: false, @@ -163,12 +163,9 @@ module.exports = function plot(gd, calcdata) { var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; - var jumpOld = 2 * effectiveHeightOfPanel(d) var selfHeight = d.calcdata.anchorToRowBlock[d.anchor].totalHeight; var otherHeight = d.calcdata.anchorToRowBlock[d.otherPanel.anchor].totalHeight; var jump = selfHeight + otherHeight; - if(jump !== jumpOld) debugger - //if(d.anchor + 2 * panelHeight >= 540) debugger if(blockY - d.anchor > otherHeight && d.anchor + jump < 540) { d.anchor += jump; anchorChanged = true; @@ -258,18 +255,6 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function rowCountOfPanel(d) { - return Math.ceil((d.calcdata.minimumFillHeight) / d.calcdata.cells.height); -} - -function effectiveHeightOfPanel(d) { - return d.calcdata.anchorToRowBlock[d.anchor].totalHeight; -} - -function effectiveHeightOfPanelA(d) { - return rowCountOfPanel(d) * d.calcdata.cells.height; -} - function rowFromTo(d) { var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; From adbf6473202556b3e2ac4f5df9f42e36d67233db Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 03:03:34 +0200 Subject: [PATCH 014/281] removing dependency from rowPitch --- src/traces/table/calc.js | 6 ++++-- src/traces/table/plot.js | 19 +++++++++---------- test/image/mocks/table_one_column.json | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index d055124e594..cfd83193313 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -53,10 +53,12 @@ module.exports = function calc(gd, trace) { var currentBlock = makeIdentity(); for(i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; - currentBlockHeight += currentRowHeight; currentBlock.rows.push({ - rowIndex: i + rowIndex: i, + rowHeight: currentRowHeight, + rowAnchor: currentAnchor + currentBlockHeight }); + currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.totalHeight = currentBlockHeight; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 99e5a239fd3..36f08af7013 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -324,9 +324,8 @@ function renderColumnBlocks(columnBlock) { columnCell .attr('transform', function(d, i) { - console.log(i) - //debugger - return 'translate(' + 0 + ' ' + i * d.column.rowPitch + ')'; + var lookup = d.calcdata.anchorToRowBlock[d.column.anchor].rows; + return 'translate(' + 0 + ' ' + (lookup[i].rowAnchor - d.column.anchor) + ')'; }) .each(function(d, i) { var spec = d.calcdata.cells.font; @@ -354,7 +353,7 @@ function renderColumnBlocks(columnBlock) { cellRect .attr('width', function(d) {return d.column.columnWidth;}) - .attr('height', function(d) {return d.column.rowPitch;}) + .attr('height', function(d, i) {return d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight;}) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { return gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); @@ -372,10 +371,10 @@ function renderColumnBlocks(columnBlock) { cellLine .attr('id', function(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex;}) - .attr('d', function(d) { + .attr('d', function(d, i) { var x1 = 0; var x2 = d.column.columnWidth; - var y = d.column.rowPitch; + var y = d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight; return d3.svg.line()([[x1, y], [x2, y]]); }); @@ -387,11 +386,11 @@ function renderColumnBlocks(columnBlock) { .classed('cellText', true); cellText - .attr('dy', function(d) { - var rowPitch = d.column.rowPitch; + .attr('dy', function(d, i) { + var rowHeight = d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight; return ({ - top: -rowPitch + c.cellPad, - middle: -rowPitch / 2, + top: -rowHeight + c.cellPad, + middle: -rowHeight / 2, bottom: -c.cellPad })[d.valign]; }) diff --git a/test/image/mocks/table_one_column.json b/test/image/mocks/table_one_column.json index c0c066ee772..9d94f49bb08 100644 --- a/test/image/mocks/table_one_column.json +++ b/test/image/mocks/table_one_column.json @@ -20,7 +20,7 @@ "header": { - "height": 20, + "height": 27, "values": [ ["Index" , "#"] From 4b06d43bbede24dfd28470625292a3347ee7fd50 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 03:04:23 +0200 Subject: [PATCH 015/281] rowPitch gone --- src/traces/table/plot.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 36f08af7013..619434e7f67 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -105,7 +105,6 @@ module.exports = function plot(gd, calcdata) { yOffset: 0, anchor: 0, values: d.calcdata.headerCells.values[d.specIndex], - rowPitch: d.calcdata.headerCells.height, dragHandle: true, rowBlockOffset: 0, calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) @@ -117,7 +116,6 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - rowPitch: d.calcdata.cells.height, rowBlockOffset: 0, calcdata: d.calcdata }); @@ -128,7 +126,6 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - rowPitch: d.calcdata.cells.height, rowBlockOffset: 1, calcdata: d.calcdata }); From c7f3a9fa44ec9668bd3ad113a7de27c95c1957f9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 03:14:33 +0200 Subject: [PATCH 016/281] no more cells.height reference --- src/traces/table/plot.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 619434e7f67..22d2a7da72b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -157,11 +157,15 @@ module.exports = function plot(gd, calcdata) { var anchorChanged = false; cellsColumnBlock .attr('transform', function(d) { - var bottom = d.calcdata.cells.values[0].length * d.calcdata.cells.height - d.calcdata.scrollHeight; - calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - var blockY = calcdata.scrollY; var selfHeight = d.calcdata.anchorToRowBlock[d.anchor].totalHeight; var otherHeight = d.calcdata.anchorToRowBlock[d.otherPanel.anchor].totalHeight; + var blockAnchors = Object.keys(d.calcdata.anchorToRowBlock); + var lastAnchor = parseInt(blockAnchors[blockAnchors.length - 1]); + var lastBlock = d.calcdata.anchorToRowBlock[lastAnchor]; + var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; + var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; + calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); + var blockY = calcdata.scrollY; var jump = selfHeight + otherHeight; if(blockY - d.anchor > otherHeight && d.anchor + jump < 540) { d.anchor += jump; From d47e56cb9f895061f640c4345e31fb73cd202558 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 16:22:30 +0200 Subject: [PATCH 017/281] rendering with proper per-row height --- src/traces/table/calc.js | 8 +++++++- src/traces/table/plot.js | 22 +++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index cfd83193313..d0917abfb39 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -30,7 +30,7 @@ module.exports = function calc(gd, trace) { var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round(20 * (Math.random() - 0.5));}); var rowAnchors = []; var acc = 0; @@ -42,6 +42,8 @@ module.exports = function calc(gd, trace) { var makeIdentity = function() { return { totalHeight: 0, + firstRowIndex: null, + lastRowIndex: null, rows: [] }; } @@ -51,6 +53,7 @@ module.exports = function calc(gd, trace) { var currentAnchor = 0; var currentBlockHeight = 0; var currentBlock = makeIdentity(); + var currentFirstRowIndex = 0; for(i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; currentBlock.rows.push({ @@ -62,8 +65,11 @@ module.exports = function calc(gd, trace) { if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.totalHeight = currentBlockHeight; + currentBlock.firstRowIndex = currentFirstRowIndex; + currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); currentAnchor += currentBlockHeight; + currentFirstRowIndex = i + 1; currentBlockHeight = 0; } } diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 22d2a7da72b..7facd463cfd 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -256,6 +256,8 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; +function textPathUrl(d) {return 'textpath_' + d.column.key + '_' + d.key;} + function rowFromTo(d) { var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; @@ -352,9 +354,14 @@ function renderColumnBlocks(columnBlock) { .append('rect') .classed('cellRect', true); + function rowHeight(d) { + var lookup = d.calcdata.anchorToRowBlock[d.column.anchor]; + return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; + } + cellRect .attr('width', function(d) {return d.column.columnWidth;}) - .attr('height', function(d, i) {return d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight;}) + .attr('height', rowHeight) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { return gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); @@ -371,11 +378,12 @@ function renderColumnBlocks(columnBlock) { .classed('cellLine', true); cellLine - .attr('id', function(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex;}) + .attr('id', textPathUrl) .attr('d', function(d, i) { var x1 = 0; var x2 = d.column.columnWidth; - var y = d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight; + var y = rowHeight(d); + return d3.svg.line()([[x1, y], [x2, y]]); }); @@ -388,10 +396,10 @@ function renderColumnBlocks(columnBlock) { cellText .attr('dy', function(d, i) { - var rowHeight = d.calcdata.anchorToRowBlock[d.column.anchor].rows[i].rowHeight; + var height = rowHeight(d); return ({ - top: -rowHeight + c.cellPad, - middle: -rowHeight / 2, + top: -height + c.cellPad, + middle: -height / 2, bottom: -c.cellPad })[d.valign]; }) @@ -405,7 +413,7 @@ function renderColumnBlocks(columnBlock) { .classed('textPath', true); textPath - .attr('xlink:href', function(d) {return '#textpath_' + d.column.key + '_' + d.column.specIndex;}) + .attr('xlink:href', function(d) {return '#' + textPathUrl(d);}) .attr('text-anchor', function(d) { return ({ left: 'start', From 2b8a077828a8f6a96641a18bbcba02a75eb9f0f8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 22:10:32 +0200 Subject: [PATCH 018/281] tmp --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7facd463cfd..b09b1bff8f9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -359,6 +359,7 @@ function renderColumnBlocks(columnBlock) { return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; } + cellRect .attr('width', function(d) {return d.column.columnWidth;}) .attr('height', rowHeight) From aa0b2dd0ebdbd6252351696a84d87d895c2beec3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 22 Aug 2017 23:15:24 +0200 Subject: [PATCH 019/281] credible down scroll --- src/traces/table/plot.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b09b1bff8f9..2fe78c9eb0d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -167,10 +167,12 @@ module.exports = function plot(gd, calcdata) { calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var blockY = calcdata.scrollY; var jump = selfHeight + otherHeight; - if(blockY - d.anchor > otherHeight && d.anchor + jump < 540) { + if(blockY - d.anchor > selfHeight && d.calcdata.anchorToRowBlock[d.anchor + jump]) { + console.log('downward') d.anchor += jump; anchorChanged = true; - } else if(d.anchor - blockY > otherHeight) { + } else if(d.anchor - blockY > selfHeight && d.calcdata.anchorToRowBlock[d.anchor - jump]) { + console.log('upward') d.anchor -= jump; anchorChanged = true; } @@ -359,7 +361,6 @@ function renderColumnBlocks(columnBlock) { return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; } - cellRect .attr('width', function(d) {return d.column.columnWidth;}) .attr('height', rowHeight) From 4c0982c9299fd72333c3e31ea8e2ec60bf474c44 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 01:05:43 +0200 Subject: [PATCH 020/281] pre index based jumps --- src/traces/table/plot.js | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2fe78c9eb0d..a9314af5ac3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -153,6 +153,8 @@ module.exports = function plot(gd, calcdata) { }) .on('drag', function(d) { var calcdata = d.calcdata; + var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; + if(direction) console.log(direction) calcdata.scrollY -= d3.event.dy; var anchorChanged = false; cellsColumnBlock @@ -160,24 +162,33 @@ module.exports = function plot(gd, calcdata) { var selfHeight = d.calcdata.anchorToRowBlock[d.anchor].totalHeight; var otherHeight = d.calcdata.anchorToRowBlock[d.otherPanel.anchor].totalHeight; var blockAnchors = Object.keys(d.calcdata.anchorToRowBlock); + var blockAnchorsNumeric = blockAnchors.map(function(v) {return parseInt(v);}); var lastAnchor = parseInt(blockAnchors[blockAnchors.length - 1]); var lastBlock = d.calcdata.anchorToRowBlock[lastAnchor]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - var blockY = calcdata.scrollY; + var scrollY = calcdata.scrollY; + //console.log(scrollY) var jump = selfHeight + otherHeight; - if(blockY - d.anchor > selfHeight && d.calcdata.anchorToRowBlock[d.anchor + jump]) { - console.log('downward') - d.anchor += jump; - anchorChanged = true; - } else if(d.anchor - blockY > selfHeight && d.calcdata.anchorToRowBlock[d.anchor - jump]) { - console.log('upward') - d.anchor -= jump; - anchorChanged = true; + if(direction === 'down' && scrollY - d.anchor > selfHeight) { + if(d.calcdata.anchorToRowBlock[d.anchor + jump]) { + console.log('downward') + d.anchor += jump; + anchorChanged = true; + } + } else if(direction === 'up' && d.anchor > scrollY + selfHeight) { + if(d.calcdata.anchorToRowBlock[d.anchor - jump]) { + console.log('upward') + d.anchor -= jump; + anchorChanged = true; + } else { + debugger + console.log('failed') + } } - var yTranslate = d.anchor - blockY + d.yOffset; + var yTranslate = d.anchor - scrollY + d.yOffset; return 'translate(0 ' + yTranslate + ')'; From 9738b6a88e2af1581b37326f3f5a99b2921a9948 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 01:14:25 +0200 Subject: [PATCH 021/281] great heterogenous row height scrolling --- src/traces/table/plot.js | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a9314af5ac3..a39718d6811 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -159,32 +159,23 @@ module.exports = function plot(gd, calcdata) { var anchorChanged = false; cellsColumnBlock .attr('transform', function(d) { - var selfHeight = d.calcdata.anchorToRowBlock[d.anchor].totalHeight; - var otherHeight = d.calcdata.anchorToRowBlock[d.otherPanel.anchor].totalHeight; - var blockAnchors = Object.keys(d.calcdata.anchorToRowBlock); - var blockAnchorsNumeric = blockAnchors.map(function(v) {return parseInt(v);}); - var lastAnchor = parseInt(blockAnchors[blockAnchors.length - 1]); + var blockAnchorKeys = Object.keys(d.calcdata.anchorToRowBlock); + var blockAnchors = blockAnchorKeys.map(function(v) {return parseInt(v);}); + var lastAnchor = blockAnchors[blockAnchors.length - 1]; var lastBlock = d.calcdata.anchorToRowBlock[lastAnchor]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var scrollY = calcdata.scrollY; - //console.log(scrollY) - var jump = selfHeight + otherHeight; - if(direction === 'down' && scrollY - d.anchor > selfHeight) { - if(d.calcdata.anchorToRowBlock[d.anchor + jump]) { - console.log('downward') - d.anchor += jump; + if(direction === 'down' && scrollY - d.anchor > d.calcdata.scrollHeight) { + if(blockAnchors.indexOf(d.anchor) + 2 < blockAnchors.length) { + d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) + 2]; anchorChanged = true; } - } else if(direction === 'up' && d.anchor > scrollY + selfHeight) { - if(d.calcdata.anchorToRowBlock[d.anchor - jump]) { - console.log('upward') - d.anchor -= jump; + } else if(direction === 'up' && d.anchor > scrollY + d.calcdata.scrollHeight) { + if(blockAnchors.indexOf(d.anchor) - 2 >= 0) { + d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) - 2]; anchorChanged = true; - } else { - debugger - console.log('failed') } } From 06ba08d052fb4228c3714180ffbccd6efdba6aa6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 01:21:37 +0200 Subject: [PATCH 022/281] gapless scroll --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a39718d6811..bb6b99e6012 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -154,7 +154,7 @@ module.exports = function plot(gd, calcdata) { .on('drag', function(d) { var calcdata = d.calcdata; var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; - if(direction) console.log(direction) + if(!direction) return; calcdata.scrollY -= d3.event.dy; var anchorChanged = false; cellsColumnBlock @@ -167,7 +167,7 @@ module.exports = function plot(gd, calcdata) { var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); var scrollY = calcdata.scrollY; - if(direction === 'down' && scrollY - d.anchor > d.calcdata.scrollHeight) { + if(direction === 'down' && scrollY - d.anchor > d.calcdata.anchorToRowBlock[d.anchor].totalHeight) { if(blockAnchors.indexOf(d.anchor) + 2 < blockAnchors.length) { d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) + 2]; anchorChanged = true; From a8c799e8e35a0f8f3557841b944ad577dbf7a6ff Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 01:28:47 +0200 Subject: [PATCH 023/281] minor --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index d0917abfb39..e9a79157338 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -30,7 +30,7 @@ module.exports = function calc(gd, trace) { var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round(20 * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 2 ? 0 : 20) * (Math.random() - 0.5));}); var rowAnchors = []; var acc = 0; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index bb6b99e6012..28c9faaed8f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -113,7 +113,7 @@ module.exports = function plot(gd, calcdata) { key: 'cells1', type: 'cells', anchor: 0, // will be mutated on scroll; points to current place - yOffset: d.calcdata.headerHeight, + yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlockOffset: 0, @@ -123,7 +123,7 @@ module.exports = function plot(gd, calcdata) { key: 'cells2', anchor: d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place type: 'cells', - yOffset: d.calcdata.headerHeight, + yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlockOffset: 1, @@ -302,6 +302,11 @@ function easeColumn(elem, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } +function rowHeight(d) { + var lookup = d.calcdata.anchorToRowBlock[d.column.anchor]; + return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; +} + function renderColumnBlocks(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch @@ -358,11 +363,6 @@ function renderColumnBlocks(columnBlock) { .append('rect') .classed('cellRect', true); - function rowHeight(d) { - var lookup = d.calcdata.anchorToRowBlock[d.column.anchor]; - return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; - } - cellRect .attr('width', function(d) {return d.column.columnWidth;}) .attr('height', rowHeight) From 5354a3378ba8ab75f24f0ff998f7ca44f65984a2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 01:53:51 +0200 Subject: [PATCH 024/281] covering multicolumn case --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 2 +- test/image/mocks/table.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index e9a79157338..079fa2664e2 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -30,7 +30,7 @@ module.exports = function calc(gd, trace) { var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 2 ? 0 : 20) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 2 ? 0 : 25) * (Math.random() - 0.5));}); var rowAnchors = []; var acc = 0; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 28c9faaed8f..459255088be 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -260,7 +260,7 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function textPathUrl(d) {return 'textpath_' + d.column.key + '_' + d.key;} +function textPathUrl(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex + '_' + d.key;} function rowFromTo(d) { var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json index 3be5713e0dd..54b5550a290 100644 --- a/test/image/mocks/table.json +++ b/test/image/mocks/table.json @@ -88,7 +88,7 @@ "prefix": ["#", "", "", "", "", "US ", ""], "suffix": ["", " class", "m", ""], - "height": 27, + "height": 20, "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], "valign": ["middle", "top", "bottom", "middle"], From 8d2d331eaa6715207cf47a3d12505bb0d11fa445 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 19:16:54 +0200 Subject: [PATCH 025/281] heterogeneous header row heights --- src/traces/table/calc.js | 8 ++++++-- src/traces/table/plot.js | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 079fa2664e2..f9db3fbdd65 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -11,6 +11,11 @@ var c = require('./constants'); var wrap = require('../../lib/gup').wrap; +function makeAnchorToRowBlock() { + + return anchorToRowBlock; +} + module.exports = function calc(gd, trace) { var domain = trace.domain; @@ -30,7 +35,7 @@ module.exports = function calc(gd, trace) { var headerHeight = headerRows * trace.header.height; var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 2 ? 0 : 25) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); var rowAnchors = []; var acc = 0; @@ -89,7 +94,6 @@ module.exports = function calc(gd, trace) { columnOrder: columnOrder, // will be mutated on column move headerHeight: headerHeight, scrollHeight: scrollHeight, - minimumFillHeight: minimumFillHeight, anchorToRowBlock: anchorToRowBlock, scrollY: 0, // will be mutated on scroll cells: trace.cells, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 459255088be..fce086f183f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -159,15 +159,15 @@ module.exports = function plot(gd, calcdata) { var anchorChanged = false; cellsColumnBlock .attr('transform', function(d) { - var blockAnchorKeys = Object.keys(d.calcdata.anchorToRowBlock); + var anchorToBlock = d.calcdata.anchorToRowBlock; + var blockAnchorKeys = Object.keys(anchorToBlock); var blockAnchors = blockAnchorKeys.map(function(v) {return parseInt(v);}); var lastAnchor = blockAnchors[blockAnchors.length - 1]; - var lastBlock = d.calcdata.anchorToRowBlock[lastAnchor]; + var lastBlock = anchorToBlock[lastAnchor]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; - calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - var scrollY = calcdata.scrollY; - if(direction === 'down' && scrollY - d.anchor > d.calcdata.anchorToRowBlock[d.anchor].totalHeight) { + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); + if(direction === 'down' && scrollY - d.anchor > anchorToBlock[d.anchor].totalHeight) { if(blockAnchors.indexOf(d.anchor) + 2 < blockAnchors.length) { d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) + 2]; anchorChanged = true; From 684dc93d69e1ba2f636300d854f27eddc37e965f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 23 Aug 2017 20:29:33 +0200 Subject: [PATCH 026/281] preparation for heterogeneous header row heights --- src/traces/table/calc.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index f9db3fbdd65..fdfc62441cf 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -31,18 +31,11 @@ module.exports = function calc(gd, trace) { var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - var headerRows = trace.header.values[0].length; - var headerHeight = headerRows * trace.header.height; + var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - - var rowAnchors = []; - var acc = 0; - for(var i = 0; i < rowHeights.length; i++) { - rowAnchors.push(acc); - acc += rowHeights[i]; - } var makeIdentity = function() { return { @@ -59,7 +52,7 @@ module.exports = function calc(gd, trace) { var currentBlockHeight = 0; var currentBlock = makeIdentity(); var currentFirstRowIndex = 0; - for(i = 0; i < rowHeights.length; i++) { + for(var i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; currentBlock.rows.push({ rowIndex: i, @@ -99,7 +92,6 @@ module.exports = function calc(gd, trace) { cells: trace.cells, headerCells: trace.header, rowHeights: rowHeights, - rowAnchors: rowAnchors, columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; From 6863929b28ca358971b074f4652ad5c2a15088c9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 24 Aug 2017 00:24:47 +0200 Subject: [PATCH 027/281] perfect heterogeneous header row heights --- src/traces/table/calc.js | 68 +++++++++++++++++++++------------------- src/traces/table/plot.js | 13 +++++--- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index fdfc62441cf..b8debf823cf 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -11,40 +11,16 @@ var c = require('./constants'); var wrap = require('../../lib/gup').wrap; -function makeAnchorToRowBlock() { - - return anchorToRowBlock; +function makeIdentity() { + return { + totalHeight: 0, + firstRowIndex: null, + lastRowIndex: null, + rows: [] + }; } -module.exports = function calc(gd, trace) { - - var domain = trace.domain; - var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); - var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); - - var columnWidths = trace.header.values.map(function(d, i) { - return Array.isArray(trace.columnwidth) ? - trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : - isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; - }); - - var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); - columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - - var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); - var scrollHeight = groupHeight - headerHeight; - var minimumFillHeight = scrollHeight + c.uplift; - - var makeIdentity = function() { - return { - totalHeight: 0, - firstRowIndex: null, - lastRowIndex: null, - rows: [] - }; - } +function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { var anchorToRowBlock = {}; var currentRowHeight; @@ -72,6 +48,33 @@ module.exports = function calc(gd, trace) { } } + return anchorToRowBlock; +} + +module.exports = function calc(gd, trace) { + + var domain = trace.domain; + var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); + var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); + + var columnWidths = trace.header.values.map(function(d, i) { + return Array.isArray(trace.columnwidth) ? + trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : + isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; + }); + + var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); + columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); + + var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); + var scrollHeight = groupHeight - headerHeight; + var minimumFillHeight = scrollHeight + c.uplift; + + var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); + var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); + var uniqueKeys = {}; var columnOrder = trace._fullInput.columnorder; @@ -88,6 +91,7 @@ module.exports = function calc(gd, trace) { headerHeight: headerHeight, scrollHeight: scrollHeight, anchorToRowBlock: anchorToRowBlock, + anchorToHeaderRowBlock: anchorToHeaderRowBlock, scrollY: 0, // will be mutated on scroll cells: trace.cells, headerCells: trace.header, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fce086f183f..550cdd2ada5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -105,6 +105,7 @@ module.exports = function plot(gd, calcdata) { yOffset: 0, anchor: 0, values: d.calcdata.headerCells.values[d.specIndex], + anchorToRowBlock: d.calcdata.anchorToHeaderRowBlock, dragHandle: true, rowBlockOffset: 0, calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) @@ -116,6 +117,7 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], + anchorToRowBlock: d.calcdata.anchorToRowBlock, rowBlockOffset: 0, calcdata: d.calcdata }); @@ -126,6 +128,7 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], + anchorToRowBlock: d.calcdata.anchorToRowBlock, rowBlockOffset: 1, calcdata: d.calcdata }); @@ -159,7 +162,7 @@ module.exports = function plot(gd, calcdata) { var anchorChanged = false; cellsColumnBlock .attr('transform', function(d) { - var anchorToBlock = d.calcdata.anchorToRowBlock; + var anchorToBlock = d.anchorToRowBlock; var blockAnchorKeys = Object.keys(anchorToBlock); var blockAnchors = blockAnchorKeys.map(function(v) {return parseInt(v);}); var lastAnchor = blockAnchors[blockAnchors.length - 1]; @@ -263,7 +266,7 @@ module.exports = function plot(gd, calcdata) { function textPathUrl(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex + '_' + d.key;} function rowFromTo(d) { - var rowBlock = d.calcdata.anchorToRowBlock[d.anchor]; + var rowBlock = d.anchorToRowBlock[d.anchor]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; return [rowFrom, rowTo]; @@ -303,7 +306,7 @@ function easeColumn(elem, d, y) { } function rowHeight(d) { - var lookup = d.calcdata.anchorToRowBlock[d.column.anchor]; + var lookup = d.anchorToRowBlock[d.column.anchor]; return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; } @@ -325,7 +328,7 @@ function renderColumnBlocks(columnBlock) { var columnCell = columnCells.selectAll('.columnCell') .data(function(d) { var fromTo = rowFromTo(d); - return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) {return {key: fromTo[0] + i, column: d, calcdata: d.calcdata, value: v};}); + return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) {return {key: fromTo[0] + i, column: d, calcdata: d.calcdata, anchorToRowBlock: d.anchorToRowBlock, value: v};}); }, gup.keyFun); columnCell.enter() @@ -336,7 +339,7 @@ function renderColumnBlocks(columnBlock) { columnCell .attr('transform', function(d, i) { - var lookup = d.calcdata.anchorToRowBlock[d.column.anchor].rows; + var lookup = d.anchorToRowBlock[d.column.anchor].rows; return 'translate(' + 0 + ' ' + (lookup[i].rowAnchor - d.column.anchor) + ')'; }) .each(function(d, i) { From da3d4a74e181cc802d1cab197f78efc3017263fe Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 24 Aug 2017 15:18:15 +0200 Subject: [PATCH 028/281] baseline for tspan based text rendering --- src/traces/table/plot.js | 46 +++++++--------------------------------- 1 file changed, 8 insertions(+), 38 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 550cdd2ada5..67c4fc3f3bd 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -263,7 +263,7 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function textPathUrl(d) {return 'textpath_' + d.column.key + '_' + d.column.specIndex + '_' + d.key;} +function textFragmentUrl(d) {return 'textFragment_' + d.column.key + '_' + d.column.specIndex + '_' + d.key;} function rowFromTo(d) { var rowBlock = d.anchorToRowBlock[d.anchor]; @@ -377,23 +377,6 @@ function renderColumnBlocks(columnBlock) { return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); }); - var cellLine = columnCell.selectAll('.cellLine') - .data(gup.repeat, gup.keyFun); - - cellLine.enter() - .append('path') - .classed('cellLine', true); - - cellLine - .attr('id', textPathUrl) - .attr('d', function(d, i) { - var x1 = 0; - var x2 = d.column.columnWidth; - var y = rowHeight(d); - - return d3.svg.line()([[x1, y], [x2, y]]); - }); - var cellText = columnCell.selectAll('.cellText') .data(gup.repeat, gup.keyFun); @@ -404,6 +387,7 @@ function renderColumnBlocks(columnBlock) { cellText .attr('dy', function(d, i) { var height = rowHeight(d); + return c.cellPad; return ({ top: -height + c.cellPad, middle: -height / 2, @@ -412,30 +396,16 @@ function renderColumnBlocks(columnBlock) { }) .each(function(d) {Drawing.font(d3.select(this), d.font);}); - var textPath = cellText.selectAll('.textPath') + var textFragment = cellText.selectAll('.textFragment') .data(gup.repeat, gup.keyFun); - textPath.enter() - .append('textPath') - .classed('textPath', true); + textFragment.enter() + .append('tspan') + .classed('textFragment', true); - textPath - .attr('xlink:href', function(d) {return '#' + textPathUrl(d);}) - .attr('text-anchor', function(d) { - return ({ - left: 'start', - right: 'end', - center: 'middle' - })[d.align]; - }) - .attr('startOffset', function(d) { - return ({ - left: c.cellPad, - right: d.column.columnWidth - c.cellPad, - center: '50%' - })[d.align]; - }) + textFragment .attr('alignment-baseline', function(d) { + return "hanging"; return ({ top: "hanging", middle: "central", From 51604489de32160fd582f8244f1a913bf655aeaf Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 24 Aug 2017 15:41:45 +0200 Subject: [PATCH 029/281] using convertToTspans --- src/traces/table/plot.js | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 67c4fc3f3bd..b22e5b4d951 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -13,6 +13,7 @@ var d3 = require('d3'); var gup = require('../../lib/gup'); var Drawing = require('../../components/drawing'); var extendFlat = require('../../lib/extend').extendFlat; +var util = require('../../lib/svg_text_utils'); module.exports = function plot(gd, calcdata) { @@ -394,24 +395,7 @@ function renderColumnBlocks(columnBlock) { bottom: -c.cellPad })[d.valign]; }) - .each(function(d) {Drawing.font(d3.select(this), d.font);}); - - var textFragment = cellText.selectAll('.textFragment') - .data(gup.repeat, gup.keyFun); - - textFragment.enter() - .append('tspan') - .classed('textFragment', true); - - textFragment - .attr('alignment-baseline', function(d) { - return "hanging"; - return ({ - top: "hanging", - middle: "central", - bottom: "alphabetic" - })[d.valign]; - }) + .attr('alignment-baseline', 'hanging') .text(function(d) { var col = d.column.specIndex; var row = d.rowNumber; @@ -419,5 +403,10 @@ function renderColumnBlocks(columnBlock) { var suffix = gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = gridPick(d.calcdata.cells.format, col, row) || ''; return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; + }) + .each(function(d) { + var selection = d3.select(this); + Drawing.font(selection, d.font); + util.convertToTspans(selection); }); }; From 815aeb6f7091212e186a5b52120011569accc7ae Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 24 Aug 2017 23:56:33 +0200 Subject: [PATCH 030/281] large mock --- .../mocks/gl2d_parcoords_very_large.json | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 test/image/mocks/gl2d_parcoords_very_large.json diff --git a/test/image/mocks/gl2d_parcoords_very_large.json b/test/image/mocks/gl2d_parcoords_very_large.json new file mode 100644 index 00000000000..360c5a59e35 --- /dev/null +++ b/test/image/mocks/gl2d_parcoords_very_large.json @@ -0,0 +1,94 @@ +{ + + 'layout': { + 'width': 1400, + 'height': 400 + }, + + 'data': [{ + + 'type': 'parcoords', + + 'domain': { + 'x': [0, 1], + 'y': [0, 1] + }, + + 'pad': [80, 80, 80, 80], + + 'line': { + + 'showscale': true, + 'reversescale': true, + 'colorscale': 'Jet', + 'cmin': -4000, + 'cmax': -100, + 'color': [-41, -1317, -164, -1856, -79, -931, -191, -2983, -341, -3846, -278, -3019, -523, -2357, -985, -3447, -211, -2842, -458, -4388, -784, -2563, -935, -2253, -313, -3667, -1479, -1030, -632, -623, -1945, -1324, -1221, -878, -947, -1615, -697, -575, -482, -905, -869, -433, -484, -349, -667, -248, -1135, -888, -1019, -223, -2067, -729, -579, -659, -334, -340, -554, -455, -377, -375, -453, -834, -934, -334, -369, -290, -354, -497, -490, -329, -729, -1794, -151, -1162, -3935, -1013, -509, -825, -997, -320, -680, -422, -785, -542, -563, -489, -1283, -680, -78, -450, -514, -449, -548, -661, -641, -503, -570, -257, -394, -450, -586, -503, -437, -590, -622, -482, -3687, -2394, -773, -1029, -619, -1561, -543, -894, -1037, -705, -208, -325, -693, -652, -855, -642, -317, -435, -310, -329, -380, -371, -610, -406, -310, -1034, -700, -367, -337, -286, -856, -350, -576, -653, -219, -325, -1200, -49, -2664, -856, -344, -520, -766, -286, -291, -1334, -591, -346, -320, -342, -393, -503, -316, -280, -256, -307, -606, -269, -302, -443, -297, -272, -281, -288, -287, -302, -414, -312, -1196, -214, -245, -282, -315, -268, -966, -270, -315, -248, -502, -316, -299, -256, -358, -276, -288, -331, -282, -845, -409, -293, -292, -481, -291, -271, -279, -270, -4948, -402, -280, -261, -293, -765, -162, -265, -266, -253, -869, -237, -285, -276, -225, -229, -446, -567, -272, -876, -260, -251, -284, -2709, -263, -3948, -479, -269, -959, -267, -762, -252, -263, -251, -485, -753, -362, -257, -910, -972, -233, -455, -673, -272, -259, -243, -616, -628, -262, -232, -733, -236, -247, -479, -983, -240, -306, -256, -2269, -262, -106, -225, -893, -238, -253, -373, -476, -234, -469, -354, -219, -731, -255, -262, -317, -275, -518, -894, -251, -3278, -1219, -256, -261, -304, -241, -251, -253, -140, -877, -231, -261, -319, -259, -250, -246, -279, -245, -262, -257, -752, -238, -311, -298, -253, -280, -296, -285, -280, -265, -503, -260, -890, -555, -289, -246, -256, -241, -286, -247, -1881, -267, -225, -252, -911, -283, -250, -466, -269, -241, -270, -259, -908, -255, -447, -432, -244, -373, -816, -391, -3466, -1384, -937, -490, -629, -837, -900, -385, -290, -249, -256, -422, -224, -210, -235, -191, -318, -960, -250, -1124, -254, -247, -639, -291, -487, -229, -225, -258, -513, -466, -347, -216, -313, -250, -242, -310, -234, -377, -234, -247, -891, -293, -242, -830, -227, -654, -238, -1341, -487, -263, -246, -240, -219, -717, -247, -730, -385, -226, -257, -238, -259, -246, -253, -418, -259, -247, -468, -270, -273, -228, -518, -262, -1035, -242, -257, -276, -1165, -252, -1456, -416, -1974, -267, -1211, -437, -481, -1143, -252, -321, -234, -891, -705, -667, -246, -771, -907, -978, -80, -272, -285, -1236, -249, -589, -96, -349, -155, -241, -239, -235, -247, -264, -557, -298, -338, -428, -238, -236, -1515, -257, -415, -389, -267, -477, -1628, -237, -248, -265, -237, -304, -229, -297, -238, -236, -243, -265, -461, -1370, -241, -948, -389, -341, -336, -603, -449, -245, -1716, -258, -66, -397, -289, -985, -299, -1063, -260, -428, -254, -254, -566, -264, -258, -911, -1156, -268, -399, -245, -430, -263, -1083, -286, -1307, -442, -217, -268, -1223, -226, -419, -281, -629, -1145, -297, -247, -341, -1003, -414, -1312, -368, -998, -343, -760, -1214, -264, -1336, -932, -1188, -268, -395, -851, -262, -797, -478, -251, -298, -833, -788, -532, -1440, -1135, -444, -913, -1876, -395, -845, -734, -1458, -843, -994, -688, -438, -349, -724, -208, -764, -722, -493, -703, -423, -465, -431, -482, -385, -1141, -1228, -689, -439, -334, -386, -761, -466, -634, -328, -477, -2190, -652, -736, -490, -394, -497, -306, -426, -395, -1566, -297, -452, -328, -271, -341, -340, -279, -363, -346, -340, -323, -462, -341, -334, -1320, -275, -304, -523, -408, -340, -315, -314, -480, -335, -328, -294, -1142, -403, -1115, -416, -155, -254, -412, -468, -873, -752, -332, -324, -731, -344, -551, -514, -303, -335, -81, -320, -286, -371, -313, -289, -282, -294, -348, -345, -758, -1006, -964, -386, -1166, -283, -501, -931, -638, -363, -474, -354, -1394, -314, -324, -365, -385, -293, -951, -316, -1082, -943, -243, -554, -303, -265, -1044, -889, -304, -938, -302, -317, -302, -290, -523, -314, -272, -917, -277, -311, -943, -836, -414, -490, -319, -289, -298, -317, -285, -267, -309, -323, -357, -277, -335, -278, -300, -742, -897, -353, -3626, -284, -287, -418, -343, -1691, -314, -270, -239, -1182, -1260, -329, -273, -311, -283, -935, -469, -256, -281, -272, -222, -1116, -417, -281, -227, -278, -933, -429, -281, -310, -940, -278, -262, -271, -263, -266, -265, -249, -263, -264, -273, -249, -258, -244, -776, -228, -247, -237, -275, -673, -712, -415, -224, -305, -248, -252, -226, -252, -896, -960, -259, -270, -234, -1483, -235, -276, -259, -946, -379, -250, -241, -249, -1238, -247, -1602, -453, -240, -1193, -238, -636, -1053, -258, -245, -1337, -441, -253, -1179, -267, -850, -678, -336, -275, -257, -276, -244, -227, -1657, -294, -932, -359, -256, -496, -1201, -423, -243, -474, -724, -237, -1016, -1814, -269, -214, -1019, -239, -256, -478, -544, -241, -473, -289, -303, -415, -261, -249, -259, -257, -259, -339, -241, -229, -245, -616, -303, -1142, -260, -250, -442, -294, -85, -1252, -1201, -285, -255, -373, -291, -249, -268, -245, -459, -841, -254, -247, -425, -935, -1043, -248, -250, -401, -268, -225, -414, -252, -339, -292, -961, -231, -874, -1041, -1530, -291, -1264, -667, -235, -259, -243, -239, -246, -882, -236, -484, -224, -242, -1247, -543, -247, -1323, -256, -234, -224, -257, -1255, -209, -307, -238, -240, -281, -3366, -639, -676, -303, -234, -255, -229, -751, -265, -232, -232, -239, -479, -264, -243, -314, -344, -1073, -263, -221, -253, -209, -337, -210, -210, -312, -295, -976, -118, -224, -978, -406, -250, -250, -304, -398, -1350, -259, -269, -241, -401, -248, -238, -1325, -248, -248, -269, -276, -850, -247, -216, -291, -1012, -243, -266, -253, -398, -895, -225, -361, -260, -248, -955, -1530, -260, -275, -271, -272, -258, -1096, -280, -262, -227, -247, -607, -245, -262, -240, -242, -248, -245, -403, -268, -253, -246, -241, -243, -243, -419, -246, -81, -257, -372, -252, -237, -249, -261, -246, -236, -252, -262, -252, -310, -238, -241, -271, -818, -236, -277, -238, -255, -238, -261, -239, -219, -249, -244, -200, -235, -263, -379, -372, -270, -260, -234, -713, -1011, -265, -259, -231, -468, -256, -167, -710, -534, -268, -313, -274, -258, -711, -260, -248, -255, -1015, -468, -514, -232, -455, -226, -358, -219, -270, -250, -129, -239, -247, -305, -264, -274, -244, -370, -1115, -230, -1834, -252, -946, -240, -249, -235, -755, -248, -1036, -244, -230, -226, -1166, -629, -311, -253, -900, -245, -907, -268, -251, -309, -248, -307, -241, -238, -820, -236, -285, -751, -232, -250, -236, -246, -754, -977, -925, -277, -894, -240, -224, -246, -56, -500, -249, -791, -1523, -225, -243, -315, -231, -267, -439, -232, -223, -238, -243, -276, -240, -259, -261, -314, -256, -323, -245, -261, -414, -286, -89, -232, -268, -818, -764, -1122, -652, -518, -279, -1081, -241, -262, -234, -171, -992, -274, -444, -321, -248, -884, -714, -231, -258, -215, -825, -246, -530, -282, -438, -259, -260, -374, -627, -578, -603, -794, -965, -227, -237, -224, -431, -242, -236, -245, -492, -242, -779, -242, -219, -246, -224, -364, -265, -188, -1278, -1909, -384, -51, -1974, -36, -225, -573, -878, -292, -213, -2668, -251, -1161, -906, -697, -914, -261, -474, -320, -564, -314, -536, -331, -274, -262, -261, -753, -815, -254, -294, -273, -259, -1798, -226, -297, -222, -258, -791, -1254, -254, -767, -259, -245, -304, -235, -260, -275, -940, -244, -843, -279, -262, -282, -1031, -233, -265, -983, -259, -256, -254, -278, -699, -1391, -1412, -285, -106, -768, -241, -372, -276, -121, -274, -257, -276, -1039, -560, -1277, -260, -267, -547, -239, -118, -423, -239, -1278, -893, -366, -352, -505, -1450, -1063, -233, -710, -500, -227, -239, -937, -784, -564, -231, -601, -281, -509, -256, -229, -264, -589, -1738, -322, -589, -868, -253, -248, -945, -128, -309, -953, -3122, -1375, -227, -251, -250, -255, -1133, -307, -247, -247, -128, -322, -283, -307, -728, -922, -257, -255, -226, -509, -221, -3099, -501, -884, -317, -961, -1064, -738, -216, -252, -933, -988, -369, -322, -324, -234, -433, -677, -386, -301, -544, -3013, -362, -320, -938, -430, -315, -349, -299, -287, -798, -331, -331, -522, -379, -277, -579, -342, -263, -255, -426, -278, -770, -269, -825, -875, -449, -248, -247, -265, -990, -446, -222, -1037, -110, -218, -417, -290, -388, -2178, -247, -522, -3693, -266, -248, -811, -427, -231, -339, -247, -457, -264, -549, -1122, -285, -971, -243, -1121, -277, -575, -447, -297, -670, -262, -500, -747, -214, -611, -727, -601, -1677, -814, -875, -234, -606, -504, -222, -943, -3983, -1216, -352, -199, -975, -3352, -314, -204, -963, -437, -1236, -331, -226, -281, -1188, -331, -658, -539, -318, -441, -291, -244, -294, -276, -267, -879, -258, -259, -261, -841, -408, -569, -796, -228, -308, -278, -287, -463, -522, -439, -301, -275, -780, -557, -260, -427, -302, -266, -268, -164, -314, -932, -290, -497, -309, -1000, -1786, -288, -237, -283, -548, -311, -288, -426, -303, -110, -82, -284, -338, -261, -285, -1551, -98, -283, -478, -4001, -262, -406, -460, -298, -357, -224, -274, -872, -90, -1089, -949, -407, -210, -541, -274, -860, -818, -2829, -240, -265, -235, -929, -574, -365, -599, -312, -377, -914, -322, -234, -251, -300, -247, -236, -240, -503, -217, -258, -258, -234, -906, -239, -262, -747, -253, -1855, -261, -451, -775, -265, -544, -413, -932, -268, -755, -1312, -698, -3463, -766, -383, -265, -509, -262, -297, -684, -407, -232, -1317, -407, -785, -458, -381, -317, -263, -282, -193, -471, -240, -637, -225, -1066, -313, -452, -803, -321, -1316, -245, -253, -1015, -258, -459, -265, -237, -281, -263, -248, -250, -254, -269, -769, -1479, -240, -260, -363, -254, -975, -248, -703, -351, -384, -257, -315, -259, -266, -271, -1136, -243, -278, -400, -905, -361, -642, -456, -362, -257, -242, -264, -1300, -255, -1413, -250, -968, -225, -255, -324, -278, -283, -425, -265, -454, -412, -1002, -316, -281, -243, -252, -1125, -336, -905, -291, -389, -602, -323, -296, -307, -108, -392, -246, -254, -254, -219, -282, -275, -607, -532, -436, -237, -218, -1216, -259, -249, -1838, -268, -215, -203, -265, -287, -808, -913, -1299, -1845, -791, -247, -714, -2586, -1130, -441, -398, -387, -226, -731, -186, -2805, -294, -954, -267, -751, -159, -307, -254, -290, -253, -277, -273, -262, -249, -503, -255, -248, -393, -272, -668, -990, -1045, -306, -244, -982, -788, -775, -1011, -1174, -1431, -141, -429, -285, -236, -217, -240, -1035, -143, -292, -808, -637, -223, -386, -871, -3825, -862, -352, -1761, -609, -906, -605, -300, -326, -438, -964, -467, -790, -249, -238, -1371, -721, -356, -261, -284, -300, -1071, -423, -649, -605, -341, -308, -85, -266, -672, -283, -271, -1070, -412, -293, -1622, -375, -226, -348, -458, -279, -254, -296, -235, -279, -399, -443, -287, -301, -500, -1182, -374, -238, -318, -101, -2923, -80, -427, -279, -267, -933, -812, -243, -822, -255, -263, -270, -259, -282, -229, -275, -250, -271, -236, -363, -182, -1314, -259, -260, -260, -1208, -147, -451, -276, -294, -85, -1024, -255, -312, -1283, -296, -277, -472, -210, -1021, -226, -235, -1046, -1677, -282, -215, -724, -1105, -262, -296, -333, -261, -274, -216, -239, -251, -293, -500, -892, -67, -1020, -971, -585, -889, -83, -210, -1002, -311, -269, -416, -706, -890, -246, -407, -675, -647, -266, -288, -855, -619, -964, -264, -276, -851, -347, -545, -788, -1030, -942, -442, -236, -246, -222, -330, -970, -506, -248, -694, -260, -469, -320, -218, -422, -297, -255, -1382, -251, -267, -1026, -574, -1076, -88, -347, -466, -86, -343, -2118, -423, -955, -470, -445, -935, -347, -308, -426, -289, -242, -582, -296, -249, -289, -273, -255, -300, -292, -409, -305, -883, -1238, -933, -260, -466, -292, -309, -400, -304, -89, -255, -301, -141, -227, -263, -48, -415, -243, -437, -359, -203, -263, -255, -306, -252, -277, -458, -849, -230, -213, -480, -358, -370, -649, -287, -227, -247, -267, -261, -383, -258, -300, -1203, -305, -840, -273, -260, -329, -234, -288, -283, -287, -245, -299, -240, -276, -1009, -183, -251, -329, -452, -265, -472, -710, -1232, -255, -265, -913, -343, -431, -288, -1293, -358, -262, -282, -245, -258, -233, -266, -238, -494, -217, -263, -248, -83, -287, -299, -368, -188, -271, -488, -1314, -244, -879, -276, -876, -408, -104, -237, -416, -97, -259, -545, -216, -1066, -806, -530, -277, -485, -283, -330, -1282, -277, -327, -248, -943, -782, -287, -260, -311, -252, -297, -117, -345, -892, -323, -268, -339, -259, -279, -254, -234, -257, -258, -84, -233, -292, -229, -250, -768, -259, -783, -251, -384, -1574, -459, -345, -259, -987, -244, -242, -279, -317, -266, -249, -1029, -262, -330, -104, -274, -1317, -268, -3084, -264, -546, -248, -322, -276, -261, -1147, -459, -247, -983, -1307, -262, -272, -98, -3188, -260, -1776, -233, -239, -329, -171, -241, -252, -370, -228, -1478, -238, -269, -252, -458, -788, -82, -387, -643, -1383, -860, -239, -250, -954, -252, -405, -261, -778, -369, -245, -339, -263, -270, -565, -235, -243, -283, -1181, -267, -299, -196, -2322, -1029, -579, -2459, -259, -250, -289, -810, -262, -904, -284, -246, -1027, -896, -882, -1115, -405, -685, -1152, -417, -856, -405, -257, -957, -252, -288, -259, -903, -444, -472, -932, -244, -1112, -277, -484, -309, -354, -698, -272, -304, -638, -915, -260, -938, -349, -2327, -795, -222, -2182, -330, -294, -127, -1030, -378, -1591, -277, -1031, -328, -796, -543, -535, -810, -150, -1074, -274, -127, -295, -1071, -405, -237, -1242, -256, -483, -842, -541, -550, -240, -252, -927, -244, -263, -516, -1047, -896, -90, -258, -89, -263, -101, -318, -264, -297, -922, -253, -242, -258, -234, -1071, -288, -302, -239, -264, -254, -234, -575, -216, -259, -623, -267, -256, -1026, -239, -443, -1010, -1410, -1119, -235, -435, -202, -658, -293, -411, -272, -801, -534, -271, -1721, -246, -254, -524, -2910, -357, -535, -243, -483, -1456, -728, -384, -678, -833, -528, -440, -795, -410, -300, -318, -188, -257, -524, -329, -252, -445, -264, -1138, -289, -419, -242, -2986, -303, -444, -319, -681, -1078, -256, -1100, -244, -241, -282, -1034, -267, -603, -1060, -490, -374, -277, -267, -282, -264, -444, -269, -260, -278, -227, -321, -242, -769, -572, -811, -250, -236, -318, -493, -1200, -497, -953, -1612, -448, -495, -1456, -362, -519, -975, -953, -278, -216, -2591, -3872, -130, -368, -940, -309, -547, -264, -39, -620, -343, -897, -1274, -234, -2464, -258, -155, -226, -854, -297, -243, -686, -285, -360, -1256, -275, -455, -285, -221, -240, -267, -268, -276, -374, -248, -699, -275, -1098, -370, -358, -223, -263, -789, -248, -2618, -571, -826, -917, -361, -223, -2277, -257, -725, -1135, -989, -2561, -2975, -470, -677, -429, -1139, -226, -661, -559, -189, -257, -1147, -615, -1260, -286, -106, -609, -617, -754, -602, -333, -945, -492, -1027, -293, -248, -260, -95, -929, -1380, -290, -272, -290, -2285, -570, -429, -648, -635, -1086, -321, -410, -286, -406, -300, -283, -250, -1162, -254, -459, -317, -228, -280, -997, -827, -313, -290, -349, -1027, -524, -303, -1103, -330, -389, -447, -428, -184, -869, -2244, -257, -250, -275, -2377, -368, -889, -320, -1095, -573, -277, -320, -981, -231, -240, -483, -539, -236, -410, -450, -1044, -510, -387, -238, -149, -262, -289, -1478, -1332, -258, -533, -238, -1092, -801, -536, -277, -1104, -324, -603, -558, -545, -390, -536, -338, -345, -346, -1140, -389, -367, -337, -367, -346, -273, -291, -225, -294, -369, -243, -310, -274, -295, -307, -301, -1297, -2212, -274, -97, -248, -269, -616, -347, -462, -322, -236, -434, -495, -286, -262, -229, -92, -301, -309, -262, -272, -278, -293, -288, -238, -235, -292, -267, -303, -1006, -255, -954, -601, -169, -1422, -1413, -437, -830, -257, -215, -1204, -1546] + }, + 'dimensions': [ + { + 'id': 'Block height', + //'constraintrange': [100000, 150000], + 'label': 'Block height', + 'values': [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 86600, 163400, 162600, 90000, 93100, 163000, 140500, 130000, 100700, 164500, 147700, 121700, 107500, 176600, 133600, 111100, 93100, 72400, 130100, 54500, 182600, 160300, 218100, 66500, 95800, 164800, 107200, 101600, 91100, 91100, 78100, 63300, 75700, 69600, 88500, 115800, 195700, 88900, 74800, 65400, 74900, 115300, 91400, 67800, 85300, 171300, 32000, 227900, 163200, 122899, 112300, 101500, 111199, 73300, 120800, 93100, 117200, 118500, 104800, 108500, 146500, 90300, 32000, 93000, 110700, 103500, 93300, 106300, 118500, 93000, 67600, 51400, 89000, 94000, 88200, 109600, 102100, 123600, 81900, 100000, 218100, 223200, 97300, 162100, 97400, 145800, 67400, 156500, 201900, 94300, 67800, 76100, 98300, 112400, 141800, 111400, 74700, 67300, 71100, 68900, 62100, 73800, 85500, 94400, 68300, 79400, 96300, 70400, 67300, 67300, 128400, 80800, 87600, 165900, 35900, 76200, 79000, 38900, 157200, 64400, 67700, 65700, 125800, 59300, 66100, 198700, 96100, 65600, 70300, 69200, 65500, 129300, 62600, 64200, 61800, 60800, 83100, 58800, 69600, 60400, 63500, 63500, 59300, 56600, 77200, 62900, 57300, 68000, 227900, 53099, 59100, 63099, 65900, 60500, 158100, 60199, 66600, 57699, 58900, 62699, 62000, 58600, 78700, 60700, 60400, 66000, 66000, 133300, 60800, 63200, 60400, 68400, 64600, 61400, 61900, 59000, 155600, 53500, 62000, 60599, 63700, 118500, 48000, 57400, 58200, 56800, 62300, 54500, 61300, 62200, 53200, 51600, 88500, 125100, 60800, 61500, 59200, 56300, 60800, 179300, 58300, 199500, 102100, 60800, 183200, 58800, 125000, 56900, 58600, 53700, 56100, 127600, 96100, 56700, 120500, 58600, 53600, 59000, 113800, 59000, 59200, 54500, 135700, 161200, 57300, 53000, 127000, 54600, 55300, 89700, 59400, 54900, 64700, 56200, 127100, 57000, 35400, 51800, 170100, 54000, 56700, 73600, 83200, 53000, 60500, 52699, 51600, 92100, 56600, 57400, 65500, 58400, 97600, 52900, 56700, 207600, 221900, 56500, 57600, 63900, 54700, 56900, 56000, 49700, 51600, 53400, 58500, 65000, 57100, 55900, 56100, 59800, 55300, 57699, 57600, 53200, 53900, 63000, 58400, 57500, 61200, 62699, 61000, 60199, 57600, 128800, 57699, 59900, 94200, 60900, 55100, 56300, 54100, 61400, 55000, 223100, 57699, 52200, 55300, 54000, 61000, 54800, 59500, 59000, 54400, 57800, 57100, 53200, 56300, 58300, 56100, 53900, 55100, 54100, 59500, 188900, 92300, 105500, 67100, 100000, 202500, 101800, 55900, 86800, 55300, 56700, 59400, 51400, 49000, 54600, 49400, 65300, 56800, 55599, 184500, 55000, 55000, 86900, 60100, 89700, 52500, 52500, 55500, 91700, 104600, 67500, 50700, 63300, 55400, 54500, 62600, 52699, 54100, 53400, 54800, 53200, 59900, 74500, 134800, 52400, 105300, 53700, 215200, 101700, 57200, 54400, 60300, 50800, 129400, 55100, 165700, 55000, 51700, 56000, 54000, 56500, 54500, 56000, 78600, 56300, 54700, 59600, 58300, 58800, 52400, 54500, 57100, 119100, 50100, 56500, 58900, 66500, 55599, 225400, 57699, 97200, 57000, 212900, 57300, 101600, 216500, 55400, 65800, 53000, 164200, 124600, 86300, 56000, 95200, 152700, 208299, 32000, 60400, 60700, 196600, 55000, 77200, 37500, 52000, 55300, 54100, 53500, 52800, 55100, 60100, 125000, 62400, 63700, 106900, 54300, 54100, 217500, 56400, 69700, 101000, 57500, 55100, 153500, 53700, 54700, 58099, 53900, 37000, 53200, 62000, 52100, 53900, 54500, 61600, 59700, 218200, 54700, 189200, 55599, 70600, 63700, 107100, 68800, 55700, 56400, 57400, 32000, 83200, 61200, 217900, 62100, 62400, 60900, 60700, 56300, 57600, 105399, 60000, 56700, 221200, 157700, 58200, 58099, 54700, 60900, 61300, 162600, 60900, 224600, 57699, 52699, 59600, 71200, 52100, 57500, 60500, 134900, 67200, 63700, 55000, 65199, 161600, 80300, 70000, 73300, 56200, 68400, 183700, 180100, 56400, 77600, 197800, 215799, 56600, 73300, 57500, 57500, 55199, 54800, 55900, 63300, 106400, 163200, 70800, 71900, 166000, 114100, 100900, 164300, 93600, 150000, 98200, 161400, 200400, 92600, 127600, 97600, 84400, 96600, 55599, 100500, 112000, 110000, 89800, 97700, 84200, 79600, 102400, 84800, 86900, 166600, 91300, 79600, 78100, 85800, 88200, 104200, 76600, 83300, 110800, 75600, 76100, 113800, 86400, 86800, 74800, 77100, 95200, 86900, 172300, 69700, 87500, 79600, 65300, 80800, 82400, 67100, 79400, 78500, 84800, 76100, 47200, 79400, 78200, 220300, 66100, 78300, 85900, 92100, 80800, 74500, 72800, 36200, 75800, 77400, 69600, 62600, 90700, 70700, 93100, 40400, 62600, 94400, 73600, 72000, 138200, 75400, 73300, 170700, 75500, 144500, 76600, 72000, 78200, 33200, 74100, 67900, 35300, 72000, 69900, 68600, 69400, 74300, 73400, 128400, 71800, 217399, 86500, 174200, 67800, 86500, 136800, 125399, 75200, 108000, 72700, 223900, 67300, 73600, 86500, 83800, 70900, 72900, 71300, 71800, 88600, 60300, 77200, 65300, 63300, 68900, 127100, 70700, 223600, 68700, 66000, 70800, 69000, 60599, 65700, 64200, 150700, 65000, 68700, 75800, 154200, 63300, 103400, 70200, 66400, 69200, 71000, 65700, 62300, 70100, 72200, 68700, 64600, 67600, 61800, 68100, 129200, 54900, 77600, 169700, 67100, 64100, 69300, 65700, 64600, 71800, 65199, 61800, 198400, 208800, 72100, 59800, 66200, 62900, 152500, 72200, 57600, 61300, 61900, 54900, 177200, 79500, 60800, 67000, 61100, 155600, 63400, 61500, 65100, 150000, 64500, 56800, 59600, 59000, 63000, 59000, 56700, 59000, 58400, 60700, 56700, 56900, 54900, 54800, 52200, 54700, 54800, 62000, 134700, 115700, 59700, 51500, 66900, 55599, 56400, 52900, 56800, 52900, 58200, 57699, 59100, 53200, 55800, 53300, 60400, 58200, 107500, 55500, 56800, 54400, 56100, 201400, 56600, 176200, 84400, 54100, 214700, 55800, 123699, 173700, 73600, 55199, 169200, 82600, 56500, 62300, 59100, 151900, 122700, 66700, 58200, 56400, 57400, 55000, 56000, 111900, 60400, 149700, 71700, 56600, 93800, 178700, 80900, 54700, 87700, 118900, 52300, 195900, 190200, 58000, 51300, 211300, 54500, 56600, 56900, 111800, 54900, 79400, 69700, 62800, 78600, 57600, 55199, 57000, 56600, 57200, 68600, 53800, 53900, 54900, 122500, 63500, 179300, 57800, 55700, 89400, 61800, 32000, 79000, 214100, 61400, 56000, 54900, 61900, 55100, 58800, 54400, 82600, 176300, 56600, 55100, 59100, 141700, 60100, 54500, 71700, 58900, 58800, 52100, 60000, 56900, 77700, 62600, 57900, 53300, 52400, 59800, 218900, 70700, 218200, 144700, 53300, 57200, 53900, 54000, 55400, 107700, 53800, 121300, 52400, 54600, 199500, 118200, 80900, 202900, 56600, 53400, 52100, 56600, 222600, 50300, 65100, 54200, 54600, 60199, 183700, 134800, 146300, 62500, 52600, 56500, 53099, 180700, 57800, 53500, 52000, 54300, 87300, 57699, 54300, 64400, 68500, 213299, 57300, 51800, 56300, 50000, 67200, 49500, 51100, 63500, 62400, 165500, 49300, 51200, 58099, 77700, 40800, 55000, 63500, 78000, 208000, 56900, 58099, 53900, 83600, 55599, 53800, 86300, 55100, 55700, 58400, 59100, 206600, 55000, 51100, 61600, 187000, 54400, 57699, 55700, 56800, 54000, 52200, 53700, 57100, 55100, 56600, 76700, 56400, 58700, 58200, 58900, 56300, 182300, 59500, 57200, 52300, 54600, 77100, 54300, 57400, 54200, 54200, 55100, 54600, 57400, 57500, 55900, 54900, 54400, 54400, 54600, 82300, 54400, 41600, 56500, 54000, 55900, 53400, 55100, 57300, 55199, 53500, 56300, 57500, 55800, 64600, 53900, 54100, 58500, 49700, 53400, 59500, 53700, 56900, 53700, 57000, 53800, 51100, 55900, 54700, 47900, 53500, 57400, 54700, 88600, 58400, 56900, 53200, 127200, 58900, 57400, 56600, 52600, 121800, 56900, 44700, 120600, 90300, 61300, 60700, 58900, 56800, 120300, 57600, 54700, 56800, 62600, 85700, 86700, 52400, 83900, 51800, 64500, 51100, 59200, 56100, 43000, 53700, 56000, 63600, 56900, 57800, 54100, 53700, 116199, 52200, 73800, 56100, 157600, 54400, 54600, 53300, 68400, 55100, 198900, 54500, 52800, 51600, 225100, 129100, 63800, 55400, 157100, 54300, 53800, 69400, 55700, 72100, 54600, 71900, 54300, 53800, 55700, 53900, 60900, 52300, 53000, 56300, 53400, 54300, 179100, 57500, 54300, 84000, 53300, 53500, 51500, 54300, 37700, 105600, 55100, 53600, 206700, 51700, 54200, 64900, 52600, 57699, 79900, 52500, 51300, 53900, 54100, 59300, 54100, 55800, 57100, 63800, 56800, 65900, 54400, 56900, 79000, 59300, 44200, 53099, 57500, 49300, 123600, 180700, 112500, 97500, 58600, 220400, 54000, 55300, 53500, 51900, 172200, 58600, 99300, 65900, 54800, 52900, 148300, 53099, 65300, 50500, 86100, 54500, 109600, 60400, 90200, 56500, 56500, 73100, 153500, 120900, 118300, 144300, 57100, 52500, 53400, 51300, 98900, 54800, 53400, 54600, 101100, 54500, 136800, 54700, 50500, 55599, 52200, 54000, 57699, 46900, 208800, 105399, 55500, 32100, 174200, 32599, 52100, 104700, 137900, 61300, 46100, 151600, 55700, 191100, 168600, 107500, 59500, 58300, 83100, 65400, 60100, 65300, 73500, 63900, 59600, 58700, 57800, 175200, 159100, 56100, 61600, 57800, 58000, 204800, 52500, 60800, 51200, 56900, 158200, 193900, 56200, 154800, 58500, 54100, 45400, 53500, 57000, 58900, 57600, 55100, 130399, 59800, 57400, 59600, 161700, 52600, 57800, 57600, 57400, 55900, 55500, 59600, 138800, 212200, 102300, 66700, 39800, 128400, 53300, 75600, 59000, 45300, 65100, 55700, 59100, 160900, 111500, 170700, 56600, 57500, 61000, 53300, 42900, 82100, 54700, 197200, 141700, 53800, 72400, 72800, 227900, 183900, 53700, 120700, 92600, 51800, 54100, 57100, 120700, 99900, 52600, 65300, 59900, 112899, 56800, 53300, 57200, 139700, 63500, 65800, 64600, 50500, 55700, 55900, 55800, 45800, 63800, 56400, 151500, 200100, 51100, 56100, 55599, 64500, 192300, 76100, 55300, 55199, 48000, 65800, 66300, 64400, 127100, 54300, 57000, 56100, 52000, 91000, 51800, 206800, 91900, 196200, 65199, 220500, 214899, 85700, 50800, 56000, 57699, 188500, 72100, 67200, 67000, 53000, 86100, 147100, 92600, 63500, 99800, 209400, 32000, 66500, 113699, 86800, 65100, 64000, 62400, 60300, 144700, 73100, 67200, 42100, 78400, 58600, 61800, 67900, 56500, 56400, 59700, 59000, 51900, 60100, 58300, 54900, 67800, 55700, 55599, 58400, 59800, 62400, 51300, 59800, 41700, 51400, 59700, 61700, 56500, 147400, 56500, 98300, 183500, 58200, 56200, 56800, 82700, 52900, 50700, 55700, 53500, 58500, 117100, 180400, 61500, 154900, 54900, 225000, 59900, 123300, 99300, 63000, 136000, 57300, 93900, 127000, 50800, 102700, 133500, 93200, 150900, 113300, 111000, 53300, 85600, 68800, 54000, 181900, 193000, 76500, 70500, 50900, 62100, 113600, 66700, 49800, 182900, 51300, 71000, 67100, 51800, 61300, 68500, 67500, 153900, 98200, 69700, 101100, 61700, 55700, 62800, 61100, 57600, 204200, 57400, 56400, 56800, 188400, 79500, 115600, 46300, 62300, 63200, 60500, 61200, 94900, 59400, 85900, 63800, 61100, 131300, 86500, 59400, 80800, 64100, 58000, 59100, 47300, 67400, 57500, 62400, 95200, 65600, 57600, 171100, 62300, 54100, 60900, 97200, 65000, 45800, 61200, 64300, 43300, 32700, 62100, 69500, 58400, 61600, 223700, 41200, 60800, 91500, 226800, 58200, 89200, 64800, 63200, 71900, 52400, 59600, 52000, 39700, 65600, 148900, 59600, 50000, 136800, 62900, 64100, 58900, 135400, 63099, 58600, 53200, 55599, 117800, 73300, 70900, 72100, 55100, 72400, 67200, 53600, 55000, 63800, 56000, 53600, 54000, 68900, 51200, 57500, 56700, 54700, 56100, 53700, 58200, 135500, 57300, 182200, 57900, 85200, 121100, 58600, 111300, 60199, 55300, 57500, 118400, 222000, 123200, 193400, 131300, 77300, 57800, 70300, 58400, 63099, 118900, 79200, 52800, 74600, 58600, 172100, 86500, 55400, 65300, 57500, 60100, 50000, 110200, 54400, 49600, 51900, 62100, 66100, 63000, 44900, 67200, 59400, 54800, 56200, 179700, 56600, 63900, 56900, 54900, 59800, 58500, 55100, 55000, 56100, 57100, 146400, 83200, 54500, 57600, 53600, 56600, 57200, 56200, 110200, 51700, 87300, 57200, 73700, 57000, 58600, 58700, 177800, 54400, 60599, 58000, 53000, 68400, 147200, 103600, 53900, 56100, 54700, 57699, 155400, 57400, 225799, 56100, 202000, 52100, 55900, 80100, 59300, 59000, 89200, 65300, 86100, 78400, 58900, 63500, 63900, 55000, 55599, 64700, 68200, 53200, 60900, 93600, 132900, 67000, 61400, 64600, 42600, 93500, 54800, 55900, 56100, 54900, 59600, 58800, 137400, 87500, 59300, 54400, 51500, 183200, 57200, 55900, 65000, 58000, 50500, 48700, 58600, 60500, 140700, 122500, 192500, 65300, 122600, 59600, 162700, 106700, 61300, 60599, 57699, 74400, 55100, 49600, 49800, 190300, 80200, 81600, 58000, 128100, 40300, 64900, 81300, 61900, 55199, 59900, 59100, 57000, 55800, 57600, 56300, 68800, 69300, 58800, 145700, 58600, 164700, 61000, 55700, 168000, 139200, 167700, 172000, 65600, 155200, 46200, 84200, 64000, 54000, 51600, 54200, 95000, 47200, 58900, 140400, 53400, 52400, 56500, 51500, 223800, 181600, 65800, 92700, 114800, 169200, 138500, 59300, 60300, 87100, 63600, 83000, 53600, 55300, 53600, 140500, 155100, 66700, 56000, 57699, 60900, 173700, 84700, 86100, 104700, 65700, 61300, 38600, 57500, 59000, 61100, 57100, 57000, 77500, 58800, 173800, 73600, 71200, 69400, 61200, 60400, 55100, 60599, 53800, 58500, 57400, 59200, 58099, 62600, 57699, 168800, 72600, 58800, 65400, 35800, 152500, 32000, 60100, 60300, 57200, 223900, 55900, 54200, 147200, 55700, 57300, 68800, 56800, 60100, 58200, 58600, 56100, 74800, 54500, 70600, 49400, 132700, 56700, 57300, 57000, 189800, 46300, 86100, 58700, 62500, 38900, 74000, 65500, 73200, 188900, 71000, 60199, 81700, 50100, 221900, 52500, 53099, 163500, 61000, 69000, 51800, 51200, 197600, 56600, 61600, 68800, 56900, 59700, 47800, 54600, 54800, 62200, 69300, 52300, 36000, 213600, 56600, 94200, 52500, 39100, 49600, 181000, 64200, 57300, 60100, 169800, 54400, 55400, 62600, 112700, 118500, 58000, 61100, 52600, 85800, 84400, 57600, 58800, 62200, 75200, 95900, 51800, 60100, 56500, 87300, 54300, 56300, 51500, 68300, 56700, 49100, 56800, 127700, 59400, 54100, 66900, 50900, 94900, 62900, 56700, 71300, 55700, 57600, 184300, 100500, 63000, 39000, 69400, 65100, 32000, 69300, 113500, 60000, 80100, 87600, 62100, 216000, 74700, 64300, 65500, 61700, 54100, 135300, 73100, 55100, 61500, 59200, 60900, 63600, 62200, 105800, 63500, 49500, 214600, 63400, 59900, 95600, 62000, 64000, 58099, 63300, 35500, 58700, 63300, 44200, 55599, 56000, 32000, 60199, 57000, 86100, 74700, 49600, 59100, 57400, 65400, 55900, 60700, 53200, 177300, 53200, 52100, 92700, 74300, 73900, 129600, 64500, 52699, 56000, 60800, 58300, 76400, 57000, 65500, 177100, 66800, 49900, 58900, 57300, 66700, 58200, 61600, 62100, 68200, 55199, 64300, 53500, 60199, 60700, 47600, 57000, 94400, 95200, 59600, 61200, 161400, 51800, 56900, 59000, 165500, 69500, 61800, 62600, 205200, 52600, 58800, 61100, 55599, 58600, 53900, 60400, 53400, 115399, 50100, 58700, 56300, 37900, 61800, 63400, 75100, 52400, 59800, 113300, 210700, 55800, 138900, 59600, 185300, 102700, 42100, 54900, 87200, 40900, 58200, 135400, 51700, 62500, 171300, 109000, 59800, 102700, 62600, 77800, 198400, 61200, 65400, 55100, 153700, 165900, 62000, 58600, 71000, 56500, 63099, 40900, 83200, 60599, 73800, 59800, 70900, 58500, 61300, 56300, 55100, 58000, 57800, 38000, 53500, 61800, 53800, 55500, 54300, 56000, 54700, 55700, 71500, 179800, 53500, 64100, 58400, 63700, 55500, 54600, 60800, 64300, 58800, 56600, 186600, 58200, 61500, 35100, 60100, 212399, 58600, 171800, 58300, 96700, 56900, 66400, 60300, 58500, 71300, 65100, 56300, 59600, 196000, 57800, 60000, 42600, 181600, 57300, 195500, 54200, 55400, 61500, 44500, 55000, 56300, 66700, 52699, 143500, 54400, 58400, 56300, 53300, 191900, 38000, 76000, 111000, 198900, 160900, 54500, 55400, 56100, 55000, 81500, 57100, 119400, 74200, 55700, 70200, 57600, 58600, 134700, 53000, 55100, 60199, 224100, 58000, 62500, 56500, 134200, 60300, 73800, 209400, 57000, 55900, 62200, 55900, 57500, 159200, 61200, 55300, 168000, 55700, 55300, 219200, 76600, 128800, 211000, 87500, 58600, 57500, 56300, 202600, 56200, 61100, 56800, 153900, 88400, 97400, 166600, 54900, 220000, 81800, 98600, 66900, 86500, 152300, 59100, 86400, 73100, 55000, 57100, 54800, 65500, 138200, 177700, 51600, 108699, 67000, 61500, 45500, 58500, 55400, 133800, 59200, 213100, 66600, 122100, 97100, 92100, 135300, 49600, 73000, 58200, 51900, 61400, 60700, 58099, 53300, 192600, 55800, 121500, 139700, 40100, 115700, 54300, 56000, 58400, 54400, 57699, 98800, 214800, 161400, 39300, 56900, 41700, 57000, 39600, 65600, 56600, 65900, 219100, 55800, 54300, 56300, 52600, 61100, 60800, 65500, 53700, 57100, 54800, 52500, 46500, 50900, 55199, 46300, 57100, 56300, 58900, 53500, 59800, 217399, 59300, 185900, 43300, 59000, 51700, 133000, 75300, 58000, 57699, 97800, 117400, 57200, 185500, 53800, 56700, 115600, 170200, 65900, 79000, 55199, 100000, 96700, 123699, 76700, 169400, 136700, 71400, 61000, 127400, 58800, 62400, 48400, 44200, 55599, 91600, 67000, 55599, 62800, 58000, 65600, 61700, 59300, 54300, 201700, 62699, 108400, 64100, 71100, 59900, 56300, 227900, 54100, 53900, 61700, 165200, 59100, 115800, 62400, 92400, 55599, 59500, 58800, 60500, 57400, 80700, 58500, 56500, 59800, 60400, 63300, 55199, 118900, 63500, 195000, 54700, 53099, 67100, 55700, 219200, 56900, 70300, 156000, 83600, 95100, 210200, 67000, 48000, 56700, 172100, 59400, 62800, 195400, 133800, 44800, 54900, 57300, 63000, 95000, 57600, 32000, 138600, 71000, 61200, 73500, 53400, 194800, 56900, 49200, 51900, 60300, 60900, 57000, 116100, 61300, 81000, 205000, 57800, 117000, 61300, 51800, 54300, 58600, 57800, 61500, 82400, 55900, 156600, 59300, 227800, 55000, 54400, 52000, 58900, 54100, 55599, 177500, 92500, 57100, 148600, 53400, 52200, 113200, 57300, 87100, 227100, 215200, 195700, 144300, 91500, 148700, 91100, 198200, 52600, 108500, 90700, 68600, 56500, 174600, 103400, 215600, 60500, 41600, 102899, 81100, 121300, 79200, 67400, 64400, 109400, 57000, 61400, 54800, 56300, 41500, 175700, 140300, 61000, 68200, 59700, 84600, 43300, 82600, 112300, 34900, 168200, 71700, 79800, 60800, 79500, 61700, 60800, 54800, 69300, 60100, 64100, 64500, 52100, 58600, 58900, 56200, 65500, 58700, 70400, 216700, 103400, 62699, 64600, 66600, 56300, 66300, 73800, 50500, 170100, 122000, 55300, 56000, 58099, 126500, 52200, 147000, 65900, 193200, 115300, 62600, 65900, 202300, 52800, 53900, 101000, 95000, 53700, 73300, 84400, 227900, 54300, 93200, 60500, 38400, 57300, 61400, 170400, 224500, 57100, 95000, 53400, 208900, 138800, 73200, 59600, 223600, 70400, 111900, 72900, 100500, 76000, 71600, 68000, 71100, 67700, 75900, 74200, 72800, 66500, 69400, 66200, 59400, 61000, 52300, 62900, 71200, 55400, 67000, 59300, 63200, 64500, 65100, 222600, 183400, 59600, 40400, 55599, 58500, 125000, 64700, 115399, 66400, 54500, 81700, 124400, 60500, 56300, 53900, 32000, 64200, 64800, 58300, 56800, 65000, 62800, 62300, 53200, 58300, 61300, 58600, 64400, 58099, 55700, 158400, 155100, 49700, 170000, 213500, 75600, 162300, 59900, 47000, 223600, 187300] + }, + { + 'id': 'Block width', + 'label': 'Block width', + 'range': [0, 700000], + 'values': [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 436900, 373600, 268630, 439000, 381800, 491200, 402800, 381400, 485600, 600000, 372200, 394700, 383800, 401100, 356500, 313200, 487100, 490700, 432299, 530300, 521500, 456700, 333800, 343200, 394000, 328200, 487700, 383600, 317700, 324600, 482900, 515100, 500100, 562700, 486000, 453400, 352900, 331300, 496200, 469099, 472500, 354700, 507700, 509000, 439300, 525300, 347600, 379000, 432800, 378800, 383200, 523800, 600000, 313600, 497700, 411300, 420000, 381100, 342800, 385900, 268630, 495800, 488000, 446400, 397900, 373300, 385700, 396500, 475700, 510600, 586800, 596000, 407600, 439200, 440800, 393100, 274600, 291900, 509799, 432800, 303000, 530600, 515900, 376800, 377400, 553500, 433600, 270800, 288000, 488000, 306800, 418000, 456900, 526300, 524500, 524000, 418800, 442800, 443200, 497200, 427500, 510300, 476000, 382700, 472200, 380400, 472900, 541100, 528200, 441599, 374600, 414099, 437299, 272500, 550000, 417299, 443700, 268630, 545800, 403400, 534400, 557200, 545200, 537400, 464300, 571200, 589400, 564000, 466500, 514500, 433200, 293600, 550100, 466599, 450100, 557200, 489000, 512200, 445600, 531000, 504400, 459799, 528800, 579800, 352900, 520700, 532000, 477900, 395600, 478900, 461300, 481400, 507500, 487200, 522299, 496000, 499600, 485200, 491500, 548300, 526000, 489600, 444000, 500900, 527600, 533200, 450000, 566500, 486300, 500700, 534900, 493000, 481100, 482500, 490900, 510200, 584700, 560700, 492000, 474600, 495300, 594100, 433700, 522500, 513100, 507500, 488100, 506400, 510400, 482700, 500400, 532000, 477700, 369600, 491200, 499400, 489200, 509099, 513600, 479600, 507299, 547600, 415300, 485900, 410400, 507700, 546700, 503300, 503600, 547700, 509200, 522400, 319700, 517200, 473000, 506800, 511400, 559200, 537900, 515300, 487500, 519000, 361100, 270800, 519000, 518200, 508200, 503900, 516500, 508600, 504900, 506500, 505300, 522000, 507500, 521400, 504600, 521400, 418700, 516700, 508400, 515400, 387000, 522299, 557300, 516599, 510600, 383600, 514700, 516700, 515600, 528200, 491500, 517900, 505000, 430300, 425300, 517800, 512600, 511599, 511300, 501599, 519099, 359700, 522400, 510400, 501100, 524600, 516000, 513800, 503100, 517000, 511400, 513700, 504000, 506900, 517000, 535700, 572700, 497900, 501900, 512600, 513800, 515000, 520700, 295100, 509700, 522299, 338800, 521300, 517200, 519500, 520800, 509300, 520700, 356000, 523000, 513600, 525100, 515700, 510000, 528300, 565200, 509300, 515500, 526900, 514200, 522200, 518500, 557400, 565100, 530700, 511100, 538200, 483700, 588800, 285200, 569100, 520800, 406300, 278300, 569500, 513900, 289000, 519600, 513600, 526900, 525500, 530300, 502000, 480000, 518500, 513000, 516900, 507000, 534300, 520400, 488500, 536000, 518900, 519000, 509400, 535500, 533600, 384900, 542700, 517200, 535700, 520500, 517100, 538700, 525900, 524200, 517100, 523600, 512900, 542400, 306800, 544600, 516599, 582200, 519900, 510900, 427200, 521300, 525900, 438200, 523500, 480000, 519600, 325400, 523300, 525200, 526500, 516400, 523800, 525400, 518700, 530800, 526400, 524400, 566400, 519500, 519700, 518400, 580400, 520600, 567600, 585000, 519300, 524300, 520800, 520900, 533400, 529500, 583500, 531400, 450000, 557600, 420700, 402900, 524500, 518700, 521800, 316400, 497100, 518900, 504400, 539400, 507000, 339700, 493800, 496700, 517500, 523400, 524400, 526200, 311300, 519200, 327600, 520400, 524800, 526400, 519200, 485200, 361000, 519300, 574400, 330400, 511800, 511200, 592800, 520900, 390400, 322200, 524600, 513300, 542400, 517200, 527300, 512700, 516100, 570800, 508900, 523500, 543500, 513700, 519700, 469000, 557400, 515000, 511000, 382700, 521400, 497900, 571100, 514099, 461100, 505600, 563300, 509200, 446300, 458000, 518000, 316500, 525600, 515700, 468600, 516300, 515400, 499000, 487500, 486900, 519099, 270200, 290900, 518000, 509900, 519300, 517299, 468700, 582300, 517200, 461100, 558600, 490500, 499099, 507100, 517600, 535200, 512100, 375300, 506100, 502200, 519600, 559900, 531200, 508100, 553600, 510700, 538600, 525200, 286400, 581800, 534900, 503500, 345400, 428300, 539400, 552000, 523400, 516300, 514099, 519200, 515800, 508000, 500400, 374900, 529900, 527100, 600000, 309600, 583500, 600000, 376000, 473900, 484799, 419300, 287200, 596600, 464600, 398900, 383900, 487000, 431900, 490700, 600000, 381100, 515800, 381500, 540900, 539100, 416500, 428800, 439300, 441300, 496000, 550800, 414300, 422100, 598200, 387800, 561100, 364000, 359700, 523400, 455300, 600000, 380400, 424000, 458600, 382500, 401100, 425100, 550500, 436599, 493200, 393200, 437900, 401100, 386300, 432299, 444799, 428200, 368800, 415700, 369900, 413400, 413000, 482100, 436000, 368600, 369300, 401300, 400400, 418300, 432299, 278800, 436100, 411800, 431300, 551100, 406300, 541500, 404200, 547200, 437000, 390200, 417900, 415800, 460600, 434900, 442600, 309300, 452000, 272200, 459700, 423300, 414799, 468900, 429300, 436700, 427400, 438800, 421100, 421700, 434000, 470700, 474799, 521599, 414400, 307300, 416700, 579600, 432400, 566100, 416200, 432500, 483100, 373200, 494799, 507400, 489700, 440800, 389200, 436599, 418000, 446500, 450700, 445200, 594100, 443900, 489000, 493300, 448900, 449700, 406000, 437400, 278100, 453400, 509500, 433000, 431200, 308600, 507500, 452500, 524700, 451700, 468700, 423600, 447200, 472600, 418500, 466000, 457000, 442299, 455000, 458400, 463800, 450900, 452900, 544200, 456500, 521700, 490900, 457200, 502500, 499099, 446800, 597000, 440600, 478700, 428700, 556900, 498300, 442000, 437900, 419000, 486000, 490700, 463000, 505500, 496700, 486200, 528300, 434200, 502600, 502400, 477800, 470500, 533400, 520700, 508400, 346400, 498900, 511300, 486900, 499300, 508100, 545700, 458400, 524300, 504700, 497299, 454300, 501100, 499900, 497800, 506900, 494500, 501000, 515300, 515000, 505300, 520200, 524099, 502600, 483000, 413400, 562300, 511700, 523500, 478800, 514600, 511100, 505500, 505300, 519099, 499600, 506900, 510500, 519900, 512400, 520400, 504500, 500900, 433200, 515900, 500700, 517100, 508200, 505900, 498900, 274800, 523200, 518100, 434600, 491100, 439900, 508300, 338800, 513900, 464600, 524000, 511100, 565900, 503700, 331700, 484200, 533800, 530700, 519799, 544000, 513200, 466100, 484799, 537100, 541300, 513500, 515100, 495600, 580400, 514600, 517000, 519600, 552000, 538400, 399700, 448000, 522100, 503600, 353100, 511300, 515700, 487700, 421700, 509200, 600000, 422400, 523700, 526700, 513000, 521500, 516400, 518100, 513300, 516700, 524400, 499099, 517299, 428600, 514700, 540300, 507500, 517200, 464900, 519099, 512100, 537200, 440900, 507900, 522500, 514799, 513900, 523500, 510100, 525100, 548400, 361100, 512700, 518100, 524400, 588900, 527800, 528500, 341500, 500100, 510300, 516000, 504200, 502900, 424200, 506599, 502700, 511000, 512200, 524099, 595200, 415700, 460400, 361800, 519700, 514300, 527300, 516900, 512900, 532100, 514900, 312800, 510400, 515100, 518500, 383900, 269400, 547800, 515000, 515100, 514300, 518700, 316300, 508700, 503200, 512700, 511599, 515500, 506599, 384900, 362200, 527700, 527500, 515600, 510100, 289800, 517400, 510600, 531900, 513800, 530100, 517600, 522700, 522900, 525700, 376000, 520100, 512100, 513900, 512400, 528600, 521900, 498500, 530200, 514700, 494200, 315900, 527900, 514700, 521599, 521599, 526700, 516400, 507900, 542600, 518600, 521500, 523500, 459700, 513400, 517900, 515400, 521400, 512900, 517600, 522100, 274700, 520800, 511599, 517000, 428600, 520500, 519799, 522800, 526400, 506700, 514000, 513100, 517900, 520200, 517600, 583600, 526800, 524400, 523900, 515900, 523300, 498700, 524200, 519200, 517500, 525100, 549400, 526000, 517200, 516900, 520700, 521000, 521300, 525700, 527200, 519400, 518600, 516900, 519600, 517400, 496300, 527400, 322400, 518300, 519200, 518400, 523400, 523100, 516599, 516100, 517900, 512500, 514600, 519500, 514200, 517600, 520200, 519200, 515200, 520100, 517000, 519600, 509900, 520900, 519799, 519900, 518200, 512400, 517700, 526200, 516700, 519799, 519900, 382200, 518900, 520000, 518200, 488700, 523600, 522299, 522299, 521900, 295200, 511599, 499400, 526900, 572800, 478500, 570100, 520000, 516599, 530600, 509799, 526000, 512000, 491599, 530200, 581800, 525800, 529700, 522200, 598700, 517400, 508500, 510200, 428700, 522200, 507100, 517299, 527600, 534400, 526500, 520700, 486900, 526200, 525600, 514799, 510400, 514900, 529600, 520100, 330400, 520800, 401100, 520600, 516000, 525100, 388800, 404700, 525800, 526400, 480100, 525700, 515300, 391100, 518100, 431599, 527800, 430300, 517400, 518700, 523500, 512400, 514300, 516100, 517299, 508200, 520900, 527200, 296700, 514400, 520100, 289600, 513900, 528000, 522700, 527600, 308500, 415200, 522800, 527500, 402800, 521400, 523300, 518800, 521200, 522200, 547400, 525300, 522800, 518000, 524800, 518300, 518300, 534100, 518400, 530400, 512800, 520500, 524900, 522500, 520200, 537200, 307300, 517200, 527300, 514099, 557900, 521599, 525600, 492800, 533800, 359300, 522299, 546000, 514200, 401500, 475200, 523900, 394000, 517800, 525400, 517600, 382800, 513200, 414900, 519000, 517100, 525300, 421700, 515300, 453800, 522299, 525300, 522200, 297000, 402100, 440400, 462900, 517700, 514200, 522299, 526700, 382000, 513200, 519799, 521000, 436200, 516400, 490400, 514099, 526800, 510600, 513400, 509900, 518900, 512400, 500400, 521700, 517100, 390400, 589900, 327700, 517100, 499799, 565300, 522299, 589000, 495000, 519099, 502299, 433100, 413000, 540000, 503200, 563400, 521599, 553100, 511500, 503200, 558600, 510200, 499799, 510100, 308500, 410700, 518400, 522700, 532000, 502400, 386700, 512700, 538900, 522900, 516300, 396900, 545300, 517400, 393900, 495600, 529600, 552900, 516900, 519300, 521800, 495100, 513500, 583300, 516800, 516300, 526400, 550500, 526300, 517100, 516800, 510400, 525000, 526500, 518200, 414300, 548400, 395800, 447800, 419799, 530100, 532300, 493200, 522600, 373100, 445500, 530000, 520500, 560400, 440000, 297700, 524200, 526100, 518600, 528400, 400700, 503000, 508600, 545500, 555400, 520600, 494900, 473200, 521599, 471700, 509099, 526800, 510800, 525700, 516900, 498300, 595700, 526300, 520600, 525600, 519400, 380300, 514099, 506100, 524000, 321100, 522500, 520000, 520600, 529700, 521800, 510300, 520500, 385100, 522200, 518300, 577600, 588400, 536100, 513100, 518000, 419000, 480700, 392500, 515900, 517400, 353900, 520800, 448300, 511200, 502700, 518500, 512900, 521300, 519799, 535700, 512299, 407000, 517100, 322600, 518700, 297300, 366500, 600000, 515200, 516300, 490700, 408800, 525700, 504300, 509600, 521300, 481400, 359700, 371300, 511900, 504300, 451300, 467600, 507700, 532300, 470600, 516800, 590300, 522000, 526000, 463900, 455600, 518500, 406100, 475600, 529000, 547300, 529000, 531400, 517500, 527800, 526600, 459500, 494200, 500000, 487000, 469000, 511300, 511700, 508600, 504500, 519900, 521700, 522299, 400400, 511100, 513900, 513900, 511100, 408500, 498900, 490600, 559100, 514200, 505500, 506300, 503800, 516599, 524200, 510100, 510600, 505700, 395700, 523100, 506599, 542700, 512700, 366700, 511800, 386800, 397700, 511000, 404200, 518300, 499400, 520500, 511800, 555900, 465500, 268630, 582200, 305800, 500800, 518400, 472200, 512700, 483300, 405400, 573000, 465600, 516500, 476000, 472000, 546000, 496200, 503400, 414000, 516800, 514000, 520800, 523700, 502900, 513900, 515400, 318200, 511500, 469900, 379700, 515300, 504200, 506500, 495500, 523200, 297100, 508100, 525600, 522800, 321100, 507299, 423900, 536700, 394000, 527100, 506900, 515400, 447800, 509900, 490900, 508000, 493400, 523200, 429900, 486800, 522100, 505400, 517299, 506800, 448600, 489000, 496800, 504300, 486200, 500300, 525300, 278500, 501900, 512400, 510400, 530000, 511500, 370200, 507600, 504500, 373400, 485300, 497600, 504200, 501100, 505400, 587500, 373900, 511500, 492299, 560600, 506500, 421500, 506100, 509099, 509300, 508600, 511300, 515200, 376500, 499900, 558600, 500200, 514400, 293900, 470700, 407400, 490100, 375800, 406100, 506100, 520900, 514099, 415600, 506200, 581600, 435400, 512500, 432800, 504200, 513900, 529300, 506000, 507000, 518400, 520600, 515900, 512200, 508200, 517900, 497500, 497100, 523300, 506800, 471000, 500600, 269500, 508100, 512600, 584400, 505900, 425000, 501900, 513300, 526800, 584700, 472500, 287400, 573200, 510700, 492200, 517600, 506300, 502800, 509200, 514400, 508800, 520600, 518200, 515100, 340000, 510500, 521000, 517400, 516800, 519900, 476700, 357200, 514000, 404600, 519300, 514900, 501200, 521200, 559700, 503000, 514500, 518100, 515100, 458600, 519200, 518300, 530500, 501100, 520600, 503800, 521599, 527200, 519300, 534200, 433200, 521599, 512100, 510400, 518500, 511599, 516500, 505600, 594900, 528900, 407600, 510400, 425800, 517100, 508700, 516599, 543700, 520400, 506300, 511599, 523000, 554000, 332400, 379900, 511500, 525100, 513700, 516400, 513600, 503400, 510400, 511200, 352600, 515200, 524000, 382400, 521900, 536300, 445300, 427200, 508700, 523800, 518800, 538100, 470400, 511300, 520900, 518700, 516200, 520700, 526600, 367700, 362200, 507200, 528800, 508200, 380900, 372500, 520300, 521500, 517900, 464000, 525900, 522299, 345600, 597300, 549000, 507000, 508800, 569100, 513400, 511599, 539300, 519700, 517299, 519300, 507600, 523200, 493300, 465700, 577300, 538600, 589000, 460100, 325400, 440200, 552600, 537500, 514200, 528100, 474900, 460000, 463300, 401500, 340400, 340200, 518700, 517400, 560500, 505200, 276800, 510800, 530500, 513100, 515000, 523300, 512000, 510600, 517400, 365200, 596600, 517500, 358600, 515700, 545500, 553000, 505000, 487000, 484700, 349200, 488700, 532400, 436200, 411300, 492600, 477600, 511000, 506500, 517299, 358800, 400700, 555400, 494900, 372200, 507800, 511300, 520300, 542100, 355900, 571500, 552800, 467500, 430700, 339400, 564100, 600000, 478700, 454500, 554800, 458400, 519300, 521700, 484099, 359500, 567700, 535200, 555500, 541900, 520500, 479700, 501100, 533700, 554300, 552300, 379700, 522500, 404900, 508300, 538600, 573200, 532700, 557100, 565900, 518500, 309200, 522100, 538500, 509400, 533200, 539900, 511900, 535400, 519900, 542900, 556800, 523100, 505900, 382700, 527400, 451500, 518400, 479300, 535600, 493100, 516300, 510800, 529600, 274700, 516500, 522400, 470500, 526800, 519300, 401300, 519000, 518900, 441599, 526800, 510100, 349400, 505000, 531900, 461100, 272200, 521500, 514799, 519200, 535000, 424300, 505000, 525600, 510500, 375100, 407500, 408600, 425000, 583700, 420700, 508100, 574900, 513700, 324400, 512299, 522900, 552100, 510800, 418200, 498000, 510900, 444700, 528100, 526300, 504099, 521300, 509500, 565800, 509700, 531100, 512400, 506400, 528700, 368900, 346700, 520300, 599300, 519400, 364400, 520100, 445700, 520200, 531600, 504500, 295700, 500200, 513200, 460600, 547600, 481400, 515700, 518100, 499700, 337200, 330600, 517500, 525300, 479000, 460400, 536200, 470500, 516100, 506500, 482200, 507800, 499600, 519099, 504400, 518800, 331800, 498100, 469400, 486200, 518400, 504099, 518000, 399400, 511000, 512200, 571100, 518000, 524900, 447600, 368500, 511200, 382200, 521000, 513400, 515600, 514300, 529500, 519400, 347900, 516200, 522900, 295600, 464799, 514099, 465600, 512000, 522000, 334300, 401000, 522700, 514200, 513900, 459099, 507700, 510500, 316200, 518900, 550100, 458700, 513200, 480300, 445900, 513400, 519000, 510700, 519000, 448300, 486200, 514400, 441700, 471200, 537400, 381700, 503700, 484799, 485800, 483000, 505100, 496599, 502100, 497800, 518000, 502500, 517100, 363100, 511400, 489600, 484900, 485300, 508000, 419300, 473900, 511800, 505800, 483300, 503700, 501200, 515200, 486100, 589600, 479300, 520400, 517299, 513300, 522100, 451700, 510600, 495600, 434900, 513400, 498600, 527900, 507400, 500300, 489300, 500700, 290900, 432000, 493800, 553300, 327400, 519799, 510100, 501500, 451400, 512400, 504400, 498200, 522200, 517800, 498900, 507200, 508300, 494099, 507400, 485200, 523800, 351500, 529700, 500700, 504500, 386000, 506400, 508300, 491700, 432100, 502800, 357100, 512700, 503000, 560900, 514400, 352000, 333500, 377100, 500500, 450100, 377500, 499799, 303100, 501800, 511000, 356300, 425300, 513500, 418000, 490600, 410700, 543000, 496700, 533000, 520000, 528400, 360400, 504900, 497400, 445000, 508600, 509300, 431700, 387900, 444799, 436200, 496000, 490500, 496900, 499000, 516800, 493000, 498700, 503200, 387400, 512900, 516900, 499400, 519400, 505500, 531300, 510900, 517700, 556400, 538300, 512500, 581200, 497200, 464200, 506200, 515000, 505400, 529900, 506100, 502600, 440800, 505600, 589800, 503100, 504099, 508200, 511700, 497200, 507800, 530800, 495000, 513100, 505600, 500700, 551700, 502600, 501599, 497900, 566800, 511100, 501800, 352200, 562800, 513500, 563100, 503000, 499099, 587700, 512900, 508300, 512700, 591100, 514200, 523800, 511000, 516700, 511900, 514300, 279100, 381800, 511700, 527600, 598300, 434600, 511000, 519900, 522200, 531000, 483500, 519700, 600000, 503700, 505800, 498400, 515800, 516900, 322900, 523700, 511500, 519600, 399600, 518500, 519700, 397500, 484600, 513700, 268630, 315400, 517200, 514500, 505900, 515300, 516000, 473100, 509099, 514500, 301900, 490500, 486900, 380200, 531800, 455000, 425100, 448300, 515200, 527100, 522299, 344700, 514200, 518500, 519099, 497800, 475100, 440200, 459700, 515900, 376300, 304500, 445500, 485800, 375000, 354000, 513200, 309700, 472900, 507299, 516300, 521900, 569700, 546300, 327100, 517900, 578300, 518800, 524000, 386000, 531300, 510600, 378600, 521400, 354000, 520200, 596800, 524200, 557800, 525100, 383600, 433600, 528500, 305900, 526000, 530100, 519200, 523900, 543400, 527400, 310200, 525900, 442000, 404400, 515800, 516599, 558500, 523300, 514200, 479700, 357800, 457800, 380700, 514900, 341800, 524500, 407400, 516300, 532800, 476599, 281100, 520600, 519500, 524300, 527000, 526200, 522400, 488700, 523100, 524200, 536500, 530300, 396000, 514700, 540900, 428100, 531600, 520600, 525500, 525100, 537000, 330700, 552700, 497800, 318000, 537300, 472299, 298100, 377500, 529200, 533300, 531200, 380000, 537300, 583800, 535800, 511200, 379700, 472600, 579400, 444400, 509799, 433500, 430500, 523700, 500600, 277800, 535700, 518500, 530200, 560800, 516200, 522700, 525000, 561000, 531700, 549000, 517200, 522600, 514000, 512200, 516500, 511400, 522600, 519700, 402100, 524900, 339000, 534900, 541700, 546700, 519600, 348100, 527100, 523700, 498600, 535500, 504700, 456200, 509300, 499500, 503600, 517700, 507100, 513500, 520900, 545600, 515300, 525500, 515300, 412700, 550000, 507800, 594700, 275700, 284100, 531200, 524300, 497600, 526100, 424000, 513200, 406100, 520600, 524000, 484600, 590700, 573700, 402900, 521400, 450200, 520500, 366400, 414500, 531300, 404700, 504400, 503100, 531300, 546200, 517299, 348800, 351000, 496900, 513600, 514900, 515200, 393600, 515800, 400400, 521400, 497700, 537300, 484200, 535100, 510100, 426100, 502400, 537200, 305700, 509200, 510900, 516200, 509900, 523000, 490000, 433000, 508700, 337600, 515800, 347200, 507700, 498500, 514099, 498000, 521300, 513600, 467700, 597800, 512600, 535700, 517600, 510400, 361500, 508400, 550900, 367600, 326100, 352700, 579200, 483200, 352800, 434600, 462100, 510700, 564600, 600000, 268630, 519400, 565500, 555200, 466900, 521900, 390200, 552600, 512000, 563600, 513800, 519600, 439900, 383100, 544900, 522200, 525900, 529000, 361000, 420000, 490000, 522000, 410200, 540600, 563200, 493900, 507500, 523200, 600000, 556000, 453800, 507800, 517100, 504300, 532700, 512000, 529500, 501800, 467100, 515700, 526900, 522299, 534600, 511400, 522400, 508400, 554200, 512900, 341500, 455800, 525300, 509400, 524099, 519400, 471200, 597300, 448200, 402800, 519300, 537200, 513000, 532300, 529800, 535000, 522700, 516200, 455400, 429700, 479799, 516400, 359000, 518400, 520400, 427200, 536700, 515900, 576100, 518100, 320200, 297400, 368200, 432600, 571800, 517600, 515400, 534900, 474200, 513300, 530600, 524099, 399500, 497299, 507500, 516500, 362100, 471800, 480600, 538100, 500400, 515800, 518200, 522000, 498000, 538500, 440800, 533600, 514300, 538000, 552600, 556500, 512000, 523900, 514099, 505700, 535800, 505900, 485100, 515300, 503500, 510400, 492200, 462600, 375000, 511599, 384700, 514500, 516400, 414300, 577900, 320200, 513300, 504300, 522200, 308000, 521500, 531300, 499300, 535800, 502600, 509300, 505600, 545000, 453800, 505700, 502000, 526500, 452900, 522100, 510900, 503100, 523600, 526500, 512800, 272000, 427299, 365300, 554800, 590700, 407900, 475500, 575700, 412299, 351000] + }, + { + 'id': 'Cylinder material', + 'label': 'Cylinder material', + 'tickvals': [0, 0.5, 1, 2, 3], + 'ticktext': ['A', 'AB', 'B', 'Y', 'Z'], + 'values': [0, 0, 1, 0.5, 2, 3, 3, 0, 1, 1, 2, 2, 3, 0, 0, 1, 2, 2, 3, 3, 0, 1, 1, 2, 3, 3, 3, 0, 2, 3, 1, 0, 1, 3, 1, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 3, 2, 2, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2, 0, 3, 0, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0, 3, 1, 1, 3, 0, 0, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 3, 2, 0, 2, 2, 2, 0, 2, 2, 2, 3, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 3, 2, 0, 2, 0, 0, 3, 0, 2, 0, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 1, 2, 3, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 0, 2, 3, 3, 2, 2, 0, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 3, 2, 0, 2, 2, 0, 1, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 3, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 2, 2, 0, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 3, 0, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 3, 2, 1, 0, 2, 0, 2, 3, 2, 0, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1] + }, + { + 'id': 'Block material', + 'label': 'Block material', + 'tickvals': [0, 1, 2, 3], + 'range': [-1, 4], + 'values': [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 2, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 3, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 2, 1, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 3, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 3, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 1, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 1, 0, 0, 2, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 1, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + 'id': 'Total weight', + 'label': 'Total weight', + 'visible': true, + 'values': [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797, 377, 1327, 462, 1009, 166, 1415, 1118, 1063, 593, 498, 959, 1331, 1146, 645, 921, 1596, 663, 568, 492, 833, 630, 445, 504, 394, 647, 314, 1039, 829, 911, 282, 925, 681, 581, 506, 368, 373, 628, 538, 418, 419, 478, 884, 847, 369, 410, 344, 396, 501, 510, 379, 733, 1649, 239, 1035, 1839, 967, 514, 875, 794, 414, 664, 447, 839, 540, 636, 499, 1059, 743, 173, 473, 519, 465, 623, 726, 631, 521, 643, 323, 424, 472, 657, 510, 521, 661, 690, 497, 1664, 2162, 828, 1062, 479, 1452, 574, 604, 1069, 766, 268, 369, 755, 644, 811, 636, 363, 375, 359, 378, 336, 413, 680, 431, 361, 493, 761, 412, 386, 339, 628, 390, 648, 611, 323, 369, 555, 142, 2133, 653, 392, 597, 740, 345, 345, 1211, 600, 396, 369, 390, 481, 498, 371, 337, 316, 363, 676, 330, 353, 527, 352, 329, 341, 349, 334, 357, 501, 363, 1066, 284, 307, 338, 367, 327, 901, 330, 367, 311, 543, 370, 355, 318, 398, 335, 346, 382, 337, 807, 365, 349, 350, 415, 346, 330, 337, 330, 2201, 489, 338, 322, 349, 744, 239, 327, 327, 317, 763, 303, 343, 334, 293, 298, 472, 558, 331, 769, 321, 315, 342, 2161, 325, 1667, 493, 328, 878, 328, 737, 315, 325, 317, 529, 727, 390, 320, 953, 729, 300, 538, 663, 333, 320, 309, 596, 591, 325, 300, 709, 303, 312, 501, 737, 306, 360, 320, 1585, 324, 196, 294, 827, 305, 316, 415, 557, 302, 550, 332, 289, 730, 319, 324, 369, 335, 532, 422, 315, 1423, 1091, 320, 323, 358, 307, 314, 317, 218, 414, 299, 323, 371, 322, 314, 311, 338, 310, 324, 319, 674, 305, 366, 356, 316, 338, 352, 343, 339, 327, 497, 323, 780, 427, 346, 311, 319, 307, 343, 312, 1695, 329, 293, 316, 429, 341, 315, 548, 330, 307, 331, 321, 427, 319, 530, 516, 310, 344, 724, 479, 2748, 667, 977, 426, 696, 755, 944, 474, 331, 314, 319, 381, 294, 282, 302, 264, 370, 449, 314, 1029, 318, 312, 706, 349, 508, 297, 293, 322, 531, 480, 396, 286, 367, 315, 308, 365, 302, 467, 302, 313, 421, 351, 295, 792, 296, 651, 305, 1207, 501, 325, 311, 302, 290, 693, 312, 681, 474, 296, 321, 305, 322, 312, 317, 453, 322, 312, 550, 331, 334, 297, 560, 324, 812, 311, 320, 336, 533, 316, 1305, 502, 857, 329, 1089, 521, 495, 1025, 316, 373, 301, 935, 685, 547, 311, 622, 851, 880, 175, 331, 343, 1122, 314, 494, 211, 329, 228, 307, 306, 302, 312, 324, 549, 354, 390, 443, 305, 303, 1364, 320, 352, 412, 328, 522, 1509, 303, 314, 326, 304, 376, 297, 354, 305, 303, 309, 324, 543, 1231, 306, 865, 477, 388, 388, 603, 532, 310, 1249, 321, 162, 431, 346, 880, 355, 789, 320, 383, 317, 317, 571, 324, 321, 810, 1075, 329, 363, 310, 385, 322, 1005, 344, 1169, 526, 286, 328, 558, 295, 505, 339, 608, 526, 352, 312, 391, 933, 448, 590, 411, 463, 391, 697, 1113, 327, 604, 845, 1066, 330, 435, 750, 325, 709, 523, 315, 353, 882, 736, 456, 1111, 1050, 454, 955, 1728, 423, 796, 793, 1348, 761, 970, 668, 459, 386, 783, 276, 820, 708, 501, 764, 445, 492, 464, 496, 419, 967, 1243, 751, 472, 377, 419, 628, 480, 701, 368, 486, 949, 668, 720, 570, 425, 576, 352, 449, 427, 1551, 349, 478, 370, 327, 381, 379, 333, 403, 387, 378, 368, 450, 382, 376, 1184, 330, 349, 416, 435, 381, 362, 362, 426, 379, 372, 345, 841, 432, 952, 441, 238, 313, 437, 392, 763, 719, 376, 370, 679, 387, 531, 591, 352, 377, 174, 366, 340, 383, 361, 341, 335, 346, 392, 390, 731, 477, 861, 419, 1073, 337, 523, 972, 624, 404, 485, 398, 1249, 366, 371, 400, 419, 344, 823, 365, 506, 925, 305, 628, 357, 323, 489, 662, 354, 833, 353, 369, 352, 342, 493, 366, 329, 862, 333, 361, 816, 785, 500, 502, 368, 343, 349, 366, 340, 325, 359, 371, 403, 333, 385, 336, 352, 716, 424, 395, 1525, 338, 342, 504, 392, 808, 362, 327, 300, 1073, 1137, 376, 332, 363, 340, 876, 396, 319, 339, 330, 290, 1026, 452, 339, 286, 336, 873, 514, 339, 363, 883, 334, 324, 331, 324, 324, 326, 313, 324, 325, 332, 313, 321, 309, 692, 296, 312, 303, 333, 649, 697, 374, 294, 357, 313, 316, 294, 316, 422, 450, 321, 331, 302, 713, 303, 335, 321, 916, 350, 313, 307, 313, 1121, 312, 1299, 481, 306, 1072, 304, 622, 970, 310, 310, 980, 472, 317, 535, 328, 898, 661, 386, 335, 320, 337, 309, 293, 1362, 351, 876, 403, 319, 514, 1102, 456, 309, 498, 706, 305, 922, 1655, 330, 284, 915, 305, 319, 522, 546, 307, 502, 341, 358, 450, 324, 314, 322, 320, 321, 388, 307, 297, 310, 605, 358, 1048, 322, 315, 468, 350, 179, 1056, 1079, 342, 319, 345, 348, 314, 329, 311, 488, 775, 318, 312, 510, 884, 776, 313, 304, 488, 329, 294, 501, 315, 381, 348, 450, 299, 414, 481, 1377, 342, 1135, 637, 302, 322, 309, 305, 311, 696, 303, 486, 293, 308, 1131, 541, 295, 1198, 319, 301, 293, 321, 1268, 281, 361, 304, 306, 339, 1439, 618, 644, 359, 302, 319, 297, 690, 327, 299, 300, 305, 503, 326, 309, 367, 392, 964, 325, 291, 317, 281, 386, 282, 281, 366, 351, 906, 198, 294, 733, 442, 350, 315, 359, 435, 1220, 322, 330, 307, 434, 313, 304, 1111, 313, 313, 330, 336, 764, 312, 286, 348, 924, 309, 327, 317, 364, 423, 294, 337, 323, 313, 718, 676, 323, 335, 332, 332, 321, 1004, 340, 324, 296, 312, 512, 311, 324, 306, 308, 313, 310, 367, 330, 317, 311, 307, 308, 309, 451, 312, 169, 320, 462, 316, 304, 314, 324, 311, 303, 316, 324, 316, 364, 305, 307, 332, 628, 303, 336, 305, 318, 305, 323, 305, 289, 314, 309, 274, 302, 326, 469, 404, 331, 323, 301, 690, 755, 327, 322, 299, 470, 319, 246, 692, 551, 327, 369, 334, 321, 694, 322, 313, 319, 758, 494, 536, 300, 483, 295, 407, 289, 330, 314, 212, 306, 312, 360, 326, 335, 310, 461, 1065, 299, 1554, 316, 883, 306, 314, 302, 381, 313, 939, 310, 298, 295, 1040, 613, 365, 317, 842, 311, 427, 322, 315, 358, 313, 356, 307, 305, 727, 303, 343, 674, 300, 314, 303, 311, 694, 456, 434, 320, 422, 307, 293, 311, 149, 510, 314, 704, 1070, 294, 309, 368, 299, 328, 471, 300, 292, 305, 309, 336, 306, 323, 323, 367, 319, 374, 311, 324, 449, 345, 175, 300, 330, 390, 740, 1029, 644, 532, 339, 966, 307, 325, 301, 245, 916, 334, 463, 373, 313, 671, 678, 298, 315, 286, 820, 312, 535, 340, 464, 322, 323, 416, 595, 571, 596, 753, 725, 295, 304, 294, 451, 308, 303, 310, 506, 308, 744, 308, 289, 311, 293, 455, 327, 263, 1153, 1348, 473, 148, 1811, 134, 294, 577, 834, 349, 287, 1848, 316, 1058, 839, 759, 799, 323, 501, 372, 598, 366, 454, 383, 334, 324, 323, 696, 763, 318, 351, 334, 321, 1631, 295, 354, 292, 321, 741, 1141, 318, 722, 320, 311, 303, 302, 323, 335, 442, 310, 807, 338, 324, 341, 958, 301, 327, 458, 321, 319, 318, 337, 670, 1254, 1019, 340, 193, 740, 308, 413, 336, 203, 330, 321, 336, 966, 561, 1178, 323, 329, 582, 306, 202, 455, 305, 1161, 845, 341, 396, 428, 1298, 973, 300, 692, 519, 296, 306, 441, 759, 572, 299, 628, 340, 514, 320, 296, 326, 569, 823, 373, 618, 410, 317, 313, 712, 210, 363, 717, 1324, 1247, 297, 315, 315, 313, 1031, 354, 312, 312, 208, 374, 338, 361, 704, 433, 320, 319, 295, 528, 291, 1356, 520, 802, 369, 856, 954, 612, 286, 316, 440, 901, 413, 373, 375, 301, 462, 645, 414, 356, 554, 2389, 377, 371, 735, 458, 368, 400, 355, 345, 756, 377, 381, 275, 417, 337, 611, 390, 326, 319, 383, 338, 375, 329, 730, 416, 532, 312, 312, 326, 741, 396, 292, 480, 196, 288, 375, 347, 477, 969, 311, 535, 1560, 328, 312, 719, 459, 299, 324, 312, 505, 325, 547, 1029, 342, 908, 308, 999, 336, 568, 466, 353, 645, 324, 518, 722, 285, 613, 699, 610, 1555, 792, 683, 302, 676, 582, 290, 865, 1675, 559, 398, 271, 459, 1523, 366, 276, 882, 488, 562, 381, 295, 339, 543, 381, 623, 551, 367, 459, 348, 309, 350, 335, 328, 792, 320, 323, 324, 767, 443, 567, 380, 290, 362, 337, 345, 483, 560, 467, 356, 334, 749, 631, 321, 460, 356, 328, 329, 241, 366, 703, 346, 515, 362, 465, 841, 344, 304, 341, 560, 364, 355, 381, 357, 194, 176, 341, 386, 322, 342, 1393, 185, 341, 499, 3154, 324, 435, 542, 353, 402, 292, 334, 413, 179, 806, 892, 494, 281, 527, 332, 655, 724, 1253, 300, 326, 302, 701, 570, 408, 669, 360, 466, 795, 373, 301, 316, 355, 312, 303, 307, 434, 287, 321, 321, 300, 686, 306, 324, 716, 316, 875, 323, 479, 751, 326, 547, 371, 438, 329, 734, 1176, 495, 2745, 736, 421, 327, 436, 323, 353, 670, 442, 300, 595, 369, 727, 484, 352, 369, 325, 341, 266, 481, 306, 323, 294, 493, 365, 400, 382, 372, 540, 310, 317, 932, 321, 404, 328, 303, 340, 324, 313, 315, 318, 331, 729, 1063, 306, 322, 339, 317, 455, 312, 693, 332, 416, 320, 362, 322, 327, 331, 1044, 309, 337, 363, 426, 407, 613, 471, 337, 321, 308, 326, 976, 318, 1265, 314, 874, 294, 319, 366, 337, 343, 453, 322, 481, 447, 749, 370, 337, 308, 316, 516, 385, 426, 349, 416, 585, 373, 353, 360, 194, 419, 311, 318, 317, 287, 341, 335, 587, 551, 393, 303, 288, 1113, 322, 313, 863, 329, 285, 276, 327, 345, 769, 956, 1183, 866, 765, 309, 668, 1849, 516, 395, 363, 427, 293, 359, 260, 1235, 339, 465, 329, 725, 242, 361, 302, 347, 318, 337, 333, 325, 313, 544, 318, 304, 436, 332, 638, 741, 969, 362, 309, 909, 751, 721, 934, 535, 1328, 221, 459, 341, 302, 287, 306, 883, 222, 351, 769, 326, 292, 353, 412, 3017, 791, 401, 1250, 603, 839, 584, 358, 381, 465, 455, 495, 609, 313, 305, 1283, 680, 404, 325, 344, 356, 987, 453, 530, 606, 391, 364, 175, 327, 610, 341, 333, 794, 448, 351, 1603, 417, 283, 395, 540, 338, 319, 354, 302, 339, 364, 526, 347, 357, 542, 840, 416, 301, 370, 191, 1251, 174, 512, 338, 329, 828, 721, 309, 777, 319, 325, 325, 322, 341, 293, 336, 314, 321, 303, 408, 257, 955, 322, 323, 323, 1101, 227, 478, 336, 350, 175, 486, 313, 359, 1170, 346, 336, 500, 282, 910, 295, 303, 971, 1226, 335, 285, 653, 1002, 325, 353, 382, 323, 334, 289, 305, 316, 349, 430, 677, 160, 914, 453, 595, 419, 173, 281, 920, 364, 331, 502, 657, 421, 311, 360, 665, 636, 327, 346, 407, 632, 471, 326, 336, 749, 391, 557, 381, 478, 442, 469, 303, 310, 292, 379, 453, 274, 312, 673, 321, 516, 371, 288, 446, 352, 318, 617, 315, 329, 939, 646, 497, 178, 394, 409, 180, 390, 922, 380, 465, 495, 396, 835, 391, 362, 511, 346, 308, 565, 345, 314, 346, 333, 316, 355, 348, 427, 360, 415, 1113, 813, 321, 486, 349, 363, 363, 359, 181, 317, 356, 223, 294, 326, 146, 372, 307, 465, 402, 275, 324, 317, 359, 316, 336, 506, 782, 298, 283, 500, 401, 412, 631, 342, 296, 311, 327, 323, 422, 321, 354, 1106, 357, 399, 333, 322, 380, 298, 345, 340, 340, 310, 354, 307, 336, 470, 258, 315, 361, 473, 326, 553, 666, 1079, 318, 326, 848, 390, 516, 344, 1169, 449, 324, 340, 310, 320, 300, 326, 305, 498, 288, 324, 312, 174, 344, 354, 409, 260, 331, 494, 1185, 309, 835, 336, 801, 428, 190, 303, 446, 185, 321, 532, 286, 493, 746, 536, 336, 499, 340, 373, 1164, 336, 378, 313, 883, 728, 344, 322, 360, 315, 353, 203, 384, 426, 369, 328, 386, 321, 337, 318, 301, 319, 320, 175, 300, 349, 296, 315, 686, 323, 698, 315, 427, 1174, 506, 396, 321, 464, 309, 308, 338, 370, 327, 313, 941, 323, 384, 194, 333, 1186, 329, 1325, 325, 558, 311, 373, 335, 323, 977, 542, 311, 460, 1188, 324, 332, 184, 2534, 322, 1325, 300, 305, 383, 250, 307, 316, 417, 297, 1378, 305, 330, 316, 506, 717, 173, 426, 637, 1256, 803, 305, 314, 718, 317, 439, 324, 755, 411, 310, 386, 325, 331, 550, 302, 309, 341, 1055, 328, 355, 265, 1013, 477, 533, 1710, 322, 315, 346, 719, 324, 844, 342, 311, 700, 424, 419, 998, 442, 664, 1037, 446, 754, 369, 321, 864, 316, 346, 322, 847, 470, 490, 865, 310, 994, 322, 501, 361, 390, 661, 332, 344, 657, 431, 322, 440, 398, 1876, 732, 292, 1528, 380, 351, 209, 476, 467, 1304, 337, 925, 378, 769, 555, 551, 774, 227, 503, 334, 205, 351, 493, 368, 304, 1131, 320, 484, 800, 281, 549, 306, 316, 809, 310, 325, 529, 939, 836, 179, 321, 176, 326, 189, 370, 327, 351, 822, 317, 308, 321, 301, 494, 346, 355, 306, 326, 318, 302, 298, 287, 323, 316, 329, 320, 475, 306, 527, 902, 575, 1023, 309, 520, 273, 723, 341, 373, 334, 854, 534, 333, 1296, 312, 318, 525, 1259, 406, 441, 309, 498, 663, 706, 423, 631, 794, 452, 393, 766, 371, 356, 309, 265, 321, 542, 379, 317, 394, 325, 522, 346, 378, 308, 1310, 358, 457, 372, 698, 799, 319, 978, 310, 307, 339, 959, 328, 598, 491, 509, 463, 337, 328, 340, 326, 475, 330, 323, 337, 290, 375, 308, 747, 310, 736, 315, 303, 369, 536, 1075, 539, 717, 1493, 477, 513, 1314, 409, 494, 454, 881, 337, 278, 2065, 1757, 212, 458, 708, 363, 560, 326, 137, 598, 390, 785, 928, 301, 1965, 321, 232, 295, 751, 354, 307, 674, 343, 398, 1135, 336, 462, 343, 290, 306, 328, 329, 334, 410, 312, 659, 335, 976, 342, 449, 293, 324, 703, 313, 2091, 583, 731, 863, 337, 292, 1122, 320, 784, 1010, 885, 1148, 1264, 492, 644, 454, 1033, 294, 655, 574, 250, 320, 1056, 617, 1132, 344, 192, 611, 686, 732, 672, 382, 449, 500, 474, 350, 314, 324, 182, 856, 1291, 347, 327, 349, 1909, 536, 461, 641, 507, 1004, 369, 445, 344, 441, 356, 341, 315, 855, 315, 404, 370, 297, 339, 465, 732, 366, 349, 396, 918, 534, 359, 508, 380, 357, 388, 465, 257, 805, 975, 321, 315, 335, 1028, 458, 838, 372, 997, 571, 335, 372, 886, 299, 306, 498, 552, 303, 449, 478, 927, 280, 415, 301, 234, 324, 346, 1107, 1192, 321, 548, 305, 983, 763, 455, 337, 985, 372, 600, 476, 555, 429, 612, 387, 391, 394, 530, 429, 410, 387, 412, 395, 333, 348, 294, 350, 413, 308, 361, 334, 350, 361, 355, 1161, 1772, 334, 185, 313, 330, 603, 397, 469, 373, 302, 465, 493, 344, 325, 297, 185, 355, 362, 324, 334, 334, 349, 345, 305, 299, 349, 328, 357, 467, 319, 891, 570, 245, 1310, 1273, 472, 775, 318, 288, 1076, 1412] + }, + { + 'id': 'Assembly total cost', + 'label': 'Assembly total cost', + 'visible': false, + 'values': [1125, 9274, 2735, 16920, 2193, 20704, 4814, 34689, 5565, 46554, 5225, 38887, 9746, 37715, 17798, 55250, 5697, 49083, 11226, 81939, 24258, 62488, 27363, 61924, 12511, 106196, 24444, 7443, 9111, 12527, 50738, 9320, 12291, 17571, 9508, 11176, 9142, 7687, 6724, 11219, 17825, 6506, 6367, 4966, 8495, 3860, 12844, 10688, 13026, 4007, 57281, 9790, 7335, 13748, 5358, 5393, 4401, 3769, 5233, 5058, 6047, 6188, 11899, 5297, 5154, 4406, 5061, 7022, 6358, 4721, 7723, 16745, 2651, 14194, 100772, 10504, 7021, 6131, 16730, 2904, 8334, 5968, 5876, 7394, 4454, 6800, 18376, 5204, 2190, 6146, 7013, 6412, 4361, 5082, 8028, 6484, 4504, 3832, 5687, 6174, 4603, 6913, 3651, 4631, 4833, 6532, 97138, 21918, 5801, 7435, 13138, 14597, 6070, 19943, 7487, 5362, 3945, 4907, 5287, 7937, 9998, 7852, 4820, 9385, 4686, 4751, 8594, 5144, 4760, 5899, 4614, 30326, 5332, 5030, 4759, 4429, 17294, 5192, 4542, 9333, 2261, 4911, 34968, 2179, 34658, 16325, 4811, 4185, 9017, 4224, 4435, 14536, 7129, 4772, 4726, 4840, 3369, 7428, 4504, 4316, 4097, 4399, 4733, 4105, 4597, 3691, 4405, 4245, 4195, 4168, 4694, 4421, 3507, 4615, 14408, 3607, 3956, 4295, 4583, 4138, 11128, 4147, 4602, 3940, 5590, 4505, 4377, 4016, 5191, 4199, 4269, 4686, 4375, 9716, 8664, 4371, 4294, 9779, 4396, 4183, 4247, 4112, 129671, 3426, 4257, 4102, 4386, 8822, 3138, 4040, 4066, 3950, 12502, 3787, 4273, 4238, 3678, 3660, 6006, 7725, 4172, 12580, 4056, 3920, 4249, 35461, 4054, 108185, 6568, 4154, 11735, 4090, 8971, 3943, 4062, 3857, 5408, 8982, 5662, 3974, 6673, 18248, 3739, 3770, 8110, 4129, 4050, 3826, 8314, 9053, 4022, 3718, 8838, 3786, 3874, 6244, 18434, 3815, 4491, 3954, 39629, 4009, 2456, 3643, 10976, 3783, 3946, 5151, 3900, 3730, 3854, 7621, 3597, 7909, 3959, 4022, 4585, 4130, 6699, 27180, 3935, 89225, 14401, 3962, 4022, 4459, 3816, 3938, 3931, 3041, 26734, 3722, 4047, 4583, 3998, 3907, 3887, 4191, 3858, 4033, 3994, 11019, 3777, 4482, 4277, 3968, 4237, 4378, 4264, 4212, 4049, 7410, 4020, 12723, 12452, 4283, 3862, 3953, 3803, 4276, 3866, 18642, 4063, 3648, 3901, 27631, 4251, 3875, 3837, 4109, 3808, 4083, 3993, 27553, 3950, 3715, 3617, 3819, 7947, 11786, 3358, 44432, 38355, 6845, 9723, 4878, 11458, 6609, 3321, 4964, 3884, 3963, 8633, 3627, 3471, 3780, 3359, 4582, 28916, 3896, 12827, 3908, 3865, 4945, 4276, 6296, 3685, 3657, 3948, 6513, 6549, 4829, 3554, 4503, 3893, 3820, 4464, 3720, 3270, 3743, 3861, 27079, 4284, 4335, 9658, 3671, 7768, 3772, 15008, 6611, 4023, 3840, 3957, 3579, 8798, 3870, 9817, 3319, 3647, 3955, 3782, 3981, 3845, 3930, 5570, 3975, 3856, 3851, 4094, 4130, 3676, 5579, 4013, 17649, 3704, 3967, 4152, 34352, 3909, 16007, 3517, 56056, 4041, 14115, 3652, 6567, 13776, 3906, 4618, 3729, 6550, 8592, 12494, 3885, 13919, 10616, 12510, 2200, 4164, 4256, 13850, 3877, 11216, 1477, 7529, 3283, 3802, 3773, 3728, 3868, 4104, 7658, 4381, 4671, 6364, 3789, 3774, 16177, 3965, 9465, 5965, 4054, 5330, 15225, 3764, 3865, 4058, 3775, 3758, 3704, 4368, 3729, 3767, 3828, 4150, 3804, 15268, 3815, 11823, 3345, 4872, 4659, 7489, 3729, 3868, 29343, 3997, 2114, 5553, 4292, 12800, 4382, 19742, 4101, 8777, 3940, 3978, 7211, 4103, 3980, 12415, 12316, 4082, 8375, 3841, 8810, 4128, 11997, 4269, 15031, 3683, 3614, 4116, 35845, 3653, 3538, 4223, 8373, 33766, 4411, 3863, 4728, 11456, 5587, 38362, 5111, 29991, 4825, 10478, 13283, 4010, 38799, 11943, 14042, 4038, 5282, 12235, 4027, 11570, 5328, 3914, 4404, 6180, 10126, 10305, 23044, 12414, 6658, 6690, 17090, 5813, 10147, 5552, 14343, 11440, 9605, 8565, 6188, 5280, 5483, 3629, 5741, 8375, 6864, 5353, 6098, 6015, 5678, 6594, 5520, 15985, 8704, 5263, 5731, 5020, 5553, 13258, 6541, 4909, 5117, 6779, 61602, 6992, 8510, 3993, 5627, 4035, 4817, 6048, 5638, 10862, 4568, 6015, 5021, 4284, 5133, 5166, 4381, 5240, 5107, 5232, 4897, 7559, 5099, 5020, 15005, 4330, 4830, 11538, 5852, 5130, 4805, 4753, 9282, 4965, 4964, 4540, 21046, 5789, 15483, 5931, 2900, 4104, 5939, 10136, 12664, 9245, 4934, 4829, 9958, 5014, 8126, 4141, 4664, 5028, 2236, 4825, 4450, 6349, 4727, 4520, 4438, 4538, 5013, 4969, 9032, 29764, 12658, 5571, 12826, 4427, 6303, 6807, 8189, 5126, 6691, 5004, 15571, 4613, 4841, 5437, 5492, 4572, 13590, 4729, 31885, 9172, 3977, 4397, 4489, 4192, 30894, 17398, 4636, 12650, 4567, 4597, 4625, 4501, 8431, 4569, 4265, 10628, 4315, 4627, 13535, 10198, 3503, 6671, 4717, 4428, 4557, 4727, 4387, 4179, 4651, 4798, 4920, 4306, 4756, 4240, 4542, 8949, 27217, 5130, 100064, 4412, 4353, 3534, 4753, 45902, 4727, 4278, 3988, 13557, 14324, 4833, 4152, 4563, 4299, 10786, 10025, 3990, 4245, 4201, 3703, 12584, 5588, 4231, 4049, 4219, 10855, 3598, 4248, 4530, 10756, 4306, 4004, 4135, 4069, 4192, 4082, 3919, 4071, 4059, 4177, 3922, 3982, 3841, 11321, 3668, 3855, 3796, 4226, 8651, 8405, 8613, 3628, 4544, 3889, 3934, 3673, 3943, 27240, 28881, 4011, 4120, 3737, 40767, 3746, 4190, 4026, 9678, 8023, 3928, 3813, 3904, 13989, 3909, 22474, 5945, 3795, 14047, 3829, 8130, 12089, 4416, 3859, 23854, 5822, 3941, 34877, 4097, 6289, 8372, 4738, 4124, 3961, 4110, 3843, 3763, 22330, 4302, 10698, 5011, 3960, 6460, 13165, 5659, 3833, 6159, 8569, 3728, 12430, 17360, 4081, 3556, 12850, 3802, 3962, 5382, 7233, 3823, 5937, 4512, 4425, 5552, 4024, 3882, 3993, 3970, 3997, 4806, 3793, 3723, 3848, 7973, 4442, 12803, 4020, 3904, 6002, 4338, 2233, 17184, 14084, 4271, 3942, 7932, 4327, 3882, 4098, 3837, 5936, 10801, 3953, 3865, 3573, 10508, 19422, 3855, 4313, 3419, 4098, 3648, 3507, 3942, 5038, 4350, 28905, 3717, 26636, 31080, 16310, 4550, 14594, 8871, 3743, 4000, 3809, 3784, 3870, 15692, 3764, 7100, 3653, 3821, 13999, 7394, 4537, 14574, 3960, 3737, 3643, 3972, 8878, 3501, 4511, 3785, 3810, 4214, 92394, 8440, 8972, 4418, 3717, 3955, 3701, 10342, 4052, 3730, 3688, 3796, 6183, 4046, 3823, 4535, 4834, 13248, 4026, 3616, 3936, 3491, 4754, 3483, 3528, 4498, 4365, 11386, 2894, 3620, 18349, 5466, 2455, 3885, 4448, 5426, 14879, 3993, 4086, 3797, 5588, 3885, 3773, 18127, 3875, 3891, 4095, 4159, 11648, 3866, 3565, 4317, 12171, 3823, 4053, 3922, 8253, 27165, 3649, 7753, 4005, 3871, 17967, 44240, 3984, 4138, 4101, 4124, 3966, 12588, 4194, 4016, 3667, 3851, 11327, 3833, 4023, 3798, 3810, 3874, 3840, 8337, 4063, 3925, 3852, 3812, 3820, 3828, 5671, 3844, 2457, 3964, 3237, 3922, 3762, 3880, 4014, 3866, 3752, 3931, 4022, 3918, 4517, 3779, 3801, 4107, 15710, 3752, 4170, 3771, 3965, 3775, 4004, 3779, 3585, 3903, 3836, 3382, 3748, 4032, 3283, 5534, 4099, 3997, 3732, 8711, 18895, 4040, 3984, 3701, 7008, 3970, 3088, 8520, 6614, 4162, 4436, 4138, 3979, 8524, 4013, 3861, 3965, 18961, 6070, 6394, 3698, 5940, 3645, 4818, 3582, 4120, 3910, 2799, 3779, 3893, 4458, 4022, 4108, 3820, 3227, 10985, 3685, 22218, 3925, 10987, 3806, 3865, 3745, 22845, 3873, 12636, 3830, 3697, 3640, 14144, 8228, 4503, 3912, 10683, 3832, 27508, 4369, 3907, 4705, 3860, 4686, 3807, 3775, 11854, 3763, 4259, 10998, 3715, 3918, 3754, 3837, 10320, 29350, 28013, 4806, 27181, 3783, 3626, 3838, 2197, 6793, 3880, 11481, 28248, 3636, 3818, 4555, 3699, 4061, 5737, 3704, 3612, 3780, 3815, 4160, 3795, 3964, 4006, 4520, 3967, 4631, 3837, 4005, 5551, 4224, 2573, 3722, 4063, 25150, 8949, 12712, 7939, 6700, 4162, 13481, 3801, 3966, 3741, 3298, 11662, 4130, 6268, 4621, 3866, 16793, 9268, 3710, 4199, 3545, 8357, 3845, 7090, 4227, 5999, 3976, 3986, 5145, 8848, 7687, 7778, 9672, 18129, 3671, 3758, 3623, 6176, 3829, 3751, 3839, 6623, 3818, 9382, 3824, 3567, 3876, 3648, 3187, 4050, 3274, 14438, 33701, 3315, 2019, 17972, 1935, 3651, 7236, 10042, 4314, 3418, 46207, 3910, 13235, 11016, 5315, 12999, 4040, 6042, 4600, 6015, 4556, 10560, 4629, 4154, 4057, 4028, 10213, 10194, 3936, 4337, 4100, 4017, 17640, 3666, 4336, 3605, 3985, 10013, 13900, 3940, 9771, 4029, 3830, 6681, 3749, 4002, 4144, 28335, 3851, 9628, 4190, 4020, 4209, 11639, 3714, 4051, 29534, 4001, 3943, 3919, 4181, 8921, 15249, 25498, 4413, 2570, 9094, 3781, 5196, 4153, 2806, 4299, 3944, 4153, 11672, 7329, 13429, 3990, 4059, 5928, 3770, 2724, 5689, 3807, 14139, 10239, 7795, 4983, 10307, 16032, 12418, 3739, 8526, 6457, 3656, 3791, 28264, 8997, 7054, 3697, 6385, 4206, 7040, 3971, 3702, 4031, 8243, 47305, 4623, 6289, 26518, 3919, 3896, 17804, 2868, 4490, 17926, 86514, 14833, 3636, 3919, 3900, 4163, 13083, 4797, 3872, 3870, 2921, 4626, 4389, 4492, 8805, 27930, 3981, 3945, 3652, 6474, 3616, 84260, 6441, 11593, 4576, 12714, 13232, 12893, 3555, 3922, 28141, 12058, 5088, 4661, 4667, 3727, 5861, 9001, 5727, 4432, 6923, 39382, 6197, 4625, 16568, 5855, 4562, 4751, 4391, 4257, 9707, 4869, 4715, 17117, 5311, 4147, 6155, 4805, 4006, 3954, 8680, 4167, 23759, 4134, 11938, 26580, 3728, 3886, 3880, 4065, 18544, 9038, 3609, 30977, 2647, 3585, 8622, 4313, 3341, 60270, 3902, 6742, 101532, 4069, 3902, 11753, 5734, 3706, 7359, 3882, 5163, 4062, 7403, 12706, 4274, 11082, 3834, 13857, 4180, 7733, 6289, 4394, 8664, 4020, 6487, 8926, 3545, 7424, 8967, 7105, 15471, 8990, 15930, 3739, 4733, 4080, 3681, 11600, 109361, 35468, 4939, 3449, 29173, 88421, 4596, 3452, 11753, 4978, 36214, 4717, 3650, 4247, 34932, 4724, 9055, 6852, 4699, 6300, 4318, 3863, 4364, 4208, 4057, 11771, 3994, 3980, 3999, 11116, 5528, 7493, 24623, 3933, 4465, 4205, 4283, 6279, 5729, 5893, 4439, 4200, 9248, 4421, 4061, 5686, 4450, 4066, 4108, 3132, 4617, 17583, 4328, 6506, 4535, 30003, 48630, 4313, 3777, 4245, 6884, 4535, 3881, 8812, 4461, 2683, 2233, 4284, 4820, 4040, 4277, 16571, 2554, 4242, 6285, 51154, 4044, 5770, 3800, 4401, 5008, 3647, 4158, 26583, 2467, 20174, 10786, 3461, 3497, 7861, 4243, 16393, 11861, 76828, 4026, 4071, 3740, 17541, 7580, 5092, 4687, 4720, 3266, 13157, 4661, 3747, 3893, 4432, 3893, 3761, 3795, 9961, 3574, 4001, 3976, 3773, 17165, 3782, 4045, 9144, 3962, 50212, 4029, 5950, 8949, 4070, 7221, 8644, 28169, 4062, 8752, 15000, 15842, 44456, 9155, 5309, 4053, 10116, 4046, 4394, 8316, 5514, 3711, 38351, 8468, 10339, 6030, 8029, 4578, 4029, 4222, 3390, 6727, 3803, 20095, 3644, 31728, 4573, 9131, 24869, 4656, 40536, 3844, 3932, 12001, 3974, 9248, 4031, 3798, 4203, 4056, 3876, 3886, 3939, 4057, 9567, 26598, 3804, 4015, 7758, 3949, 29312, 3902, 8209, 7521, 5578, 3987, 4785, 3995, 4079, 4112, 12730, 3823, 4210, 8367, 27490, 4937, 8779, 6457, 7775, 3957, 3823, 4042, 22441, 3978, 15741, 3913, 12279, 3646, 3940, 5004, 4172, 4199, 5890, 4245, 5994, 5525, 18737, 4526, 4310, 3837, 3909, 33292, 4777, 27477, 4301, 5769, 8151, 4658, 4344, 4495, 2657, 5789, 3851, 3932, 3934, 3683, 4207, 4138, 8298, 6530, 8710, 3782, 3585, 13380, 3997, 3900, 49974, 4074, 3540, 3419, 4076, 4261, 9672, 6695, 14148, 50140, 9092, 3985, 9640, 42657, 33535, 8852, 8334, 5261, 3730, 22730, 3339, 76534, 4819, 28020, 4070, 8981, 2923, 4505, 4593, 4316, 3911, 4185, 4135, 4015, 3895, 5559, 3947, 4231, 5169, 4122, 8906, 18540, 11809, 4399, 3866, 11489, 9502, 10162, 11780, 34617, 14012, 2961, 5785, 4343, 3766, 3585, 3799, 14853, 2997, 4256, 9665, 19975, 3645, 8150, 26579, 49058, 11073, 4814, 31254, 7724, 11033, 8315, 4314, 4509, 5916, 28810, 5994, 15238, 3883, 3771, 13249, 9488, 4866, 3982, 4169, 4354, 12208, 5757, 12358, 7437, 4743, 4418, 2405, 4048, 10157, 4252, 4071, 19869, 5500, 4254, 11221, 5164, 4153, 4884, 3785, 4207, 3912, 4325, 3755, 4161, 8314, 3687, 4203, 4409, 5546, 22831, 5131, 3903, 4589, 2432, 80943, 2199, 3585, 4205, 4049, 12623, 11762, 3815, 9929, 3934, 4023, 4371, 3987, 4218, 3830, 4139, 3910, 4533, 3782, 5007, 3306, 23891, 3988, 4008, 4002, 13496, 3002, 5976, 4142, 4357, 2414, 30186, 4189, 4749, 13952, 4589, 4189, 5993, 3502, 13135, 3665, 3739, 11784, 28602, 4450, 3574, 10675, 13041, 4002, 4349, 4771, 4001, 4159, 3482, 3804, 3884, 4343, 9972, 16927, 2221, 12913, 29211, 7041, 27050, 2402, 3485, 11956, 4511, 4063, 3515, 9775, 27027, 3871, 8808, 8094, 8066, 4060, 4286, 26107, 7034, 28205, 4038, 4148, 12288, 5029, 6825, 24260, 30775, 28412, 5946, 3777, 3890, 3615, 4738, 29181, 16464, 3920, 8606, 4059, 5257, 4640, 3570, 6020, 4387, 3958, 40271, 3907, 4062, 12193, 4527, 31964, 2436, 4879, 9400, 2240, 4846, 59578, 8689, 28097, 6135, 9008, 12433, 5015, 4496, 3579, 4307, 3807, 8084, 4643, 3879, 4300, 4138, 4068, 4424, 4336, 6213, 4457, 26961, 14333, 13269, 4073, 6316, 4332, 4492, 8378, 4443, 2350, 4011, 4427, 2909, 3752, 3989, 1997, 8651, 3891, 5882, 5091, 3443, 4074, 3974, 4512, 3921, 4204, 5164, 10883, 3711, 3570, 6328, 5074, 5141, 8367, 4363, 3678, 3889, 4145, 4042, 5286, 3989, 4476, 13140, 4539, 25758, 4129, 4004, 4694, 3864, 4295, 4277, 4463, 3857, 4439, 3782, 4186, 30163, 3261, 3942, 5408, 6214, 4099, 3875, 9581, 15415, 3965, 4083, 10985, 4853, 3614, 4321, 14442, 3146, 4061, 4248, 3869, 4031, 3748, 4124, 3763, 7007, 3547, 4060, 3906, 2375, 4294, 4412, 5156, 3421, 4143, 6916, 14716, 3866, 10080, 4168, 11257, 6132, 2617, 3796, 5781, 2543, 4022, 7851, 3579, 31698, 10449, 7074, 4179, 6623, 4294, 4985, 14197, 4219, 4643, 3871, 10871, 10158, 4303, 4042, 4687, 3933, 4395, 2669, 5223, 26888, 4835, 4120, 4863, 4033, 4234, 3945, 3787, 4005, 4006, 2384, 3737, 4331, 3717, 3897, 11221, 3970, 11405, 3906, 5170, 26275, 5172, 4725, 4027, 29448, 3856, 3820, 4221, 4553, 4084, 3920, 12274, 4041, 4563, 2432, 4168, 14781, 4089, 84860, 4055, 6853, 3917, 4639, 4187, 4046, 15864, 3795, 3896, 29479, 14289, 4031, 4153, 2588, 41096, 4004, 28909, 3755, 3826, 4556, 3108, 3827, 3932, 4954, 3685, 14009, 3794, 4092, 3929, 5161, 10867, 2372, 5304, 7846, 14855, 10527, 3801, 3892, 17953, 3898, 5557, 4010, 8929, 5144, 3868, 4846, 4033, 4106, 7961, 3734, 3844, 4228, 14218, 4070, 4390, 3578, 64666, 30739, 9257, 42766, 3995, 3910, 4320, 11739, 4026, 10762, 4262, 3868, 21774, 27155, 26769, 13667, 5432, 8575, 13691, 5792, 12304, 8357, 3962, 12225, 3930, 4287, 3987, 10619, 5986, 6403, 11136, 3844, 13668, 4749, 6511, 4570, 5367, 9270, 4129, 5042, 6824, 27699, 3999, 28366, 4786, 30493, 10545, 3619, 38201, 4702, 4334, 2851, 30809, 3274, 21828, 4164, 12971, 4680, 9109, 6845, 6667, 9545, 3102, 31606, 4117, 3017, 4334, 31897, 8413, 3756, 13786, 3943, 7094, 9861, 17684, 7372, 3802, 3923, 13130, 3832, 4035, 6716, 13120, 10771, 2451, 3981, 2509, 4019, 2530, 4595, 4017, 4468, 12432, 3922, 3813, 3969, 3716, 31879, 4280, 4485, 3782, 4025, 3901, 3719, 18455, 3560, 3943, 19801, 4049, 3957, 30692, 3774, 3690, 12946, 43153, 12827, 3480, 3642, 3492, 5065, 4683, 8439, 4097, 5979, 7318, 4074, 27698, 3828, 3955, 7204, 80055, 4851, 11026, 3846, 6536, 41579, 8716, 5304, 9580, 9725, 10335, 8879, 9245, 8502, 4393, 7028, 3207, 3943, 6586, 4696, 3914, 9070, 4049, 33617, 4304, 8600, 3814, 81235, 4422, 6506, 4557, 7048, 19991, 3954, 13795, 3822, 3798, 4260, 11751, 4101, 7718, 31546, 6384, 3247, 4172, 4088, 4228, 4035, 5786, 4094, 3987, 4185, 3877, 4554, 3840, 8856, 17877, 11098, 3877, 3743, 4629, 5448, 14210, 5504, 17927, 15188, 5892, 6491, 15609, 4910, 8230, 29322, 11412, 4175, 3866, 34283, 101349, 2855, 3210, 17724, 4466, 6815, 4038, 1938, 8412, 4895, 12817, 23221, 3737, 32782, 3984, 3123, 3650, 12300, 4338, 3889, 8256, 4272, 5260, 14199, 4117, 6801, 4269, 3612, 3803, 4083, 4070, 4216, 5383, 3891, 9386, 4152, 13778, 7919, 3149, 3636, 4064, 11473, 3886, 34380, 6906, 11939, 10572, 7726, 3639, 58427, 3988, 5494, 13997, 12759, 69547, 82624, 6238, 9041, 5960, 13276, 3667, 7896, 6782, 3844, 3967, 12716, 7470, 14500, 4257, 2617, 7419, 4804, 8821, 4705, 4733, 28271, 6839, 30762, 4321, 3868, 3984, 2542, 11350, 13299, 4292, 4368, 4264, 27377, 8775, 5744, 7910, 12689, 12160, 4769, 5551, 4261, 5514, 4379, 4244, 3879, 21386, 4042, 9266, 4556, 3667, 4165, 29895, 11939, 4558, 4237, 4917, 13036, 6889, 4424, 32664, 4694, 8153, 9377, 5507, 3342, 10823, 62847, 3939, 3912, 4122, 66439, 3210, 10350, 4615, 12868, 7511, 4255, 4616, 12370, 3704, 3788, 6565, 6764, 3760, 5382, 5920, 13436, 16417, 5747, 3951, 2810, 4018, 4297, 24861, 15191, 3990, 6731, 3764, 13253, 9573, 10539, 4175, 13712, 4754, 7612, 10652, 6949, 5321, 4285, 4785, 4906, 4827, 33385, 5270, 5091, 4739, 5003, 4787, 4146, 4299, 3657, 4368, 5066, 3848, 4575, 4150, 4381, 4496, 4471, 14916, 29694, 4159, 2529, 3889, 4098, 8034, 4757, 6803, 4640, 3780, 5750, 7248, 4255, 3991, 3723, 2276, 4447, 4513, 4048, 4071, 4323, 4361, 4313, 3757, 3874, 4314, 4087, 4463, 30169, 3933, 11064, 8721, 3231, 14337, 15420, 5613, 10373, 4057, 3450, 14347, 15572] + }, + { + 'id': 'Assembly penalty weight', + 'label': 'Assembly penalty weight', + 'values': [9, 794, 34, 1409, 17, 536, 39, 7133, 115, 9843, 107, 7017, 273, 5131, 1210, 9032, 82, 7312, 252, 16778, 760, 4349, 891, 4228, 123, 10800, 1593, 467, 260, 226, 2940, 803, 689, 420, 422, 1229, 275, 198, 150, 423, 423, 134, 146, 89, 248, 55, 612, 401, 546, 52, 4208, 307, 194, 257, 91, 93, 178, 133, 99, 98, 131, 345, 461, 90, 96, 69, 91, 160, 148, 81, 274, 1332, 31, 667, 11733, 502, 163, 354, 480, 67, 252, 120, 303, 181, 162, 153, 1142, 251, 17, 131, 165, 135, 162, 222, 230, 154, 198, 58, 109, 132, 189, 159, 102, 167, 218, 147, 11969, 2288, 316, 467, 234, 1025, 169, 497, 435, 265, 49, 82, 252, 234, 372, 229, 79, 127, 76, 82, 105, 97, 207, 115, 75, 1014, 259, 95, 84, 68, 404, 91, 183, 273, 49, 82, 1378, 14, 5405, 769, 86, 168, 308, 67, 69, 818, 200, 87, 79, 86, 100, 174, 77, 66, 58, 74, 206, 62, 73, 129, 71, 63, 65, 67, 71, 72, 116, 76, 696, 46, 55, 66, 77, 61, 460, 62, 77, 55, 146, 77, 71, 58, 93, 64, 68, 82, 66, 364, 113, 69, 69, 145, 69, 62, 65, 62, 19984, 113, 65, 60, 69, 307, 33, 60, 60, 57, 676, 52, 67, 64, 49, 50, 129, 196, 63, 690, 59, 56, 66, 5409, 60, 13549, 146, 62, 466, 61, 305, 56, 60, 56, 138, 299, 102, 58, 406, 1019, 51, 137, 247, 63, 59, 54, 226, 257, 59, 51, 286, 52, 55, 143, 1039, 53, 73, 58, 4807, 59, 22, 49, 411, 52, 57, 98, 129, 51, 143, 90, 47, 284, 57, 59, 77, 63, 162, 849, 56, 8935, 711, 58, 59, 73, 53, 56, 57, 30, 822, 50, 59, 78, 59, 56, 55, 65, 54, 60, 58, 532, 52, 75, 71, 57, 65, 70, 67, 65, 60, 173, 59, 717, 203, 68, 55, 57, 53, 67, 55, 1579, 61, 49, 56, 877, 66, 56, 142, 62, 53, 62, 58, 873, 57, 132, 126, 54, 98, 622, 103, 9106, 1860, 454, 148, 206, 412, 423, 103, 77, 55, 57, 118, 49, 45, 52, 40, 77, 960, 56, 603, 57, 55, 225, 68, 146, 50, 49, 58, 159, 142, 88, 46, 76, 56, 54, 75, 51, 100, 51, 55, 842, 69, 59, 353, 49, 236, 52, 829, 150, 60, 54, 54, 47, 277, 55, 309, 104, 49, 58, 52, 59, 55, 57, 116, 58, 55, 143, 62, 63, 50, 151, 59, 515, 53, 58, 64, 1357, 56, 961, 117, 3664, 61, 696, 128, 147, 639, 56, 79, 51, 342, 268, 245, 55, 311, 413, 505, 17, 63, 67, 713, 55, 199, 17, 89, 34, 53, 53, 51, 55, 60, 192, 71, 84, 130, 52, 52, 1033, 58, 122, 113, 61, 134, 1110, 52, 55, 60, 52, 68, 50, 71, 52, 52, 54, 61, 139, 861, 53, 464, 105, 86, 84, 207, 125, 54, 3281, 58, 15, 108, 68, 523, 71, 1197, 59, 120, 57, 57, 187, 60, 58, 483, 696, 61, 109, 54, 121, 60, 563, 67, 797, 130, 47, 61, 1473, 49, 119, 65, 231, 1307, 71, 55, 85, 491, 114, 1705, 96, 1039, 86, 346, 690, 60, 1724, 462, 677, 61, 106, 664, 59, 590, 134, 56, 71, 355, 338, 168, 1600, 612, 141, 437, 1438, 111, 367, 283, 942, 412, 453, 259, 128, 92, 277, 45, 304, 278, 156, 269, 123, 136, 121, 148, 104, 1063, 676, 257, 125, 85, 105, 301, 142, 232, 85, 150, 4912, 226, 287, 135, 108, 147, 77, 123, 109, 1131, 72, 131, 84, 63, 88, 88, 66, 95, 89, 90, 81, 222, 88, 85, 808, 64, 76, 179, 115, 88, 78, 77, 236, 85, 83, 71, 1381, 113, 1075, 118, 31, 58, 117, 144, 653, 301, 84, 81, 315, 88, 207, 155, 74, 86, 17, 80, 68, 166, 77, 69, 67, 71, 89, 88, 303, 989, 509, 105, 642, 67, 153, 405, 231, 94, 147, 90, 889, 76, 81, 98, 104, 71, 773, 78, 1146, 413, 55, 178, 73, 61, 1077, 421, 74, 503, 73, 77, 73, 69, 255, 76, 63, 420, 65, 76, 752, 363, 112, 151, 78, 68, 72, 78, 67, 61, 75, 80, 91, 65, 84, 65, 72, 292, 847, 91, 11709, 67, 67, 110, 86, 2467, 77, 63, 54, 662, 742, 82, 63, 75, 66, 434, 144, 58, 65, 63, 48, 594, 115, 65, 53, 64, 433, 119, 65, 75, 438, 65, 59, 62, 60, 61, 60, 56, 60, 60, 63, 56, 58, 54, 561, 49, 55, 52, 64, 254, 271, 115, 48, 73, 55, 56, 49, 56, 853, 954, 59, 62, 51, 1951, 52, 64, 59, 430, 100, 56, 53, 55, 717, 55, 1725, 131, 53, 681, 53, 229, 536, 63, 54, 842, 126, 57, 1413, 61, 321, 252, 84, 63, 58, 63, 54, 50, 2153, 69, 432, 92, 57, 151, 677, 118, 54, 140, 279, 52, 519, 1391, 61, 46, 538, 53, 58, 135, 178, 53, 140, 69, 72, 115, 59, 56, 58, 58, 58, 85, 53, 50, 54, 218, 72, 618, 59, 56, 127, 69, 18, 1321, 688, 67, 57, 98, 69, 56, 61, 54, 133, 382, 57, 55, 120, 434, 1165, 55, 60, 108, 61, 49, 114, 56, 86, 69, 957, 50, 814, 1112, 1052, 70, 751, 257, 51, 59, 54, 52, 55, 392, 52, 160, 49, 53, 726, 181, 64, 806, 57, 51, 49, 58, 629, 45, 74, 52, 53, 65, 9789, 237, 263, 72, 51, 57, 50, 337, 60, 51, 50, 53, 143, 60, 54, 76, 87, 580, 60, 48, 57, 44, 84, 45, 45, 75, 70, 470, 26, 48, 1034, 110, 56, 56, 73, 108, 837, 59, 62, 53, 110, 55, 52, 1450, 55, 55, 62, 64, 426, 55, 46, 68, 509, 54, 60, 57, 107, 846, 49, 93, 59, 55, 992, 2282, 59, 63, 62, 62, 58, 577, 65, 59, 49, 55, 208, 54, 59, 53, 53, 55, 54, 109, 61, 57, 55, 53, 54, 54, 116, 55, 19, 58, 98, 56, 52, 56, 59, 55, 52, 56, 59, 56, 75, 52, 53, 62, 758, 52, 64, 52, 57, 52, 59, 52, 47, 56, 54, 42, 51, 60, 101, 101, 62, 59, 51, 274, 1101, 60, 58, 50, 155, 58, 34, 270, 169, 62, 76, 63, 58, 272, 59, 55, 57, 1092, 137, 159, 51, 132, 49, 92, 47, 62, 56, 26, 53, 55, 73, 60, 63, 54, 98, 564, 50, 3025, 56, 444, 53, 55, 52, 564, 55, 537, 54, 50, 49, 667, 228, 75, 57, 409, 54, 869, 63, 56, 76, 55, 75, 53, 52, 623, 52, 66, 534, 51, 56, 52, 54, 337, 989, 902, 72, 848, 53, 48, 55, 15, 157, 55, 586, 1108, 49, 54, 76, 50, 61, 125, 51, 48, 52, 54, 64, 53, 59, 59, 76, 58, 79, 54, 59, 114, 67, 21, 51, 61, 726, 306, 600, 234, 162, 65, 594, 53, 59, 51, 36, 485, 63, 131, 79, 55, 867, 285, 50, 60, 46, 330, 55, 171, 66, 126, 58, 59, 98, 247, 199, 210, 330, 1010, 49, 52, 48, 126, 54, 52, 54, 151, 53, 318, 53, 47, 55, 49, 95, 60, 39, 760, 3499, 103, 13, 1582, 12, 49, 190, 388, 69, 45, 6497, 56, 640, 418, 246, 757, 59, 140, 78, 174, 76, 172, 82, 63, 60, 59, 331, 352, 57, 69, 63, 58, 1417, 49, 70, 48, 58, 336, 732, 57, 319, 58, 54, 72, 52, 59, 63, 918, 54, 363, 64, 59, 66, 515, 51, 60, 1002, 58, 57, 57, 64, 270, 883, 1867, 68, 22, 309, 53, 97, 64, 25, 64, 58, 64, 523, 186, 826, 59, 61, 166, 53, 24, 118, 53, 758, 400, 95, 90, 158, 954, 549, 51, 271, 153, 49, 53, 914, 320, 185, 50, 193, 65, 164, 58, 50, 60, 217, 2632, 79, 187, 810, 57, 55, 976, 27, 74, 988, 8719, 865, 49, 56, 56, 59, 614, 77, 55, 55, 27, 79, 67, 74, 283, 897, 58, 57, 49, 157, 48, 7908, 153, 430, 77, 511, 575, 285, 46, 56, 904, 492, 96, 79, 80, 51, 123, 265, 108, 72, 175, 6523, 163, 78, 437, 122, 76, 88, 71, 67, 333, 83, 82, 326, 100, 64, 181, 86, 60, 57, 119, 64, 639, 62, 622, 806, 126, 55, 55, 60, 1051, 128, 48, 1104, 23, 47, 116, 68, 104, 4048, 55, 164, 11963, 61, 55, 605, 120, 50, 85, 55, 125, 60, 183, 600, 67, 464, 54, 631, 64, 199, 132, 71, 253, 59, 153, 295, 46, 210, 284, 233, 1168, 369, 390, 51, 204, 156, 48, 454, 13920, 1427, 90, 42, 967, 9234, 76, 43, 469, 117, 1506, 82, 49, 65, 1401, 82, 262, 172, 78, 131, 68, 54, 69, 64, 61, 438, 58, 59, 59, 395, 112, 192, 700, 51, 74, 64, 67, 137, 155, 125, 72, 63, 318, 173, 59, 120, 72, 61, 61, 34, 77, 941, 68, 152, 75, 1036, 2493, 67, 52, 66, 177, 75, 68, 120, 72, 23, 17, 66, 85, 59, 67, 1079, 21, 66, 143, 11880, 59, 113, 134, 71, 92, 48, 63, 812, 20, 1241, 446, 111, 45, 195, 64, 778, 609, 7556, 54, 60, 51, 944, 195, 95, 214, 77, 100, 716, 79, 51, 56, 72, 55, 52, 53, 155, 47, 58, 58, 51, 897, 53, 60, 297, 57, 2646, 59, 130, 313, 60, 178, 115, 911, 61, 300, 801, 317, 9038, 308, 102, 60, 158, 59, 70, 255, 111, 51, 1691, 112, 345, 133, 101, 77, 60, 66, 41, 147, 53, 449, 49, 1156, 76, 131, 717, 79, 1595, 54, 57, 507, 58, 134, 60, 52, 65, 60, 55, 56, 57, 61, 315, 2179, 53, 59, 94, 57, 987, 55, 266, 89, 105, 58, 78, 59, 61, 62, 613, 54, 65, 109, 870, 93, 248, 138, 94, 58, 53, 60, 785, 57, 911, 56, 491, 49, 57, 83, 64, 66, 120, 61, 132, 113, 1080, 77, 66, 54, 56, 1274, 84, 868, 69, 109, 217, 79, 70, 74, 23, 110, 55, 57, 57, 48, 65, 63, 223, 169, 123, 52, 47, 692, 58, 56, 2946, 61, 46, 43, 60, 67, 339, 407, 779, 2965, 325, 56, 298, 6838, 1303, 125, 108, 103, 49, 585, 39, 6512, 75, 852, 61, 298, 32, 74, 66, 68, 57, 64, 63, 59, 55, 145, 57, 58, 105, 62, 259, 1056, 528, 73, 54, 476, 325, 335, 501, 1382, 903, 29, 121, 67, 52, 47, 53, 846, 30, 69, 339, 438, 48, 103, 812, 10805, 400, 89, 3049, 211, 419, 223, 71, 80, 125, 938, 137, 693, 55, 52, 820, 294, 91, 59, 66, 71, 553, 118, 235, 207, 85, 74, 19, 60, 416, 66, 62, 1242, 113, 69, 1218, 98, 54, 88, 136, 65, 57, 70, 51, 65, 108, 129, 67, 72, 145, 710, 98, 53, 78, 21, 7564, 17, 120, 65, 61, 500, 611, 54, 350, 57, 60, 64, 58, 65, 50, 63, 56, 66, 52, 93, 38, 1462, 59, 59, 59, 684, 30, 130, 63, 69, 19, 1015, 59, 77, 762, 71, 64, 139, 45, 552, 49, 52, 529, 3101, 67, 46, 501, 592, 59, 70, 83, 59, 63, 46, 53, 56, 69, 153, 885, 16, 541, 981, 196, 841, 18, 45, 498, 75, 61, 115, 302, 836, 55, 114, 248, 233, 60, 68, 780, 225, 860, 60, 64, 649, 89, 175, 668, 1088, 925, 127, 52, 55, 48, 82, 979, 293, 55, 263, 59, 130, 78, 47, 121, 70, 57, 1886, 56, 61, 519, 172, 1172, 19, 88, 137, 18, 86, 4092, 118, 859, 139, 127, 489, 89, 74, 116, 68, 53, 210, 72, 55, 68, 63, 58, 71, 69, 123, 73, 842, 723, 775, 59, 139, 69, 74, 109, 73, 19, 58, 72, 29, 50, 59, 13, 115, 54, 124, 93, 43, 60, 57, 74, 56, 64, 126, 388, 50, 46, 144, 92, 97, 238, 67, 49, 55, 61, 59, 102, 58, 72, 679, 73, 763, 63, 59, 81, 52, 67, 66, 68, 54, 71, 53, 64, 1041, 38, 56, 92, 133, 60, 144, 294, 1454, 57, 60, 422, 86, 121, 67, 775, 93, 60, 66, 54, 58, 51, 61, 52, 159, 47, 60, 55, 18, 67, 71, 96, 40, 62, 156, 798, 54, 390, 64, 412, 121, 22, 52, 116, 21, 59, 195, 46, 1153, 356, 171, 64, 149, 66, 84, 762, 64, 80, 55, 441, 337, 67, 59, 76, 56, 71, 24, 90, 815, 80, 61, 85, 59, 65, 57, 51, 58, 58, 18, 51, 69, 50, 56, 551, 59, 572, 56, 102, 1107, 126, 87, 59, 983, 54, 53, 65, 77, 61, 56, 523, 59, 82, 21, 63, 802, 61, 8238, 60, 175, 55, 79, 64, 59, 1136, 134, 55, 994, 788, 59, 63, 21, 7677, 59, 1377, 51, 53, 81, 35, 53, 57, 96, 50, 932, 53, 61, 56, 126, 371, 18, 103, 229, 875, 382, 53, 56, 993, 56, 111, 59, 316, 96, 54, 85, 60, 62, 203, 51, 54, 66, 679, 61, 71, 42, 4768, 1085, 289, 4911, 59, 56, 68, 608, 59, 412, 66, 55, 604, 842, 817, 619, 110, 258, 642, 117, 668, 110, 58, 484, 57, 68, 58, 410, 127, 142, 437, 54, 617, 71, 147, 75, 95, 280, 62, 80, 216, 879, 59, 926, 88, 4185, 356, 48, 4600, 81, 69, 27, 1094, 100, 1870, 64, 548, 81, 328, 174, 170, 339, 31, 1122, 63, 28, 70, 1173, 111, 52, 719, 58, 160, 362, 352, 183, 53, 56, 781, 54, 60, 161, 562, 408, 19, 58, 20, 60, 21, 78, 60, 71, 486, 57, 53, 58, 51, 1170, 68, 72, 53, 60, 57, 51, 377, 46, 58, 439, 61, 58, 1085, 53, 129, 538, 1842, 598, 55, 126, 43, 201, 72, 113, 62, 339, 177, 62, 1294, 55, 57, 172, 7283, 91, 176, 54, 147, 1940, 282, 102, 288, 355, 167, 125, 328, 113, 71, 78, 39, 58, 164, 81, 56, 128, 60, 1299, 68, 116, 53, 7338, 72, 136, 78, 237, 1244, 57, 618, 54, 53, 66, 519, 61, 209, 1141, 148, 98, 64, 61, 65, 60, 126, 61, 59, 64, 51, 78, 54, 310, 336, 388, 56, 52, 77, 141, 691, 143, 929, 1094, 129, 151, 960, 93, 272, 989, 455, 64, 49, 4784, 12101, 27, 96, 959, 74, 176, 60, 12, 230, 87, 724, 1656, 51, 4285, 58, 32, 49, 659, 70, 54, 256, 67, 94, 736, 63, 146, 66, 48, 53, 61, 61, 64, 100, 55, 284, 63, 616, 97, 92, 48, 60, 583, 55, 5038, 189, 627, 420, 93, 48, 3879, 58, 289, 644, 522, 5278, 7955, 139, 266, 122, 622, 49, 240, 182, 46, 58, 623, 213, 745, 67, 22, 209, 216, 299, 207, 83, 899, 155, 1094, 69, 55, 59, 21, 440, 828, 68, 64, 68, 4618, 334, 121, 232, 511, 565, 79, 113, 67, 111, 71, 66, 56, 1396, 57, 134, 77, 49, 65, 1026, 632, 76, 68, 89, 549, 166, 72, 1224, 82, 104, 131, 120, 39, 394, 4543, 58, 56, 63, 5089, 98, 398, 78, 581, 194, 64, 78, 500, 50, 53, 148, 172, 52, 112, 129, 577, 286, 108, 53, 30, 59, 68, 987, 823, 58, 169, 52, 590, 333, 172, 64, 616, 80, 207, 181, 176, 104, 172, 85, 87, 87, 1255, 104, 95, 84, 95, 87, 63, 68, 49, 69, 96, 54, 75, 63, 70, 74, 72, 786, 3447, 63, 21, 55, 62, 219, 88, 148, 79, 52, 122, 167, 67, 59, 50, 19, 72, 74, 60, 62, 65, 69, 67, 52, 52, 69, 61, 72, 1047, 57, 451, 238, 35, 934, 908, 124, 364, 58, 46, 698, 1102] + }, + { + 'id': 'Height st width', + 'label': 'Height st width', + 'values': [236630, 326876, 347086, 437333, 457543, 105963, 568000, 216420, 236630, 326876, 347086, 437333, 457543, 105963, 568000, 216420, 236630, 326876, 347086, 437333, 457543, 105963, 568000, 216420, 236630, 326876, 350300, 210200, 106030, 349000, 288700, 328200, 262300, 251400, 384900, 435500, 224500, 273000, 276300, 224500, 222900, 202100, 394000, 418300, 302200, 475800, 338900, 296400, 115700, 276700, 298200, 163400, 380500, 282000, 226600, 233500, 404799, 451800, 424400, 493100, 397500, 337600, 157200, 242399, 421400, 403700, 397600, 239400, 416300, 441200, 354000, 354000, 315599, 151100, 269600, 255900, 270900, 422299, 488800, 240300, 376900, 318200, 302800, 262600, 238000, 277400, 122130, 405500, 455999, 353400, 287200, 269800, 292400, 290200, 357200, 417600, 519200, 544600, 318600, 345200, 352600, 283500, 172500, 168299, 427900, 332800, 84900, 307400, 418600, 214700, 280000, 407700, 366200, 114300, 86100, 393700, 239000, 341900, 358600, 413900, 382700, 412600, 344099, 375500, 372100, 428300, 365400, 436500, 390500, 288300, 403900, 301000, 376599, 470700, 460900, 374300, 246200, 333300, 349700, 106600, 514099, 341100, 364700, 229730, 388600, 339000, 466700, 491500, 419400, 478100, 398200, 372500, 493300, 498400, 396200, 445300, 367700, 164300, 487500, 402400, 388300, 496400, 405900, 453400, 376000, 470600, 440900, 396300, 469500, 523200, 275700, 457800, 474700, 409900, 167700, 425800, 402200, 418300, 441599, 426700, 364200, 435800, 433000, 427500, 432600, 485600, 464000, 431000, 365300, 440200, 467200, 467200, 384000, 433200, 425500, 437500, 474500, 424600, 416500, 421100, 429000, 451200, 429099, 507200, 430000, 414000, 431599, 475600, 385700, 465100, 454900, 450700, 425800, 451900, 449099, 420500, 447200, 480400, 389200, 244500, 430400, 437900, 430000, 452800, 452800, 300300, 449000, 348100, 313200, 425100, 227200, 448900, 421700, 446400, 445000, 494000, 453100, 394799, 223600, 460500, 352500, 448200, 457800, 500200, 424099, 456300, 428300, 464500, 225400, 109600, 461700, 465200, 381200, 449300, 461200, 418900, 445500, 451599, 440600, 465800, 380400, 464400, 469200, 469600, 248600, 462700, 451700, 441800, 303800, 469300, 496800, 463900, 459000, 291500, 458100, 459300, 450100, 469799, 393900, 465000, 448300, 222700, 203400, 461300, 455000, 447700, 456599, 444700, 463100, 310000, 470800, 457000, 442600, 459600, 458900, 457900, 447000, 457200, 456100, 456000, 446400, 453700, 463100, 472700, 514300, 440400, 440700, 449900, 452800, 454799, 463100, 166300, 452000, 462400, 244600, 460400, 462100, 463200, 466700, 447900, 465700, 132900, 465300, 461400, 469799, 461700, 449000, 473500, 505700, 450300, 461100, 469099, 457100, 469000, 462200, 499099, 509000, 476800, 456000, 484099, 424200, 399900, 192900, 463600, 453700, 306300, 75800, 467700, 458000, 202200, 464300, 456900, 467500, 474099, 481300, 447400, 430600, 453200, 456200, 461300, 322500, 479300, 465400, 401599, 475900, 429200, 466500, 456900, 480000, 441900, 280300, 475200, 466500, 472400, 465100, 462600, 476100, 473200, 470100, 463700, 468800, 459700, 482500, 232300, 409799, 464200, 476900, 466200, 295700, 325500, 464099, 471500, 377900, 472700, 350600, 464500, 159700, 468300, 473500, 470500, 462400, 467299, 470900, 462700, 452200, 470100, 469700, 506800, 461200, 460900, 466000, 525900, 463500, 448500, 534900, 462800, 465400, 454300, 465300, 308000, 471800, 486300, 474400, 237100, 500300, 319100, 186400, 469099, 452900, 468800, 152200, 372500, 432600, 448400, 444200, 354300, 131400, 461799, 436300, 456800, 326800, 469400, 449000, 273800, 467200, 272300, 466300, 471300, 473600, 464099, 425100, 236000, 456900, 510700, 223500, 457500, 457100, 375300, 464500, 320700, 221200, 467100, 458200, 388900, 463500, 472600, 454600, 462200, 533800, 455700, 461500, 491400, 459799, 465200, 407400, 497700, 296800, 456300, 193500, 465800, 427299, 507400, 407000, 392299, 449900, 506900, 451800, 414299, 374799, 456800, 98600, 463500, 453300, 407700, 455600, 459099, 441400, 382100, 426900, 462400, 49000, 133200, 459799, 451800, 464600, 456400, 407400, 419700, 456300, 236500, 500900, 437800, 439500, 435900, 465500, 477700, 451599, 240400, 438900, 438500, 464600, 494700, 369600, 427800, 483600, 437400, 482400, 456800, 102700, 401700, 478500, 425900, 147600, 212500, 482800, 478700, 465900, 458800, 458900, 464400, 459900, 444700, 394000, 211700, 459099, 455200, 434000, 195500, 482600, 435700, 282400, 323900, 386599, 257900, 86800, 504000, 337000, 301300, 299500, 390400, 376300, 390200, 488000, 271100, 426000, 283800, 456700, 459500, 314100, 344000, 352400, 274700, 404700, 471200, 336200, 336300, 510000, 283600, 484500, 280700, 248900, 447800, 379200, 486200, 294000, 337200, 383800, 305400, 305900, 338200, 378200, 366900, 405700, 313600, 372600, 320300, 303900, 365200, 365400, 349700, 284000, 339600, 322700, 334000, 334799, 261800, 369900, 290300, 283400, 309200, 319600, 343800, 359500, 242600, 360300, 334400, 361700, 488500, 315600, 470800, 311100, 506800, 374400, 295800, 344300, 343800, 322400, 359500, 369300, 138600, 376500, 127700, 383100, 351300, 336599, 435700, 355200, 368800, 392100, 366800, 351200, 353100, 364600, 396400, 401400, 393200, 342600, 89900, 330200, 405400, 364600, 479600, 279400, 307100, 407900, 265200, 422100, 283500, 422400, 367200, 302700, 352800, 347100, 373600, 379400, 373400, 505500, 383600, 411800, 428000, 385600, 380800, 278900, 366700, 54500, 384700, 443500, 362200, 362200, 248000, 441800, 388300, 374000, 386700, 400000, 347800, 293000, 409300, 315100, 395800, 390600, 373100, 384000, 392700, 401500, 380800, 380700, 475500, 391900, 454099, 429099, 389099, 373300, 444200, 369200, 427299, 373500, 414600, 359400, 491200, 433700, 370200, 372700, 357200, 287600, 281900, 390900, 445700, 430500, 423300, 375800, 362000, 445000, 441100, 415900, 415600, 356200, 441200, 447600, 279400, 437800, 355700, 423500, 437800, 443000, 395700, 393900, 467500, 445100, 438300, 391300, 442100, 443200, 438800, 448500, 433800, 444300, 458400, 460100, 450500, 468000, 469400, 447800, 421000, 278700, 446599, 452000, 472000, 411900, 459000, 454700, 452600, 448500, 466200, 441400, 449200, 451400, 466700, 456599, 467100, 444099, 442700, 325700, 460400, 443900, 462700, 452100, 304500, 442299, 98600, 438800, 464000, 219899, 435300, 316200, 334600, 265200, 458700, 295400, 441400, 454600, 503600, 444600, 179800, 361500, 467100, 472500, 463400, 486599, 458200, 410100, 372900, 476700, 391599, 441800, 458500, 401800, 401700, 433700, 462299, 431900, 433100, 486100, 203800, 257800, 464099, 452299, 141800, 456800, 459099, 430800, 309900, 454300, 520600, 352700, 460900, 448100, 455400, 466300, 459400, 461500, 456100, 448100, 470600, 445200, 462400, 306100, 451200, 361000, 449700, 461500, 375500, 457299, 480099, 458200, 226800, 446500, 466500, 459900, 452000, 468400, 451300, 470700, 465800, 184800, 456100, 463000, 465300, 447200, 467700, 474000, 269800, 441200, 451500, 463900, 444200, 446000, 346500, 444000, 444799, 457700, 459799, 464300, 376300, 345000, 242200, 217100, 466400, 457100, 473400, 462900, 457500, 424400, 461100, 191500, 458000, 460500, 319000, 265700, 188500, 344900, 458400, 461700, 462200, 462100, 93699, 458400, 438100, 458500, 457000, 455300, 322900, 250100, 215900, 465200, 474900, 459099, 457000, 109100, 459600, 457100, 479900, 459500, 442800, 459900, 468400, 458500, 457200, 162700, 462800, 460300, 457600, 462400, 461400, 472400, 447400, 466700, 452299, 328700, 266600, 476700, 456599, 443900, 480800, 471700, 452900, 429900, 334600, 461700, 463400, 469600, 376100, 457800, 464099, 429099, 466300, 457200, 459200, 463000, 68100, 465800, 460500, 455400, 241600, 466100, 462100, 467100, 469600, 452700, 461800, 459400, 460800, 465100, 461000, 506900, 470400, 465700, 465700, 457000, 467000, 316400, 464700, 462000, 465200, 470500, 472299, 471700, 459799, 462700, 466500, 465900, 466700, 468300, 469700, 463500, 463700, 462500, 465200, 462800, 414000, 473000, 280800, 461800, 465200, 462500, 470000, 468000, 459300, 460900, 464400, 456200, 457100, 463700, 449600, 463700, 466100, 460700, 465500, 466700, 457500, 465900, 453000, 467200, 462800, 466100, 467100, 456500, 463000, 478300, 463200, 462400, 465200, 293600, 460500, 463100, 465000, 361500, 464700, 464900, 465700, 469300, 173400, 454700, 454700, 406300, 482500, 417200, 509400, 461100, 459799, 410300, 452200, 471300, 455200, 429000, 444500, 495100, 473400, 445800, 470400, 534200, 466300, 449300, 454099, 385700, 468500, 451100, 453700, 470700, 476599, 472400, 467000, 370700, 474000, 451800, 458700, 352800, 460500, 475000, 466800, 262000, 465700, 202200, 466100, 463200, 473500, 163700, 275600, 462000, 471000, 323000, 471400, 461500, 321700, 462400, 359500, 473200, 358400, 463100, 464900, 467800, 458500, 453400, 463800, 464300, 451900, 467500, 472900, 117600, 456900, 465800, 205600, 460600, 474500, 471200, 473300, 270800, 309600, 467700, 473900, 196100, 469700, 469099, 453900, 468600, 464500, 467500, 472800, 471500, 464099, 470700, 459000, 464200, 478300, 461300, 466599, 456000, 454600, 470500, 465600, 441200, 477900, 263100, 464099, 469799, 464799, 434300, 340900, 413100, 395300, 475200, 138900, 468300, 490700, 460700, 349600, 303000, 465300, 294700, 451900, 470600, 464700, 234500, 460100, 349600, 468500, 431000, 470800, 312100, 454900, 363600, 465800, 468800, 449099, 143500, 281200, 322100, 318600, 460600, 461700, 468900, 475400, 283100, 458400, 466400, 466400, 335100, 461900, 353600, 459400, 476300, 455000, 461200, 455900, 461200, 465500, 291600, 416300, 461599, 358300, 415700, 295100, 465000, 395100, 427400, 461000, 542900, 343400, 463400, 311200, 264500, 305500, 480500, 444900, 480300, 456200, 493000, 446200, 429700, 494700, 450600, 441100, 452299, 133300, 251600, 462299, 461100, 474200, 444400, 181900, 460200, 478100, 471700, 459400, 238700, 351400, 461200, 239100, 437100, 475500, 507500, 463400, 462299, 462900, 437500, 458400, 452900, 457000, 458900, 466800, 388800, 473700, 459300, 459200, 453000, 469099, 471000, 458600, 275500, 336200, 293500, 381100, 380000, 401700, 479000, 417600, 463600, 327800, 380400, 474300, 461400, 399500, 328500, 127000, 467600, 468600, 457600, 475100, 357800, 420900, 453900, 348300, 413700, 466800, 422500, 400400, 293700, 287800, 455400, 406100, 418200, 473900, 462800, 441200, 475000, 426400, 468000, 460300, 459500, 267400, 457299, 452800, 466800, 181400, 459000, 454200, 456000, 479200, 466100, 454400, 464700, 339300, 458400, 461900, 426100, 388300, 485000, 457000, 462400, 354500, 288400, 316400, 460600, 462200, 305900, 455000, 382000, 446800, 375600, 464200, 455900, 465200, 467800, 444700, 460500, 200200, 425200, 126400, 453500, 76800, 151600, 514300, 464400, 460300, 433000, 220300, 453600, 437100, 442600, 468300, 395300, 212600, 278700, 448400, 404500, 241900, 435599, 441200, 418600, 383800, 451700, 526300, 459600, 465700, 319200, 382500, 451300, 364000, 397200, 470400, 485500, 461100, 474900, 461100, 468100, 467600, 407600, 434099, 441700, 432100, 401200, 455600, 456100, 450200, 444700, 457500, 470400, 462500, 358700, 459700, 454200, 452200, 454600, 261100, 442400, 392299, 375600, 456000, 449300, 449500, 421100, 463700, 473500, 454400, 457100, 447200, 278600, 342700, 445100, 387800, 457800, 141700, 451900, 263500, 298400, 448000, 268200, 461000, 405500, 393500, 461000, 453200, 332000, 175430, 431300, 192500, 389799, 465100, 386599, 443900, 429300, 223500, 380000, 389099, 446000, 425100, 409900, 432400, 429500, 453600, 231100, 465500, 443000, 453700, 471900, 441599, 445400, 447900, 164300, 413300, 400200, 278600, 453600, 448500, 443700, 434400, 465600, 92899, 450700, 469200, 466000, 132700, 427800, 308300, 490400, 331700, 463900, 446400, 454200, 352900, 450500, 405000, 444200, 432299, 391900, 343400, 427400, 441300, 441300, 459300, 447700, 401300, 421599, 439300, 441900, 391000, 434700, 467700, 107400, 439600, 458300, 449500, 432800, 446500, 324400, 446400, 440200, 330100, 452600, 435500, 434700, 442700, 443800, 363800, 332700, 450700, 400800, 333800, 448300, 332299, 441300, 445900, 437400, 456200, 451700, 463200, 336800, 434300, 409700, 440600, 464400, 157100, 407800, 343300, 431200, 240400, 343000, 447500, 467700, 458500, 297800, 432900, 510700, 363300, 457400, 360400, 437000, 460300, 474300, 442200, 451000, 464799, 466599, 447000, 461000, 450700, 461200, 442800, 441000, 469600, 448600, 335500, 443300, 87300, 450200, 427400, 463300, 447299, 313700, 441700, 458000, 469300, 466300, 250500, 164200, 379799, 379400, 414900, 459799, 436000, 444400, 446100, 395500, 429600, 467800, 443600, 456500, 167900, 424000, 465600, 452100, 459300, 459799, 426700, 247000, 459600, 355000, 467400, 452800, 435100, 458200, 514799, 435800, 455100, 463300, 458900, 278900, 462600, 454400, 473600, 446200, 460800, 445300, 466500, 472200, 463200, 477100, 286800, 438400, 457600, 452800, 464900, 455000, 459300, 449400, 484700, 477200, 320300, 453200, 352100, 460100, 450100, 457900, 365900, 466000, 445700, 453600, 470000, 485600, 185200, 276300, 457600, 469000, 459000, 458700, 358200, 446000, 284600, 455100, 150600, 463100, 468100, 302300, 462600, 477299, 356100, 361900, 422600, 445400, 459900, 474600, 406500, 456300, 465300, 454000, 448000, 467500, 465700, 274100, 229300, 440200, 467400, 443600, 338300, 279000, 465500, 465600, 461800, 409099, 466300, 463500, 208200, 509799, 489700, 452600, 457299, 385900, 456200, 455700, 474300, 461700, 466800, 470600, 449000, 462700, 352600, 343200, 384799, 473300, 466400, 400500, 162700, 333500, 491300, 476900, 456500, 453700, 419799, 410400, 413500, 211200, 260200, 258600, 460700, 389300, 520200, 440300, 195500, 448900, 475300, 453200, 455900, 466300, 456200, 453000, 461100, 296400, 527300, 458700, 212900, 457100, 380800, 492000, 449300, 319000, 345500, 181500, 316700, 466800, 281000, 365100, 408400, 413600, 457000, 454900, 463100, 263800, 353500, 496500, 354500, 318800, 455400, 454799, 468800, 318300, 174300, 505700, 460100, 352700, 261500, 200900, 504799, 539700, 391599, 390900, 471800, 404799, 464000, 468100, 343600, 204400, 501000, 479200, 497800, 481000, 346800, 395000, 415000, 429000, 488600, 491000, 341100, 465000, 345900, 447200, 481500, 516200, 455200, 498300, 392100, 444900, 238000, 452700, 477299, 449000, 478100, 479300, 458100, 476900, 462500, 483700, 498700, 460500, 448200, 213900, 454799, 392700, 453000, 443500, 383100, 461099, 456200, 450500, 472400, 50800, 460600, 468200, 323300, 471100, 462000, 332500, 462200, 458800, 383400, 468200, 454000, 274600, 450500, 461300, 411700, 139500, 464799, 457500, 462200, 345200, 378000, 418900, 466900, 448000, 336200, 333500, 343100, 351800, 394799, 349700, 447900, 493200, 463600, 102500, 459799, 469799, 388600, 449799, 349200, 446200, 459700, 247100, 471500, 464700, 435300, 464400, 449799, 518000, 455100, 476300, 450200, 437100, 476400, 332900, 133100, 463700, 505100, 466900, 325300, 470500, 264700, 456000, 474300, 444400, 125900, 445800, 457800, 398000, 434900, 362900, 457700, 457000, 447100, 251400, 246200, 459900, 466500, 416800, 385200, 440300, 418700, 456000, 450000, 394900, 453500, 443300, 467600, 436100, 462100, 282700, 441300, 341700, 426800, 464300, 437200, 467100, 304500, 448100, 455500, 499799, 462299, 467299, 263300, 268000, 448200, 343200, 451599, 448300, 483599, 445000, 416000, 459400, 267800, 428600, 460800, 79600, 390100, 449799, 400100, 450300, 467900, 199000, 327900, 467600, 452700, 454700, 398200, 444099, 448300, 210400, 455400, 500600, 244100, 449799, 420400, 350300, 451400, 455000, 452600, 455700, 412800, 427500, 451100, 397500, 415600, 481400, 349699, 443500, 427800, 399700, 408300, 455500, 437500, 444700, 432400, 462100, 441800, 463900, 185799, 458200, 437500, 392200, 411000, 434099, 289700, 409400, 459099, 449799, 422500, 445400, 424799, 458200, 420600, 412500, 412500, 470500, 458400, 456000, 455400, 393500, 449000, 433500, 366700, 458200, 434300, 474400, 447200, 439600, 441700, 443700, 196500, 336800, 434200, 492100, 166000, 468000, 453200, 442500, 285900, 442900, 442600, 435600, 317000, 465200, 440100, 446100, 452700, 435500, 453500, 424799, 470400, 236100, 479600, 442000, 448200, 348100, 444600, 444900, 416599, 379700, 443000, 243800, 302000, 447200, 422000, 454799, 166700, 230799, 335000, 445600, 362900, 336599, 441599, 167700, 450100, 448500, 185000, 316300, 453700, 315300, 428000, 332900, 344600, 435500, 467600, 464900, 374700, 194500, 442900, 438800, 374000, 452100, 446200, 390800, 304700, 384200, 362400, 436200, 419600, 438400, 437700, 460500, 437900, 440700, 445400, 349400, 459400, 455100, 445600, 463900, 451200, 475300, 456200, 462000, 484900, 358500, 459000, 517100, 438800, 400500, 450700, 460400, 444600, 465600, 447299, 446000, 254200, 447400, 528300, 468000, 444000, 295800, 453100, 325400, 449500, 434099, 438100, 446700, 445300, 442200, 480400, 437500, 445300, 438300, 370800, 453300, 441800, 309600, 381200, 456200, 367600, 448800, 443700, 526200, 468400, 453300, 456400, 524400, 461500, 380300, 456599, 458300, 455600, 461000, 87200, 343800, 435700, 416599, 399400, 273700, 456500, 464500, 466100, 476000, 402000, 462600, 480600, 429500, 450100, 428200, 458200, 458300, 188200, 470700, 456400, 459400, 175500, 460500, 457200, 341000, 350400, 453400, 194830, 106000, 460200, 458600, 443700, 459400, 458500, 313900, 447900, 459200, 133900, 434799, 431599, 161000, 455200, 326200, 214100, 360800, 456599, 469600, 466000, 142100, 458000, 457400, 462299, 343900, 386700, 342800, 293100, 461000, 156300, 222700, 346900, 418900, 288500, 201700, 454099, 223299, 399799, 452299, 459200, 467100, 504200, 408100, 149400, 466300, 469600, 451800, 462500, 340500, 472800, 455200, 244800, 462200, 140900, 453600, 474700, 427100, 465700, 389799, 334000, 360600, 470300, 254000, 464600, 469400, 461100, 470600, 350800, 471599, 188700, 386200, 401900, 288700, 461500, 460600, 500100, 468900, 456500, 380900, 143000, 296400, 341400, 458000, 300100, 467500, 367800, 450700, 476200, 410700, 62000, 464799, 465200, 468000, 474400, 465100, 461599, 423200, 469400, 467100, 481700, 477800, 349500, 463800, 485700, 381800, 474500, 464300, 466599, 471599, 477200, 113300, 493400, 311900, 274700, 478300, 420600, 165100, 302200, 471200, 475600, 433400, 262600, 480100, 398300, 482000, 454500, 264100, 302400, 513500, 365400, 454600, 333500, 333800, 400000, 423900, 108400, 399000, 447100, 469200, 433400, 457400, 460300, 476599, 516800, 476100, 457400, 450200, 467000, 451200, 454200, 450900, 449700, 463300, 465400, 200400, 462200, 230600, 470800, 470600, 486800, 463300, 120200, 473000, 469799, 436900, 370300, 445600, 340400, 446900, 407100, 448000, 458200, 448300, 453000, 463500, 464900, 456800, 469000, 455500, 352299, 486700, 452600, 475800, 212200, 89100, 476500, 471200, 430500, 470400, 204800, 456300, 335800, 364600, 440400, 389500, 380500, 506700, 354900, 464700, 278100, 461100, 303600, 219100, 397500, 359900, 449500, 445800, 468300, 451200, 459700, 316799, 212399, 425900, 452400, 441400, 461800, 198800, 458900, 351200, 469500, 437400, 476400, 427200, 419000, 448800, 345100, 297400, 479400, 188700, 447900, 459099, 461900, 451300, 465200, 428500, 350600, 452800, 181000, 456500, 119400, 452700, 444099, 462100, 439099, 467200, 458000, 290200, 505300, 455500, 387100, 464200, 458200, 248299, 451100, 463800, 140500, 110900, 157000, 434900, 391700, 204100, 343500, 263900, 458100, 456100, 509300, 200030, 462900, 390900, 451800, 251300, 461400, 348600, 449700, 430900, 442299, 434600, 452200, 375500, 273700, 487900, 460800, 471100, 472700, 319500, 244300, 349700, 461000, 342000, 480900, 478600, 450600, 424900, 410900, 565100, 387800, 382100, 428000, 456300, 424799, 471000, 451200, 474700, 432500, 407000, 451599, 462400, 470200, 476000, 452500, 466200, 442900, 495500, 442500, 124800, 352400, 462600, 444799, 457500, 463100, 404900, 523500, 397700, 232700, 397299, 481900, 457000, 474200, 403300, 482800, 375700, 450300, 262200, 314400, 417200, 450500, 156700, 465600, 466500, 326200, 441700, 462200, 502800, 433700, 92300, 243100, 275000, 372100, 533400, 460300, 454000, 364500, 249700, 456200, 435600, 470700, 190600, 358500, 434300, 456900, 138500, 401400, 368700, 465200, 399900, 439799, 446599, 454000, 426900, 470800, 364900, 459400, 441500, 471500, 483200, 490300, 452600, 462900, 461800, 442800, 464600, 450500, 418100, 456000, 440300, 445900, 427100, 240000, 191600, 452000, 344300, 458900, 457900, 289300, 513200, 204800, 446900, 449799, 440500, 183600, 461000, 475000, 445400, 503799, 438400, 444500, 447299, 488200, 388800, 442900, 439700, 473300, 394600, 460800, 452299, 438700, 465500, 470800, 354400, 116900, 377600, 195300, 341300, 515100, 245600, 415600, 528700, 188700, 163700] + }, + { + 'id': 'Min height width', + 'label': 'Min height width', + 'values': [5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, -5909, 102666, -16955, 135803, -28000, 124758, 5137, 113712, 42910, 126039, 135736, 46100, 54920, 113880, 100220, 91860, 52140, 104500, 110480, 82230, 69120, 136490, 97950, 79780, 44390, 23330, 86870, 1469, 130450, 114629, 184720, 32180, 56400, 131980, 58430, 63240, 59330, 58640, 29810, 11790, 25690, 13330, 39900, 70460, 160410, 55770, 25179, 18490, 27650, 79830, 40630, 16900, 41369, 118770, -2760, 190000, 119920, 85020, 73980, 49120, 51200, 41940, 71030, 51970, 75200, 80390, 70520, 69910, 119636, 40720, -16800, 48360, 70910, 66170, 54730, 66650, 70930, 41940, 8919, -8201, 48240, 50080, 44120, 70290, 74640, 94410, 30920, 56720, 187800, 170140, 45710, 124420, 59660, 90450, 24040, 129420, 173100, 45500, 37120, 34300, 52610, 59770, 89350, 59000, 32820, 23020, 26780, 19180, 19350, 22770, 37900, 56130, 21080, 41360, 49010, 16290, 14480, 23140, 90940, 39390, 43869, 138650, -19100, 34470, 34630, 12036, 102620, 24060, 14260, 9980, 71280, 5559, 19670, 141580, 37160, 9199, 23650, 17750, 22180, 99940, 7589, 17540, 16790, 5080, 34200, 7580, 25040, 7300, 13060, 17520, 6419, -1381, 41910, 10830, 4100, 20210, 188340, 5209, 12970, 14960, 15149, 11780, 105870, 10600, 16640, 9179, 9750, 7869, 9400, 9640, 34300, 10610, 7640, 12680, 21000, 76650, 12170, 13130, 6909, 19100, 16490, 13150, 12810, 7980, 97129, -2571, 12800, 13140, 14170, 59090, 4630, 5150, 6889, 6050, 13490, 3860, 10260, 13930, 3160, -1600, 40730, 88140, 11680, 11560, 10280, 5390, 9440, 131340, 7570, 144740, 60570, 12210, 142160, 8029, 70330, 6570, 8240, -1070, 5180, 75360, 64130, 4979, 73200, 7920, 2460, 3080, 60010, 7470, 10450, 2600, 99590, 134120, 5400, 1179, 76180, 4209, 3650, 38840, 8910, 4250, 14170, 3999, 76350, 4860, -15060, -341, 128230, 2330, 5859, 22060, 44500, 770, 4769, 1039, 539, 53740, 5130, 5729, 13939, 5580, 48450, 1110, 6199, 164570, 179370, 4720, 6339, 12740, 3569, 6740, 4089, 13730, -641, 2360, 8390, 12540, 5500, 4519, 5790, 8100, 4159, 6329, 7200, 2510, 2199, 9430, 1130, 7710, 11010, 11439, 9619, 8699, 5529, 99290, 6729, 7670, 60320, 8769, 3379, 4350, 2020, 10470, 2929, 187500, 5399, 839, 2790, 2430, 9999, 1970, 2979, 8070, 2849, 5110, 5679, 979, 4449, 2559, -410, 829, 3989, 279, 11130, 130020, 63780, 48590, 15020, 59370, 174670, 44850, 4510, 57900, 3340, 5340, 6710, -1150, -4031, 4400, 1400, 13450, 5500, 3909, 133800, 1570, 2959, 38050, 6499, 37810, 599, 1560, 1949, 38340, 66110, 13230, -1020, 9730, 3350, 2790, 8729, 109, 1679, 1690, 2440, 1910, 5659, 43820, 80340, 739, 47080, 1709, 164110, 58980, 5069, 1810, 16480, -1550, 81400, 3139, 133160, 2669, -821, 3349, 2360, 4120, 1960, 4129, 25520, 3660, 2260, 2959, 6350, 6830, 559, -3540, 5040, 62340, -8401, 4570, 6469, 14420, 3509, 172060, 4749, 38850, 3860, 167900, 1540, 59530, 176210, 2949, 13930, 819, 132560, 74890, 34410, 5559, 41260, 102000, 174330, -17380, 10730, 8950, 144260, 2560, 24580, 6370, 80, 22540, 2060, 1019, 160, 3180, 11580, 88900, 10470, 6260, 73860, 3119, 2980, 158220, 4309, 30660, 68780, 5040, 3770, 99260, 1980, 1970, 6829, 2289, -20080, 2310, 9650, -2251, 2529, 2530, 14700, 3959, 166700, 3599, 150930, 3459, 20810, 6590, 55690, 22690, 5139, 69, 6480, -12630, 37400, 9400, 186250, 9540, 10830, 14040, 9070, 4760, 7700, 56650, 11310, 4790, 194180, 128610, 6400, 7109, 2769, 9170, 14430, 104370, 9179, 178490, 1839, 3649, 9690, 20490, 339, 3980, 9289, 97370, 16590, 13480, 3039, 9209, 108480, 29490, 14640, 22230, 2340, 15880, 155060, 121920, 2909, 27250, 163260, 172970, 2660, 18100, 5159, 5870, 3790, 2880, 4320, 12500, 56360, 125710, 17810, 19190, 106000, 83140, 42550, 104300, 56000, 102609, 49720, 119469, 171680, 32940, 81140, 57710, 46010, 47900, 12410, 51430, 52000, 71890, 38220, 59550, 30110, 25690, 60750, 41920, 42970, 122470, 41700, 24520, 36670, 43590, 28380, 65420, 20490, 46900, 74830, 23260, 30570, 53800, 48360, 44400, 28940, 38850, 55090, 44390, 117250, 26040, 38180, 40279, 21509, 40690, 43770, 23870, 34920, 35680, 47920, 34530, 10209, 38060, 36900, 172090, 22500, 41440, 48970, 51970, 40759, 32670, 29570, 8320, 32190, 36220, 26469, 7490, 50070, 16550, 52680, -14320, 18900, 55380, 31810, 30419, 92140, 31910, 29040, 139770, 30299, 117280, 30630, 29670, 36720, -13690, 31170, 24230, -7440, 28120, 27790, 26429, 26000, 27230, 25920, 76240, 30360, 186670, 44830, 116240, 24560, 29890, 95180, 82150, 26890, 70680, 23220, 173160, 18330, 29520, 47580, 40140, 29100, 28250, 26230, 27280, 29190, 15910, 28300, 15970, 18410, 23929, 86500, 26960, 195790, 23360, 15049, 27500, 25880, 29740, 14950, 18950, 98230, 19830, 21830, 33440, 109480, 16040, 61550, 23600, 20700, 24970, 25500, 19860, 15920, 25010, 26910, 14280, 18950, 15430, 12709, 22380, 78950, 4990, 32920, 110000, 23040, 16230, 26429, 10009, 14770, 27599, 21410, 19900, 149800, 159730, 25800, 9250, 16530, 14280, 99670, 28780, 7340, 11060, 14120, 7850, 123859, 27430, 9960, 32360, 11210, 104469, 14710, 11570, 14290, 95429, 18660, 4369, 9129, 9270, 17570, 8890, 6709, 9220, 7710, 11250, 6599, 5370, 3400, 4270, 179, 2290, 4540, 13700, 93360, 59470, 8529, -851, 19020, 4139, 5289, 2350, 6269, 990, 8240, 7010, 8050, 1210, 4560, 1259, 9949, 8110, 64180, 3909, 6729, 2690, 5280, 150810, 6709, 148720, 32080, 2289, 171240, 6690, 79710, 122870, 39720, 3809, 122739, 30200, 5390, 5709, 8730, 118730, 74280, 13320, 5130, 4419, 3000, 3679, 9389, 63420, 6690, 95570, 20350, 5090, 44240, 120660, 29440, 2999, 35740, 63700, -1540, 155930, 145400, 5790, 939, 175990, 3370, 5030, 8129, 69630, 3980, 19400, 27460, 10430, 25930, 6300, 3050, 5360, 4789, 5870, 16930, 1360, 3990, 3170, 79640, 12030, 125269, 7050, 3980, 42910, 9890, -19210, 25280, 170010, 10610, 3749, 3420, 10510, 2749, 7790, 1890, 27759, 140190, 5329, 3289, 6660, 82810, 7319, 1650, 37550, 8889, 7769, 499, 9579, 6610, 35280, 11940, 7629, 2200, 1180, 7390, 159380, 29129, 172160, 108520, 1330, 5769, 1170, 2310, 4110, 54490, 2309, 90020, 1360, 3090, 147650, 79810, 53960, 148120, 5100, 1890, 669, 4730, 190970, -570, 14780, 2929, 3439, 8649, 133040, 96310, 110079, 9729, -151, 4940, 2090, 151720, 6060, 2439, -1190, 2919, 34290, 5939, 2029, 12110, 15930, 175700, 5290, 589, 4910, -1241, 14340, -2690, 1250, 10480, 10930, 116080, 17710, -1590, 6629, 25540, -11360, 2330, 11860, 27210, 153740, 5040, 5950, 1549, 37630, 4259, 2010, 34760, 2959, 4410, 6640, 6889, 179130, 2920, -60, 9899, 144140, 2350, 5719, 3420, 4159, 3330, 799, 2390, 5310, 3079, 4840, 18340, 3719, 6260, 5810, 7309, 3969, 132430, 7079, 5280, 549, 2090, 22160, 1699, 5679, 2509, 2129, 2999, 2469, 4830, 4780, 3960, 3040, 2710, 2440, 2859, 32670, 1659, 9360, 4670, 2080, 4059, 1059, 2789, 5639, 3589, 1709, 5050, 6039, 3850, 13180, 2140, 2079, 6579, -1821, 1389, 7799, 1739, 5910, 1610, 5020, 1809, -721, 4659, 2929, -4720, 1829, 5420, 2709, 50380, 6510, 4900, 1380, 78330, 6539, 5170, 4370, 409, 92280, 5740, -5240, 67910, 33020, 13450, 3690, 6899, 5139, 67240, 6620, 2099, 5599, 13440, 32679, 28520, -180, 30930, -421, 4630, -641, 8349, 5080, 129, 1480, 5289, 11870, 4140, 4360, 1450, 1629, 67510, -421, 21240, 4620, 106560, 2909, 1640, 1290, 35360, 3020, 158790, 2440, 1200, -911, 186220, 88630, 11220, 2760, 109090, 1729, 2269, 30290, 3889, 28940, 1820, 28870, 2559, 1930, 3350, 2659, 9469, 690, 1270, 5479, 1309, 1579, 149430, 6060, 2289, 55039, 1910, 699, -770, 1540, 6850, 64080, 2819, 850, 166420, -441, 1869, 13020, 480, 5479, 25160, -31, -981, 2100, 1620, 7470, 2270, 2390, 5259, 10760, 5520, 13850, 1910, 4650, 26980, 5580, 13470, 1379, 4770, -2110, 67810, 128539, 59940, 48220, 5219, 184470, 1770, 699, 2079, 11750, 124680, 6210, 59900, 14120, 2260, 1140, 110020, 1779, 23809, -1401, 34390, 1970, 67430, 8870, 44820, 4270, 3970, 20880, 123800, 80690, 74260, 98010, 5329, 1080, 1170, -1370, 60700, 3479, 1419, 2499, 57480, 2859, 87760, 3290, -2181, 4539, 859, 3010, 5810, -4340, 158760, 53230, 3790, -6940, 115210, -171, 389, 54720, 81370, 9070, -12800, 102100, 3790, 140870, 125290, 66200, 5500, 7980, 26760, 13240, 4789, 14150, 23180, 8039, 8580, 8720, 6790, 144350, 118030, 4259, 9330, 4600, 7759, 166130, 1229, 6909, -1090, 5270, 118510, 139370, 4460, 115410, 8939, 1140, -9890, 1809, 5070, 6720, 8089, 3749, 72070, 8120, 5770, 6959, 106649, -31, 6090, 5920, 6360, 3400, 2849, 7780, 97370, 157360, 62720, 21920, -2180, 75390, 69, 26280, 6740, 7990, 20550, 2700, 7050, 104860, 67500, 140930, 4179, 4890, 9140, 459, 2829, 31800, 3839, 142650, 86160, 1739, 22910, 25480, 175740, 136730, 2790, 68020, 41520, -771, 2410, 7269, 61130, 47270, 539, 12740, 7960, 74870, 5390, 2690, 4800, 107590, 11250, 13799, 12540, -2471, 3520, 4869, 3750, 7290, 11580, 4570, 93740, 141260, -2510, 4790, 3800, 22599, 144230, 36850, 3710, 3459, 12609, 13720, 21469, 13280, 76830, 2449, 5709, 3969, 19, 37430, 569, 166100, 40190, 163939, 13330, 190770, 178250, 25700, -721, 4369, 8630, 147620, 19530, 16770, 16040, 869, 37960, 111130, 55470, 12310, 49370, 164270, -14760, 15730, 60470, 39740, 13420, 4970, 10200, 7700, 98310, 27540, 15350, 1490, 30840, 5699, 7070, 15000, 3360, 4649, 6919, 6340, 5950, 10680, 8300, 6199, 20900, 4570, 4429, 7540, 9350, 10410, -871, 7570, 1659, 289, 8310, 10310, 5390, 106550, 6610, 49240, 127590, 6780, 5649, 6169, 32320, 1240, -1721, 4690, 2439, 7929, 77530, 128090, 10840, 100630, 3630, 188329, 8720, 84620, 59530, 11900, 95580, 5470, 43960, 74950, -381, 47110, 86950, 66336, 92680, 82720, 60920, 1459, 38380, 17530, 5669, 141360, 135700, 29940, 18850, 3299, 14900, 59000, 17080, -541, 141500, -381, 19600, 15020, -571, 11010, 17110, 15960, 122080, 47050, 22710, 63130, 10169, 5280, 12150, 11550, 5280, 174490, 6590, 3839, 4519, 156290, 28769, 73210, -7371, 22900, 10490, 9810, 9660, 50119, 8410, 36810, 13000, 11760, 78980, 43510, 10720, 28590, 13560, 6270, 8420, 2440, 18500, 7820, 11970, 46580, 15570, 5070, 143250, 12110, 2859, 9860, 44200, 13850, 8780, 10440, 13850, 5960, -15830, 12340, 19080, 8290, 11060, 164950, 3810, 9650, 42270, 170740, 7550, 47050, 14190, 12290, 20970, 1540, 8470, 479, 2050, 15610, 93040, 9579, -1440, 107410, 15830, 23360, 9890, 97820, 22490, 7990, 1110, 4190, 76240, 22679, 12740, 28560, 3850, 29120, 16780, 2210, 2070, 13200, 5299, 1759, 1940, 17310, -20, 6679, 4910, 4949, 6390, 1370, 7520, 88400, 7240, 155250, 7090, 33940, 62660, 8009, 68800, 10009, 3970, 4819, 59930, 174750, 94460, 136080, 80230, 28080, 6040, 19670, 8119, 12180, 67460, 28320, 739, 22780, 7090, 138100, 35450, 3299, 13560, 5820, 8109, 2330, 74480, 3000, 9140, -31, 10610, 15980, 10880, -11070, 16900, 7950, 2989, 4690, 133840, 4680, 12070, 3850, 4790, 7740, 8119, 2940, 2280, 4170, 3679, 103080, 31040, 3290, 6560, 1750, 5440, 5550, 5639, 50710, -1191, 46540, 6160, 31120, 5290, 7730, 7040, 123430, 2360, 9969, 6840, 699, 13000, 113960, 65610, 2749, 3590, 3329, 6059, 104040, 7060, 174760, 4980, 166740, 579, 3500, 41860, 7109, 5370, 44670, 22580, 35230, 26020, 7019, 9689, 16860, 3870, 3509, 12830, 16580, 1130, 8240, 56830, 96679, 16279, 8519, 13779, 4509, 56250, 2770, 3750, 4310, 8500, 7010, 6570, 102840, 27770, 4400, 3700, 619, 126290, 5859, 4740, 11070, 6030, -1230, -3230, 7840, 8179, 91370, 75930, 134770, 11439, 63700, 13590, 130160, 62680, 6040, 6850, 6279, 21589, 7609, 3599, 3469, 150150, 46160, 47580, 6130, 76360, -15750, 14380, 53620, 10820, 2150, 8590, 7600, 4670, 4599, 6539, 4560, 32280, 9640, 7049, 109840, 7030, 110150, 5699, 5200, 119300, 90730, 132780, 123130, 12360, 111580, 5070, 34940, 16240, 2900, 949, 2470, 59120, 7129, 3359, 90910, 16180, 1620, 5370, -530, 169590, 146010, 8650, 37420, 68050, 126130, 104560, 2890, 300, 39230, 18150, 27519, 7760, 3370, 1429, 92090, 119149, 9929, 2479, 2150, 6709, 121649, 36730, 35990, 51330, 10270, 6070, 629, 5249, 18510, 10270, 3240, -320, 24230, 3089, 117210, 21750, 40279, 17190, 7349, 9460, 1779, 6609, 2610, 4960, 5409, 4910, 2419, 10290, 7109, 130530, 19860, 13650, 13560, -12130, 98940, -17310, 8470, 9220, 4239, 196430, 4250, 1960, 100150, 3020, 5370, 28670, 4899, 8210, 14040, 5920, 5090, 39860, 3999, 17410, 3290, 105480, 4550, 5820, 5080, 136300, 3870, 35600, 6140, 11450, 1390, 33250, 24640, 30700, 130530, 28929, 9389, 24210, -1271, 189460, 1270, 809, 108290, 9919, 27180, 1999, 109, 153130, 3790, 8969, 18390, 4769, 8749, -8780, 3630, 1690, 10960, 18660, -570, -890, 178930, 4570, 34270, 560, 2660, -2411, 136430, 12180, 4140, 9649, 140230, 4380, 4079, 16540, 57939, 70360, 6430, 9289, 2630, 52080, 51340, 5849, 6270, 14300, 29160, 42280, 4750, 8489, 5850, 39080, 3519, 6339, -410, 17860, 4819, 15920, 6989, 80760, 10780, 2259, 16490, -900, 54960, 11800, 5480, 14190, 3900, 5109, 139540, 63650, 11880, 779, 17300, 13759, -19560, 17870, 60550, 8060, 45310, 35980, 9810, 186439, 28220, 12890, 18940, 10500, 1900, 101870, 33000, 2829, 10080, 7810, 14990, 12830, 11150, 74180, 11610, -5510, 168730, 12080, 11870, 51010, 10660, 12100, 7029, 11399, -9330, 10080, 11860, 29, 8480, 2259, -6170, 9830, 8520, 37520, 26400, -911, 9440, 7189, 15620, 4100, 10450, 1490, 140990, 2060, 3139, 44210, 25770, 23100, 87670, 17110, 1519, 5420, 12470, 7930, 26280, 5479, 16890, 118140, 18870, -2140, 7170, 5970, 14490, 13030, 10540, 12540, 24710, 3859, 14440, 709, 9459, 10670, -1331, 6929, 65310, 52000, 10220, 5870, 128660, -181, 5890, 8850, 120360, 18260, 11359, 12780, 152980, 819, 8909, 10380, 4769, 9190, 3159, 11880, 1019, 80250, -2871, 8630, 5849, -701, 11160, 12569, 25930, 9190, 9520, 77590, 159430, 5500, 82810, 8159, 150100, 69350, 4390, 4850, 42190, 3150, 8220, 105090, 1519, 11399, 135670, 66470, 8450, 60900, 13540, 36730, 144100, 11530, 12100, 3100, 100860, 129860, 11510, 8860, 26500, 5639, 12170, -2270, 44410, 16120, 30179, 10200, 21850, 8809, 11399, 4620, 5800, 8129, 7480, -741, 2209, 10109, 3860, 3560, 3750, 2869, 3609, 3930, 15860, 125970, 2250, 5980, 8679, 17280, 4880, 3100, 10260, 11310, 8189, 6340, 142520, 7639, 2520, -15210, 9689, 161580, 7429, 122080, 7520, 43620, 7400, 15089, 9739, 8429, 16130, 14840, 6140, 9810, 139320, 6690, 9819, 7380, 125320, 5950, 139190, 3900, 5490, 2730, -6791, 4170, 5029, 7589, 1279, 91120, 3300, 6729, 5110, 1869, 163990, -181, 24830, 58240, 139070, 117440, 3400, 3409, 3880, 1900, 33150, 5130, 59400, 23830, 5120, 20360, 6019, 6909, 102410, 629, 3950, 8239, 184140, 6149, 10530, 16750, 85740, 8930, 46936, 177860, 5280, 4449, 11610, 4369, 5900, 111890, 10290, 3850, 137810, 6650, 6610, 181180, 23420, 83300, 168490, 42670, 7079, 4789, 4069, 168130, 4780, 9250, 4890, 104120, 40890, 53380, 120630, 3310, 182369, 51350, 54050, 18320, 49000, 116900, 7780, 55430, 25810, 4270, 5470, 2610, 8530, 83570, 144990, -191, 50870, 15120, 9100, 6899, 5369, 4339, 95940, 7060, 177700, 14580, 62420, 44680, 36320, 82790, 11240, 29640, 5350, 21309, 8799, 7690, 6179, 909, 138260, 3059, 90480, 87110, -4101, 75260, 2719, 4339, 2549, 2070, 6279, 50830, 179020, 115620, 1230, 5409, 7520, 4549, -1141, 13970, 3320, 18240, 190990, 3740, 2349, 3870, -101, 8480, 8560, 16630, 1389, 4679, 1150, -531, 6899, -571, 1109, 3489, 3940, 4239, 6350, 989, 6099, 184330, 4029, 136120, 11500, 5270, 4470, 103190, 37550, 5079, 4369, 44680, 79400, 3469, 127120, 219, 5580, 77630, 122940, 7959, 34560, 4220, 56650, 53650, 71330, 26640, 141620, 83130, 19550, 7979, 71320, 7180, 10129, -4100, -11900, 2429, 36700, 15280, 3340, 11399, 6780, 13950, 10560, 7040, 2330, 161490, 10209, 74500, 10610, 16930, 5230, 4339, 193090, 1389, 1530, 11840, 111649, 8630, 70180, 11470, 42450, 5239, 7730, 8089, 9149, 5310, 26140, 6969, 3950, 8270, 19130, 8300, 4419, 59429, 35930, 166590, 1579, 669, 17340, 3090, 176800, 5580, 29690, 103940, 31200, 46640, 151130, 9630, 7710, 4560, 127080, 7350, 26160, 153950, 80670, 4330, 4460, 6990, 9869, 40380, 5870, -2880, 103500, 21309, 9840, 22010, 1879, 155440, 5320, 9159, -240, 10530, 7170, 8580, 62590, 10290, 38390, 154760, 4079, 86430, 10380, 709, 2680, 7610, 5500, 12500, 39100, 5030, 122840, 7719, 193080, 4229, 4550, 590, 9099, 1969, 4239, 130730, 32719, 5840, 95030, 1640, 1160, 77050, 6460, 32010, 190340, 182590, 160430, 86380, 43179, 113420, 47640, 151990, 1530, 52040, 30700, 41736, 4560, 118050, 47880, 168909, 8310, 2580, 47640, 29900, 64940, 27820, 15440, 20410, 71090, 2509, 9179, 2210, 3400, 5400, 133700, 91300, 8799, 27180, 5639, 28280, -6090, 31850, 59980, -25100, 112600, 26320, 29020, 9090, 29070, 8429, 9599, 1850, 19120, 13390, 12529, 11810, -130, 5140, 7759, 3960, 14660, 3279, 19110, 182550, 57820, 10169, 13660, 14190, 4360, 19180, 14070, 5679, 129820, 70070, 1580, 4700, 4869, 73520, -1301, 94730, 14280, 147660, 72330, 14620, 14260, 166400, 959, 1859, 58280, 41330, 2109, 15690, 32590, 195880, 24560, 56380, 17240, -18780, 5540, 9860, 116910, 177079, 5770, 41940, 990, 168950, 89070, 22450, 7950, 187390, 23220, 63840, 19090, 50460, 24420, 19780, 15800, 21300, 13850, 31820, 20840, 21370, 12700, 14140, 10550, 8199, 8609, 890, 12330, 17620, 4809, 18490, 7769, 12850, 13460, 15880, 176340, 145900, 8440, 1930, 4149, 6859, 83570, 6909, 83379, 15069, 4069, 29480, 93600, 8350, 3169, 3969, -21580, 13939, 13870, 7739, 2300, 19620, 12230, 12100, 549, 13010, 9090, 7509, 14090, 5739, 3050, 107120, 127899, 6969, 133470, 158020, 16530, 121510, 12350, -10570, 182369, 152200] + }, + { + 'id': 'Min width diameter', + 'label': 'Min width diameter', + 'values': [98453, 319366, 234498, 455411, 391333, 147711, 479081, 208910, 124041, 344954, 280876, 501789, 368624, 98453, 429823, 234498, 170419, 391333, 258167, 479081, 319366, 124041, 455411, 280876, 147711, 368624, 315981, 203423, 170419, 318081, 237211, 321023, 258211, 260481, 341011, 429823, 273989, 296489, 285589, 302889, 235581, 214989, 388889, 392489, 334089, 432089, 423289, 358489, 235589, 244989, 223823, 229989, 389489, 262681, 219489, 226389, 312723, 344923, 401889, 464489, 387789, 283223, 254689, 233089, 397989, 370889, 374289, 256489, 409489, 410789, 294711, 380711, 203011, 280789, 288211, 234211, 284989, 353623, 479081, 143423, 399489, 313089, 249823, 282889, 172623, 287689, 170419, 325623, 389789, 348189, 299689, 275089, 215523, 226323, 377489, 412389, 416623, 497789, 309389, 340989, 270623, 294889, 104423, 121723, 339623, 334589, 132823, 386011, 345723, 206623, 256481, 408911, 289011, 149881, 117823, 317823, 208589, 319789, 286723, 428089, 426289, 425789, 320589, 321881, 344989, 398989, 306581, 412089, 305823, 284489, 373989, 282189, 302723, 442889, 429989, 343389, 253681, 315889, 267123, 174289, 379823, 319089, 345489, 170419, 447589, 305189, 436189, 387023, 446989, 439189, 366089, 472989, 491189, 465789, 368289, 416289, 263023, 195389, 451889, 368389, 351889, 458989, 318823, 413989, 347389, 360823, 406189, 361589, 430589, 481589, 254689, 422489, 361823, 379689, 297389, 380689, 363089, 383189, 409289, 388989, 424089, 397789, 401389, 386989, 346911, 450089, 427789, 391389, 345789, 402689, 429389, 434989, 351789, 468289, 365381, 402489, 436689, 372081, 382889, 384289, 392689, 411989, 440111, 390523, 393789, 376389, 397089, 495889, 335489, 424289, 414889, 409289, 389889, 408189, 412189, 384489, 402189, 433789, 379489, 271389, 392989, 401189, 390989, 410889, 415389, 381389, 409089, 449389, 317089, 387689, 312189, 409489, 448489, 405089, 405389, 449489, 364611, 424189, 221489, 418989, 302823, 408589, 413189, 389023, 439689, 417089, 389289, 420789, 262889, 172589, 420789, 419989, 409989, 405689, 418289, 410389, 406689, 408289, 407089, 423789, 409289, 423189, 406389, 423189, 320489, 418489, 410189, 417189, 216823, 424089, 387123, 395681, 412389, 239011, 416489, 418489, 417389, 429989, 393289, 419689, 406789, 332089, 327089, 419589, 414389, 413389, 413089, 403389, 420889, 261489, 424189, 412189, 402889, 426389, 417789, 415589, 404889, 418789, 413189, 415489, 405789, 408689, 418789, 437489, 474489, 399689, 403689, 414389, 415589, 416789, 422489, 196889, 411489, 424089, 217881, 423089, 418989, 421289, 422589, 411089, 422489, 211411, 424789, 415389, 426889, 417489, 411789, 430089, 395023, 411089, 417289, 428689, 415989, 423989, 420289, 387223, 394923, 432489, 390181, 439989, 313523, 490589, 115023, 398923, 399881, 236123, 180089, 399323, 343723, 190789, 421389, 415389, 405981, 427289, 432089, 403789, 381789, 420289, 414789, 418689, 408789, 436089, 422189, 318323, 437789, 420689, 420789, 411189, 437289, 435389, 286689, 444489, 418989, 437489, 422289, 418889, 440489, 427689, 354023, 418889, 425389, 414689, 444189, 208589, 446389, 418389, 483989, 421689, 412689, 328989, 423089, 427689, 339989, 425289, 381789, 421389, 227189, 353123, 426989, 428289, 418189, 425589, 427189, 420489, 432589, 428189, 426189, 396223, 421289, 421489, 420189, 435811, 422389, 446681, 486789, 421089, 426089, 422589, 422689, 435189, 359323, 485289, 433189, 351789, 387423, 322489, 304689, 426289, 420489, 423589, 146223, 398889, 397981, 406189, 418481, 408789, 241489, 395589, 398489, 419289, 425189, 426189, 405281, 141123, 398281, 229389, 422189, 426589, 428189, 420989, 386989, 262789, 421089, 476189, 232189, 413589, 412989, 494589, 422689, 269481, 223989, 426389, 368711, 397811, 418989, 429089, 414489, 417889, 426211, 410689, 425289, 445289, 415489, 421489, 370789, 387223, 416789, 412789, 284489, 351223, 399689, 472889, 415889, 290923, 407389, 393123, 410989, 348089, 359789, 419789, 218289, 427389, 417489, 370389, 395381, 417189, 400789, 389289, 388689, 420889, 171989, 146311, 419789, 388981, 421089, 396381, 370489, 484089, 418989, 362889, 388423, 392289, 400889, 408889, 419389, 365023, 413889, 277089, 407889, 403989, 421389, 461689, 432989, 409889, 455389, 412489, 440389, 426989, 188189, 483589, 436689, 405289, 247189, 330089, 441189, 453789, 425189, 418089, 415889, 374611, 417589, 409789, 330223, 276689, 408981, 406181, 501789, 211389, 413323, 455411, 277789, 375689, 314623, 274711, 188989, 452011, 366389, 300689, 285689, 316823, 333689, 320523, 501789, 282889, 345623, 283289, 442689, 440889, 318289, 330589, 341089, 271123, 325823, 452589, 316089, 323889, 477281, 289589, 390923, 265789, 261489, 353223, 310711, 501789, 210223, 325789, 288423, 284289, 302889, 326889, 380323, 338389, 394989, 294989, 339689, 302889, 288089, 334089, 346589, 329989, 270589, 317489, 271689, 315189, 314789, 383889, 337789, 270389, 248381, 303089, 302189, 320089, 334089, 134211, 337889, 313589, 333089, 452889, 308089, 443289, 305989, 448989, 338789, 291989, 296981, 317589, 362389, 336689, 344389, 211089, 353789, 173989, 289523, 325089, 316589, 370689, 331089, 338489, 329189, 340589, 322889, 323489, 335789, 372489, 376589, 423389, 316189, 209089, 318489, 481389, 334189, 467889, 246023, 334289, 384889, 274989, 396589, 409189, 391489, 342589, 290989, 338389, 319789, 348289, 352489, 346989, 449511, 345689, 318823, 395089, 350689, 351489, 285081, 339189, 179889, 355189, 411289, 334789, 332989, 210389, 409289, 354289, 426489, 353489, 370489, 325389, 348989, 302423, 320289, 367789, 358789, 344089, 356789, 360189, 365589, 352689, 354689, 445989, 358289, 423489, 392689, 358989, 404289, 400889, 348589, 498789, 342389, 380489, 258523, 458689, 353711, 343789, 339689, 320789, 387789, 392489, 364789, 407289, 398489, 387989, 430089, 313281, 404389, 404189, 379589, 372289, 435189, 422489, 410189, 248189, 400689, 413089, 316723, 401089, 409889, 447489, 360189, 426089, 406489, 399089, 356089, 402889, 401689, 399589, 408689, 396289, 402789, 417089, 416789, 407089, 421989, 425889, 404389, 384789, 315189, 464089, 390781, 425289, 380589, 416389, 412889, 407289, 407089, 420889, 401389, 408689, 412289, 421689, 367811, 422189, 406289, 402689, 288611, 394981, 402489, 418889, 409989, 407689, 400689, 176589, 424989, 419889, 336389, 392889, 341689, 410089, 240589, 415689, 343681, 425789, 412889, 467689, 405489, 161523, 385989, 435589, 432489, 421589, 445789, 414989, 367889, 386589, 438889, 443089, 415289, 416889, 397389, 482189, 416389, 418789, 421389, 453789, 440189, 301489, 303411, 423889, 405389, 254889, 413089, 417489, 343111, 323489, 410989, 501789, 324189, 425489, 428489, 414789, 423289, 418189, 419889, 415089, 418489, 426189, 400889, 419089, 330389, 416489, 442089, 409289, 418989, 366689, 420889, 413889, 438989, 342689, 409689, 424289, 393881, 415689, 425289, 411889, 426889, 450189, 262889, 414489, 419889, 354223, 490689, 429589, 430289, 243289, 329923, 412089, 417789, 334023, 404689, 325989, 408389, 404489, 412789, 413989, 425889, 496989, 317489, 362189, 263589, 421489, 416089, 429089, 418689, 414689, 411181, 416689, 214589, 412189, 416889, 420289, 285689, 171189, 449589, 416789, 416889, 416089, 420489, 146123, 410489, 404989, 414489, 413389, 417289, 408389, 286689, 263989, 429489, 429289, 417389, 411889, 191589, 419189, 412389, 433689, 415589, 431889, 419389, 424489, 424689, 427489, 277789, 421889, 413889, 415689, 414189, 430389, 423689, 400289, 431989, 416489, 395989, 217689, 429689, 416489, 423389, 351423, 428489, 418189, 409689, 444389, 420389, 423289, 425289, 361489, 415189, 419689, 417189, 423189, 414689, 419389, 423889, 176489, 422589, 413389, 418789, 330389, 422289, 421589, 424589, 405481, 408489, 415789, 392181, 419689, 421989, 419389, 485389, 428589, 426189, 425689, 417689, 425089, 400489, 425989, 420989, 419289, 426889, 428481, 427789, 418989, 418689, 422489, 422789, 423089, 404781, 428989, 421189, 420389, 418689, 421389, 419189, 398089, 429189, 224189, 420089, 349023, 420189, 425189, 424889, 418389, 417889, 419689, 414289, 416389, 421289, 415989, 419389, 421989, 420989, 416989, 421889, 418789, 421389, 411689, 422689, 421589, 421689, 419989, 414189, 419489, 427989, 418489, 421589, 349723, 283989, 420689, 421789, 419989, 390489, 425389, 424089, 424089, 423689, 196989, 413389, 401189, 428689, 474589, 380289, 471889, 421789, 418389, 432389, 411589, 427789, 413789, 393389, 431989, 483589, 427589, 431489, 423989, 500489, 419189, 410289, 411989, 330489, 423989, 408889, 419089, 429389, 436189, 428289, 350523, 342311, 427989, 355423, 416589, 412189, 416689, 431389, 421889, 232189, 422589, 302889, 422389, 417789, 426889, 290589, 306489, 427589, 428189, 381889, 427489, 417089, 292889, 419889, 333389, 429589, 332089, 419189, 420489, 425289, 414189, 416089, 417889, 419089, 409989, 422689, 428989, 198489, 416189, 421889, 191389, 415689, 429789, 424489, 429389, 210289, 316989, 424589, 429289, 281881, 423189, 425089, 420589, 422989, 423989, 449189, 427089, 424589, 419789, 426589, 420089, 420089, 435889, 420189, 432189, 414589, 422289, 426689, 424289, 421989, 438989, 209089, 418989, 429089, 415889, 459689, 423389, 427389, 394589, 435589, 261089, 424089, 447789, 415989, 303289, 376989, 425689, 295789, 419589, 427189, 419389, 284589, 414989, 316689, 420789, 372511, 427089, 323489, 417089, 355589, 424089, 427089, 423989, 198789, 303889, 342189, 364689, 419489, 415989, 424089, 428489, 283789, 414989, 421589, 422789, 337989, 418189, 392189, 415889, 428589, 412389, 415189, 339723, 420689, 414189, 402189, 423489, 346923, 292189, 445311, 229489, 418889, 401589, 467089, 424089, 490789, 396789, 420889, 404089, 334889, 242823, 441789, 404989, 465189, 423389, 408511, 413289, 382281, 460389, 411989, 401589, 411889, 210289, 312489, 420189, 424489, 433789, 404189, 242111, 414489, 440689, 424689, 418089, 298689, 447089, 419189, 295689, 397389, 431389, 431981, 418689, 421089, 423589, 396889, 415289, 485089, 418589, 418089, 428189, 452289, 428089, 418889, 418589, 412189, 426789, 428289, 419989, 316089, 450189, 297589, 349589, 321589, 431889, 434089, 394989, 424389, 274889, 347289, 431789, 422289, 462189, 341789, 153111, 425989, 427889, 374011, 430189, 302489, 404789, 410389, 447289, 457189, 399681, 396689, 352281, 423389, 373489, 410889, 428589, 412589, 427489, 418689, 400089, 497489, 428089, 422389, 381011, 421189, 282089, 415889, 407889, 425789, 222889, 377911, 421789, 376011, 431489, 423589, 412089, 422289, 286889, 423989, 420089, 479389, 490189, 437889, 414889, 419789, 320789, 382489, 294289, 417689, 419189, 255689, 422589, 350089, 412989, 404489, 420289, 414689, 423089, 421589, 437489, 414089, 308789, 418889, 224389, 420489, 199089, 268289, 479081, 416989, 418089, 392489, 310589, 427489, 406089, 411389, 423089, 383189, 261489, 273089, 413689, 406089, 353089, 369389, 409489, 411381, 372389, 418589, 492089, 423789, 427789, 365689, 357389, 420289, 307889, 377389, 430789, 402711, 430789, 433189, 419289, 406881, 428389, 361289, 395989, 401789, 388789, 298823, 413089, 413489, 410389, 406289, 398981, 423489, 424089, 302189, 412889, 392981, 415689, 340923, 310289, 400689, 392389, 460889, 415989, 407289, 408089, 405589, 418389, 403281, 411889, 366011, 407489, 297489, 424889, 408389, 444489, 414489, 268489, 413589, 288589, 299489, 412789, 305989, 420089, 401189, 422289, 413589, 457689, 367289, 124041, 437611, 161211, 379881, 420189, 302023, 342523, 385089, 307189, 474789, 367389, 418289, 377789, 373789, 401411, 397989, 405189, 315789, 372211, 415789, 422589, 425489, 404689, 415689, 417189, 219989, 413289, 371689, 281489, 417089, 405989, 408289, 397289, 424989, 198889, 409889, 427389, 424589, 222889, 409089, 325689, 438489, 295789, 428889, 408689, 417189, 349589, 365311, 392689, 409789, 395189, 424989, 259723, 388589, 423889, 407189, 419089, 408589, 350389, 390789, 398589, 406089, 387989, 402089, 427089, 180289, 403689, 414189, 412189, 431789, 413289, 225611, 386681, 406289, 275189, 387089, 399389, 405989, 402889, 407189, 489289, 275689, 413289, 394089, 462389, 408289, 323289, 335923, 410889, 411089, 410389, 413089, 416989, 278289, 401689, 460389, 330023, 416189, 195689, 372489, 309189, 391889, 205623, 307889, 407889, 422689, 415889, 317389, 407989, 411423, 337189, 342323, 334589, 405989, 415689, 431089, 407789, 408789, 420189, 422389, 394981, 413989, 409989, 419689, 399289, 398889, 425089, 408589, 372789, 402389, 171289, 409889, 414389, 486189, 407689, 326789, 380981, 415089, 428589, 486489, 374289, 166481, 474989, 412489, 393989, 419389, 385381, 404589, 410989, 416189, 410589, 422389, 419989, 394181, 241789, 412289, 400081, 419189, 418589, 421689, 378489, 258989, 415789, 306389, 421089, 416689, 402989, 400281, 461489, 404789, 393581, 419889, 416889, 360389, 420989, 397381, 432289, 402889, 422389, 405589, 423389, 428989, 421089, 435989, 334989, 423389, 413889, 412189, 397581, 413389, 418289, 407389, 496689, 407981, 309389, 412189, 327589, 418889, 410489, 418389, 445489, 422189, 408089, 390681, 424789, 455789, 234189, 281689, 390581, 426889, 415489, 418189, 392681, 405189, 412189, 412989, 254389, 416989, 425789, 284189, 423689, 438089, 347089, 328989, 410489, 425589, 420589, 439889, 372189, 413089, 422689, 420489, 417989, 422489, 428389, 269489, 263989, 408989, 430589, 409989, 282689, 274289, 422089, 423289, 419689, 365789, 427689, 424089, 247389, 499089, 428081, 408789, 410589, 470889, 415189, 413389, 394711, 421489, 419089, 421089, 409389, 424989, 395089, 295523, 479089, 394011, 490789, 361889, 227189, 270023, 454389, 416581, 393281, 429889, 376689, 361789, 365089, 303289, 242189, 241989, 420489, 419189, 462289, 406989, 178589, 412589, 432289, 414889, 416789, 425089, 413789, 366011, 419189, 266989, 498389, 419289, 260389, 417489, 447289, 454789, 406789, 388789, 386489, 250989, 390489, 434189, 291611, 313089, 394389, 379389, 412789, 408289, 419089, 260589, 302489, 457189, 396689, 273989, 409589, 390381, 422089, 443889, 257689, 473289, 454589, 369289, 332489, 241189, 465889, 501789, 380489, 356289, 456589, 360189, 421089, 423489, 339511, 261289, 469489, 436989, 457289, 443689, 422289, 381489, 380181, 435489, 456089, 454089, 281489, 424289, 306689, 410089, 440389, 474989, 434489, 458889, 395723, 420289, 210989, 423889, 368323, 411189, 434989, 441689, 413689, 437189, 398981, 372723, 458589, 424889, 361311, 261781, 429189, 353289, 420189, 381089, 437389, 394889, 346123, 412589, 431389, 176489, 418289, 424189, 372289, 428589, 421089, 303089, 420789, 420689, 343389, 428589, 411889, 251189, 406789, 433689, 362889, 173989, 423289, 416589, 420989, 436789, 326089, 406789, 427389, 412289, 276889, 309289, 310389, 326789, 485489, 322489, 409889, 476689, 415489, 226189, 414089, 424689, 453889, 340623, 319989, 399789, 412689, 346489, 429889, 428089, 405889, 423089, 411289, 467589, 411489, 432889, 414189, 385481, 430489, 270689, 248489, 422089, 501089, 421189, 266189, 421889, 347489, 421989, 433389, 334323, 197489, 401989, 414989, 339681, 449389, 383189, 417489, 419889, 401489, 192611, 232389, 419289, 427089, 380789, 362189, 437989, 372289, 417889, 408289, 383989, 409589, 401389, 420889, 406189, 420589, 233589, 399889, 371189, 387989, 373811, 405889, 419789, 301189, 412789, 413989, 472889, 419789, 426689, 349389, 198323, 412989, 283989, 422789, 392481, 417389, 416089, 431289, 398481, 249689, 417989, 401981, 197389, 366589, 415889, 295423, 413789, 423789, 236089, 302789, 424489, 415989, 415689, 360889, 409489, 412289, 217989, 420689, 451889, 360489, 414989, 382089, 347689, 415189, 420789, 389781, 420789, 350089, 387989, 416189, 343489, 372989, 439189, 283489, 382781, 386589, 387589, 384789, 406889, 398389, 403889, 399589, 419789, 404289, 372511, 264889, 413189, 391389, 386689, 387089, 409789, 321089, 375689, 413589, 407589, 385089, 405489, 402989, 416989, 387889, 491389, 381089, 422189, 419089, 415089, 423889, 353489, 412389, 397389, 336689, 415189, 400389, 429689, 409189, 402089, 391089, 402489, 192689, 333789, 395589, 383123, 229189, 349623, 411889, 403289, 353189, 414189, 334223, 399989, 423989, 347623, 400689, 408989, 410089, 395889, 409189, 386989, 425589, 253289, 431489, 402489, 406289, 287789, 408189, 410089, 393489, 333889, 404589, 258889, 414489, 404789, 462689, 416189, 253789, 235289, 278889, 402289, 351889, 279289, 401589, 204889, 403589, 412789, 258089, 327089, 415289, 319789, 392389, 312489, 444789, 398489, 434789, 421789, 430189, 262189, 406689, 399189, 346789, 410389, 411089, 333489, 289689, 346589, 337989, 397789, 392289, 398689, 400789, 418589, 394789, 400489, 404989, 289189, 414689, 418689, 401189, 421189, 407289, 433089, 412689, 419489, 458189, 417381, 367911, 482989, 398989, 365989, 407989, 416789, 407189, 431689, 407889, 404389, 342589, 407389, 491589, 404889, 405889, 409989, 413489, 398989, 409589, 432589, 396789, 414889, 407389, 402489, 453489, 332423, 403389, 399689, 468589, 412889, 403589, 253989, 464589, 415289, 442181, 404789, 400889, 489489, 414689, 410089, 414489, 492889, 415989, 379211, 412789, 418489, 413689, 369711, 180889, 283589, 413489, 429389, 500089, 336389, 412789, 421689, 423989, 432789, 385289, 421489, 501789, 405489, 407589, 400189, 417589, 418689, 224689, 425489, 413289, 421389, 301389, 420289, 421489, 299289, 386389, 415489, 170419, 217189, 418989, 416289, 407689, 417089, 417789, 374889, 410889, 416289, 180981, 392289, 388689, 281989, 433589, 356789, 326889, 350089, 416989, 406181, 424089, 246489, 415989, 420289, 420889, 399589, 376889, 341989, 361489, 417689, 278089, 206289, 347289, 387589, 276789, 255789, 414989, 211489, 328311, 409089, 418089, 423689, 471489, 448089, 228889, 419689, 480089, 420589, 425789, 287789, 433089, 340423, 280389, 423189, 255789, 421989, 498589, 425989, 459589, 426889, 285389, 335389, 430289, 207689, 427789, 431889, 398281, 425689, 445189, 429189, 211989, 427689, 343789, 306189, 417589, 418389, 460289, 425089, 415989, 381489, 259589, 359589, 282489, 416689, 243589, 426289, 309189, 418089, 434589, 378389, 182889, 422389, 421289, 426089, 428789, 427989, 424189, 390489, 424889, 425989, 438289, 432089, 297789, 416489, 442689, 329889, 433389, 422389, 427289, 426889, 366823, 232489, 431781, 399589, 173411, 367123, 374089, 127923, 279289, 408281, 435089, 361023, 281789, 439089, 462881, 437589, 412989, 281489, 374389, 481189, 323481, 411589, 335289, 332289, 425489, 402389, 179589, 437489, 397581, 409281, 462589, 395281, 424489, 404081, 462789, 433489, 450789, 418989, 424389, 393081, 413989, 418289, 413189, 401681, 421489, 303889, 426689, 240789, 436689, 397111, 448489, 421389, 249889, 428889, 425489, 400389, 437289, 406489, 357989, 411089, 401289, 333423, 419489, 408889, 415289, 422689, 447389, 417089, 427289, 417089, 314489, 451789, 409589, 496489, 177489, 185889, 432989, 426089, 399389, 381511, 325789, 368611, 307889, 376011, 425789, 386389, 492489, 475489, 304689, 423189, 351989, 422289, 268189, 316289, 386711, 306489, 334223, 404889, 433089, 447989, 419089, 250589, 252789, 398689, 415389, 416689, 416989, 295389, 417589, 302189, 423189, 399489, 439089, 385989, 436889, 411889, 327889, 404189, 438989, 207489, 410989, 412689, 417989, 411689, 424789, 391789, 334789, 410489, 239389, 417589, 248989, 386781, 328323, 415889, 399789, 423089, 415389, 369489, 499589, 414389, 437489, 396681, 412189, 216911, 410189, 380723, 269389, 227889, 254489, 480989, 384989, 254589, 336389, 363889, 412489, 466389, 501789, 170419, 421189, 467289, 456989, 368689, 423689, 291989, 454389, 341823, 465389, 343623, 421389, 341689, 284889, 446689, 423989, 427689, 430789, 262789, 321789, 345411, 423789, 311989, 442389, 393023, 395689, 409289, 424989, 501789, 457789, 355589, 409589, 418889, 406089, 434489, 413789, 431289, 403589, 368889, 394781, 428689, 424089, 436389, 413189, 424189, 410189, 455989, 414689, 243289, 357589, 427089, 411189, 425889, 398481, 350281, 499089, 349989, 304589, 421089, 438989, 414789, 434089, 431589, 364823, 424489, 417989, 357189, 331489, 381589, 418189, 260789, 420189, 422189, 328989, 438489, 417689, 477889, 419889, 221989, 199189, 269989, 334389, 473589, 419389, 417189, 413981, 375989, 415089, 432389, 425889, 301289, 399089, 386581, 418289, 263889, 373589, 382389, 417181, 402189, 417589, 348023, 423789, 399789, 440289, 342589, 435389, 416089, 439789, 454389, 458289, 413789, 425689, 415889, 407489, 437589, 407689, 386889, 417089, 405289, 412189, 393989, 364389, 276789, 413389, 286489, 416289, 418189, 316089, 479689, 221989, 415089, 406089, 423989, 209789, 423289, 433089, 401089, 437589, 404389, 411089, 407389, 446789, 355589, 407489, 403789, 428289, 354689, 423889, 412689, 404889, 425389, 428289, 414589, 173789, 329089, 220711, 456589, 492489, 309689, 377289, 477489, 314089, 206411] + }, + { + 'id': 'RF block', + 'label': 'RF block', + 'values': [1417, 23377, 3376, 33336, 5635, 10812, 6898, 21273, 2484, 35126, 5626, 51096, 7384, 22020, 18912, 52449, 7498, 87528, 11359, 107154, 9197, 18159, 13115, 41120, 4254, 53966, 17129, 14957, 12469, 12882, 19875, 23547, 16325, 15238, 15452, 31817, 18210, 16237, 13815, 24070, 14163, 10748, 16292, 12787, 19559, 10597, 34781, 25859, 23121, 7331, 19298, 17056, 18788, 12009, 8997, 9280, 10990, 9825, 13690, 14547, 15443, 14758, 22429, 9324, 13396, 10915, 12615, 13307, 16842, 12533, 11312, 29347, 2923, 28796, 42332, 12953, 14401, 16151, 23973, 4730, 21716, 13116, 13175, 15085, 8140, 14046, 15629, 13231, 5612, 14571, 14929, 12812, 9048, 10826, 20129, 17258, 12673, 11513, 12391, 14423, 10741, 14543, 4797, 6770, 12516, 15056, 26071, 38770, 15137, 15072, 11241, 26828, 8765, 10555, 10704, 13486, 6364, 10951, 12683, 21652, 27201, 21344, 10776, 9748, 11037, 12370, 8567, 13685, 11766, 12085, 11494, 20165, 13118, 14030, 13022, 10399, 14657, 11485, 10530, 13011, 6136, 10941, 24564, 2983, 44046, 27024, 13288, 11442, 25304, 11719, 10889, 42292, 21241, 13750, 11650, 12963, 7752, 11368, 12729, 10642, 9786, 12557, 11922, 10954, 10880, 9807, 11606, 10332, 11490, 12266, 8847, 11958, 9329, 11618, 30498, 9096, 9656, 10880, 12137, 10590, 30171, 10776, 12029, 10048, 9194, 12699, 11935, 10320, 12246, 10999, 11670, 12919, 10448, 28090, 9996, 11446, 11869, 11452, 11130, 10617, 10938, 10938, 61633, 9401, 10986, 10264, 11382, 26443, 7246, 10959, 10865, 10461, 15205, 10010, 11370, 10761, 9628, 10072, 15113, 15277, 10752, 15445, 10415, 10409, 11365, 42807, 10732, 80687, 14568, 10607, 25736, 10835, 25227, 10372, 10690, 10861, 9204, 24356, 9578, 10690, 16420, 32922, 9966, 10328, 22516, 11073, 10370, 10319, 16053, 12519, 10850, 10016, 23430, 9967, 10409, 16565, 33216, 10086, 11852, 10717, 71528, 10854, 6473, 9864, 24531, 10169, 10465, 13817, 8117, 10114, 10539, 9383, 9575, 9905, 10607, 10809, 12302, 11300, 17273, 19981, 10379, 62047, 32661, 10668, 10740, 11887, 10168, 10328, 10606, 5848, 19699, 9904, 10606, 12471, 10735, 10454, 10221, 11269, 10282, 10788, 10518, 13610, 10157, 12402, 12469, 10341, 11117, 11692, 11407, 11290, 10950, 11411, 10684, 15902, 9235, 11594, 10388, 10673, 10287, 11358, 10456, 21224, 11029, 9757, 10623, 20290, 11303, 10606, 10576, 10914, 10215, 11150, 10688, 20300, 10648, 10158, 9969, 10490, 9674, 14900, 8394, 58012, 9555, 18938, 12074, 10625, 16410, 18293, 8646, 7452, 10486, 10598, 10851, 9883, 9527, 9921, 8487, 12350, 21204, 10475, 33939, 10793, 10449, 12448, 11840, 16981, 9941, 9714, 10921, 17966, 13494, 13501, 9559, 12461, 10527, 10273, 12408, 10142, 8618, 10065, 10490, 19855, 11973, 6992, 27078, 9865, 22933, 10190, 39964, 15056, 10890, 10469, 9225, 9722, 22231, 10448, 16940, 8739, 9933, 10792, 10162, 10820, 10476, 10596, 15300, 10848, 10490, 10626, 11052, 11152, 9908, 10688, 10853, 23939, 10974, 10706, 11293, 25292, 10575, 44141, 9329, 42453, 11111, 33703, 9989, 14744, 29684, 10627, 12450, 10102, 10804, 22365, 15455, 10235, 17927, 28090, 22636, 5696, 10830, 11452, 37616, 10548, 14079, 2381, 9319, 5708, 10278, 10270, 10173, 10438, 10466, 14781, 11824, 13649, 11169, 10106, 10054, 48407, 10727, 8452, 10180, 11032, 9142, 27478, 10124, 10562, 10836, 10135, 7096, 9831, 11865, 10439, 10077, 10337, 10278, 10402, 40924, 10160, 24221, 8787, 12698, 13555, 20043, 9006, 10211, 30486, 10615, 5012, 13470, 11561, 21404, 11943, 35820, 10150, 10799, 10569, 10388, 18464, 10494, 10739, 17119, 10382, 10994, 10169, 10365, 10862, 10219, 35420, 11482, 36677, 10085, 9303, 10751, 26201, 9832, 9444, 11268, 16820, 24669, 11580, 10429, 13545, 31487, 14811, 28689, 13605, 22274, 13142, 15556, 39192, 11083, 28305, 22002, 32055, 11237, 14968, 15304, 10818, 14371, 9237, 10504, 11672, 15811, 20320, 13030, 18281, 37483, 10853, 18766, 33670, 11700, 25359, 13903, 19952, 17043, 18835, 21038, 13206, 10850, 13772, 8348, 14495, 25290, 14003, 13966, 12454, 16773, 15792, 14666, 12615, 18555, 20326, 13386, 16211, 11108, 12505, 18943, 13578, 13475, 9963, 13037, 24033, 10640, 25696, 8173, 12725, 9708, 9863, 12975, 12783, 29488, 10613, 15552, 10566, 9981, 11013, 10682, 10087, 12383, 11656, 10325, 10872, 8027, 11261, 11077, 38056, 10047, 9527, 9601, 12561, 10987, 10731, 10944, 6680, 11525, 10922, 10432, 38982, 12574, 19619, 12819, 8162, 9543, 12403, 9836, 14314, 22537, 11423, 11359, 16214, 12020, 11313, 9979, 10532, 11140, 5538, 11040, 10342, 7274, 11035, 10156, 9986, 10486, 12454, 12438, 24463, 20432, 20455, 12397, 37736, 10196, 18212, 15145, 18863, 13024, 13364, 12974, 41227, 11856, 11346, 11326, 12760, 10202, 15894, 11309, 22422, 17922, 9380, 11075, 11609, 9989, 21795, 16305, 10791, 18100, 10980, 12215, 10666, 10339, 7981, 12100, 10235, 28922, 10339, 11453, 15440, 24216, 8614, 14903, 11618, 10720, 10714, 11399, 10649, 10249, 11125, 11523, 13787, 10415, 12882, 10920, 11001, 23505, 19807, 12172, 76180, 10338, 10975, 8062, 13561, 20564, 11107, 9966, 8921, 34621, 36878, 11835, 10960, 11871, 10982, 29514, 10178, 10481, 11149, 10573, 9197, 34702, 15114, 11222, 7482, 11016, 28924, 9036, 11100, 12007, 30205, 10454, 10890, 10902, 10595, 10095, 10696, 10249, 10609, 10740, 10824, 10277, 10679, 10296, 13965, 9912, 10483, 9972, 10735, 19105, 24162, 10498, 9856, 11457, 10418, 10479, 9695, 10405, 20038, 21024, 10611, 10964, 10095, 18471, 10126, 11042, 10546, 13961, 9864, 10287, 10254, 10350, 36948, 10205, 19478, 16141, 10222, 32500, 9865, 19020, 32054, 7968, 10325, 26167, 15826, 10497, 26223, 10784, 11040, 21312, 13074, 11326, 10699, 11514, 10271, 9270, 27080, 11929, 29848, 13399, 10618, 16773, 38775, 15158, 10308, 16630, 24280, 10359, 26577, 25968, 11063, 9358, 24236, 10131, 10633, 8785, 16274, 10153, 17928, 10168, 12024, 15155, 10751, 10514, 10726, 10694, 10684, 12918, 10318, 9723, 10353, 18212, 11901, 35670, 10645, 10501, 14751, 11704, 5960, 21709, 33016, 11319, 10692, 9730, 11579, 10545, 10898, 10450, 16733, 20856, 10557, 10411, 9420, 31288, 35500, 10552, 7849, 8744, 10903, 9795, 9018, 10362, 11398, 11504, 21077, 9900, 19523, 22921, 48955, 10100, 35563, 17163, 10109, 10710, 10407, 10174, 10338, 19927, 10088, 11713, 9719, 10242, 37731, 15195, 6232, 41049, 10615, 10017, 9755, 10709, 14637, 9291, 11864, 10109, 10156, 11304, 67519, 17390, 17379, 12079, 10161, 10612, 9842, 15579, 10903, 9928, 10148, 10154, 16966, 10889, 10372, 12307, 13177, 26663, 10878, 9647, 10531, 9319, 13014, 9437, 9204, 12344, 11695, 29491, 4829, 9900, 33272, 14803, 6452, 10605, 11949, 14380, 41594, 10764, 11066, 10315, 13599, 10388, 10160, 22538, 10492, 10394, 11021, 11273, 16408, 10459, 9505, 11608, 27802, 10337, 10946, 10642, 10364, 19852, 9766, 9477, 10783, 10463, 32639, 33506, 10877, 11257, 11148, 11070, 10769, 32854, 11405, 10836, 9867, 10488, 14866, 10453, 10822, 10211, 10304, 10483, 10395, 10455, 11100, 10595, 10385, 10249, 10315, 10299, 14743, 10506, 4196, 10680, 8481, 10569, 10217, 10535, 10788, 10380, 10104, 10496, 10774, 10578, 12092, 10172, 10273, 11082, 28496, 10138, 11213, 10182, 10541, 10214, 10813, 10209, 9657, 10418, 10325, 9225, 10075, 10889, 8608, 11322, 11055, 10799, 10054, 22351, 34451, 10954, 10801, 10028, 10797, 10584, 8069, 23265, 19284, 10490, 12889, 11179, 10694, 23407, 10668, 10530, 10576, 33861, 16659, 18867, 10082, 16290, 9883, 14526, 9639, 10930, 10400, 6394, 10245, 10304, 11994, 10994, 11345, 10426, 8470, 17899, 10053, 16420, 10516, 29232, 10200, 10599, 10119, 14293, 10478, 27110, 10359, 9926, 9912, 29435, 17805, 12276, 10674, 26997, 10445, 20195, 9146, 10524, 10816, 10555, 10744, 10242, 10180, 14829, 10046, 11402, 13681, 9995, 10387, 10157, 10482, 15997, 21537, 20617, 7234, 19940, 10347, 9837, 10492, 3567, 15063, 10527, 14404, 26219, 9845, 10367, 12283, 10012, 11008, 16150, 10090, 9801, 10182, 10385, 11210, 10227, 10945, 10796, 12408, 10596, 12523, 10445, 10863, 15001, 11714, 4158, 10011, 11102, 18453, 25567, 34427, 21636, 17312, 11486, 25894, 10305, 11143, 10014, 7083, 29212, 11225, 13217, 12442, 10534, 30505, 18992, 9916, 9305, 9562, 14432, 10474, 15954, 11336, 14433, 10782, 10858, 13947, 13731, 16533, 18216, 23681, 32935, 9827, 10190, 9891, 12630, 10233, 10130, 10387, 15376, 10256, 24143, 10237, 9739, 10317, 9752, 8255, 10923, 8741, 37789, 61374, 8664, 4220, 34907, 3366, 9820, 18920, 28985, 11698, 10181, 82710, 10549, 34749, 25408, 11746, 16455, 10624, 17395, 12460, 11048, 12144, 12643, 13238, 11049, 10607, 10713, 16579, 22372, 10607, 11766, 11282, 10549, 22312, 9792, 12057, 9784, 10705, 21263, 39010, 10601, 20597, 10461, 10502, 8825, 10079, 10800, 11227, 20574, 10297, 28465, 11264, 10799, 11484, 32910, 10132, 10895, 21699, 10646, 10735, 10696, 11264, 19742, 42988, 41859, 10492, 5759, 24954, 10411, 13437, 11267, 5603, 10173, 10822, 11230, 33464, 17149, 11761, 10849, 11071, 10266, 10318, 5839, 14954, 10101, 39692, 29152, 9676, 12924, 11540, 43420, 30908, 9929, 23278, 17192, 9964, 10193, 20560, 27021, 19244, 9997, 11196, 11353, 14331, 10630, 9783, 10959, 14011, 21597, 12489, 10930, 19611, 10617, 10366, 32400, 5912, 12172, 32577, 65364, 44139, 10069, 10473, 10503, 9310, 33098, 10077, 10394, 10412, 5522, 12512, 10444, 11968, 23134, 20539, 10636, 10680, 9865, 17915, 9652, 57471, 17323, 19811, 12337, 19754, 25944, 18475, 9532, 10535, 20382, 26345, 13869, 12280, 12403, 10090, 14846, 17309, 11379, 11821, 18237, 46284, 7399, 12253, 21048, 14545, 12262, 14172, 11900, 11608, 23811, 11756, 12709, 11665, 13314, 11359, 11199, 13162, 11013, 10641, 10930, 11373, 16875, 10709, 14663, 19210, 9117, 10354, 10345, 10785, 33407, 11203, 9776, 22824, 5670, 9550, 10557, 11541, 8667, 41163, 10187, 17357, 76115, 10894, 10300, 14510, 15094, 9959, 9200, 10324, 8811, 10727, 15676, 34492, 11302, 30983, 10239, 27184, 11148, 16012, 13382, 11702, 18726, 10832, 16952, 24133, 9454, 21152, 22064, 5202, 29716, 8219, 18975, 10078, 11633, 10604, 9357, 25145, 82471, 25294, 13270, 8653, 20891, 41040, 11945, 9080, 25991, 8592, 26568, 12760, 9918, 11163, 25627, 12672, 15235, 18263, 11658, 12806, 11580, 10176, 11538, 10923, 11015, 18276, 10587, 10847, 10852, 18896, 14635, 16942, 18271, 8292, 12197, 11126, 11489, 14929, 9764, 15179, 11765, 10865, 25110, 10109, 10387, 15412, 11745, 10938, 10866, 7458, 11852, 31513, 11403, 16621, 11869, 22140, 27762, 11317, 10083, 11296, 18886, 12088, 4649, 10649, 11756, 5362, 5696, 11160, 12697, 10587, 11287, 49254, 5111, 11307, 16226, 65648, 10693, 12976, 9795, 11685, 13300, 9676, 11079, 19515, 4971, 36232, 30848, 8851, 9364, 12046, 10543, 27251, 14449, 25057, 8742, 10756, 10119, 31794, 16824, 13457, 13126, 10940, 8487, 15164, 12277, 10026, 10669, 11707, 10301, 10134, 10264, 12246, 9538, 10608, 10708, 9828, 30769, 10272, 10700, 22730, 10375, 28088, 10679, 15887, 26494, 10750, 16367, 10320, 20659, 11089, 25920, 37391, 9229, 57506, 24371, 13704, 10908, 12191, 10632, 11670, 22268, 14633, 10035, 28198, 10394, 18725, 16048, 9974, 12317, 10831, 11404, 8516, 12843, 10178, 13677, 9834, 23288, 11986, 11347, 18648, 12240, 21040, 10354, 10543, 29142, 10722, 11426, 11068, 9953, 11366, 10677, 10497, 10617, 10630, 11202, 22069, 48435, 10150, 10683, 9589, 10529, 21533, 10302, 24630, 9491, 12154, 10609, 10864, 10744, 10824, 11051, 35643, 10335, 11128, 10196, 20262, 14029, 15512, 13132, 9473, 10776, 10227, 10858, 27460, 10466, 41882, 10425, 23124, 9776, 10710, 10243, 11306, 11631, 13932, 9667, 15904, 15014, 34062, 12569, 10702, 10223, 10575, 24485, 12828, 20228, 11740, 11350, 15787, 12331, 11897, 11918, 5419, 11540, 10408, 10647, 10595, 9036, 11470, 11221, 15296, 19651, 11423, 10007, 9515, 38820, 10686, 10398, 23090, 11000, 9523, 9228, 10795, 11570, 25015, 16290, 41501, 23156, 27076, 9705, 16633, 39615, 25068, 11360, 10211, 14392, 9340, 16150, 8181, 51944, 8740, 17771, 10974, 24164, 8383, 11886, 6533, 11492, 10738, 11183, 11084, 10903, 10390, 9487, 10620, 8266, 15542, 11094, 17072, 33639, 33150, 12483, 10196, 29392, 24209, 18940, 30223, 25634, 20366, 6509, 14943, 10926, 10030, 9480, 10221, 15497, 6424, 12117, 25062, 13167, 9658, 9925, 19563, 62188, 21058, 14014, 57943, 19077, 25315, 15032, 12432, 13616, 14913, 20394, 17053, 26546, 10478, 10214, 21465, 18236, 14091, 11012, 11873, 12159, 33008, 14540, 14730, 20518, 13484, 12526, 4889, 10978, 11327, 11275, 11315, 37227, 15152, 12142, 30949, 13920, 6760, 13238, 10143, 11176, 10785, 12044, 10015, 11509, 10305, 9929, 11989, 11969, 9381, 19884, 14021, 9348, 12366, 6139, 60031, 5686, 9360, 11195, 11103, 17782, 14637, 10345, 24660, 10742, 10857, 9383, 10755, 11377, 8993, 11301, 10398, 8455, 9976, 13778, 8067, 31746, 10800, 10741, 10798, 37306, 6794, 15761, 11289, 11595, 4846, 20598, 9148, 10764, 41269, 10303, 11103, 17525, 9367, 22586, 9782, 10147, 33394, 28569, 9935, 9319, 13227, 30809, 10949, 11866, 12566, 10833, 11049, 10057, 10110, 10675, 11593, 12021, 30957, 4385, 23884, 21501, 21241, 19901, 4683, 9416, 28303, 12191, 11174, 9041, 15090, 19681, 10345, 9568, 22790, 20433, 10896, 11544, 19006, 7436, 17652, 10867, 11300, 14826, 12256, 18901, 17356, 22603, 20761, 15085, 10008, 10169, 9754, 12484, 21462, 10322, 10221, 21330, 10370, 9100, 12219, 9615, 12862, 11684, 10562, 30345, 10522, 11059, 28976, 8969, 23416, 4984, 13203, 11497, 6010, 12975, 44056, 10758, 18000, 16477, 11233, 19186, 12322, 12033, 8707, 11488, 10317, 14374, 9960, 10525, 11512, 11073, 9890, 11719, 11539, 10378, 12021, 20131, 34812, 16470, 10299, 14957, 11583, 12118, 10190, 11986, 5592, 10248, 11855, 6832, 9332, 11067, 4082, 10369, 9916, 15017, 12934, 9081, 10595, 10432, 11759, 10559, 11043, 8917, 21134, 9891, 9176, 16130, 12942, 13627, 18725, 10904, 9808, 10271, 10536, 10638, 13854, 10695, 11433, 39161, 11455, 18960, 11107, 10703, 12723, 9257, 11431, 11105, 10333, 10313, 11585, 10344, 11084, 21966, 8377, 10323, 8185, 14299, 10609, 10551, 16646, 11337, 10546, 10707, 26303, 12953, 9294, 11267, 39151, 8228, 10602, 11245, 10260, 10439, 9924, 10518, 10226, 13153, 9727, 10631, 10293, 4908, 11351, 11699, 13297, 7873, 10887, 13199, 39299, 10164, 28920, 11162, 21162, 10873, 5283, 9938, 13808, 5140, 10517, 12483, 9389, 23219, 19894, 16043, 11175, 14779, 11053, 10940, 39710, 10974, 12795, 10458, 29754, 19573, 11346, 10526, 11079, 10434, 11672, 6137, 10845, 18903, 11224, 10704, 12516, 10495, 11055, 10604, 9788, 10452, 10533, 4945, 9983, 11643, 9712, 10519, 13844, 10913, 14131, 10514, 14742, 33770, 8857, 13931, 10485, 20982, 10189, 10240, 11140, 12490, 10792, 10299, 28767, 10669, 13604, 6395, 10977, 39186, 10903, 61691, 10745, 18824, 10159, 12396, 11054, 10595, 20240, 9738, 10219, 21439, 41329, 10739, 10896, 4868, 52815, 10708, 38900, 9872, 9994, 13546, 8304, 10149, 10501, 14794, 9865, 24487, 10105, 10997, 10480, 8867, 15620, 4849, 14141, 21448, 44760, 24356, 10123, 10512, 32705, 10711, 14130, 10830, 26961, 13539, 10216, 12642, 10823, 11040, 13619, 10147, 10247, 11415, 30393, 10969, 11854, 7609, 46668, 22548, 7873, 62534, 10747, 10471, 11411, 14595, 10810, 26857, 11315, 10359, 13682, 19665, 19345, 27815, 14945, 20679, 31038, 13784, 15296, 10509, 10744, 22472, 10520, 11555, 10757, 27673, 14992, 14989, 27100, 10319, 27530, 7593, 15409, 11668, 10774, 17530, 11036, 8222, 10799, 20249, 10742, 20896, 13897, 38765, 18303, 9745, 71755, 12680, 11783, 5892, 22802, 8486, 23485, 11273, 24528, 12647, 27395, 18613, 19047, 25991, 6369, 22035, 11269, 4850, 11819, 23594, 10413, 10210, 38584, 10776, 11590, 26886, 12407, 15941, 10203, 10543, 16827, 10406, 10801, 16961, 25091, 26117, 4995, 10669, 4570, 10934, 5509, 12342, 11069, 11221, 18032, 10606, 10294, 10794, 10149, 23535, 11605, 11509, 10267, 10945, 10808, 10208, 12462, 9539, 10996, 13746, 11135, 10701, 22650, 10277, 9871, 22744, 23044, 33427, 3378, 9747, 8703, 7656, 9463, 10656, 11297, 15888, 14886, 11302, 38639, 10594, 10537, 14643, 57349, 14269, 11499, 10223, 15088, 28919, 23684, 13888, 13690, 26912, 12774, 11234, 26520, 10459, 11919, 8800, 9204, 10845, 18581, 12632, 10618, 11108, 10805, 24695, 11472, 10718, 10299, 55165, 12039, 11745, 12596, 12705, 36938, 10675, 25627, 10441, 10320, 11116, 32508, 10810, 18654, 23086, 16685, 8342, 11231, 10819, 11306, 10918, 16246, 10979, 10863, 11223, 8547, 12869, 10174, 26564, 10143, 16311, 10658, 10181, 12059, 9562, 32135, 9438, 29761, 26396, 16018, 16535, 46584, 14336, 9155, 21595, 27259, 11287, 7579, 38688, 46567, 6178, 8256, 31900, 12278, 19151, 10862, 3608, 15766, 12738, 15914, 42111, 10020, 36021, 10692, 6690, 9883, 15079, 12033, 9900, 22825, 11361, 11951, 37286, 11418, 10924, 11337, 9619, 10213, 10856, 11048, 10842, 12414, 10325, 16869, 11143, 25523, 9572, 8037, 9731, 10596, 14328, 10393, 41055, 20795, 14812, 29254, 9532, 9682, 22098, 10576, 14922, 27530, 22068, 44823, 62466, 15851, 17035, 13790, 32455, 9763, 22771, 20480, 5260, 10708, 36714, 21263, 35770, 11534, 5466, 21040, 12474, 25403, 12246, 12780, 19804, 14025, 22915, 11714, 10546, 10914, 4907, 25442, 21807, 11633, 9574, 11884, 20814, 10725, 15213, 21476, 24079, 34650, 11473, 14708, 11460, 14527, 12063, 11321, 10635, 38457, 9976, 11387, 12442, 9942, 11507, 21903, 14923, 12090, 12044, 13137, 23724, 16638, 12050, 23906, 12763, 10095, 10450, 16574, 7953, 23314, 46235, 10924, 10452, 11349, 49136, 8569, 28080, 12395, 31054, 17199, 10749, 12401, 23741, 9983, 10240, 14952, 18745, 10093, 15763, 15947, 22766, 9734, 11323, 9103, 8183, 10813, 11526, 31744, 37984, 10665, 18484, 10234, 28322, 24927, 12733, 11218, 26552, 11835, 19255, 13685, 18189, 14281, 11213, 12967, 12791, 13413, 23402, 14537, 13631, 13160, 14190, 13652, 11060, 11685, 9787, 11534, 14020, 10163, 11664, 11130, 11526, 11963, 11541, 36500, 31777, 11087, 5208, 10415, 11008, 17780, 13966, 11527, 12402, 9959, 15587, 11744, 11524, 10972, 9728, 6301, 11682, 11987, 10687, 11419, 10401, 11515, 11320, 10253, 9305, 11693, 10882, 11733, 22243, 10735, 29551, 12129, 7360, 16884, 43866, 16754, 22618, 10169, 10098, 31603, 17397] + } + ] + }] +}; \ No newline at end of file From a5978907345716a492a3a147e84db03b398bad4c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 25 Aug 2017 23:02:56 +0200 Subject: [PATCH 031/281] prep 1 --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 49 +++++++++++++++++--------- test/image/mocks/table.json | 4 +-- test/image/mocks/table_one_column.json | 10 +++--- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index b8debf823cf..496a64f4f27 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -67,7 +67,7 @@ module.exports = function calc(gd, trace) { columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + 30 + Math.round((i < 0 ? 0 : 0) * (Math.random() - 0.5));}); var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b22e5b4d951..a25bbdc8329 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -193,7 +193,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(columnBlock); + renderColumnBlocks(cellsColumnBlock); }); } }) @@ -339,10 +339,6 @@ function renderColumnBlocks(columnBlock) { columnCell.exit().remove(); columnCell - .attr('transform', function(d, i) { - var lookup = d.anchorToRowBlock[d.column.anchor].rows; - return 'translate(' + 0 + ' ' + (lookup[i].rowAnchor - d.column.anchor) + ')'; - }) .each(function(d, i) { var spec = d.calcdata.cells.font; var col = d.column.specIndex; @@ -369,7 +365,6 @@ function renderColumnBlocks(columnBlock) { cellRect .attr('width', function(d) {return d.column.columnWidth;}) - .attr('height', rowHeight) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { return gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); @@ -385,16 +380,9 @@ function renderColumnBlocks(columnBlock) { .append('text') .classed('cellText', true); + + // it is only in this leaf selection that the actual cell height can be recovered... cellText - .attr('dy', function(d, i) { - var height = rowHeight(d); - return c.cellPad; - return ({ - top: -height + c.cellPad, - middle: -height / 2, - bottom: -c.cellPad - })[d.valign]; - }) .attr('alignment-baseline', 'hanging') .text(function(d) { var col = d.column.specIndex; @@ -405,8 +393,37 @@ function renderColumnBlocks(columnBlock) { return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; }) .each(function(d) { - var selection = d3.select(this); + var element = this; + var selection = d3.select(element); + var initialBbox = element.getBoundingClientRect(); + var initialHeight = initialBbox.bottom - initialBbox.top; Drawing.font(selection, d.font); util.convertToTspans(selection); + var bbox = element.getBoundingClientRect(); + var height = bbox.bottom - bbox.top; + console.log(initialHeight, height); + //if(initialHeight !== height) debugger; }); + + // ... therefore all channels for selections above that need to know the height are set below + // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses + + columnCell + .attr('transform', function(d, i) { + var lookup = d.anchorToRowBlock[d.column.anchor].rows; + return 'translate(' + 0 + ' ' + (lookup[i].rowAnchor - d.column.anchor) + ')'; + }); + + cellRect.attr('height', rowHeight); + + cellText.attr('dy', function(d, i) { + var height = rowHeight(d); + return c.cellPad; + return ({ + top: -height + c.cellPad, + middle: -height / 2, + bottom: -c.cellPad + })[d.valign]; + }); + }; diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json index 54b5550a290..3789d06a2ef 100644 --- a/test/image/mocks/table.json +++ b/test/image/mocks/table.json @@ -59,7 +59,7 @@ "values": [ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20), - ["A", "A", "B", "AB", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), + ["A", "X
B
C", "A", "B", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666].slice(0, 20), [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000].slice(0, 20), [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797].slice(0, 20), @@ -91,7 +91,7 @@ "height": 20, "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], - "valign": ["middle", "top", "bottom", "middle"], + "valign": ["top", "top", "bottom", "middle"], "line": { "color": [ diff --git a/test/image/mocks/table_one_column.json b/test/image/mocks/table_one_column.json index 9d94f49bb08..d2ed39fb953 100644 --- a/test/image/mocks/table_one_column.json +++ b/test/image/mocks/table_one_column.json @@ -1,7 +1,7 @@ { "layout": { "width": 1000, - "height": 600, + "height": 800, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} }, @@ -48,7 +48,7 @@ "cells": { "values": [ - [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20) + [0,"1
B
C",2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20) ], "format": [ @@ -56,12 +56,12 @@ ], "prefix": ["#"], - "suffix": [""], + "suffix": ["cell"], - "height": 27, + "height": 15, "align": ["right"], - "valign": ["middle"], + "valign": ["bottom"], "line": { "color": [ From aba14b454b041dc246cf6dec2cf26a4b0faa8b8f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 30 Aug 2017 16:21:29 +0200 Subject: [PATCH 032/281] pretty good carry --- src/traces/table/calc.js | 5 +- src/traces/table/plot.js | 98 ++++++++++++++++++-------- test/image/mocks/table_one_column.json | 2 +- 3 files changed, 74 insertions(+), 31 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 496a64f4f27..a1df7718339 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -33,12 +33,15 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentBlock.rows.push({ rowIndex: i, rowHeight: currentRowHeight, - rowAnchor: currentAnchor + currentBlockHeight + rowHeightStretch: 0, + rowAnchor: currentAnchor + currentBlockHeight, + rowAnchorCarry: 0 }); currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.totalHeight = currentBlockHeight; + currentBlock.totalHeightStretch = 0; currentBlock.firstRowIndex = currentFirstRowIndex; currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a25bbdc8329..fb394c2cc9f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -105,6 +105,9 @@ module.exports = function plot(gd, calcdata) { type: 'header', yOffset: 0, anchor: 0, + page: 0, + currentAnchorCarry: 0, + anchorCarry: 0, values: d.calcdata.headerCells.values[d.specIndex], anchorToRowBlock: d.calcdata.anchorToHeaderRowBlock, dragHandle: true, @@ -115,6 +118,9 @@ module.exports = function plot(gd, calcdata) { key: 'cells1', type: 'cells', anchor: 0, // will be mutated on scroll; points to current place + page: 0, + currentAnchorCarry: 0, + anchorCarry: 0, yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -125,6 +131,9 @@ module.exports = function plot(gd, calcdata) { var revolverPanel2 = extendFlat({}, d, { key: 'cells2', anchor: d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place + page: 1, + currentAnchorCarry: 0, + anchorCarry: 0, type: 'cells', yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, @@ -172,14 +181,16 @@ module.exports = function plot(gd, calcdata) { var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(direction === 'down' && scrollY - d.anchor > anchorToBlock[d.anchor].totalHeight) { - if(blockAnchors.indexOf(d.anchor) + 2 < blockAnchors.length) { - d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) + 2]; - anchorChanged = true; + if(d.page + 2 < blockAnchors.length) { + d.page += 2; + d.anchor = blockAnchors[d.page]; + anchorChanged = d.key; } } else if(direction === 'up' && d.anchor > scrollY + d.calcdata.scrollHeight) { - if(blockAnchors.indexOf(d.anchor) - 2 >= 0) { - d.anchor = blockAnchors[blockAnchors.indexOf(d.anchor) - 2]; - anchorChanged = true; + if(d.page - 2 >= 0) { + d.page -= 2; + d.anchor = blockAnchors[d.page]; + anchorChanged = d.key; } } @@ -193,7 +204,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(cellsColumnBlock); + renderColumnBlocks(cellsColumnBlock.filter(function(d) {return d.key === anchorChanged;})); }); } }) @@ -264,8 +275,6 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function textFragmentUrl(d) {return 'textFragment_' + d.column.key + '_' + d.column.specIndex + '_' + d.key;} - function rowFromTo(d) { var rowBlock = d.anchorToRowBlock[d.anchor]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; @@ -306,11 +315,6 @@ function easeColumn(elem, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } -function rowHeight(d) { - var lookup = d.anchorToRowBlock[d.column.anchor]; - return lookup.rows[d.key - lookup.firstRowIndex].rowHeight; -} - function renderColumnBlocks(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch @@ -329,7 +333,15 @@ function renderColumnBlocks(columnBlock) { var columnCell = columnCells.selectAll('.columnCell') .data(function(d) { var fromTo = rowFromTo(d); - return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) {return {key: fromTo[0] + i, column: d, calcdata: d.calcdata, anchorToRowBlock: d.anchorToRowBlock, value: v};}); + return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { + return { + key: fromTo[0] + i, + column: d, + calcdata: d.calcdata, + anchorToRowBlock: d.anchorToRowBlock, + value: v + }; + }); }, gup.keyFun); columnCell.enter() @@ -381,6 +393,8 @@ function renderColumnBlocks(columnBlock) { .classed('cellText', true); + var rowCarry = 0; + // it is only in this leaf selection that the actual cell height can be recovered... cellText .attr('alignment-baseline', 'hanging') @@ -392,7 +406,7 @@ function renderColumnBlocks(columnBlock) { var format = gridPick(d.calcdata.cells.format, col, row) || ''; return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; }) - .each(function(d) { + .each(function(d, i) { var element = this; var selection = d3.select(element); var initialBbox = element.getBoundingClientRect(); @@ -401,29 +415,55 @@ function renderColumnBlocks(columnBlock) { util.convertToTspans(selection); var bbox = element.getBoundingClientRect(); var height = bbox.bottom - bbox.top; - console.log(initialHeight, height); - //if(initialHeight !== height) debugger; + var l = lookup(d); + l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; + var increase = Math.max(0, height - initialHeight); + console.log(d.column.key) + if(increase) { + l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; + d.column.anchorCarry += increase; + } }); + console.log('retabulate?') + // ... therefore all channels for selections above that need to know the height are set below // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses columnCell .attr('transform', function(d, i) { - var lookup = d.anchorToRowBlock[d.column.anchor].rows; - return 'translate(' + 0 + ' ' + (lookup[i].rowAnchor - d.column.anchor) + ')'; + return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; }); cellRect.attr('height', rowHeight); - cellText.attr('dy', function(d, i) { - var height = rowHeight(d); - return c.cellPad; - return ({ - top: -height + c.cellPad, - middle: -height / 2, - bottom: -c.cellPad - })[d.valign]; - }); + cellText + .attr('dy', function(d, i) { + var height = rowHeight(d); + console.log(height) + //return height / 2; + return ({ + top: -height + c.cellPad, + middle: -height / 2, + bottom: -c.cellPad - 20 + height + })[d.valign]; + }); }; + +function lookup(d) { + return d.anchorToRowBlock[d.column.anchor]; +} + +function rowOffset(d, i) { + var l = lookup(d); + var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry) - (d.column.anchor + 0 * d.column.anchorCarry); + return o; +} + +function rowHeight(d) { + var l = lookup(d); + var h = l.rows[d.key - l.firstRowIndex].rowHeight + l.rows[d.key - l.firstRowIndex].rowHeightStretch; + return h; +} + diff --git a/test/image/mocks/table_one_column.json b/test/image/mocks/table_one_column.json index d2ed39fb953..6647be209e6 100644 --- a/test/image/mocks/table_one_column.json +++ b/test/image/mocks/table_one_column.json @@ -48,7 +48,7 @@ "cells": { "values": [ - [0,"1
B
C",2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20) + [0,0 || "1
B
C",2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20) ], "format": [ From 6144a5df967f0f16ddfa5935daa706c796eaaca2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 00:25:22 +0200 Subject: [PATCH 033/281] rowblocks everywhere --- src/traces/table/calc.js | 10 ++++++++++ src/traces/table/plot.js | 22 +++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index a1df7718339..fd9d1a351c9 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -40,6 +40,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; + currentBlock.firstRowAnchor = currentAnchor; currentBlock.totalHeight = currentBlockHeight; currentBlock.totalHeightStretch = 0; currentBlock.firstRowIndex = currentFirstRowIndex; @@ -75,8 +76,15 @@ module.exports = function calc(gd, trace) { var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; + function rb(anchorToRowBlock) { + var blockAnchorKeys = Object.keys(anchorToRowBlock); + return blockAnchorKeys.map(function(k) {return anchorToRowBlock[k];}) + } + var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); + var rowBlocks = rb(anchorToRowBlock); + var headerRowBlocks = rb(anchorToHeaderRowBlock); var uniqueKeys = {}; @@ -95,6 +103,8 @@ module.exports = function calc(gd, trace) { scrollHeight: scrollHeight, anchorToRowBlock: anchorToRowBlock, anchorToHeaderRowBlock: anchorToHeaderRowBlock, + rowBlocks: rowBlocks, + headerRowBlocks: headerRowBlocks, scrollY: 0, // will be mutated on scroll cells: trace.cells, headerCells: trace.header, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fb394c2cc9f..883aab46405 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -110,6 +110,7 @@ module.exports = function plot(gd, calcdata) { anchorCarry: 0, values: d.calcdata.headerCells.values[d.specIndex], anchorToRowBlock: d.calcdata.anchorToHeaderRowBlock, + rowBlocks: d.calcdata.headerRowBlocks, dragHandle: true, rowBlockOffset: 0, calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) @@ -125,12 +126,13 @@ module.exports = function plot(gd, calcdata) { dragHandle: false, values: d.calcdata.cells.values[d.specIndex], anchorToRowBlock: d.calcdata.anchorToRowBlock, + rowBlocks: d.calcdata.rowBlocks, rowBlockOffset: 0, calcdata: d.calcdata }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place + anchor: d.calcdata.rowBlocks[0].totalHeight, //d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place page: 1, currentAnchorCarry: 0, anchorCarry: 0, @@ -139,6 +141,7 @@ module.exports = function plot(gd, calcdata) { dragHandle: false, values: d.calcdata.cells.values[d.specIndex], anchorToRowBlock: d.calcdata.anchorToRowBlock, + rowBlocks: d.calcdata.rowBlocks, rowBlockOffset: 1, calcdata: d.calcdata }); @@ -172,15 +175,14 @@ module.exports = function plot(gd, calcdata) { var anchorChanged = false; cellsColumnBlock .attr('transform', function(d) { - var anchorToBlock = d.anchorToRowBlock; - var blockAnchorKeys = Object.keys(anchorToBlock); - var blockAnchors = blockAnchorKeys.map(function(v) {return parseInt(v);}); - var lastAnchor = blockAnchors[blockAnchors.length - 1]; - var lastBlock = anchorToBlock[lastAnchor]; + var rowBlocks = d.rowBlocks; + var currentBlock = rowBlocks[d.page]; + var blockAnchors = rowBlocks.map(function(v) {return v.firstRowAnchor;}); + var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(direction === 'down' && scrollY - d.anchor > anchorToBlock[d.anchor].totalHeight) { + if(direction === 'down' && scrollY - d.anchor > currentBlock.totalHeight) { if(d.page + 2 < blockAnchors.length) { d.page += 2; d.anchor = blockAnchors[d.page]; @@ -276,7 +278,7 @@ module.exports = function plot(gd, calcdata) { }; function rowFromTo(d) { - var rowBlock = d.anchorToRowBlock[d.anchor]; + var rowBlock = d.rowBlocks[d.page]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; return [rowFrom, rowTo]; @@ -338,7 +340,9 @@ function renderColumnBlocks(columnBlock) { key: fromTo[0] + i, column: d, calcdata: d.calcdata, + page: d.page, anchorToRowBlock: d.anchorToRowBlock, + rowBlocks: d.rowBlocks, value: v }; }); @@ -452,7 +456,7 @@ function renderColumnBlocks(columnBlock) { }; function lookup(d) { - return d.anchorToRowBlock[d.column.anchor]; + return d.rowBlocks[d.page]; } function rowOffset(d, i) { From 53727ab83dc6181d0f3275050c52fd0f581a512c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 00:27:46 +0200 Subject: [PATCH 034/281] no anchorToRowBlock anymore --- src/traces/table/calc.js | 4 ++-- src/traces/table/plot.js | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index fd9d1a351c9..92f2c8f657c 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -101,8 +101,8 @@ module.exports = function calc(gd, trace) { columnOrder: columnOrder, // will be mutated on column move headerHeight: headerHeight, scrollHeight: scrollHeight, - anchorToRowBlock: anchorToRowBlock, - anchorToHeaderRowBlock: anchorToHeaderRowBlock, + //anchorToRowBlock: anchorToRowBlock, + //anchorToHeaderRowBlock: anchorToHeaderRowBlock, rowBlocks: rowBlocks, headerRowBlocks: headerRowBlocks, scrollY: 0, // will be mutated on scroll diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 883aab46405..b7a1808650f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -109,7 +109,6 @@ module.exports = function plot(gd, calcdata) { currentAnchorCarry: 0, anchorCarry: 0, values: d.calcdata.headerCells.values[d.specIndex], - anchorToRowBlock: d.calcdata.anchorToHeaderRowBlock, rowBlocks: d.calcdata.headerRowBlocks, dragHandle: true, rowBlockOffset: 0, @@ -125,14 +124,13 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - anchorToRowBlock: d.calcdata.anchorToRowBlock, rowBlocks: d.calcdata.rowBlocks, rowBlockOffset: 0, calcdata: d.calcdata }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: d.calcdata.rowBlocks[0].totalHeight, //d.calcdata.anchorToRowBlock[revolverPanel1.anchor].totalHeight, // will be mutated on scroll; points to current place + anchor: d.calcdata.rowBlocks[0].totalHeight, // will be mutated on scroll; points to current place page: 1, currentAnchorCarry: 0, anchorCarry: 0, @@ -140,7 +138,6 @@ module.exports = function plot(gd, calcdata) { yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - anchorToRowBlock: d.calcdata.anchorToRowBlock, rowBlocks: d.calcdata.rowBlocks, rowBlockOffset: 1, calcdata: d.calcdata @@ -341,7 +338,6 @@ function renderColumnBlocks(columnBlock) { column: d, calcdata: d.calcdata, page: d.page, - anchorToRowBlock: d.anchorToRowBlock, rowBlocks: d.rowBlocks, value: v }; From bfbc222f6d1e2ac1b750d3d6bb82bdbae2401363 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 00:48:04 +0200 Subject: [PATCH 035/281] fixed repeating increase of same thing --- src/traces/table/plot.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b7a1808650f..69e4dcafc92 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -417,8 +417,7 @@ function renderColumnBlocks(columnBlock) { var height = bbox.bottom - bbox.top; var l = lookup(d); l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; - var increase = Math.max(0, height - initialHeight); - console.log(d.column.key) + var increase = Math.max(0, height - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); if(increase) { l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; d.column.anchorCarry += increase; From 1e7e91f740e5ade7c06f687d3446a103f3dbf64e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 01:02:42 +0200 Subject: [PATCH 036/281] putting 2nd panel out of the view --- src/traces/table/plot.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 69e4dcafc92..b1f72bb03a4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -130,8 +130,8 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: d.calcdata.rowBlocks[0].totalHeight, // will be mutated on scroll; points to current place - page: 1, + anchor: -d.calcdata.rowBlocks[1].totalHeight, // will be mutated on scroll; points to current place + page: -1, currentAnchorCarry: 0, anchorCarry: 0, type: 'cells', @@ -179,7 +179,7 @@ module.exports = function plot(gd, calcdata) { var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(direction === 'down' && scrollY - d.anchor > currentBlock.totalHeight) { + if(d.page < 0 || direction === 'down' && scrollY - d.anchor > currentBlock.totalHeight) { if(d.page + 2 < blockAnchors.length) { d.page += 2; d.anchor = blockAnchors[d.page]; @@ -421,6 +421,10 @@ function renderColumnBlocks(columnBlock) { if(increase) { l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; d.column.anchorCarry += increase; + d.rowBlocks[d.page].totalHeight += increase; + for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + d.rowBlocks[p].firstRowAnchor += increase; + } } }); From 5647b447b5a61ad30a877cc4bffd9114753ea144 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 01:11:37 +0200 Subject: [PATCH 037/281] 1.,2. panels OK, rest and scrollback aren't --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 92f2c8f657c..ef5fca686a0 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -34,7 +34,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { rowIndex: i, rowHeight: currentRowHeight, rowHeightStretch: 0, - rowAnchor: currentAnchor + currentBlockHeight, + rowAnchor: currentBlockHeight, rowAnchorCarry: 0 }); currentBlockHeight += currentRowHeight; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b1f72bb03a4..fef2657e370 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -177,7 +177,7 @@ module.exports = function plot(gd, calcdata) { var blockAnchors = rowBlocks.map(function(v) {return v.firstRowAnchor;}); var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var bottom = lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; + var bottom = lastBlock.firstRowAnchor + lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > currentBlock.totalHeight) { if(d.page + 2 < blockAnchors.length) { @@ -460,7 +460,8 @@ function lookup(d) { function rowOffset(d, i) { var l = lookup(d); - var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry) - (d.column.anchor + 0 * d.column.anchorCarry); + // if(d.column.anchor) debugger + var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry + l.firstRowAnchor) - (d.column.anchor + 0 * d.column.anchorCarry); return o; } From fea8944a636ac5ba8c5165233be98bbfbf57ff8c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:20:52 +0200 Subject: [PATCH 038/281] baseline for fixing extra gap --- src/traces/table/calc.js | 2 ++ src/traces/table/plot.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index ef5fca686a0..b7cd167d636 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -28,6 +28,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { var currentBlockHeight = 0; var currentBlock = makeIdentity(); var currentFirstRowIndex = 0; + var blockCounter = 0; for(var i = 0; i < rowHeights.length; i++) { currentRowHeight = rowHeights[i]; currentBlock.rows.push({ @@ -40,6 +41,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; + currentBlock.key = blockCounter++; currentBlock.firstRowAnchor = currentAnchor; currentBlock.totalHeight = currentBlockHeight; currentBlock.totalHeightStretch = 0; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fef2657e370..ad2e91d3971 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -416,13 +416,16 @@ function renderColumnBlocks(columnBlock) { var bbox = element.getBoundingClientRect(); var height = bbox.bottom - bbox.top; var l = lookup(d); - l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; var increase = Math.max(0, height - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); + if(d.column.anchorCarry) console.log('anchor carry increase!!!!!!!!!!') + //l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; if(increase) { + console.log('increase!!!!!!!!!!') l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; d.column.anchorCarry += increase; d.rowBlocks[d.page].totalHeight += increase; for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + console.log('increasing firstRowAnchor on block', d.rowBlocks[p].key, 'from', d.rowBlocks[p].firstRowAnchor, 'by', increase) d.rowBlocks[p].firstRowAnchor += increase; } } From ae934451dc85c1dc5e309038902dc4dfdc9026e9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:22:02 +0200 Subject: [PATCH 039/281] fixing extra gap --- src/traces/table/plot.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ad2e91d3971..2cd8e6490d2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -106,7 +106,6 @@ module.exports = function plot(gd, calcdata) { yOffset: 0, anchor: 0, page: 0, - currentAnchorCarry: 0, anchorCarry: 0, values: d.calcdata.headerCells.values[d.specIndex], rowBlocks: d.calcdata.headerRowBlocks, @@ -119,7 +118,6 @@ module.exports = function plot(gd, calcdata) { type: 'cells', anchor: 0, // will be mutated on scroll; points to current place page: 0, - currentAnchorCarry: 0, anchorCarry: 0, yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, @@ -132,7 +130,6 @@ module.exports = function plot(gd, calcdata) { key: 'cells2', anchor: -d.calcdata.rowBlocks[1].totalHeight, // will be mutated on scroll; points to current place page: -1, - currentAnchorCarry: 0, anchorCarry: 0, type: 'cells', yOffset: d.calcdata.headerHeight, // fixme @@ -417,12 +414,14 @@ function renderColumnBlocks(columnBlock) { var height = bbox.bottom - bbox.top; var l = lookup(d); var increase = Math.max(0, height - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); - if(d.column.anchorCarry) console.log('anchor carry increase!!!!!!!!!!') //l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; if(increase) { console.log('increase!!!!!!!!!!') l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; - d.column.anchorCarry += increase; + for(var r = (d.key - l.firstRowIndex) + 1; r < l.rows.length; r++) { + l.rows[r].rowAnchorCarry += increase; + } + //d.column.anchorCarry = increase; d.rowBlocks[d.page].totalHeight += increase; for(var p = d.page + 1; p < d.rowBlocks.length; p++) { console.log('increasing firstRowAnchor on block', d.rowBlocks[p].key, 'from', d.rowBlocks[p].firstRowAnchor, 'by', increase) From b8d1a47d9c7f602299ce2169515b0a52e6d588e8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:36:51 +0200 Subject: [PATCH 040/281] clean up 1 --- src/traces/table/plot.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2cd8e6490d2..2501d54fe04 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -106,7 +106,6 @@ module.exports = function plot(gd, calcdata) { yOffset: 0, anchor: 0, page: 0, - anchorCarry: 0, values: d.calcdata.headerCells.values[d.specIndex], rowBlocks: d.calcdata.headerRowBlocks, dragHandle: true, @@ -118,7 +117,6 @@ module.exports = function plot(gd, calcdata) { type: 'cells', anchor: 0, // will be mutated on scroll; points to current place page: 0, - anchorCarry: 0, yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -130,7 +128,6 @@ module.exports = function plot(gd, calcdata) { key: 'cells2', anchor: -d.calcdata.rowBlocks[1].totalHeight, // will be mutated on scroll; points to current place page: -1, - anchorCarry: 0, type: 'cells', yOffset: d.calcdata.headerHeight, // fixme dragHandle: false, @@ -414,24 +411,18 @@ function renderColumnBlocks(columnBlock) { var height = bbox.bottom - bbox.top; var l = lookup(d); var increase = Math.max(0, height - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); - //l.rows[d.key - l.firstRowIndex].rowAnchorCarry += d.column.anchorCarry; if(increase) { - console.log('increase!!!!!!!!!!') l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; for(var r = (d.key - l.firstRowIndex) + 1; r < l.rows.length; r++) { l.rows[r].rowAnchorCarry += increase; } - //d.column.anchorCarry = increase; - d.rowBlocks[d.page].totalHeight += increase; for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - console.log('increasing firstRowAnchor on block', d.rowBlocks[p].key, 'from', d.rowBlocks[p].firstRowAnchor, 'by', increase) d.rowBlocks[p].firstRowAnchor += increase; } + d.rowBlocks[d.page].totalHeight += increase; } }); - console.log('retabulate?') - // ... therefore all channels for selections above that need to know the height are set below // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses @@ -463,7 +454,7 @@ function lookup(d) { function rowOffset(d, i) { var l = lookup(d); // if(d.column.anchor) debugger - var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry + l.firstRowAnchor) - (d.column.anchor + 0 * d.column.anchorCarry); + var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry + l.firstRowAnchor) - d.column.anchor; return o; } From dac8a6270563f09761eb1da076f6a7580b67252d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:38:16 +0200 Subject: [PATCH 041/281] clean up 2 --- src/traces/table/plot.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2501d54fe04..43ee520ed41 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -436,8 +436,6 @@ function renderColumnBlocks(columnBlock) { cellText .attr('dy', function(d, i) { var height = rowHeight(d); - console.log(height) - //return height / 2; return ({ top: -height + c.cellPad, middle: -height / 2, From 1c4509c8146f09cfc8ee6edd2b7261f76e559b7a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:39:38 +0200 Subject: [PATCH 042/281] clean up 3 --- src/traces/table/plot.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 43ee520ed41..3be705a74b9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -387,8 +387,6 @@ function renderColumnBlocks(columnBlock) { .classed('cellText', true); - var rowCarry = 0; - // it is only in this leaf selection that the actual cell height can be recovered... cellText .attr('alignment-baseline', 'hanging') @@ -400,7 +398,7 @@ function renderColumnBlocks(columnBlock) { var format = gridPick(d.calcdata.cells.format, col, row) || ''; return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; }) - .each(function(d, i) { + .each(function(d) { var element = this; var selection = d3.select(element); var initialBbox = element.getBoundingClientRect(); @@ -434,7 +432,7 @@ function renderColumnBlocks(columnBlock) { cellRect.attr('height', rowHeight); cellText - .attr('dy', function(d, i) { + .attr('dy', function(d) { var height = rowHeight(d); return ({ top: -height + c.cellPad, @@ -451,7 +449,6 @@ function lookup(d) { function rowOffset(d, i) { var l = lookup(d); - // if(d.column.anchor) debugger var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry + l.firstRowAnchor) - d.column.anchor; return o; } From 0a78d3af7e25b3919d8ca45b7916b74851776db0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:41:56 +0200 Subject: [PATCH 043/281] clean up 4 - killing carry --- src/traces/table/calc.js | 3 +-- src/traces/table/plot.js | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index b7cd167d636..07afd68426c 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -35,8 +35,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { rowIndex: i, rowHeight: currentRowHeight, rowHeightStretch: 0, - rowAnchor: currentBlockHeight, - rowAnchorCarry: 0 + rowAnchor: currentBlockHeight }); currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3be705a74b9..aa79eb689a3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -412,7 +412,7 @@ function renderColumnBlocks(columnBlock) { if(increase) { l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; for(var r = (d.key - l.firstRowIndex) + 1; r < l.rows.length; r++) { - l.rows[r].rowAnchorCarry += increase; + l.rows[r].rowAnchor += increase; } for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; @@ -449,7 +449,7 @@ function lookup(d) { function rowOffset(d, i) { var l = lookup(d); - var o = (l.rows[i].rowAnchor + l.rows[i].rowAnchorCarry + l.firstRowAnchor) - d.column.anchor; + var o = (l.rows[i].rowAnchor + l.firstRowAnchor) - d.column.anchor; return o; } From 1e48b348293b021dff46caa6eb56b0fb930745e6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 12:43:41 +0200 Subject: [PATCH 044/281] clean up 5 --- src/traces/table/plot.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index aa79eb689a3..b264b392017 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -117,7 +117,7 @@ module.exports = function plot(gd, calcdata) { type: 'cells', anchor: 0, // will be mutated on scroll; points to current place page: 0, - yOffset: d.calcdata.headerHeight, // fixme + yOffset: d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -129,7 +129,7 @@ module.exports = function plot(gd, calcdata) { anchor: -d.calcdata.rowBlocks[1].totalHeight, // will be mutated on scroll; points to current place page: -1, type: 'cells', - yOffset: d.calcdata.headerHeight, // fixme + yOffset: d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -401,14 +401,12 @@ function renderColumnBlocks(columnBlock) { .each(function(d) { var element = this; var selection = d3.select(element); - var initialBbox = element.getBoundingClientRect(); - var initialHeight = initialBbox.bottom - initialBbox.top; + var l = lookup(d); + var initialHeight = element.getBoundingClientRect().height; Drawing.font(selection, d.font); util.convertToTspans(selection); - var bbox = element.getBoundingClientRect(); - var height = bbox.bottom - bbox.top; - var l = lookup(d); - var increase = Math.max(0, height - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); + var renderedHeight = element.getBoundingClientRect().height; + var increase = Math.max(0, renderedHeight - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); if(increase) { l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; for(var r = (d.key - l.firstRowIndex) + 1; r < l.rows.length; r++) { From 5d20556d267baa054b31be164fd12104b654c5e7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 15:42:32 +0200 Subject: [PATCH 045/281] no `stretch`; 50% fewer bbox measurements --- src/traces/table/calc.js | 2 -- src/traces/table/plot.js | 27 ++++++++++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 07afd68426c..965d73c3b81 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -34,7 +34,6 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentBlock.rows.push({ rowIndex: i, rowHeight: currentRowHeight, - rowHeightStretch: 0, rowAnchor: currentBlockHeight }); currentBlockHeight += currentRowHeight; @@ -43,7 +42,6 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentBlock.key = blockCounter++; currentBlock.firstRowAnchor = currentAnchor; currentBlock.totalHeight = currentBlockHeight; - currentBlock.totalHeightStretch = 0; currentBlock.firstRowIndex = currentFirstRowIndex; currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b264b392017..0e506d5cb8d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -399,23 +399,36 @@ function renderColumnBlocks(columnBlock) { return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; }) .each(function(d) { + var element = this; var selection = d3.select(element); - var l = lookup(d); - var initialHeight = element.getBoundingClientRect().height; + + // finalize what's in the DOM Drawing.font(selection, d.font); util.convertToTspans(selection); + + var l = lookup(d); + var rowIndex = d.key - l.firstRowIndex; var renderedHeight = element.getBoundingClientRect().height; - var increase = Math.max(0, renderedHeight - initialHeight - l.rows[d.key - l.firstRowIndex].rowHeightStretch); + var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); + if(increase) { - l.rows[d.key - l.firstRowIndex].rowHeightStretch += increase; - for(var r = (d.key - l.firstRowIndex) + 1; r < l.rows.length; r++) { + + // current row height increased + l.rows[d.key - l.firstRowIndex].rowHeight += increase; + + // current block height increased + d.rowBlocks[d.page].totalHeight += increase; + + // subsequent rows in block pushed south + for(var r = rowIndex + 1; r < l.rows.length; r++) { l.rows[r].rowAnchor += increase; } + + // subsequent blocks pushed down for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; } - d.rowBlocks[d.page].totalHeight += increase; } }); @@ -453,7 +466,7 @@ function rowOffset(d, i) { function rowHeight(d) { var l = lookup(d); - var h = l.rows[d.key - l.firstRowIndex].rowHeight + l.rows[d.key - l.firstRowIndex].rowHeightStretch; + var h = l.rows[d.key - l.firstRowIndex].rowHeight; return h; } From 80e9933c5aa92096cda75d2ccb783a4fcd7260f0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 15:48:21 +0200 Subject: [PATCH 046/281] pure shuffle --- src/traces/table/plot.js | 81 ++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 0e506d5cb8d..58c7f9a6726 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -268,46 +268,6 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function rowFromTo(d) { - var rowBlock = d.rowBlocks[d.page]; - var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; - var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; - return [rowFrom, rowTo]; -} - -function columnMoved(gd, calcdata, i, indices) { - - var o = calcdata[i][0].gdColumnsOriginalOrder; - calcdata[i][0].gdColumns.sort(function (a, b) { - return indices[o.indexOf(a)] - indices[o.indexOf(b)]; - }); - - calcdata[i][0].columnorder = indices; - - gd.emit('plotly_restyle'); -} - -function gridPick(spec, col, row) { - if(Array.isArray(spec)) { - const column = spec[Math.min(col, spec.length - 1)]; - if(Array.isArray(column)) { - return column[Math.min(row, column.length - 1)]; - } else { - return column; - } - } else { - return spec; - } -} - -function easeColumn(elem, d, y) { - d3.select(elem) - .transition() - .ease(c.releaseTransitionEase, 1, .75) - .duration(c.releaseTransitionDuration) - .attr('transform', 'translate(' + d.x + ' ' + y + ')'); -} - function renderColumnBlocks(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch @@ -454,6 +414,46 @@ function renderColumnBlocks(columnBlock) { }; +function rowFromTo(d) { + var rowBlock = d.rowBlocks[d.page]; + var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; + return [rowFrom, rowTo]; +} + +function columnMoved(gd, calcdata, i, indices) { + + var o = calcdata[i][0].gdColumnsOriginalOrder; + calcdata[i][0].gdColumns.sort(function (a, b) { + return indices[o.indexOf(a)] - indices[o.indexOf(b)]; + }); + + calcdata[i][0].columnorder = indices; + + gd.emit('plotly_restyle'); +} + +function gridPick(spec, col, row) { + if(Array.isArray(spec)) { + const column = spec[Math.min(col, spec.length - 1)]; + if(Array.isArray(column)) { + return column[Math.min(row, column.length - 1)]; + } else { + return column; + } + } else { + return spec; + } +} + +function easeColumn(elem, d, y) { + d3.select(elem) + .transition() + .ease(c.releaseTransitionEase, 1, .75) + .duration(c.releaseTransitionDuration) + .attr('transform', 'translate(' + d.x + ' ' + y + ')'); +} + function lookup(d) { return d.rowBlocks[d.page]; } @@ -469,4 +469,3 @@ function rowHeight(d) { var h = l.rows[d.key - l.firstRowIndex].rowHeight; return h; } - From a424fc18d1d41b1ac127e6a7e8b8aa76e10f208e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 17:42:44 +0200 Subject: [PATCH 047/281] mock chg --- test/image/mocks/table.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/image/mocks/table.json b/test/image/mocks/table.json index 3789d06a2ef..2be579aab6c 100644 --- a/test/image/mocks/table.json +++ b/test/image/mocks/table.json @@ -1,9 +1,9 @@ { "layout": { "width": 1000, - "height": 300, + "height": 610, "title": "Widget parameters and cost", - "margin": {"t": 80, "r": 60, "b": 54, "l": 60} + "margin": {"t": 380, "r": 60, "b": 54, "l": 60} }, "data": [{ @@ -20,7 +20,7 @@ "header": { - "height": 20, + "height": 25, "values": [ ["Index" , "#"], @@ -50,7 +50,7 @@ "font": { "family": "Arial", - "size": 16, + "size": 12, "color": "white" } }, @@ -59,7 +59,7 @@ "values": [ [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].slice(0, 20), - ["A", "X
B
C", "A", "B", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), + ["A", "X
B
C
D", "A", "B", "Y", "Z", "Z", "A", "B", "B", "Y", "Y", "Z", "A", "A", "B", "Y", "Y", "Z", "Z"].slice(0, 20), [32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666, 32000, 162666].slice(0, 20), [268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000, 489543, 268630, 600000, 379086, 268630, 489543, 379086, 600000].slice(0, 20), [160, 1324, 252, 1711, 173, 624, 228, 2474, 371, 3103, 312, 2408, 460, 1727, 754, 2457, 227, 1963, 354, 2797].slice(0, 20), @@ -91,7 +91,7 @@ "height": 20, "align": ["right", "center", "right", "center", "right", "right", "right", "left", "right", "right", "right"], - "valign": ["top", "top", "bottom", "middle"], + "valign": ["bottom"], "line": { "color": [ From 7246536f7f23fdbbb1589a8c2fc0cbf426c00cbb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 31 Aug 2017 17:47:48 +0200 Subject: [PATCH 048/281] one-cell mock --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 86 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/image/mocks/table_one_cell.json diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 58c7f9a6726..16084cdf4b4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -126,7 +126,7 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: -d.calcdata.rowBlocks[1].totalHeight, // will be mutated on scroll; points to current place + anchor: d.calcdata.rowBlocks[1] ? -d.calcdata.rowBlocks[1].totalHeight : 0, // will be mutated on scroll; points to current place page: -1, type: 'cells', yOffset: d.calcdata.headerHeight, diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json new file mode 100644 index 00000000000..f385a8f36f1 --- /dev/null +++ b/test/image/mocks/table_one_cell.json @@ -0,0 +1,86 @@ +{ + "layout": { + "width": 1000, + "height": 810, + "title": "Widget parameters and cost", + "margin": {"t": 380, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [50], + "columnorder": [0], + + "header": { + + "height": 30, + + "values": [ + ["Index" , "#"] + ], + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 12, + "color": "white" + } + }, + + "cells": { + + "values": [ + [0 || "1
B
CD"] + ], + + "format": [ + null + ], + + "prefix": ["#"], + "suffix": ["cell"], + + "height": 15, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fill": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "verdana", + "size": 12, + "color": ["black"] + } + } + }] +} From 0566c21318d3ac77a974a765b79514ea8c2b75a8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 3 Sep 2017 15:59:30 +0200 Subject: [PATCH 049/281] works with normal text (but not LaTeX yet - Y is wrong) --- src/traces/table/plot.js | 33 +++++++++++++++++++++------- test/image/mocks/table_one_cell.json | 8 +++---- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 16084cdf4b4..4609787c0d8 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -339,17 +339,23 @@ function renderColumnBlocks(columnBlock) { return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); }); - var cellText = columnCell.selectAll('.cellText') + var cellTextHolder = columnCell.selectAll('.cellText') + .data(gup.repeat, gup.keyFun); + + cellTextHolder.enter() + .append('g') + .classed('cellTextHolder', true); + + var cellText = cellTextHolder.selectAll('.cellText') .data(gup.repeat, gup.keyFun); cellText.enter() .append('text') .classed('cellText', true); - // it is only in this leaf selection that the actual cell height can be recovered... cellText - .attr('alignment-baseline', 'hanging') + //.attr('alignment-baseline', 'hanging') .text(function(d) { var col = d.column.specIndex; var row = d.rowNumber; @@ -369,7 +375,9 @@ function renderColumnBlocks(columnBlock) { var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; - var renderedHeight = element.getBoundingClientRect().height; + var box = element.getBoundingClientRect(); + var renderedHeight = box.height; + var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); if(increase) { @@ -403,15 +411,24 @@ function renderColumnBlocks(columnBlock) { cellRect.attr('height', rowHeight); cellText - .attr('dy', function(d) { + .attr('transform', function(d) { var height = rowHeight(d); - return ({ - top: -height + c.cellPad, + var yOffset = ({ + top: c.cellPad, middle: -height / 2, - bottom: -c.cellPad - 20 + height + bottom: -c.cellPad + height })[d.valign]; + return 'translate(0 ' + yOffset + ')'; + return yOffset; }); + cellTextHolder + .attr('transform', function(d) { + var element = this; + var box = element.parentElement.getBoundingClientRect(); + var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); + return 'translate(' + c.cellPad + ' ' + (rectBox.bottom - box.bottom - c.cellPad) + ')'; + }); }; function rowFromTo(d) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index f385a8f36f1..6d1e66f1593 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -48,17 +48,17 @@ "cells": { "values": [ - [0 || "1
B
CD"] + ["$LaTeX$" || "AX
B
Plotly

CD"] ], "format": [ null ], - "prefix": ["#"], - "suffix": ["cell"], + //"prefix": ["#"], + //"suffix": ["cell"], - "height": 15, + "height": 5, "align": ["right"], "valign": ["bottom"], From 72ee5d51fbfe1be9dee858a770220f2afafdfd57 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 3 Sep 2017 16:05:37 +0200 Subject: [PATCH 050/281] proper vertical positioning of MathJax --- src/traces/table/plot.js | 29 ++++++++++++++++------------ test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 4609787c0d8..64a0a7eeb74 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -197,7 +197,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(cellsColumnBlock.filter(function(d) {return d.key === anchorChanged;})); + renderColumnBlocks(gd, cellsColumnBlock.filter(function(d) {return d.key === anchorChanged;})); }); } }) @@ -205,7 +205,7 @@ module.exports = function plot(gd, calcdata) { }) ); - renderColumnBlocks(columnBlock); // initial render + renderColumnBlocks(gd, columnBlock); // initial render var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') .data(gup.repeat, gup.keyFun); @@ -268,7 +268,7 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function renderColumnBlocks(columnBlock) { +function renderColumnBlocks(gd, columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization @@ -353,6 +353,19 @@ function renderColumnBlocks(columnBlock) { .append('text') .classed('cellText', true); + var finalizeYPosition = function(cellTextHolder) { + return function() { + cellTextHolder + .attr('transform', function (d) { + var element = this; + var box = element.parentElement.getBoundingClientRect(); + var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); + var yPosition = (rectBox.top - box.top + c.cellPad) + return 'translate(' + c.cellPad + ' ' + yPosition + ')'; + }); + }; + }; + // it is only in this leaf selection that the actual cell height can be recovered... cellText //.attr('alignment-baseline', 'hanging') @@ -371,7 +384,7 @@ function renderColumnBlocks(columnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection); + util.convertToTspans(selection, gd, finalizeYPosition(d3.select(element.parentElement))); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; @@ -421,14 +434,6 @@ function renderColumnBlocks(columnBlock) { return 'translate(0 ' + yOffset + ')'; return yOffset; }); - - cellTextHolder - .attr('transform', function(d) { - var element = this; - var box = element.parentElement.getBoundingClientRect(); - var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); - return 'translate(' + c.cellPad + ' ' + (rectBox.bottom - box.bottom - c.cellPad) + ')'; - }); }; function rowFromTo(d) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 6d1e66f1593..aa0145c3f41 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 1000, + "width": 300, "height": 810, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} @@ -48,7 +48,7 @@ "cells": { "values": [ - ["$LaTeX$" || "AX
B
Plotly

CD"] + ["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "AX
B
Plotly

CD"] ], "format": [ @@ -58,7 +58,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 5, + "height": 9, "align": ["right"], "valign": ["bottom"], From 81fda3e6662f05c2473e970b4e8becf0226f3b9e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 4 Sep 2017 12:28:05 +0200 Subject: [PATCH 051/281] tmp --- src/traces/table/plot.js | 5 ++++- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 64a0a7eeb74..18fcd9ef73f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -138,7 +138,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2/*, headerPanel*/]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -361,11 +361,14 @@ function renderColumnBlocks(gd, columnBlock) { var box = element.parentElement.getBoundingClientRect(); var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); var yPosition = (rectBox.top - box.top + c.cellPad) + debugger + //var yPosition = (rectBox.bottom - box.bottom + c.cellPad) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); }; }; + // it is only in this leaf selection that the actual cell height can be recovered... cellText //.attr('alignment-baseline', 'hanging') diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index aa0145c3f41..88e9c61c300 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -48,7 +48,7 @@ "cells": { "values": [ - ["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "AX
B
Plotly

CD"] + [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly

CD"][1]] ], "format": [ From 06474df85da2a50d40feb1db1f75ecf61ac0cec1 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 4 Sep 2017 15:46:05 +0200 Subject: [PATCH 052/281] tmp2 --- src/traces/table/plot.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 18fcd9ef73f..0267d677ac2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -339,7 +339,7 @@ function renderColumnBlocks(gd, columnBlock) { return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); }); - var cellTextHolder = columnCell.selectAll('.cellText') + var cellTextHolder = columnCell.selectAll('.cellTextHolder') .data(gup.repeat, gup.keyFun); cellTextHolder.enter() @@ -365,10 +365,21 @@ function renderColumnBlocks(gd, columnBlock) { //var yPosition = (rectBox.bottom - box.bottom + c.cellPad) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); + + cellTextHolder.select('.cellText') + .attr('transform', function(d) { + var height = rowHeight(d); + var yOffset = ({ + top: c.cellPad, + middle: -height / 2, + bottom: -c.cellPad + height + })[d.valign]; + return 'translate(0 ' + yOffset + ')'; + return yOffset; + }) }; }; - // it is only in this leaf selection that the actual cell height can be recovered... cellText //.attr('alignment-baseline', 'hanging') @@ -387,7 +398,7 @@ function renderColumnBlocks(gd, columnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection, gd, finalizeYPosition(d3.select(element.parentElement))); + util.convertToTspans(selection, gd, finalizeYPosition(d3.select(element.parentElement.parentElement))); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; @@ -425,18 +436,6 @@ function renderColumnBlocks(gd, columnBlock) { }); cellRect.attr('height', rowHeight); - - cellText - .attr('transform', function(d) { - var height = rowHeight(d); - var yOffset = ({ - top: c.cellPad, - middle: -height / 2, - bottom: -c.cellPad + height - })[d.valign]; - return 'translate(0 ' + yOffset + ')'; - return yOffset; - }); }; function rowFromTo(d) { From 0c29e2ae4dc6e97944f23c1fdb36ad672a207c34 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 4 Sep 2017 20:28:16 +0200 Subject: [PATCH 053/281] baseline for fix --- src/traces/table/plot.js | 83 +++++++++++++++------------- test/image/mocks/table_one_cell.json | 4 +- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 0267d677ac2..5abb8ab03ce 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -353,20 +353,51 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); - var finalizeYPosition = function(cellTextHolder) { + var finalizeYPosition = function(element, d) { return function() { + var columnCell = d3.select(element.parentElement.parentElement); + var l = lookup(d); + var rowIndex = d.key - l.firstRowIndex; + var box = element.getBoundingClientRect(); + var renderedHeight = box.height; + + var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); + + if(increase) { + + // current row height increased + l.rows[d.key - l.firstRowIndex].rowHeight += increase; + + // current block height increased + d.rowBlocks[d.page].totalHeight += increase; + + // subsequent rows in block pushed south + for(var r = rowIndex + 1; r < l.rows.length; r++) { + l.rows[r].rowAnchor += increase; + } + + // subsequent blocks pushed down + for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + d.rowBlocks[p].firstRowAnchor += increase; + } + } + + var cellTextHolder = columnCell.select('.cellTextHolder'); + + if(1) cellTextHolder .attr('transform', function (d) { var element = this; var box = element.parentElement.getBoundingClientRect(); var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); - var yPosition = (rectBox.top - box.top + c.cellPad) - debugger - //var yPosition = (rectBox.bottom - box.bottom + c.cellPad) + //var yPosition = (rectBox.top - box.top) + var yPosition = (rectBox.bottom - box.bottom) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); - cellTextHolder.select('.cellText') + columnCell.select('.cellRect').attr('height', rowHeight); + + cellTextHolder.selectAll('.cellText') .attr('transform', function(d) { var height = rowHeight(d); var yOffset = ({ @@ -376,7 +407,13 @@ function renderColumnBlocks(gd, columnBlock) { })[d.valign]; return 'translate(0 ' + yOffset + ')'; return yOffset; - }) + }); + + if(0) + columnCell + .attr('transform', function(d, i) { + return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; + }); }; }; @@ -398,44 +435,12 @@ function renderColumnBlocks(gd, columnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection, gd, finalizeYPosition(d3.select(element.parentElement.parentElement))); - - var l = lookup(d); - var rowIndex = d.key - l.firstRowIndex; - var box = element.getBoundingClientRect(); - var renderedHeight = box.height; - - var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); - - if(increase) { - - // current row height increased - l.rows[d.key - l.firstRowIndex].rowHeight += increase; - - // current block height increased - d.rowBlocks[d.page].totalHeight += increase; - - // subsequent rows in block pushed south - for(var r = rowIndex + 1; r < l.rows.length; r++) { - l.rows[r].rowAnchor += increase; - } - - // subsequent blocks pushed down - for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchor += increase; - } - } + util.convertToTspans(selection, gd, finalizeYPosition(element, d)); }); // ... therefore all channels for selections above that need to know the height are set below // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses - columnCell - .attr('transform', function(d, i) { - return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; - }); - - cellRect.attr('height', rowHeight); }; function rowFromTo(d) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 88e9c61c300..b6ccc733d16 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -48,7 +48,7 @@ "cells": { "values": [ - [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly

CD"][1]] + [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"][0]] ], "format": [ @@ -58,7 +58,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 9, + "height": 1, "align": ["right"], "valign": ["bottom"], From 19efe5f8e1a9eae9aeb95443116bf2e2ebabb3a4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 4 Sep 2017 20:30:58 +0200 Subject: [PATCH 054/281] looks wonderful for both regular and MathJax --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 0a71c25f1fc..132afb075a3 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -11,7 +11,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, - cellPad: 4, + cellPad: 0, uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5abb8ab03ce..26e8a738712 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -384,19 +384,20 @@ function renderColumnBlocks(gd, columnBlock) { var cellTextHolder = columnCell.select('.cellTextHolder'); + columnCell.select('.cellRect').attr('height', rowHeight); + if(1) cellTextHolder .attr('transform', function (d) { var element = this; var box = element.parentElement.getBoundingClientRect(); var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); - //var yPosition = (rectBox.top - box.top) - var yPosition = (rectBox.bottom - box.bottom) + var yPosition = (rectBox.top - box.top) + //var yPosition = (rectBox.bottom - box.bottom) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); - columnCell.select('.cellRect').attr('height', rowHeight); - + if(0) cellTextHolder.selectAll('.cellText') .attr('transform', function(d) { var height = rowHeight(d); @@ -409,7 +410,7 @@ function renderColumnBlocks(gd, columnBlock) { return yOffset; }); - if(0) + if(1) columnCell .attr('transform', function(d, i) { return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; From c8be760242444b6a681f4c2de1a530d8a6434ece Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 00:19:15 +0200 Subject: [PATCH 055/281] looks wonderful for both regular and MathJax 2 --- src/traces/table/calc.js | 3 ++- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 12 +++++++----- test/image/mocks/table_one_cell.json | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 965d73c3b81..ab171eda84e 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -36,6 +36,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { rowHeight: currentRowHeight, rowAnchor: currentBlockHeight }); + console.log('calc rowHeight is', currentRowHeight) currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; @@ -70,7 +71,7 @@ module.exports = function calc(gd, trace) { columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height + 30 + Math.round((i < 0 ? 0 : 0) * (Math.random() - 0.5));}); + var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 132afb075a3..6ebb41c75aa 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -11,7 +11,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, - cellPad: 0, + cellPad: 20, uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 26e8a738712..1ff97448f56 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -358,15 +358,19 @@ function renderColumnBlocks(gd, columnBlock) { var columnCell = d3.select(element.parentElement.parentElement); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; - var box = element.getBoundingClientRect(); + var box = element.parentElement.getBoundingClientRect(); + var renderedHeight = box.height; var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); + console.log('current height is', renderedHeight, 'and model rowHeight is',l.rows[rowIndex].rowHeight ) + console.log('checking if height increase is needed') if(increase) { - +console.log('height increase!') // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight += increase; + console.log('new rowHeight is', l.rows[d.key - l.firstRowIndex].rowHeight) // current block height increased d.rowBlocks[d.page].totalHeight += increase; @@ -386,14 +390,12 @@ function renderColumnBlocks(gd, columnBlock) { columnCell.select('.cellRect').attr('height', rowHeight); - if(1) cellTextHolder .attr('transform', function (d) { var element = this; var box = element.parentElement.getBoundingClientRect(); var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); - var yPosition = (rectBox.top - box.top) - //var yPosition = (rectBox.bottom - box.bottom) + var yPosition = (rectBox.top - box.top + c.cellPad) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index b6ccc733d16..ee1c7d4f35d 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,7 +20,7 @@ "header": { - "height": 30, + "height": 20, "values": [ ["Index" , "#"] From f546eb242818562c94389dfbdd764fef9c4cb700 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 00:20:38 +0200 Subject: [PATCH 056/281] cleanup --- src/traces/table/plot.js | 18 +----------------- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 1ff97448f56..4c9983658b5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -364,10 +364,8 @@ function renderColumnBlocks(gd, columnBlock) { var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); - console.log('current height is', renderedHeight, 'and model rowHeight is',l.rows[rowIndex].rowHeight ) - console.log('checking if height increase is needed') if(increase) { -console.log('height increase!') + // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight += increase; console.log('new rowHeight is', l.rows[d.key - l.firstRowIndex].rowHeight) @@ -399,20 +397,6 @@ console.log('height increase!') return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); - if(0) - cellTextHolder.selectAll('.cellText') - .attr('transform', function(d) { - var height = rowHeight(d); - var yOffset = ({ - top: c.cellPad, - middle: -height / 2, - bottom: -c.cellPad + height - })[d.valign]; - return 'translate(0 ' + yOffset + ')'; - return yOffset; - }); - - if(1) columnCell .attr('transform', function(d, i) { return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index ee1c7d4f35d..5b46b843a4d 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -48,7 +48,7 @@ "cells": { "values": [ - [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"][0]] + [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"][1]] ], "format": [ From f84905f794b09e4fcce34a478bb703427a5684bc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 00:51:43 +0200 Subject: [PATCH 057/281] awesome but doesn't handle header row increases yet --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 12 ++++++++---- test/image/mocks/table_one_cell.json | 6 +++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 6ebb41c75aa..0a71c25f1fc 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -11,7 +11,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, - cellPad: 20, + cellPad: 4, uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 4c9983658b5..ba427a830d8 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -138,7 +138,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2/*, headerPanel*/]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -355,6 +355,7 @@ function renderColumnBlocks(gd, columnBlock) { var finalizeYPosition = function(element, d) { return function() { + var cellTextHolder = d3.select(element.parentElement); var columnCell = d3.select(element.parentElement.parentElement); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; @@ -382,9 +383,11 @@ function renderColumnBlocks(gd, columnBlock) { for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; } - } - var cellTextHolder = columnCell.select('.cellTextHolder'); + if(d.column.type === 'header') { + // somehow push down possibly already rendered `cells` type rows + } + } columnCell.select('.cellRect').attr('height', rowHeight); @@ -398,7 +401,8 @@ function renderColumnBlocks(gd, columnBlock) { }); columnCell - .attr('transform', function(d, i) { + .attr('transform', function(d) { + var i = d.key; return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; }); }; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 5b46b843a4d..f0e6f23bb2a 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,7 +20,7 @@ "header": { - "height": 20, + "height": 30, "values": [ ["Index" , "#"] @@ -48,7 +48,7 @@ "cells": { "values": [ - [["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"][1]] + ["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"] ], "format": [ @@ -58,7 +58,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 1, + "height": 100, "align": ["right"], "valign": ["bottom"], From 364e5a13ab20e0940e494e58d464fcf300260e49 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 15:29:50 +0200 Subject: [PATCH 058/281] preparing to bump height --- src/traces/table/plot.js | 9 +++++++++ test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ba427a830d8..dc2390d7f48 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -357,6 +357,7 @@ function renderColumnBlocks(gd, columnBlock) { return function() { var cellTextHolder = d3.select(element.parentElement); var columnCell = d3.select(element.parentElement.parentElement); + var columnCells = d3.select(element.parentElement.parentElement.parentElement); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; var box = element.parentElement.getBoundingClientRect(); @@ -387,6 +388,14 @@ function renderColumnBlocks(gd, columnBlock) { if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows } + + if(d.column.type === 'cells') { + columnCells.selectAll('.columnCell').filter(function(dd) { + return dd.key > d.key; + }).each(function(dd) { + console.log('will bump height', dd.key); + }) + } } columnCell.select('.cellRect').attr('height', rowHeight); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index f0e6f23bb2a..043b5827b24 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -58,7 +58,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 100, + "height": 1, "align": ["right"], "valign": ["bottom"], From 778ae6d056a9f84bcb2503de53a9644468d2ef88 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 16:14:31 +0200 Subject: [PATCH 059/281] preparing for rippling through Y --- src/traces/table/plot.js | 11 +++++++---- test/image/mocks/table_one_cell.json | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index dc2390d7f48..1d311d40768 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -353,6 +353,10 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); + var verticalBump = function() { + console.log('vertically bumping (due to changed height)') + } + var finalizeYPosition = function(element, d) { return function() { var cellTextHolder = d3.select(element.parentElement); @@ -390,10 +394,9 @@ function renderColumnBlocks(gd, columnBlock) { } if(d.column.type === 'cells') { - columnCells.selectAll('.columnCell').filter(function(dd) { - return dd.key > d.key; - }).each(function(dd) { - console.log('will bump height', dd.key); + columnCells.selectAll('.columnCell').each(function(dd) { + if(dd.key > d.key) + console.log('will bump height', dd.key); }) } } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 043b5827b24..2f9719ac34d 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -48,7 +48,10 @@ "cells": { "values": [ - ["$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "AX
B
Plotly
CD"] + [ + "AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + ] ], "format": [ From faea3cb4509fd0e27c126194c5333804c0e8b896 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 20:30:52 +0200 Subject: [PATCH 060/281] extracting out bumper --- src/traces/table/plot.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 1d311d40768..6e74fe94f80 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -353,9 +353,18 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); - var verticalBump = function() { - console.log('vertically bumping (due to changed height)') - } + var verticalBump = function(increase, rowIndex, l, d) { + console.log('vertically bumping (due to changed height)'); + // subsequent rows in block pushed south + for(var r = rowIndex + 1; r < l.rows.length; r++) { + l.rows[r].rowAnchor += increase; + } + + // subsequent blocks pushed down + for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + d.rowBlocks[p].firstRowAnchor += increase; + } + }; var finalizeYPosition = function(element, d) { return function() { @@ -379,15 +388,7 @@ function renderColumnBlocks(gd, columnBlock) { // current block height increased d.rowBlocks[d.page].totalHeight += increase; - // subsequent rows in block pushed south - for(var r = rowIndex + 1; r < l.rows.length; r++) { - l.rows[r].rowAnchor += increase; - } - - // subsequent blocks pushed down - for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchor += increase; - } + verticalBump(increase, rowIndex, l, d); if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows From d8aa184066ff06cea034caab9a1193deaf810755 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 21:26:15 +0200 Subject: [PATCH 061/281] push down possibly previously rendered cells --- src/traces/table/plot.js | 18 +++++++----------- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6e74fe94f80..e51916195fb 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -357,6 +357,7 @@ function renderColumnBlocks(gd, columnBlock) { console.log('vertically bumping (due to changed height)'); // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { + console.log('height bumping row', r); l.rows[r].rowAnchor += increase; } @@ -377,13 +378,14 @@ function renderColumnBlocks(gd, columnBlock) { var renderedHeight = box.height; - var increase = Math.max(0, renderedHeight + 2 * c.cellPad - l.rows[rowIndex].rowHeight); + var requiredHeight = renderedHeight + 2 * c.cellPad; + var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); + var increase = finalHeight - l.rows[rowIndex].rowHeight; if(increase) { // current row height increased - l.rows[d.key - l.firstRowIndex].rowHeight += increase; - console.log('new rowHeight is', l.rows[d.key - l.firstRowIndex].rowHeight) + l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; // current block height increased d.rowBlocks[d.page].totalHeight += increase; @@ -393,13 +395,6 @@ function renderColumnBlocks(gd, columnBlock) { if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows } - - if(d.column.type === 'cells') { - columnCells.selectAll('.columnCell').each(function(dd) { - if(dd.key > d.key) - console.log('will bump height', dd.key); - }) - } } columnCell.select('.cellRect').attr('height', rowHeight); @@ -413,7 +408,8 @@ function renderColumnBlocks(gd, columnBlock) { return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); - columnCell + // translate all downstream cells + columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) .attr('transform', function(d) { var i = d.key; return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 2f9719ac34d..d3c2d0bdf38 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -49,8 +49,8 @@ "values": [ [ - "AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "AX
B
Plotly
CD", ] ], From ee33431ecb42979a330d010949d51b015a913f87 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 21:34:14 +0200 Subject: [PATCH 062/281] sparing bump - only do so if increase happened --- src/traces/table/plot.js | 5 ++++- test/image/mocks/table_one_cell.json | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e51916195fb..6243e9482b5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -409,11 +409,14 @@ function renderColumnBlocks(gd, columnBlock) { }); // translate all downstream cells - columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) + // if there's no increase, then the subsequent rows don't need to be pushed down + var impactedColumCells = increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell; + impactedColumCells .attr('transform', function(d) { var i = d.key; return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; }); + }; }; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index d3c2d0bdf38..e07854e982c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -50,7 +50,21 @@ "values": [ [ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "AX
B
Plotly
CD", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", ] ], From 83f0b157590c49cccd435d55312c553e5f23b9a2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 22:48:04 +0200 Subject: [PATCH 063/281] extracting out stuff and pre bumping block --- src/traces/table/plot.js | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6243e9482b5..7176d86f6c9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -353,7 +353,7 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); - var verticalBump = function(increase, rowIndex, l, d) { + function verticalBump(increase, rowIndex, l, d) { console.log('vertically bumping (due to changed height)'); // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { @@ -365,10 +365,17 @@ function renderColumnBlocks(gd, columnBlock) { for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; } - }; + } - var finalizeYPosition = function(element, d) { - return function() { + function translateY(impactedColumCells) { + impactedColumCells + .attr('transform', function(d) { + return 'translate(' + 0 + ' ' + rowOffset(d, d.key) + ')'; + }); + } + + function finalizeYPositionMaker(element, d) { + return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentElement); var columnCell = d3.select(element.parentElement.parentElement); var columnCells = d3.select(element.parentElement.parentElement.parentElement); @@ -410,15 +417,19 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream cells // if there's no increase, then the subsequent rows don't need to be pushed down - var impactedColumCells = increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell; - impactedColumCells - .attr('transform', function(d) { - var i = d.key; - return 'translate(' + 0 + ' ' + rowOffset(d, i) + ')'; - }); + translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) + // translate all downstream panels (naturally, max. 1 of 2) + if(increase) { + d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + .each(function(dd) { + if(dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor) { + debugger; + } + }); + } }; - }; + } // it is only in this leaf selection that the actual cell height can be recovered... cellText @@ -438,7 +449,7 @@ function renderColumnBlocks(gd, columnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection, gd, finalizeYPosition(element, d)); + util.convertToTspans(selection, gd, finalizeYPositionMaker(element, d)); }); // ... therefore all channels for selections above that need to know the height are set below From 271f518dabfabe1e775c755722d772f6f88b6297 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 23:54:40 +0200 Subject: [PATCH 064/281] extracting out column y translate --- src/traces/table/plot.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7176d86f6c9..77963b30171 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -150,7 +150,7 @@ module.exports = function plot(gd, calcdata) { columnBlock .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) - .attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + .call(columnBlockPositionY); cellsColumnBlock .call(d3.behavior.drag() @@ -457,6 +457,10 @@ function renderColumnBlocks(gd, columnBlock) { }; +function columnBlockPositionY(columnBlock) { + columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); +} + function rowFromTo(d) { var rowBlock = d.rowBlocks[d.page]; var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; From 648d50aa26c067f96297997f31a3664492453a8f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 5 Sep 2017 23:58:28 +0200 Subject: [PATCH 065/281] bumping the block if need be --- src/traces/table/plot.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 77963b30171..25a6d4c3642 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -422,11 +422,8 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream panels (naturally, max. 1 of 2) if(increase) { d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') - .each(function(dd) { - if(dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor) { - debugger; - } - }); + .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) + .call(columnBlockPositionY); } }; } From 09138d2b369ecacfe57edb029326d842c21555a6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 6 Sep 2017 00:00:36 +0200 Subject: [PATCH 066/281] two columns --- test/image/mocks/table_one_cell.json | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index e07854e982c..756454b91ec 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 300, + "width": 400, "height": 810, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} @@ -23,7 +23,8 @@ "height": 30, "values": [ - ["Index" , "#"] + ["Index" , "#"], + ["Index2" , "##"] ], "align": ["right"], @@ -48,6 +49,24 @@ "cells": { "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ], [ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", @@ -66,6 +85,7 @@ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", ] + ], "format": [ From 952174c776fe51de947f7883b298381586cf06b2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 6 Sep 2017 01:08:49 +0200 Subject: [PATCH 067/281] bench for fixing 'gap' --- src/traces/table/plot.js | 4 ++-- test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 25a6d4c3642..95555ef4ac3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -49,7 +49,7 @@ module.exports = function plot(gd, calcdata) { .style('box-sizing', 'content-box'); tableControlView - .attr('transform', function(d) {return 'translate(' + d.size.l + ',' + d.size.t + ')';}) + .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}) .attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); var yColumn = tableControlView.selectAll('.yColumn') @@ -60,7 +60,7 @@ module.exports = function plot(gd, calcdata) { .classed('yColumn', true); yColumn - .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); + .attr('transform', function(d) {console.log(d.x); return 'translate(' + d.x + ' 0)';}); yColumn .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 756454b91ec..e74a59714de 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 400, + "width": 500, "height": 810, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} @@ -16,7 +16,7 @@ }, "columnwidth": [50], - "columnorder": [0], + "columnorder": [0, 1], "header": { @@ -84,7 +84,7 @@ "7AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", - ] + ].map(function(d, i) {return i}) ], From 8bf532bdcd7e087dff3dc4862cf21f035639c64b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 6 Sep 2017 18:06:18 +0200 Subject: [PATCH 068/281] fixing column mismatch --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 95555ef4ac3..e858700ddc3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -268,6 +268,7 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; + function renderColumnBlocks(gd, columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch From 897c74e1977cdd2e7f8db913fb6fe61a1e90f8e3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 6 Sep 2017 20:59:04 +0200 Subject: [PATCH 069/281] bench --- src/traces/table/plot.js | 24 +++++++++++++++++++----- test/image/mocks/table_one_cell.json | 14 +++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e858700ddc3..da279456bf2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -138,7 +138,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + return [revolverPanel1/*, revolverPanel2, headerPanel*/]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -268,7 +268,6 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; - function renderColumnBlocks(gd, columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch @@ -371,7 +370,9 @@ function renderColumnBlocks(gd, columnBlock) { function translateY(impactedColumCells) { impactedColumCells .attr('transform', function(d) { - return 'translate(' + 0 + ' ' + rowOffset(d, d.key) + ')'; + var yOffset = rowOffset(d, d.key); + console.log('height induced translateY to', yOffset) + return 'translate(' + 0 + ' ' + yOffset + ')'; }); } @@ -420,11 +421,24 @@ function renderColumnBlocks(gd, columnBlock) { // if there's no increase, then the subsequent rows don't need to be pushed down translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) - // translate all downstream panels (naturally, max. 1 of 2) + // translate all downstream revolver column panels (naturally, max. 1 of 2) if(increase) { d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) - .call(columnBlockPositionY); + .call(columnBlockPositionY) + + //debugger + d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + .filter(function(dd) { return + dd.type === 'cells' && // don't worry about the header rows (yet) + d.column.key === dd.key; // don't worry about other panels (why tho?) + }) + .selectAll('.columnCell') + .filter(function(dd) {return + //dd.key > d.key // only bump preceding columns + //debugger + ;}) + .call(translateY); } }; } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index e74a59714de..6baacddd258 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -50,9 +50,9 @@ "values": [ [ - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", @@ -66,11 +66,11 @@ "7AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", - ], + ].map(function(d, i) {return i}), [ - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", @@ -84,9 +84,9 @@ "7AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", - ].map(function(d, i) {return i}) + ].map(function(d, i) {return d}) - ], + ].map(function(a) {return a.slice(0, 2)}), "format": [ null From 51f3d69d4a7ccc1f70460807cb4ca4f2ce4b9e51 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 6 Sep 2017 22:31:22 +0200 Subject: [PATCH 070/281] works fine w/ revolving scroller --- src/traces/table/plot.js | 59 ++++++++++++++++++++++------ test/image/mocks/table_one_cell.json | 12 +++--- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index da279456bf2..23f10879bad 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -60,7 +60,7 @@ module.exports = function plot(gd, calcdata) { .classed('yColumn', true); yColumn - .attr('transform', function(d) {console.log(d.x); return 'translate(' + d.x + ' 0)';}); + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); yColumn .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) @@ -138,7 +138,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1/*, revolverPanel2, headerPanel*/]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -354,10 +354,8 @@ function renderColumnBlocks(gd, columnBlock) { .classed('cellText', true); function verticalBump(increase, rowIndex, l, d) { - console.log('vertically bumping (due to changed height)'); // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { - console.log('height bumping row', r); l.rows[r].rowAnchor += increase; } @@ -371,11 +369,29 @@ function renderColumnBlocks(gd, columnBlock) { impactedColumCells .attr('transform', function(d) { var yOffset = rowOffset(d, d.key); - console.log('height induced translateY to', yOffset) return 'translate(' + 0 + ' ' + yOffset + ')'; }); } + function translateY2(impactedColumCells) { + impactedColumCells + .attr('transform', function(d) { + var yOffset = rowOffset(d, d.key); + return 'translate(' + 0 + ' ' + yOffset + ')'; + }); + } + + function setRowHeight(columnCell) { + columnCell.select('.cellRect').attr('height', rowHeight); + } + + function setRowHeight2(columnCell) { + columnCell.select('.cellRect').attr('height', function(d) { + var newValue = rowHeight(d); + return newValue; + }); + } + function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentElement); @@ -406,7 +422,7 @@ function renderColumnBlocks(gd, columnBlock) { } } - columnCell.select('.cellRect').attr('height', rowHeight); + columnCell.call(setRowHeight); cellTextHolder .attr('transform', function (d) { @@ -427,18 +443,34 @@ function renderColumnBlocks(gd, columnBlock) { .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) .call(columnBlockPositionY) - //debugger - d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') - .filter(function(dd) { return - dd.type === 'cells' && // don't worry about the header rows (yet) + + // height increasing stuff in the same row + d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + .filter(function(dd) { + return dd.type === 'cells' && // don't worry about the header rows (yet) + d.column.key === dd.key; // don't worry about other panels (why tho?) + }) + .selectAll('.columnCell') + .filter(function(dd) {return true + //dd.key > d.key // only bump preceding columns + //debugger + ;}) + .call(setRowHeight2); + + + + //downshifting other cells + d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + .filter(function(dd) { + return dd.type === 'cells' && // don't worry about the header rows (yet) d.column.key === dd.key; // don't worry about other panels (why tho?) }) .selectAll('.columnCell') - .filter(function(dd) {return + .filter(function(dd) {return true //dd.key > d.key // only bump preceding columns //debugger ;}) - .call(translateY); + .call(translateY2); } }; } @@ -519,7 +551,8 @@ function lookup(d) { function rowOffset(d, i) { var l = lookup(d); - var o = (l.rows[i].rowAnchor + l.firstRowAnchor) - d.column.anchor; + // fixme unify this with the next function, e.g. `l.rows[i - l.firstRowIndex]` + var o = (l.rows[i - l.firstRowIndex].rowAnchor + l.firstRowAnchor) - d.column.anchor; return o; } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 6baacddd258..56b66263f2e 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -50,9 +50,9 @@ "values": [ [ - //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", - //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", @@ -68,9 +68,9 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", - //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", @@ -86,7 +86,7 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 2)}), + ].map(function(a) {return a.slice(0, Infinity)}), "format": [ null @@ -95,7 +95,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 1, + "height": 5, "align": ["right"], "valign": ["bottom"], From 1d72175d24d8f0043d352ca63cb01c9ebc749f16 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 00:13:00 +0200 Subject: [PATCH 071/281] cleanup --- src/traces/table/plot.js | 43 +++++++++------------------- test/image/mocks/table_one_cell.json | 29 +++++++++++++++---- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 23f10879bad..316cc9ff5c5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -365,33 +365,6 @@ function renderColumnBlocks(gd, columnBlock) { } } - function translateY(impactedColumCells) { - impactedColumCells - .attr('transform', function(d) { - var yOffset = rowOffset(d, d.key); - return 'translate(' + 0 + ' ' + yOffset + ')'; - }); - } - - function translateY2(impactedColumCells) { - impactedColumCells - .attr('transform', function(d) { - var yOffset = rowOffset(d, d.key); - return 'translate(' + 0 + ' ' + yOffset + ')'; - }); - } - - function setRowHeight(columnCell) { - columnCell.select('.cellRect').attr('height', rowHeight); - } - - function setRowHeight2(columnCell) { - columnCell.select('.cellRect').attr('height', function(d) { - var newValue = rowHeight(d); - return newValue; - }); - } - function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentElement); @@ -455,7 +428,7 @@ function renderColumnBlocks(gd, columnBlock) { //dd.key > d.key // only bump preceding columns //debugger ;}) - .call(setRowHeight2); + .call(setRowHeight); @@ -470,7 +443,7 @@ function renderColumnBlocks(gd, columnBlock) { //dd.key > d.key // only bump preceding columns //debugger ;}) - .call(translateY2); + .call(translateY); } }; } @@ -549,6 +522,18 @@ function lookup(d) { return d.rowBlocks[d.page]; } +function translateY(impactedColumCells) { + impactedColumCells + .attr('transform', function(d) { + var yOffset = rowOffset(d, d.key); + return 'translate(' + 0 + ' ' + yOffset + ')'; + }); +} + +function setRowHeight(columnCell) { + columnCell.select('.cellRect').attr('height', rowHeight); +} + function rowOffset(d, i) { var l = lookup(d); // fixme unify this with the next function, e.g. `l.rows[i - l.firstRowIndex]` diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 56b66263f2e..b1ea274866c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 500, + "width": 600, "height": 810, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} @@ -15,16 +15,17 @@ "y": [0, 1] }, - "columnwidth": [50], - "columnorder": [0, 1], + "columnwidth": [20, 50, 50], + "columnorder": [0, 1, 2], "header": { - "height": 30, + "height": [30, 20], "values": [ ["Index" , "#"], - ["Index2" , "##"] + ["Column 2" , "kg"], + ["Column 3" , "hours"] ], "align": ["right"], @@ -84,6 +85,24 @@ "7AX
B
Plotly
CD", "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) ].map(function(a) {return a.slice(0, Infinity)}), From a530aeadeebf119c3dbb1c58c1cefb9a8bbf0da7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 00:14:08 +0200 Subject: [PATCH 072/281] remove parentElement 1 --- src/traces/table/plot.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 316cc9ff5c5..3f445d61b59 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -367,12 +367,12 @@ function renderColumnBlocks(gd, columnBlock) { function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { - var cellTextHolder = d3.select(element.parentElement); - var columnCell = d3.select(element.parentElement.parentElement); - var columnCells = d3.select(element.parentElement.parentElement.parentElement); + var cellTextHolder = d3.select(element.parentNode); + var columnCell = d3.select(element.parentNode.parentNode); + var columnCells = d3.select(element.parentNode.parentNode.parentNode); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; - var box = element.parentElement.getBoundingClientRect(); + var box = element.parentNode.getBoundingClientRect(); var renderedHeight = box.height; @@ -400,8 +400,8 @@ function renderColumnBlocks(gd, columnBlock) { cellTextHolder .attr('transform', function (d) { var element = this; - var box = element.parentElement.getBoundingClientRect(); - var rectBox = d3.select(element.parentElement).select('.cellRect').node().getBoundingClientRect(); + var box = element.parentNode.getBoundingClientRect(); + var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); var yPosition = (rectBox.top - box.top + c.cellPad) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); @@ -412,13 +412,13 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream revolver column panels (naturally, max. 1 of 2) if(increase) { - d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) .call(columnBlockPositionY) // height increasing stuff in the same row - d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') .filter(function(dd) { return dd.type === 'cells' && // don't worry about the header rows (yet) d.column.key === dd.key; // don't worry about other panels (why tho?) @@ -433,7 +433,7 @@ function renderColumnBlocks(gd, columnBlock) { //downshifting other cells - d3.select(element.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement).selectAll('.columnBlock') + d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') .filter(function(dd) { return dd.type === 'cells' && // don't worry about the header rows (yet) d.column.key === dd.key; // don't worry about other panels (why tho?) From 7bf3b6d457750e07230cf448cdb34195158254e2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 00:29:44 +0200 Subject: [PATCH 073/281] remove parentElement 2 --- src/traces/table/calc.js | 1 - src/traces/table/plot.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index ab171eda84e..1c236d11a51 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -36,7 +36,6 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { rowHeight: currentRowHeight, rowAnchor: currentBlockHeight }); - console.log('calc rowHeight is', currentRowHeight) currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3f445d61b59..7dbf77c956a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -418,7 +418,7 @@ function renderColumnBlocks(gd, columnBlock) { // height increasing stuff in the same row - d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') + columnBlock .filter(function(dd) { return dd.type === 'cells' && // don't worry about the header rows (yet) d.column.key === dd.key; // don't worry about other panels (why tho?) @@ -433,7 +433,7 @@ function renderColumnBlocks(gd, columnBlock) { //downshifting other cells - d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') + columnBlock .filter(function(dd) { return dd.type === 'cells' && // don't worry about the header rows (yet) d.column.key === dd.key; // don't worry about other panels (why tho?) From 6971915d95b3e6916928411bbd9ecdc73e6d64bb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 15:42:43 +0200 Subject: [PATCH 074/281] removing parentNode crowd --- src/traces/table/plot.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7dbf77c956a..7e755bc13d4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -412,7 +412,7 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream revolver column panels (naturally, max. 1 of 2) if(increase) { - d3.select(element.parentNode.parentNode.parentNode.parentNode.parentNode).selectAll('.columnBlock') + columnBlock.filter(function(dd) {return dd.xIndex === d.column.xIndex;}) .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) .call(columnBlockPositionY) @@ -430,8 +430,6 @@ function renderColumnBlocks(gd, columnBlock) { ;}) .call(setRowHeight); - - //downshifting other cells columnBlock .filter(function(dd) { From c7ef24df546b0d7c46fc6bafc9e53fbb7c8b9f35 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 15:47:26 +0200 Subject: [PATCH 075/281] simplify --- src/traces/table/plot.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7e755bc13d4..9df48726438 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -424,10 +424,6 @@ function renderColumnBlocks(gd, columnBlock) { d.column.key === dd.key; // don't worry about other panels (why tho?) }) .selectAll('.columnCell') - .filter(function(dd) {return true - //dd.key > d.key // only bump preceding columns - //debugger - ;}) .call(setRowHeight); //downshifting other cells From 986933615855b5b54588ffef53f0fba6799a9584 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 16:30:33 +0200 Subject: [PATCH 076/281] header rows look reasonable --- src/traces/table/plot.js | 6 ++---- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 9df48726438..a1318a17dae 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -420,8 +420,7 @@ function renderColumnBlocks(gd, columnBlock) { // height increasing stuff in the same row columnBlock .filter(function(dd) { - return dd.type === 'cells' && // don't worry about the header rows (yet) - d.column.key === dd.key; // don't worry about other panels (why tho?) + return d.column.key === dd.key; // don't worry about other panels (why tho?) }) .selectAll('.columnCell') .call(setRowHeight); @@ -429,8 +428,7 @@ function renderColumnBlocks(gd, columnBlock) { //downshifting other cells columnBlock .filter(function(dd) { - return dd.type === 'cells' && // don't worry about the header rows (yet) - d.column.key === dd.key; // don't worry about other panels (why tho?) + return d.column.key === dd.key; // don't worry about other panels (why tho?) }) .selectAll('.columnCell') .filter(function(dd) {return true diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index b1ea274866c..3cf7fba5eaa 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -24,7 +24,7 @@ "values": [ ["Index" , "#"], - ["Column 2" , "kg"], + ["Column 2" , "1AX
B
Plotly
CD"], ["Column 3" , "hours"] ], From cd6d859c3b3da98773c55745582b334f55fb1980 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 16:34:20 +0200 Subject: [PATCH 077/281] simplifying bumps --- src/traces/table/plot.js | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a1318a17dae..3247197404c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -412,30 +412,19 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream revolver column panels (naturally, max. 1 of 2) if(increase) { - columnBlock.filter(function(dd) {return dd.xIndex === d.column.xIndex;}) - .filter(function(dd) {return dd.type === 'cells' && d.column.type === 'cells' && dd.anchor > d.column.anchor;}) - .call(columnBlockPositionY) - - - // height increasing stuff in the same row columnBlock - .filter(function(dd) { - return d.column.key === dd.key; // don't worry about other panels (why tho?) - }) - .selectAll('.columnCell') - .call(setRowHeight); + .filter(function(dd) {return ( + dd.xIndex === d.column.xIndex && + dd.type === 'cells' && + d.column.type === 'cells' && + dd.anchor > d.column.anchor + );}) + .call(columnBlockPositionY) - //downshifting other cells columnBlock - .filter(function(dd) { - return d.column.key === dd.key; // don't worry about other panels (why tho?) - }) .selectAll('.columnCell') - .filter(function(dd) {return true - //dd.key > d.key // only bump preceding columns - //debugger - ;}) - .call(translateY); + .call(setRowHeight) // height increasing stuff in the same row + .call(translateY); //downshifting other cells } }; } From 7de89307d5573273ff356f5a197c0667a7ef697c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 16:36:48 +0200 Subject: [PATCH 078/281] oversimplification --- src/traces/table/plot.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3247197404c..de65bab697f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -413,15 +413,7 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream revolver column panels (naturally, max. 1 of 2) if(increase) { columnBlock - .filter(function(dd) {return ( - dd.xIndex === d.column.xIndex && - dd.type === 'cells' && - d.column.type === 'cells' && - dd.anchor > d.column.anchor - );}) .call(columnBlockPositionY) - - columnBlock .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row .call(translateY); //downshifting other cells From 6a6b876713384de34081f8a1dfbd0928aef5b932 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 20:32:40 +0200 Subject: [PATCH 079/281] avoid some work --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index de65bab697f..6dda4e474c7 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -393,10 +393,10 @@ function renderColumnBlocks(gd, columnBlock) { if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows } + } else { + columnCell.call(setRowHeight); // simply set the height } - columnCell.call(setRowHeight); - cellTextHolder .attr('transform', function (d) { var element = this; From 027cd3ae2d4108280427b7a2c9249d2d82ef8dff Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 7 Sep 2017 20:34:39 +0200 Subject: [PATCH 080/281] regrouping stuff as per conditional --- src/traces/table/plot.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6dda4e474c7..b25e9334a47 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -393,6 +393,13 @@ function renderColumnBlocks(gd, columnBlock) { if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows } + + // translate all downstream revolver column panels (naturally, max. 1 of 2) + columnBlock + .call(columnBlockPositionY) + .selectAll('.columnCell') + .call(setRowHeight) // height increasing stuff in the same row + .call(translateY); //downshifting other cells } else { columnCell.call(setRowHeight); // simply set the height } @@ -409,15 +416,6 @@ function renderColumnBlocks(gd, columnBlock) { // translate all downstream cells // if there's no increase, then the subsequent rows don't need to be pushed down translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) - - // translate all downstream revolver column panels (naturally, max. 1 of 2) - if(increase) { - columnBlock - .call(columnBlockPositionY) - .selectAll('.columnCell') - .call(setRowHeight) // height increasing stuff in the same row - .call(translateY); //downshifting other cells - } }; } From 6811b1c52f7a1a24e3483ebcd146a7ca5ad40004 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 8 Sep 2017 10:52:10 +0200 Subject: [PATCH 081/281] bench for header row thingie --- test/image/mocks/table_one_cell.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 3cf7fba5eaa..558a571568b 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,13 +20,13 @@ "header": { - "height": [30, 20], + "height": [1,1], "values": [ ["Index" , "#"], ["Column 2" , "1AX
B
Plotly
CD"], ["Column 3" , "hours"] - ], + ].map(function(r) {return r.slice(1, 2)}).slice(1, 2), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, Infinity)}), + ].map(function(a) {return a.slice(1, 2)}).slice(0, 1), "format": [ null From e1b2d0a5bac3e27927aa3cd602b6a1507cbf245a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 8 Sep 2017 11:16:02 +0200 Subject: [PATCH 082/281] minimal bench --- test/image/mocks/table_one_cell.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 558a571568b..2815d20e91d 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,11 +20,11 @@ "header": { - "height": [1,1], + "height": 1, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], - ["Column 2" , "1AX
B
Plotly
CD"], + ["Column 2" , "Header" ||"1AX
B
Plotly
CD"], ["Column 3" , "hours"] ].map(function(r) {return r.slice(1, 2)}).slice(1, 2), From 1acad4fab39e30b2cf61672570044158b42c15c0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 8 Sep 2017 12:51:55 +0200 Subject: [PATCH 083/281] minimal bench --- test/image/mocks/table_one_cell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 2815d20e91d..26a1b0d84a7 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 5, + "height": 50, "align": ["right"], "valign": ["bottom"], From 8cf39a3c4b2e8b80a216e730d02a2c8ad5fbf3bd Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 11:50:48 +0200 Subject: [PATCH 084/281] fixed --- src/traces/table/calc.js | 4 ++-- src/traces/table/plot.js | 24 ++++++++++++++++++++---- test/image/mocks/table_one_cell.json | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 1c236d11a51..c4391b0df15 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -69,7 +69,7 @@ module.exports = function calc(gd, trace) { var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); + var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + 0 * Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; @@ -88,7 +88,7 @@ module.exports = function calc(gd, trace) { var uniqueKeys = {}; var columnOrder = trace._fullInput.columnorder; - +console.log('calc headerHeight', headerHeight) var calcdata = { key: trace.index, translateX: domain.x[0] * gd._fullLayout._size.w, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b25e9334a47..7039cf75084 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -138,7 +138,8 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + console.log('height yOffsets', headerPanel.yOffset, revolverPanel1.yOffset, revolverPanel2.yOffset) + return [revolverPanel1, /*revolverPanel2, */headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -367,6 +368,7 @@ function renderColumnBlocks(gd, columnBlock) { function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { + console.log('finalizeYPositionMaker height', d.value) var cellTextHolder = d3.select(element.parentNode); var columnCell = d3.select(element.parentNode.parentNode); var columnCells = d3.select(element.parentNode.parentNode.parentNode); @@ -380,6 +382,8 @@ function renderColumnBlocks(gd, columnBlock) { var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); var increase = finalHeight - l.rows[rowIndex].rowHeight; + console.log('height increase:', increase) + if(increase) { // current row height increased @@ -391,12 +395,21 @@ function renderColumnBlocks(gd, columnBlock) { verticalBump(increase, rowIndex, l, d); if(d.column.type === 'header') { + console.log('height increase, `header`') // somehow push down possibly already rendered `cells` type rows } - // translate all downstream revolver column panels (naturally, max. 1 of 2) + window.monfera = true + console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) columnBlock - .call(columnBlockPositionY) + .each(function(dd) { + console.log('height thinking:', dd.anchor, dd.yOffset, d.column.anchor, d.column.yOffset) + if(d.column !== dd && dd.anchor + dd.yOffset >= d.column.anchor + d.column.yOffset) { + console.log('height increase in each:', increase) + dd.yOffset += increase; + } + }) + .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row .call(translateY); //downshifting other cells @@ -446,7 +459,10 @@ function renderColumnBlocks(gd, columnBlock) { }; function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + columnBlock.attr('transform', function(d) { + //if(window.monfera) debugger + console.log('height induced translate:', d.anchor, d.yOffset) + return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); } function rowFromTo(d) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 26a1b0d84a7..43a6a338d21 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -24,7 +24,7 @@ "values": [ ["Index" , "#"], - ["Column 2" , "Header" ||"1AX
B
Plotly
CD"], + ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "hours"] ].map(function(r) {return r.slice(1, 2)}).slice(1, 2), From 5add9c9061db29921c7b0d3e1389faf878b4292e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 12:19:24 +0200 Subject: [PATCH 085/281] actually good for some reason (previous one wasn't) --- src/traces/table/plot.js | 24 +++++++++++++++++++----- test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7039cf75084..bfe0e98b3ce 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -139,7 +139,7 @@ module.exports = function plot(gd, calcdata) { revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; console.log('height yOffsets', headerPanel.yOffset, revolverPanel1.yOffset, revolverPanel2.yOffset) - return [revolverPanel1, /*revolverPanel2, */headerPanel]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() @@ -354,18 +354,25 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); - function verticalBump(increase, rowIndex, l, d) { + function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { l.rows[r].rowAnchor += increase; } + } + function verticalBumpBlocks(increase, d) { // subsequent blocks pushed down for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; } } + function verticalBump(increase, rowIndex, l, d) { + verticalBumpRows(increase, rowIndex, l); + verticalBumpBlocks(increase, d); + } + function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { console.log('finalizeYPositionMaker height', d.value) @@ -392,11 +399,17 @@ function renderColumnBlocks(gd, columnBlock) { // current block height increased d.rowBlocks[d.page].totalHeight += increase; - verticalBump(increase, rowIndex, l, d); - if(d.column.type === 'header') { console.log('height increase, `header`') // somehow push down possibly already rendered `cells` type rows + columnBlock.each(function(dd, i) { + if(i === 1) //{return;} + verticalBumpBlocks(increase, dd); + }) + verticalBumpRows(increase, rowIndex, l); + } + else { + verticalBump(increase, rowIndex, l, d); } window.monfera = true @@ -406,7 +419,8 @@ function renderColumnBlocks(gd, columnBlock) { console.log('height thinking:', dd.anchor, dd.yOffset, d.column.anchor, d.column.yOffset) if(d.column !== dd && dd.anchor + dd.yOffset >= d.column.anchor + d.column.yOffset) { console.log('height increase in each:', increase) - dd.yOffset += increase; + + //dd.yOffset += increase; } }) .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 43a6a338d21..af40300aa3e 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 810, + "height": 610, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "hours"] - ].map(function(r) {return r.slice(1, 2)}).slice(1, 2), + ].map(function(r) {return r.slice(0, Infinity)}).slice(1, 2), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(1, 2)}).slice(0, 1), + ].map(function(a) {return a.slice(0, Infinity)}).slice(0, 1), "format": [ null From 4b3125151e9091f20e3f61795e6437d5f61aeb41 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 12:22:22 +0200 Subject: [PATCH 086/281] minor simpl. --- src/traces/table/plot.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index bfe0e98b3ce..745e91b2247 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -368,11 +368,6 @@ function renderColumnBlocks(gd, columnBlock) { } } - function verticalBump(increase, rowIndex, l, d) { - verticalBumpRows(increase, rowIndex, l); - verticalBumpBlocks(increase, d); - } - function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { console.log('finalizeYPositionMaker height', d.value) @@ -406,12 +401,13 @@ function renderColumnBlocks(gd, columnBlock) { if(i === 1) //{return;} verticalBumpBlocks(increase, dd); }) - verticalBumpRows(increase, rowIndex, l); } else { - verticalBump(increase, rowIndex, l, d); + verticalBumpBlocks(increase, d); } + verticalBumpRows(increase, rowIndex, l); + window.monfera = true console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) columnBlock From 8b7540b58e811738e648f12b2ea42225bb978cf3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 12:29:35 +0200 Subject: [PATCH 087/281] fix baseline --- test/image/mocks/table_one_cell.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index af40300aa3e..75f09eed0db 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 610, + "height": 710, "title": "Widget parameters and cost", "margin": {"t": 380, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "hours"] - ].map(function(r) {return r.slice(0, Infinity)}).slice(1, 2), + ].map(function(r) {return r.slice(0, Infinity)}).slice(0, 3), "align": ["right"], "valign": "middle", @@ -69,21 +69,21 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "4AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "5AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "6AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "7AX
B
Plotly
CD", - "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "8AX
B
Plotly
CD", ].map(function(d, i) {return d}), [ @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, Infinity)}).slice(0, 1), + ].map(function(a) {return a.slice(0, Infinity)}).slice(0, 3), "format": [ null @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 50, + "height": 1, "align": ["right"], "valign": ["bottom"], From 3e028d628446b20d46710247f07179bdb95c0db9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 12:36:23 +0200 Subject: [PATCH 088/281] simpl. --- src/traces/table/plot.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 745e91b2247..2fa514963b1 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -387,7 +387,6 @@ function renderColumnBlocks(gd, columnBlock) { console.log('height increase:', increase) if(increase) { - // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; @@ -411,14 +410,6 @@ function renderColumnBlocks(gd, columnBlock) { window.monfera = true console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) columnBlock - .each(function(dd) { - console.log('height thinking:', dd.anchor, dd.yOffset, d.column.anchor, d.column.yOffset) - if(d.column !== dd && dd.anchor + dd.yOffset >= d.column.anchor + d.column.yOffset) { - console.log('height increase in each:', increase) - - //dd.yOffset += increase; - } - }) .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row From 3c023311ec3787b3195a1c2530410227368806eb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 10 Sep 2017 12:40:12 +0200 Subject: [PATCH 089/281] bench --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2fa514963b1..3eb5522eb7f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -394,7 +394,7 @@ function renderColumnBlocks(gd, columnBlock) { d.rowBlocks[d.page].totalHeight += increase; if(d.column.type === 'header') { - console.log('height increase, `header`') + console.log('height increase, `header` item cnt', columnBlock[0].length) // somehow push down possibly already rendered `cells` type rows columnBlock.each(function(dd, i) { if(i === 1) //{return;} diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 75f09eed0db..5d6e41cd5dc 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "hours"] - ].map(function(r) {return r.slice(0, Infinity)}).slice(0, 3), + ].map(function(r) {return r.slice(0, 1)}).slice(0, 2), "align": ["right"], "valign": "middle", @@ -69,7 +69,7 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "A" || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, Infinity)}).slice(0, 3), + ].map(function(a) {return a.slice(0, 1)}).slice(0, 2), "format": [ null From 9e291dbd0a195b6f08272f8844f0707cd2a9ccb3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 05:49:28 +0200 Subject: [PATCH 090/281] bench --- test/image/mocks/table_one_cell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 5d6e41cd5dc..fa6cc389ad4 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -3,7 +3,7 @@ "width": 600, "height": 710, "title": "Widget parameters and cost", - "margin": {"t": 380, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0.1 || 380, "r": 60, "b": 54, "l": 60} }, "data": [{ From 7a12fb87790e9d03c11d716b0d90c02e76aac8e4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 06:15:53 +0200 Subject: [PATCH 091/281] candidate --- src/traces/table/plot.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3eb5522eb7f..745ebae25c8 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -361,10 +361,25 @@ function renderColumnBlocks(gd, columnBlock) { } } - function verticalBumpBlocks(increase, d) { + function verticalBumpBlocks(increase, d, xIndex) { // subsequent blocks pushed down - for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchor += increase; + //console.log('xIndex', xIndex) + if(xIndex === 0) { + for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + //console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) + d.rowBlocks[p].firstRowAnchor += increase; + } + } + } + + function verticalBumpBlocksAll(increase, d, xIndex) { + // subsequent blocks pushed down + console.log('xIndex', xIndex) + if(xIndex === 0) { + for(var p = 0; p < d.rowBlocks.length; p++) { + console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) + d.rowBlocks[p].firstRowAnchor += increase; + } } } @@ -396,13 +411,16 @@ function renderColumnBlocks(gd, columnBlock) { if(d.column.type === 'header') { console.log('height increase, `header` item cnt', columnBlock[0].length) // somehow push down possibly already rendered `cells` type rows + var bumped = false columnBlock.each(function(dd, i) { - if(i === 1) //{return;} - verticalBumpBlocks(increase, dd); + if(!bumped && dd.type !== 'header') { + verticalBumpBlocksAll(increase, dd, dd.xIndex); + bumped = true; + } }) } else { - verticalBumpBlocks(increase, d); + verticalBumpBlocks(increase, d, d.column.xIndex); } verticalBumpRows(increase, rowIndex, l); From 69281767b8d4c9d5bc19e0a97a4d4c74d27ec902 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 06:18:42 +0200 Subject: [PATCH 092/281] reopened multirow/column --- test/image/mocks/table_one_cell.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index fa6cc389ad4..8f191e3f747 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 710, + "height": 330, "title": "Widget parameters and cost", "margin": {"t": 0.1 || 380, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "hours"] - ].map(function(r) {return r.slice(0, 1)}).slice(0, 2), + ].map(function(r) {return r.slice(0, Infinity)}).slice(0, Infinity), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 1)}).slice(0, 2), + ].map(function(a) {return a.slice(0, Infinity)}).slice(0, Infinity), "format": [ null From a3d2e81ef93d873f9bb237fc43507fa1c348911e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 10:42:41 +0200 Subject: [PATCH 093/281] mock update --- test/image/mocks/table_one_cell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 8f191e3f747..d866927fce6 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -25,7 +25,7 @@ "values": [ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], - ["Column 3" , "hours"] + ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] ].map(function(r) {return r.slice(0, Infinity)}).slice(0, Infinity), "align": ["right"], From 99f37d455cf4f1473b9c22e7ab344de96b51e957 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 15:27:15 +0200 Subject: [PATCH 094/281] mock update --- test/image/mocks/table_one_cell.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index d866927fce6..3a018660b00 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,9 +1,9 @@ { "layout": { "width": 600, - "height": 330, + "height": 330 + 380, "title": "Widget parameters and cost", - "margin": {"t": 0.1 || 380, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} }, "data": [{ From 18c8948093552b508ff2618c813844dd6b97a4f8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 18:55:36 +0200 Subject: [PATCH 095/281] good header-first rendering --- src/traces/table/plot.js | 27 +++++++++++++++++++++++---- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 745ebae25c8..b8d0f814c3e 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -147,7 +147,7 @@ module.exports = function plot(gd, calcdata) { .classed('columnBlock', true) .style('user-select', 'none'); - var cellsColumnBlock = columnBlock.filter(function(d) {return d.type === 'cells';}); + var cellsColumnBlock = columnBlock.filter(cellsBlock); columnBlock .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) @@ -206,7 +206,13 @@ module.exports = function plot(gd, calcdata) { }) ); - renderColumnBlocks(gd, columnBlock); // initial render + // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) + // but blocks are _entered_ the way they are due to painter's algo (header on top) + var cellText1 = renderColumnBlockContainers(columnBlock.filter(headerBlock)); + var cellText2 = renderColumnBlockContainers(columnBlock.filter(cellsBlock)); + + renderColumnBlockContents(gd, columnBlock, columnBlock.filter(headerBlock), cellText1); // initial render: + renderColumnBlockContents(gd, columnBlock, columnBlock.filter(cellsBlock), cellText2); // initial render: normal cell rows var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') .data(gup.repeat, gup.keyFun); @@ -270,6 +276,11 @@ module.exports = function plot(gd, calcdata) { }; function renderColumnBlocks(gd, columnBlock) { + var cellText = renderColumnBlockContainers(columnBlock); + renderColumnBlockContents(gd, columnBlock, cellText); +} + +function renderColumnBlockContainers(columnBlock) { // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization @@ -354,6 +365,11 @@ function renderColumnBlocks(gd, columnBlock) { .append('text') .classed('cellText', true); + return cellText; +} + +function renderColumnBlockContents(gd, allColumnBlock, columnBlock, cellText) { + function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { @@ -412,7 +428,7 @@ function renderColumnBlocks(gd, columnBlock) { console.log('height increase, `header` item cnt', columnBlock[0].length) // somehow push down possibly already rendered `cells` type rows var bumped = false - columnBlock.each(function(dd, i) { + allColumnBlock.each(function(dd, i) { if(!bumped && dd.type !== 'header') { verticalBumpBlocksAll(increase, dd, dd.xIndex); bumped = true; @@ -475,7 +491,7 @@ function renderColumnBlocks(gd, columnBlock) { // ... therefore all channels for selections above that need to know the height are set below // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses -}; +} function columnBlockPositionY(columnBlock) { columnBlock.attr('transform', function(d) { @@ -552,3 +568,6 @@ function rowHeight(d) { var h = l.rows[d.key - l.firstRowIndex].rowHeight; return h; } + +function cellsBlock(d) {return d.type === 'cells';} +function headerBlock(d) {return d.type === 'header';} \ No newline at end of file diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 3a018660b00..c2b804ba8f4 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, Infinity)}).slice(0, Infinity), + ].map(function(r) {return r.slice(0, 100)}).slice(0, 100), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, Infinity)}).slice(0, Infinity), + ].map(function(a) {return a.slice(0, 100)}).slice(0, Infinity), "format": [ null From 497d2db9ee269229295ecc360f1a6fd2f62a453b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 19:42:07 +0200 Subject: [PATCH 096/281] simplification --- src/traces/table/plot.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b8d0f814c3e..c03c43d7941 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -198,7 +198,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(function(d) {return d.key === anchorChanged;})); + renderColumnBlocks(gd, cellsColumnBlock.filter(anchorChanged), cellsColumnBlock.filter(anchorChanged)); }); } }) @@ -208,11 +208,9 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - var cellText1 = renderColumnBlockContainers(columnBlock.filter(headerBlock)); - var cellText2 = renderColumnBlockContainers(columnBlock.filter(cellsBlock)); - renderColumnBlockContents(gd, columnBlock, columnBlock.filter(headerBlock), cellText1); // initial render: - renderColumnBlockContents(gd, columnBlock, columnBlock.filter(cellsBlock), cellText2); // initial render: normal cell rows + renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); + renderColumnBlocks(gd, columnBlock.filter(cellsBlock), columnBlock); var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') .data(gup.repeat, gup.keyFun); @@ -275,13 +273,7 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; -function renderColumnBlocks(gd, columnBlock) { - var cellText = renderColumnBlockContainers(columnBlock); - renderColumnBlockContents(gd, columnBlock, cellText); -} - -function renderColumnBlockContainers(columnBlock) { - +function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization @@ -365,11 +357,6 @@ function renderColumnBlockContainers(columnBlock) { .append('text') .classed('cellText', true); - return cellText; -} - -function renderColumnBlockContents(gd, allColumnBlock, columnBlock, cellText) { - function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south for(var r = rowIndex + 1; r < l.rows.length; r++) { @@ -570,4 +557,5 @@ function rowHeight(d) { } function cellsBlock(d) {return d.type === 'cells';} -function headerBlock(d) {return d.type === 'header';} \ No newline at end of file +function headerBlock(d) {return d.type === 'header';} +function anchorChanged(d) {return d.key === anchorChanged;} \ No newline at end of file From e0e11f635fa058e0b3e481ac9a72a8b69a773f0a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 19:43:43 +0200 Subject: [PATCH 097/281] fix (anchorChanged); minor factoring out --- src/traces/table/plot.js | 63 ++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c03c43d7941..6b2145e475d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -198,7 +198,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(anchorChanged), cellsColumnBlock.filter(anchorChanged)); + renderColumnBlocks(gd, cellsColumnBlock.filter(anchorChangedFn), cellsColumnBlock.filter(anchorChangedFn)); }); } }) @@ -357,35 +357,6 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .append('text') .classed('cellText', true); - function verticalBumpRows(increase, rowIndex, l) { - // subsequent rows in block pushed south - for(var r = rowIndex + 1; r < l.rows.length; r++) { - l.rows[r].rowAnchor += increase; - } - } - - function verticalBumpBlocks(increase, d, xIndex) { - // subsequent blocks pushed down - //console.log('xIndex', xIndex) - if(xIndex === 0) { - for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - //console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) - d.rowBlocks[p].firstRowAnchor += increase; - } - } - } - - function verticalBumpBlocksAll(increase, d, xIndex) { - // subsequent blocks pushed down - console.log('xIndex', xIndex) - if(xIndex === 0) { - for(var p = 0; p < d.rowBlocks.length; p++) { - console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) - d.rowBlocks[p].firstRowAnchor += increase; - } - } - } - function finalizeYPositionMaker(element, d) { return function finalizeYPosition() { console.log('finalizeYPositionMaker height', d.value) @@ -558,4 +529,34 @@ function rowHeight(d) { function cellsBlock(d) {return d.type === 'cells';} function headerBlock(d) {return d.type === 'header';} -function anchorChanged(d) {return d.key === anchorChanged;} \ No newline at end of file +function anchorChangedFn(d) {return d.key === anchorChanged;} + +function verticalBumpRows(increase, rowIndex, l) { + // subsequent rows in block pushed south + for(var r = rowIndex + 1; r < l.rows.length; r++) { + l.rows[r].rowAnchor += increase; + } +} + +function verticalBumpBlocks(increase, d, xIndex) { + // subsequent blocks pushed down + //console.log('xIndex', xIndex) + if(xIndex === 0) { + for(var p = d.page + 1; p < d.rowBlocks.length; p++) { + //console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) + d.rowBlocks[p].firstRowAnchor += increase; + } + } +} + +function verticalBumpBlocksAll(increase, d, xIndex) { + // subsequent blocks pushed down + console.log('xIndex', xIndex) + if(xIndex === 0) { + for(var p = 0; p < d.rowBlocks.length; p++) { + console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) + d.rowBlocks[p].firstRowAnchor += increase; + } + } +} + From bf23fb219ec92c8c94c9e942185830d018615d6c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 20:47:07 +0200 Subject: [PATCH 098/281] abstracting out more functions --- src/traces/table/plot.js | 137 +++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6b2145e475d..232caddaa33 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -357,74 +357,6 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .append('text') .classed('cellText', true); - function finalizeYPositionMaker(element, d) { - return function finalizeYPosition() { - console.log('finalizeYPositionMaker height', d.value) - var cellTextHolder = d3.select(element.parentNode); - var columnCell = d3.select(element.parentNode.parentNode); - var columnCells = d3.select(element.parentNode.parentNode.parentNode); - var l = lookup(d); - var rowIndex = d.key - l.firstRowIndex; - var box = element.parentNode.getBoundingClientRect(); - - var renderedHeight = box.height; - - var requiredHeight = renderedHeight + 2 * c.cellPad; - var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); - var increase = finalHeight - l.rows[rowIndex].rowHeight; - - console.log('height increase:', increase) - - if(increase) { - // current row height increased - l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; - - // current block height increased - d.rowBlocks[d.page].totalHeight += increase; - - if(d.column.type === 'header') { - console.log('height increase, `header` item cnt', columnBlock[0].length) - // somehow push down possibly already rendered `cells` type rows - var bumped = false - allColumnBlock.each(function(dd, i) { - if(!bumped && dd.type !== 'header') { - verticalBumpBlocksAll(increase, dd, dd.xIndex); - bumped = true; - } - }) - } - else { - verticalBumpBlocks(increase, d, d.column.xIndex); - } - - verticalBumpRows(increase, rowIndex, l); - - window.monfera = true - console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) - columnBlock - .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) - .selectAll('.columnCell') - .call(setRowHeight) // height increasing stuff in the same row - .call(translateY); //downshifting other cells - } else { - columnCell.call(setRowHeight); // simply set the height - } - - cellTextHolder - .attr('transform', function (d) { - var element = this; - var box = element.parentNode.getBoundingClientRect(); - var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); - var yPosition = (rectBox.top - box.top + c.cellPad) - return 'translate(' + c.cellPad + ' ' + yPosition + ')'; - }); - - // translate all downstream cells - // if there's no increase, then the subsequent rows don't need to be pushed down - translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) - }; - } - // it is only in this leaf selection that the actual cell height can be recovered... cellText //.attr('alignment-baseline', 'hanging') @@ -443,7 +375,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection, gd, finalizeYPositionMaker(element, d)); + util.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, columnBlock, element, d)); }); // ... therefore all channels for selections above that need to know the height are set below @@ -560,3 +492,70 @@ function verticalBumpBlocksAll(increase, d, xIndex) { } } +function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { + return function finalizeYPosition() { + console.log('finalizeYPositionMaker height', d.value) + var cellTextHolder = d3.select(element.parentNode); + var columnCell = d3.select(element.parentNode.parentNode); + var columnCells = d3.select(element.parentNode.parentNode.parentNode); + var l = lookup(d); + var rowIndex = d.key - l.firstRowIndex; + var box = element.parentNode.getBoundingClientRect(); + + var renderedHeight = box.height; + + var requiredHeight = renderedHeight + 2 * c.cellPad; + var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); + var increase = finalHeight - l.rows[rowIndex].rowHeight; + + console.log('height increase:', increase) + + if(increase) { + // current row height increased + l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; + + // current block height increased + d.rowBlocks[d.page].totalHeight += increase; + + if(d.column.type === 'header') { + console.log('height increase, `header` item cnt', columnBlock[0].length) + // somehow push down possibly already rendered `cells` type rows + var bumped = false + allColumnBlock.each(function(dd, i) { + if(!bumped && dd.type !== 'header') { + verticalBumpBlocksAll(increase, dd, dd.xIndex); + bumped = true; + } + }) + } + else { + verticalBumpBlocks(increase, d, d.column.xIndex); + } + + verticalBumpRows(increase, rowIndex, l); + + window.monfera = true + console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) + columnBlock + .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) + .selectAll('.columnCell') + .call(setRowHeight) // height increasing stuff in the same row + .call(translateY); //downshifting other cells + } else { + columnCell.call(setRowHeight); // simply set the height + } + + cellTextHolder + .attr('transform', function (d) { + var element = this; + var box = element.parentNode.getBoundingClientRect(); + var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); + var yPosition = (rectBox.top - box.top + c.cellPad) + return 'translate(' + c.cellPad + ' ' + yPosition + ')'; + }); + + // translate all downstream cells + // if there's no increase, then the subsequent rows don't need to be pushed down + translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) + }; +} From 115f132fd2f48fd74c5980e73b5c5b36b413fd97 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 20:52:02 +0200 Subject: [PATCH 099/281] even better fix - no occlusion even if cells rows have no async content --- src/traces/table/plot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 232caddaa33..8c1fdfa6e13 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -536,7 +536,7 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { window.monfera = true console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) - columnBlock + allColumnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row From 479f1201e5a4bd16a0a01a244e829c6b8913e7a2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 21:02:12 +0200 Subject: [PATCH 100/281] remove console.log and debug lines --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index c4391b0df15..97609b25552 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -88,7 +88,7 @@ module.exports = function calc(gd, trace) { var uniqueKeys = {}; var columnOrder = trace._fullInput.columnorder; -console.log('calc headerHeight', headerHeight) + var calcdata = { key: trace.index, translateX: domain.x[0] * gd._fullLayout._size.w, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8c1fdfa6e13..14b2f1bea3a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -138,7 +138,6 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - console.log('height yOffsets', headerPanel.yOffset, revolverPanel1.yOffset, revolverPanel2.yOffset) return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); @@ -384,10 +383,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { } function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) { - //if(window.monfera) debugger - console.log('height induced translate:', d.anchor, d.yOffset) - return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); } function rowFromTo(d) { @@ -472,10 +468,8 @@ function verticalBumpRows(increase, rowIndex, l) { function verticalBumpBlocks(increase, d, xIndex) { // subsequent blocks pushed down - //console.log('xIndex', xIndex) if(xIndex === 0) { for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - //console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) d.rowBlocks[p].firstRowAnchor += increase; } } @@ -483,10 +477,8 @@ function verticalBumpBlocks(increase, d, xIndex) { function verticalBumpBlocksAll(increase, d, xIndex) { // subsequent blocks pushed down - console.log('xIndex', xIndex) if(xIndex === 0) { for(var p = 0; p < d.rowBlocks.length; p++) { - console.log('bumping d.rowBlocks[', p, '].firstRowAnchor by', increase) d.rowBlocks[p].firstRowAnchor += increase; } } @@ -494,7 +486,6 @@ function verticalBumpBlocksAll(increase, d, xIndex) { function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { return function finalizeYPosition() { - console.log('finalizeYPositionMaker height', d.value) var cellTextHolder = d3.select(element.parentNode); var columnCell = d3.select(element.parentNode.parentNode); var columnCells = d3.select(element.parentNode.parentNode.parentNode); @@ -508,8 +499,6 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); var increase = finalHeight - l.rows[rowIndex].rowHeight; - console.log('height increase:', increase) - if(increase) { // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; @@ -518,7 +507,6 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { d.rowBlocks[d.page].totalHeight += increase; if(d.column.type === 'header') { - console.log('height increase, `header` item cnt', columnBlock[0].length) // somehow push down possibly already rendered `cells` type rows var bumped = false allColumnBlock.each(function(dd, i) { @@ -534,8 +522,6 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { verticalBumpRows(increase, rowIndex, l); - window.monfera = true - console.log('height columBlock count:', columnBlock[0].map(function(d) {return d.__data__.key})) allColumnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') From 4fe4ec92fd25d0dd892a5209e8285c3deea30e21 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 21:04:25 +0200 Subject: [PATCH 101/281] remove unused vars --- src/traces/table/plot.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 14b2f1bea3a..1273838f7a6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -374,7 +374,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - util.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, columnBlock, element, d)); + util.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); // ... therefore all channels for selections above that need to know the height are set below @@ -484,7 +484,7 @@ function verticalBumpBlocksAll(increase, d, xIndex) { } } -function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { +function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); var columnCell = d3.select(element.parentNode.parentNode); @@ -509,7 +509,7 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows var bumped = false - allColumnBlock.each(function(dd, i) { + columnBlock.each(function(dd) { if(!bumped && dd.type !== 'header') { verticalBumpBlocksAll(increase, dd, dd.xIndex); bumped = true; @@ -522,7 +522,7 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { verticalBumpRows(increase, rowIndex, l); - allColumnBlock + columnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row @@ -532,7 +532,7 @@ function finalizeYPositionMaker(allColumnBlock, columnBlock, element, d) { } cellTextHolder - .attr('transform', function (d) { + .attr('transform', function () { var element = this; var box = element.parentNode.getBoundingClientRect(); var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); From fe248b5b55a11c8457895920e1c11e9d48fcc465 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 21:10:31 +0200 Subject: [PATCH 102/281] minor simplifications --- src/traces/table/plot.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 1273838f7a6..f62866d308f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -197,7 +197,7 @@ module.exports = function plot(gd, calcdata) { d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(anchorChangedFn), cellsColumnBlock.filter(anchorChangedFn)); + renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) {return d.key === anchorChanged;}), cellsColumnBlock.filter(function (d) {return d.key === anchorChanged;})); }); } }) @@ -444,20 +444,17 @@ function setRowHeight(columnCell) { function rowOffset(d, i) { var l = lookup(d); - // fixme unify this with the next function, e.g. `l.rows[i - l.firstRowIndex]` - var o = (l.rows[i - l.firstRowIndex].rowAnchor + l.firstRowAnchor) - d.column.anchor; - return o; + return lookupRow(l, i).rowAnchor + l.firstRowAnchor - d.column.anchor; } function rowHeight(d) { var l = lookup(d); - var h = l.rows[d.key - l.firstRowIndex].rowHeight; - return h; + return lookupRow(l, d.key).rowHeight; } +function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} function cellsBlock(d) {return d.type === 'cells';} function headerBlock(d) {return d.type === 'header';} -function anchorChangedFn(d) {return d.key === anchorChanged;} function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south From c77cab9cfca5bcb179a106ee78c4cf2a14d15d53 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 21:23:09 +0200 Subject: [PATCH 103/281] well working case - no increases happening --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 3 ++- test/image/mocks/table_one_cell.json | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 0a71c25f1fc..f71ba7f9c24 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -19,5 +19,5 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, - clipView: false + clipView: true }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f62866d308f..6c7f6133aa5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -193,6 +193,7 @@ module.exports = function plot(gd, calcdata) { }); if(anchorChanged) { + console.log('Anchor changed!') window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes @@ -336,7 +337,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .attr('width', function(d) {return d.column.columnWidth;}) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { - return gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); + return c.clipView ? ({header: 'blue', cells1: 'red', cells2: 'green'})[d.column.key] : gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); }) .attr('fill', function(d) { return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index c2b804ba8f4..13dee7f1956 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,7 +20,7 @@ "header": { - "height": 1, // fixme for some reason it doesn't recognize arrays here + "height": 60, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 1, + "height": 80, "align": ["right"], "valign": ["bottom"], From 58402731cda0834d63734493b4825d67dbe22a4b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 22:08:51 +0200 Subject: [PATCH 104/281] don't white flash async cells --- src/traces/table/plot.js | 9 ++++++--- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6c7f6133aa5..05921c801ab 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -375,6 +375,8 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); + columnCell.call(setRowHeight); + translateY(columnCell); util.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); @@ -498,6 +500,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { var increase = finalHeight - l.rows[rowIndex].rowHeight; if(increase) { + debugger // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; @@ -525,8 +528,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { .selectAll('.columnCell') .call(setRowHeight) // height increasing stuff in the same row .call(translateY); //downshifting other cells - } else { - columnCell.call(setRowHeight); // simply set the height } cellTextHolder @@ -540,6 +541,8 @@ function finalizeYPositionMaker(columnBlock, element, d) { // translate all downstream cells // if there's no increase, then the subsequent rows don't need to be pushed down - translateY(increase ? columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;}) : columnCell) + if(increase) { + translateY(columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;})) + } }; } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 13dee7f1956..4bba5cff2d1 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 330 + 380, + "height": 330 + 380 - 0, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} }, From 29b4c33bef996dc92aff8a8128b427f53c16e54c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 11 Sep 2017 23:50:00 +0200 Subject: [PATCH 105/281] bench 0 --- src/traces/table/plot.js | 6 +++++- test/image/mocks/table_one_cell.json | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 05921c801ab..a587a31a8a0 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -17,6 +17,10 @@ var util = require('../../lib/svg_text_utils'); module.exports = function plot(gd, calcdata) { + if(c.clipView) { + gd._fullLayout._paper.attr('height', 2000); + } + var table = gd._fullLayout._paper.selectAll('.table') .data(calcdata.map(gup.unwrap), gup.keyFun); @@ -138,7 +142,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2/*, headerPanel*/]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 4bba5cff2d1..42fedbca73c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 330 + 380 - 0, + "height": 330 + 380 - 200, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} }, @@ -20,13 +20,13 @@ "header": { - "height": 60, // fixme for some reason it doesn't recognize arrays here + "height": 0, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 100)}).slice(0, 100), + ].map(function(r) {return r.slice(0, 100)}).slice(0, 2), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 100)}).slice(0, Infinity), + ].map(function(a) {return a.slice(0, 100)}).slice(0, 2), "format": [ null From 8960249a46d3fe875f1846a3fb6709158da5d288 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 00:18:18 +0200 Subject: [PATCH 106/281] good but 1 column only --- src/traces/table/plot.js | 2 -- test/image/mocks/table_one_cell.json | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a587a31a8a0..2cbda08f641 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -197,7 +197,6 @@ module.exports = function plot(gd, calcdata) { }); if(anchorChanged) { - console.log('Anchor changed!') window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes @@ -504,7 +503,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { var increase = finalHeight - l.rows[rowIndex].rowHeight; if(increase) { - debugger // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 42fedbca73c..c3872347639 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 330 + 380 - 200, + "height": 330 + 380 - 220, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 100)}).slice(0, 2), + ].map(function(r) {return r.slice(0, 100)}).slice(1, 2), "align": ["right"], "valign": "middle", @@ -69,7 +69,7 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "A" || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "0 A" || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 100)}).slice(0, 2), + ].map(function(a) {return a.slice(0, 19)}).slice(1, 2), "format": [ null @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 80, + "height": 40, "align": ["right"], "valign": ["bottom"], From 51199fb54fe7c8ccd23a32bb0f5d4ab0d77e353d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 00:27:46 +0200 Subject: [PATCH 107/281] bench --- test/image/mocks/table_one_cell.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index c3872347639..56eb3b93ad8 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 100)}).slice(1, 2), + ].map(function(r) {return r.slice(0, 100)}).slice(0, 2), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 19)}).slice(1, 2), + ].map(function(a) {return a.slice(0, 19)}).slice(0, 2), "format": [ null From 93eb8427af11207591d3c2d6cb7dd91fdcdeb1dc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 00:29:16 +0200 Subject: [PATCH 108/281] disused --- src/traces/table/plot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2cbda08f641..3540fc1227d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -490,7 +490,6 @@ function verticalBumpBlocksAll(increase, d, xIndex) { function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); - var columnCell = d3.select(element.parentNode.parentNode); var columnCells = d3.select(element.parentNode.parentNode.parentNode); var l = lookup(d); var rowIndex = d.key - l.firstRowIndex; From c8bd5573d4733717d907f19dae4178a8150bdbe8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 01:02:36 +0200 Subject: [PATCH 109/281] bench pre doing away with some anchor stuff --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3540fc1227d..948360c9b5d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -471,7 +471,7 @@ function verticalBumpRows(increase, rowIndex, l) { function verticalBumpBlocks(increase, d, xIndex) { // subsequent blocks pushed down - if(xIndex === 0) { + if(xIndex === 1) { for(var p = d.page + 1; p < d.rowBlocks.length; p++) { d.rowBlocks[p].firstRowAnchor += increase; } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 56eb3b93ad8..05e9281a538 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -16,7 +16,7 @@ }, "columnwidth": [20, 50, 50], - "columnorder": [0, 1, 2], + "columnorder": [0, 1], "header": { From bd4375bca37d4101443e38ee947b5e436c04a605 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 01:16:00 +0200 Subject: [PATCH 110/281] bench pre doing away with some anchor stuff --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 948360c9b5d..440db81f433 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -142,7 +142,7 @@ module.exports = function plot(gd, calcdata) { }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2/*, headerPanel*/]; // order due to SVG using painter's algo + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo }, gup.keyFun); columnBlock.enter() diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 05e9281a538..a67e19b482b 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 330 + 380 - 220, + "height": 330 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} }, @@ -16,17 +16,17 @@ }, "columnwidth": [20, 50, 50], - "columnorder": [0, 1], + "columnorder": [0, 1, 2], "header": { - "height": 0, // fixme for some reason it doesn't recognize arrays here + "height": 20, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 100)}).slice(0, 2), + ].map(function(r) {return r.slice(0, 100)}).slice(0, 4), "align": ["right"], "valign": "middle", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 19)}).slice(0, 2), + ].map(function(a) {return a.slice(0, 19)}).slice(0, 4), "format": [ null From 13676a171d0994f20badac8a218e75ed77814d20 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 01:24:19 +0200 Subject: [PATCH 111/281] removed block totalHeight --- src/traces/table/calc.js | 2 -- src/traces/table/plot.js | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 97609b25552..40e6ee51800 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -13,7 +13,6 @@ var wrap = require('../../lib/gup').wrap; function makeIdentity() { return { - totalHeight: 0, firstRowIndex: null, lastRowIndex: null, rows: [] @@ -41,7 +40,6 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.key = blockCounter++; currentBlock.firstRowAnchor = currentAnchor; - currentBlock.totalHeight = currentBlockHeight; currentBlock.firstRowIndex = currentFirstRowIndex; currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 440db81f433..2c9e850be6a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -130,7 +130,7 @@ module.exports = function plot(gd, calcdata) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', - anchor: d.calcdata.rowBlocks[1] ? -d.calcdata.rowBlocks[1].totalHeight : 0, // will be mutated on scroll; points to current place + anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place page: -1, type: 'cells', yOffset: d.calcdata.headerHeight, @@ -177,7 +177,7 @@ module.exports = function plot(gd, calcdata) { var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var bottom = lastBlock.firstRowAnchor + lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(d.page < 0 || direction === 'down' && scrollY - d.anchor > currentBlock.totalHeight) { + if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blockAnchors.length) { d.page += 2; d.anchor = blockAnchors[d.page]; @@ -461,6 +461,7 @@ function rowHeight(d) { function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} function cellsBlock(d) {return d.type === 'cells';} function headerBlock(d) {return d.type === 'header';} +function totalHeight(rowBlock) {return rowBlock.rows.reduce(function(p,n) {return n.rowHeight + p;}, 0)} function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south @@ -505,9 +506,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; - // current block height increased - d.rowBlocks[d.page].totalHeight += increase; - if(d.column.type === 'header') { // somehow push down possibly already rendered `cells` type rows var bumped = false From b9e33f5e5185f0adc79035e5bfee9bd2ebf530ca Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 02:26:04 +0200 Subject: [PATCH 112/281] loop stead of reduce --- src/traces/table/plot.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2c9e850be6a..c3cf53b5a3a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -461,7 +461,17 @@ function rowHeight(d) { function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} function cellsBlock(d) {return d.type === 'cells';} function headerBlock(d) {return d.type === 'header';} -function totalHeight(rowBlock) {return rowBlock.rows.reduce(function(p,n) {return n.rowHeight + p;}, 0)} +function totalHeight(rowBlock) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + total += rowBlock.rows[i].rowHeight; + } + return total; +} + +function rowAnchor(rowBlock, row) { + return rowBlock.rows.reduce(function(p,n) {return n.rowHeight + p;}, 0) +} function verticalBumpRows(increase, rowIndex, l) { // subsequent rows in block pushed south From f8045d68c56efaff4e259d27ac60c5e960518168 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 02:34:34 +0200 Subject: [PATCH 113/281] got rid of rowAnchor --- src/traces/table/calc.js | 3 +-- src/traces/table/plot.js | 18 +++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 40e6ee51800..fcef03ce664 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -32,8 +32,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { currentRowHeight = rowHeights[i]; currentBlock.rows.push({ rowIndex: i, - rowHeight: currentRowHeight, - rowAnchor: currentBlockHeight + rowHeight: currentRowHeight }); currentBlockHeight += currentRowHeight; if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c3cf53b5a3a..348ffe1f914 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -175,7 +175,7 @@ module.exports = function plot(gd, calcdata) { var blockAnchors = rowBlocks.map(function(v) {return v.firstRowAnchor;}); var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var bottom = lastBlock.firstRowAnchor + lastRow.rowAnchor + lastRow.rowHeight - d.calcdata.scrollHeight; + var bottom = lastBlock.firstRowAnchor + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blockAnchors.length) { @@ -450,7 +450,7 @@ function setRowHeight(columnCell) { function rowOffset(d, i) { var l = lookup(d); - return lookupRow(l, i).rowAnchor + l.firstRowAnchor - d.column.anchor; + return rowAnchor(l, lookupRow(l, i)) + l.firstRowAnchor - d.column.anchor; } function rowHeight(d) { @@ -470,14 +470,12 @@ function totalHeight(rowBlock) { } function rowAnchor(rowBlock, row) { - return rowBlock.rows.reduce(function(p,n) {return n.rowHeight + p;}, 0) -} - -function verticalBumpRows(increase, rowIndex, l) { - // subsequent rows in block pushed south - for(var r = rowIndex + 1; r < l.rows.length; r++) { - l.rows[r].rowAnchor += increase; + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + if(rowBlock.rows[i] === row) break; + total += rowBlock.rows[i].rowHeight; } + return total; } function verticalBumpBlocks(increase, d, xIndex) { @@ -530,8 +528,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { verticalBumpBlocks(increase, d, d.column.xIndex); } - verticalBumpRows(increase, rowIndex, l); - columnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') From 120804869e07b72e828dd24e00df9c2af9cde4e1 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 02:56:42 +0200 Subject: [PATCH 114/281] pre removing firstRowAnchor --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index fcef03ce664..31f3b394067 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -38,7 +38,7 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.key = blockCounter++; - currentBlock.firstRowAnchor = currentAnchor; + currentBlock.firstRowAnchr = currentAnchor; currentBlock.firstRowIndex = currentFirstRowIndex; currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 348ffe1f914..9cda4a1d0a4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -172,10 +172,10 @@ module.exports = function plot(gd, calcdata) { .attr('transform', function(d) { var rowBlocks = d.rowBlocks; var currentBlock = rowBlocks[d.page]; - var blockAnchors = rowBlocks.map(function(v) {return v.firstRowAnchor;}); + var blockAnchors = rowBlocks.map(function(v) {return firstRowAnchor(v);}); var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var bottom = lastBlock.firstRowAnchor + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; + var bottom = firstRowAnchor(lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blockAnchors.length) { @@ -448,9 +448,13 @@ function setRowHeight(columnCell) { columnCell.select('.cellRect').attr('height', rowHeight); } +function firstRowAnchor(l) { + return l.firstRowAnchr; +} + function rowOffset(d, i) { var l = lookup(d); - return rowAnchor(l, lookupRow(l, i)) + l.firstRowAnchor - d.column.anchor; + return rowAnchor(l, lookupRow(l, i)) + firstRowAnchor(l) - d.column.anchor; } function rowHeight(d) { @@ -482,7 +486,7 @@ function verticalBumpBlocks(increase, d, xIndex) { // subsequent blocks pushed down if(xIndex === 1) { for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchor += increase; + d.rowBlocks[p].firstRowAnchr += increase; } } } @@ -491,7 +495,7 @@ function verticalBumpBlocksAll(increase, d, xIndex) { // subsequent blocks pushed down if(xIndex === 0) { for(var p = 0; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchor += increase; + d.rowBlocks[p].firstRowAnchr += increase; } } } From 6756d6cd50834e73fd8db7a1a7eb327fbf2b6e14 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 03:10:17 +0200 Subject: [PATCH 115/281] partially removing firstRowAnchor --- src/traces/table/plot.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 9cda4a1d0a4..be1cc8a3d4f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -172,10 +172,10 @@ module.exports = function plot(gd, calcdata) { .attr('transform', function(d) { var rowBlocks = d.rowBlocks; var currentBlock = rowBlocks[d.page]; - var blockAnchors = rowBlocks.map(function(v) {return firstRowAnchor(v);}); + var blockAnchors = rowBlocks.map(function(v) {return firstRowAnchor(rowBlocks, v);}); var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var bottom = firstRowAnchor(lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; + var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blockAnchors.length) { @@ -436,10 +436,10 @@ function lookup(d) { return d.rowBlocks[d.page]; } -function translateY(impactedColumCells) { - impactedColumCells +function translateY(columCell) { + columCell .attr('transform', function(d) { - var yOffset = rowOffset(d, d.key); + var yOffset = rowOffset(d.rowBlocks, d, d.key); return 'translate(' + 0 + ' ' + yOffset + ')'; }); } @@ -448,13 +448,18 @@ function setRowHeight(columnCell) { columnCell.select('.cellRect').attr('height', rowHeight); } -function firstRowAnchor(l) { - return l.firstRowAnchr; +function firstRowAnchor(rowBlocks, l) { + var total = 0; + for(var i = 0; i < rowBlocks.length; i++) { + if(rowBlocks[i] === l) break; + total += totalHeight(rowBlocks[i]); + } + return total; } -function rowOffset(d, i) { +function rowOffset(rowBlocks, d, i) { var l = lookup(d); - return rowAnchor(l, lookupRow(l, i)) + firstRowAnchor(l) - d.column.anchor; + return rowAnchor(l, lookupRow(l, i)) + firstRowAnchor(rowBlocks, l) - d.column.anchor; } function rowHeight(d) { From ee897045b4e976995c62939d7fbdb6a0fd85b9ac Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 03:33:10 +0200 Subject: [PATCH 116/281] tentative --- src/traces/table/calc.js | 9 +++++---- src/traces/table/plot.js | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 31f3b394067..c2df2753532 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -10,6 +10,7 @@ var c = require('./constants'); var wrap = require('../../lib/gup').wrap; +var extendFlat = require('../../lib/extend').extendFlat; function makeIdentity() { return { @@ -72,15 +73,15 @@ module.exports = function calc(gd, trace) { var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - function rb(anchorToRowBlock) { + function rb(anchorToRowBlock, auxiliary) { var blockAnchorKeys = Object.keys(anchorToRowBlock); - return blockAnchorKeys.map(function(k) {return anchorToRowBlock[k];}) + return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}) } var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); - var rowBlocks = rb(anchorToRowBlock); - var headerRowBlocks = rb(anchorToHeaderRowBlock); + var headerRowBlocks = rb(anchorToHeaderRowBlock, []); + var rowBlocks = rb(anchorToRowBlock, headerRowBlocks); var uniqueKeys = {}; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index be1cc8a3d4f..c0bb9889574 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -121,7 +121,7 @@ module.exports = function plot(gd, calcdata) { type: 'cells', anchor: 0, // will be mutated on scroll; points to current place page: 0, - yOffset: d.calcdata.headerHeight, + yOffset: 0,//d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -133,7 +133,7 @@ module.exports = function plot(gd, calcdata) { anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place page: -1, type: 'cells', - yOffset: d.calcdata.headerHeight, + yOffset: 0,//d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -439,7 +439,8 @@ function lookup(d) { function translateY(columCell) { columCell .attr('transform', function(d) { - var yOffset = rowOffset(d.rowBlocks, d, d.key); + //if(d.rowBlocks[0].auxiliaryBlocks.length) debugger + var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); return 'translate(' + 0 + ' ' + yOffset + ')'; }); } From 7427e6e46b6a9a215c06027b2b82e77005bc1cb2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 03:36:44 +0200 Subject: [PATCH 117/281] phasing out yOffset --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c0bb9889574..78b8d564c78 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -191,7 +191,7 @@ module.exports = function plot(gd, calcdata) { } } - var yTranslate = d.anchor - scrollY + d.yOffset; + var yTranslate = d.anchor - scrollY + 0 * d.yOffset; return 'translate(0 ' + yTranslate + ')'; @@ -389,7 +389,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { } function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + d.yOffset) + ')';}); + columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + 0 * d.yOffset) + ')';}); } function rowFromTo(d) { From b73cd33acc25671be835df0abd7100ca1c7b90d5 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 03:40:34 +0200 Subject: [PATCH 118/281] eliminating bumpers --- src/traces/table/plot.js | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 78b8d564c78..e5d568b3c26 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -488,24 +488,6 @@ function rowAnchor(rowBlock, row) { return total; } -function verticalBumpBlocks(increase, d, xIndex) { - // subsequent blocks pushed down - if(xIndex === 1) { - for(var p = d.page + 1; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchr += increase; - } - } -} - -function verticalBumpBlocksAll(increase, d, xIndex) { - // subsequent blocks pushed down - if(xIndex === 0) { - for(var p = 0; p < d.rowBlocks.length; p++) { - d.rowBlocks[p].firstRowAnchr += increase; - } - } -} - function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); @@ -524,20 +506,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; - if(d.column.type === 'header') { - // somehow push down possibly already rendered `cells` type rows - var bumped = false - columnBlock.each(function(dd) { - if(!bumped && dd.type !== 'header') { - verticalBumpBlocksAll(increase, dd, dd.xIndex); - bumped = true; - } - }) - } - else { - verticalBumpBlocks(increase, d, d.column.xIndex); - } - columnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') From 953fd728b7f2c783c04f7c0379caaf9adc38c94d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 10:28:18 +0200 Subject: [PATCH 119/281] eliminating yOffset, scrollHeight --- src/traces/table/calc.js | 9 +++------ src/traces/table/plot.js | 15 ++++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index c2df2753532..8bf4bddf81c 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -67,8 +67,8 @@ module.exports = function calc(gd, trace) { var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - var headerRowHeights = trace.header.values[0].map(function(_, i) {return trace.header.height + 0 * Math.round((i < 0 ? 0 : 25) * (Math.random() - 0.5));}); - var rowHeights = trace.cells.values[0].map(function(_, i) {return trace.cells.height;}); + var headerRowHeights = trace.header.values[0].map(function() {return trace.header.height;}); + var rowHeights = trace.cells.values[0].map(function() {return trace.cells.height;}); var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; @@ -96,10 +96,7 @@ module.exports = function calc(gd, trace) { height: groupHeight, columnWidths: columnWidths, columnOrder: columnOrder, // will be mutated on column move - headerHeight: headerHeight, - scrollHeight: scrollHeight, - //anchorToRowBlock: anchorToRowBlock, - //anchorToHeaderRowBlock: anchorToHeaderRowBlock, + groupHeight: groupHeight, rowBlocks: rowBlocks, headerRowBlocks: headerRowBlocks, scrollY: 0, // will be mutated on scroll diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e5d568b3c26..b5ee6e0dd5a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -107,7 +107,6 @@ module.exports = function plot(gd, calcdata) { var headerPanel = extendFlat({}, d, { key: 'header', type: 'header', - yOffset: 0, anchor: 0, page: 0, values: d.calcdata.headerCells.values[d.specIndex], @@ -121,7 +120,6 @@ module.exports = function plot(gd, calcdata) { type: 'cells', anchor: 0, // will be mutated on scroll; points to current place page: 0, - yOffset: 0,//d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -133,7 +131,6 @@ module.exports = function plot(gd, calcdata) { anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place page: -1, type: 'cells', - yOffset: 0,//d.calcdata.headerHeight, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, @@ -175,7 +172,9 @@ module.exports = function plot(gd, calcdata) { var blockAnchors = rowBlocks.map(function(v) {return firstRowAnchor(rowBlocks, v);}); var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - d.calcdata.scrollHeight; + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + var scrollHeight = d.calcdata.groupHeight - headerHeight; + var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blockAnchors.length) { @@ -183,7 +182,7 @@ module.exports = function plot(gd, calcdata) { d.anchor = blockAnchors[d.page]; anchorChanged = d.key; } - } else if(direction === 'up' && d.anchor > scrollY + d.calcdata.scrollHeight) { + } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; d.anchor = blockAnchors[d.page]; @@ -191,10 +190,9 @@ module.exports = function plot(gd, calcdata) { } } - var yTranslate = d.anchor - scrollY + 0 * d.yOffset; + var yTranslate = d.anchor - scrollY; return 'translate(0 ' + yTranslate + ')'; - }); if(anchorChanged) { window.clearTimeout(d.currentRepaint); @@ -389,7 +387,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { } function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + (d.anchor + 0 * d.yOffset) + ')';}); + columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); } function rowFromTo(d) { @@ -439,7 +437,6 @@ function lookup(d) { function translateY(columCell) { columCell .attr('transform', function(d) { - //if(d.rowBlocks[0].auxiliaryBlocks.length) debugger var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); return 'translate(' + 0 + ' ' + yOffset + ')'; }); From 07e28569786513c70c16338b8991572ecb4d23df Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:00:16 +0200 Subject: [PATCH 120/281] factor out util --- src/lib/index.js | 7 +++++++ src/traces/sankey/render.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib/index.js b/src/lib/index.js index 25eff611e5c..ba940b9ae92 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -135,6 +135,13 @@ lib.pauseEvent = function(e) { return false; }; +/** + * SVG painter's algo worked around with reinsertion + */ +lib.raiseToTop = function raiseToTop(elem) { + elem.parentNode.appendChild(elem); +}; + // constrain - restrict a number v to be between v0 and v1 lib.constrain = function(v, v0, v1) { if(v0 > v1) return Math.max(v1, Math.min(v0, v)); diff --git a/src/traces/sankey/render.js b/src/traces/sankey/render.js index ba2e5eae09d..bf0151798b9 100644 --- a/src/traces/sankey/render.js +++ b/src/traces/sankey/render.js @@ -317,7 +317,7 @@ function attachDragHandler(sankeyNode, sankeyLink, callbacks) { .on('dragstart', function(d) { if(d.arrangement === 'fixed') return; - this.parentNode.appendChild(this); // bring element to top (painter's algo) + Lib.raiseToTop(this); d.interactionState.dragInProgress = d.node; saveCurrentDragPosition(d.node); if(d.interactionState.hovered) { From 9683f45fc41f8d3d7e841ca7a793b4b6dbe8dfef Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:00:27 +0200 Subject: [PATCH 121/281] factor out some utils --- src/traces/table/plot.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b5ee6e0dd5a..099bffedb9b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -13,7 +13,8 @@ var d3 = require('d3'); var gup = require('../../lib/gup'); var Drawing = require('../../components/drawing'); var extendFlat = require('../../lib/extend').extendFlat; -var util = require('../../lib/svg_text_utils'); +var svgUtil = require('../../lib/svg_text_utils'); +var raiseToTop = require('../../lib').raiseToTop; module.exports = function plot(gd, calcdata) { @@ -70,11 +71,13 @@ module.exports = function plot(gd, calcdata) { .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) .call(d3.behavior.drag() .origin(function(d) { - easeColumn(this, d, -c.uplift); - this.parentNode.appendChild(this); + var movedColumn = d3.select(this); + easeColumn(movedColumn, d, -c.uplift); + raiseToTop(this); return d; }) .on('drag', function(d) { + var movedColumn = d3.select(this); d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); var newOrder = yColumn.data().sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}); newOrder.forEach(function(dd, i) { @@ -87,14 +90,15 @@ module.exports = function plot(gd, calcdata) { .ease(c.transitionEase) .duration(c.transitionDuration) .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - d3.select(this) - .transition().duration(0) // this just cancels the easeColumn easing in .origin + movedColumn + .call(cancelEeaseColumn) .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); }) .on('dragend', function(d) { + var movedColumn = d3.select(this); var p = d.calcdata; d.x = d.xScale(d); - easeColumn(this, d, 0); + easeColumn(movedColumn, d, 0); columnMoved(gd, calcdata, p.key, p.columns.map(function(dd) {return dd.xIndex;})); }) ); @@ -378,7 +382,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { Drawing.font(selection, d.font); columnCell.call(setRowHeight); translateY(columnCell); - util.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); + svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); // ... therefore all channels for selections above that need to know the height are set below @@ -422,14 +426,18 @@ function gridPick(spec, col, row) { } } -function easeColumn(elem, d, y) { - d3.select(elem) +function easeColumn(selection, d, y) { + selection .transition() .ease(c.releaseTransitionEase, 1, .75) .duration(c.releaseTransitionDuration) .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } +function cancelEeaseColumn(selection) { + selection.transition().duration(0); +} + function lookup(d) { return d.rowBlocks[d.page]; } From b912564954bed1f706f05fdad7fffb80272c83b4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:14:35 +0200 Subject: [PATCH 122/281] factor out cancelTransition --- src/lib/index.js | 7 +++++++ src/traces/table/plot.js | 5 +---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/index.js b/src/lib/index.js index ba940b9ae92..03c3f1abb6d 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -142,6 +142,13 @@ lib.raiseToTop = function raiseToTop(elem) { elem.parentNode.appendChild(elem); }; +/** + * cancel a possibly pending transition; returned selection may be used by caller + */ +lib.cancelTransition = function(selection) { + return selection.transition().duration(0); +}; + // constrain - restrict a number v to be between v0 and v1 lib.constrain = function(v, v0, v1) { if(v0 > v1) return Math.max(v1, Math.min(v0, v)); diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 099bffedb9b..fe6959b9cf7 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -15,6 +15,7 @@ var Drawing = require('../../components/drawing'); var extendFlat = require('../../lib/extend').extendFlat; var svgUtil = require('../../lib/svg_text_utils'); var raiseToTop = require('../../lib').raiseToTop; +var cancelEeaseColumn = require('../../lib').cancelTransition; module.exports = function plot(gd, calcdata) { @@ -434,10 +435,6 @@ function easeColumn(selection, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } -function cancelEeaseColumn(selection) { - selection.transition().duration(0); -} - function lookup(d) { return d.rowBlocks[d.page]; } From d53bbe81274e6ddbb8135a2e1b0d78b81c76fbc2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:18:11 +0200 Subject: [PATCH 123/281] rowBlockOffset removed --- src/traces/table/plot.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fe6959b9cf7..3176f4550da 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -117,7 +117,6 @@ module.exports = function plot(gd, calcdata) { values: d.calcdata.headerCells.values[d.specIndex], rowBlocks: d.calcdata.headerRowBlocks, dragHandle: true, - rowBlockOffset: 0, calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) }); var revolverPanel1 = extendFlat({}, d, { @@ -128,7 +127,6 @@ module.exports = function plot(gd, calcdata) { dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, - rowBlockOffset: 0, calcdata: d.calcdata }); var revolverPanel2 = extendFlat({}, d, { @@ -139,7 +137,6 @@ module.exports = function plot(gd, calcdata) { dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks, - rowBlockOffset: 1, calcdata: d.calcdata }); revolverPanel1.otherPanel = revolverPanel2; From 4c303be92d8285e4d6c32b0d7a9c8e53ebbbe817 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:23:14 +0200 Subject: [PATCH 124/281] no need to extend row panels --- src/traces/table/plot.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3176f4550da..88310185320 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -126,8 +126,7 @@ module.exports = function plot(gd, calcdata) { page: 0, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks, - calcdata: d.calcdata + rowBlocks: d.calcdata.rowBlocks }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', @@ -136,8 +135,7 @@ module.exports = function plot(gd, calcdata) { type: 'cells', dragHandle: false, values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks, - calcdata: d.calcdata + rowBlocks: d.calcdata.rowBlocks }); revolverPanel1.otherPanel = revolverPanel2; revolverPanel2.otherPanel = revolverPanel1; From 31e0a9fd72f6e20e29bd707b3e2321a74d7131ad Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:26:46 +0200 Subject: [PATCH 125/281] comments removed --- src/traces/table/plot.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 88310185320..05c69f1285e 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -358,9 +358,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .append('text') .classed('cellText', true); - // it is only in this leaf selection that the actual cell height can be recovered... cellText - //.attr('alignment-baseline', 'hanging') .text(function(d) { var col = d.column.specIndex; var row = d.rowNumber; @@ -380,10 +378,6 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { translateY(columnCell); svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); - - // ... therefore all channels for selections above that need to know the height are set below - // It's not clear from the variable bindings: `enter` ordering is also driven by the painter's algo that SVG uses - } function columnBlockPositionY(columnBlock) { From a3ad7490fc87144722ef51bd99d8ea04a38c5b59 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:31:20 +0200 Subject: [PATCH 126/281] regroup tricky parts --- src/traces/table/plot.js | 71 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 05c69f1285e..d53008e5f31 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -380,19 +380,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { }); } -function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); -} - -function rowFromTo(d) { - var rowBlock = d.rowBlocks[d.page]; - var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; - var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; - return [rowFrom, rowTo]; -} - function columnMoved(gd, calcdata, i, indices) { - var o = calcdata[i][0].gdColumnsOriginalOrder; calcdata[i][0].gdColumns.sort(function (a, b) { return indices[o.indexOf(a)] - indices[o.indexOf(b)]; @@ -424,29 +412,26 @@ function easeColumn(selection, d, y) { .attr('transform', 'translate(' + d.x + ' ' + y + ')'); } -function lookup(d) { - return d.rowBlocks[d.page]; -} +function cellsBlock(d) {return d.type === 'cells';} +function headerBlock(d) {return d.type === 'header';} -function translateY(columCell) { - columCell - .attr('transform', function(d) { - var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); - return 'translate(' + 0 + ' ' + yOffset + ')'; - }); -} -function setRowHeight(columnCell) { - columnCell.select('.cellRect').attr('height', rowHeight); +/** + * The tricky parts + */ + +function lookup(d) {return d.rowBlocks[d.page];} +function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} + +function rowFromTo(d) { + var rowBlock = d.rowBlocks[d.page]; + var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; + return [rowFrom, rowTo]; } -function firstRowAnchor(rowBlocks, l) { - var total = 0; - for(var i = 0; i < rowBlocks.length; i++) { - if(rowBlocks[i] === l) break; - total += totalHeight(rowBlocks[i]); - } - return total; +function columnBlockPositionY(columnBlock) { + columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); } function rowOffset(rowBlocks, d, i) { @@ -459,9 +444,6 @@ function rowHeight(d) { return lookupRow(l, d.key).rowHeight; } -function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} -function cellsBlock(d) {return d.type === 'cells';} -function headerBlock(d) {return d.type === 'header';} function totalHeight(rowBlock) { var total = 0; for(var i = 0; i < rowBlock.rows.length; i++) { @@ -479,6 +461,27 @@ function rowAnchor(rowBlock, row) { return total; } +function translateY(columCell) { + columCell + .attr('transform', function(d) { + var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + return 'translate(' + 0 + ' ' + yOffset + ')'; + }); +} + +function setRowHeight(columnCell) { + columnCell.select('.cellRect').attr('height', rowHeight); +} + +function firstRowAnchor(rowBlocks, l) { + var total = 0; + for(var i = 0; i < rowBlocks.length; i++) { + if(rowBlocks[i] === l) break; + total += totalHeight(rowBlocks[i]); + } + return total; +} + function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); From aac68d0e5212b4dfb3d61ce07164bd5fe0c3f4a7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 11:37:05 +0200 Subject: [PATCH 127/281] regroup tricky parts 2 --- src/traces/table/plot.js | 169 +++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 77 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d53008e5f31..17220c42764 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -108,39 +108,7 @@ module.exports = function plot(gd, calcdata) { .remove(); var columnBlock = yColumn.selectAll('.columnBlock') - .data(function(d) { - var headerPanel = extendFlat({}, d, { - key: 'header', - type: 'header', - anchor: 0, - page: 0, - values: d.calcdata.headerCells.values[d.specIndex], - rowBlocks: d.calcdata.headerRowBlocks, - dragHandle: true, - calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) - }); - var revolverPanel1 = extendFlat({}, d, { - key: 'cells1', - type: 'cells', - anchor: 0, // will be mutated on scroll; points to current place - page: 0, - dragHandle: false, - values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks - }); - var revolverPanel2 = extendFlat({}, d, { - key: 'cells2', - anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place - page: -1, - type: 'cells', - dragHandle: false, - values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks - }); - revolverPanel1.otherPanel = revolverPanel2; - revolverPanel2.otherPanel = revolverPanel1; - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo - }, gup.keyFun); + .data(splitToPanels, gup.keyFun); columnBlock.enter() .append('g') @@ -159,51 +127,9 @@ module.exports = function plot(gd, calcdata) { d3.event.stopPropagation(); return d; }) - .on('drag', function(d) { - var calcdata = d.calcdata; - var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; - if(!direction) return; - calcdata.scrollY -= d3.event.dy; - var anchorChanged = false; - cellsColumnBlock - .attr('transform', function(d) { - var rowBlocks = d.rowBlocks; - var currentBlock = rowBlocks[d.page]; - var blockAnchors = rowBlocks.map(function(v) {return firstRowAnchor(rowBlocks, v);}); - var lastBlock = rowBlocks[rowBlocks.length - 1]; - var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); - var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; - var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { - if(d.page + 2 < blockAnchors.length) { - d.page += 2; - d.anchor = blockAnchors[d.page]; - anchorChanged = d.key; - } - } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { - if(d.page - 2 >= 0) { - d.page -= 2; - d.anchor = blockAnchors[d.page]; - anchorChanged = d.key; - } - } - - var yTranslate = d.anchor - scrollY; - - return 'translate(0 ' + yTranslate + ')'; - }); - if(anchorChanged) { - window.clearTimeout(d.currentRepaint); - d.currentRepaint = window.setTimeout(function() { - // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes - // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) {return d.key === anchorChanged;}), cellsColumnBlock.filter(function (d) {return d.key === anchorChanged;})); - }); - } - }) + .on('drag', makeDragRow(cellsColumnBlock)) .on('dragend', function(d) { + // fixme emit plotly notification }) ); @@ -482,6 +408,95 @@ function firstRowAnchor(rowBlocks, l) { return total; } +function splitToPanels(d) { + var headerPanel = extendFlat({}, d, { + key: 'header', + type: 'header', + anchor: 0, + page: 0, + values: d.calcdata.headerCells.values[d.specIndex], + rowBlocks: d.calcdata.headerRowBlocks, + dragHandle: true, + calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) + }); + var revolverPanel1 = extendFlat({}, d, { + key: 'cells1', + type: 'cells', + anchor: 0, // will be mutated on scroll; points to current place + page: 0, + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowBlocks: d.calcdata.rowBlocks + }); + var revolverPanel2 = extendFlat({}, d, { + key: 'cells2', + anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place + page: -1, + type: 'cells', + dragHandle: false, + values: d.calcdata.cells.values[d.specIndex], + rowBlocks: d.calcdata.rowBlocks + }); + revolverPanel1.otherPanel = revolverPanel2; + revolverPanel2.otherPanel = revolverPanel1; + return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo +} + +function makeDragRow(cellsColumnBlock) { + return function dragRow (d) { + var calcdata = d.calcdata; + var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; + if(!direction) return; + calcdata.scrollY -= d3.event.dy; + var anchorChanged = false; + cellsColumnBlock + .attr('transform', function (d) { + var rowBlocks = d.rowBlocks; + var currentBlock = rowBlocks[d.page]; + var blockAnchors = rowBlocks.map(function (v) { + return firstRowAnchor(rowBlocks, v); + }); + var lastBlock = rowBlocks[rowBlocks.length - 1]; + var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) { + return p + totalHeight(n) + }, 0); + var scrollHeight = d.calcdata.groupHeight - headerHeight; + var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); + if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { + if(d.page + 2 < blockAnchors.length) { + d.page += 2; + d.anchor = blockAnchors[d.page]; + anchorChanged = d.key; + } + } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { + if(d.page - 2 >= 0) { + d.page -= 2; + d.anchor = blockAnchors[d.page]; + anchorChanged = d.key; + } + } + + var yTranslate = d.anchor - scrollY; + + return 'translate(0 ' + yTranslate + ')'; + }); + if(anchorChanged) { + window.clearTimeout(d.currentRepaint); + d.currentRepaint = window.setTimeout(function () { + // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes + // some repaints invisible ie. wasteful (DOM work blocks the main thread) + renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) { + return d.key === anchorChanged; + }), cellsColumnBlock.filter(function (d) { + return d.key === anchorChanged; + })); + }); + } + } +} + function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); From da33f837980d570c75dd322bd520145c7e993576 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:00:25 +0200 Subject: [PATCH 128/281] make column sorting possible even if column on edge is much thinner --- src/traces/table/plot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 17220c42764..391098ec144 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -79,8 +79,9 @@ module.exports = function plot(gd, calcdata) { }) .on('drag', function(d) { var movedColumn = d3.select(this); + var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;} d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); - var newOrder = yColumn.data().sort(function(a, b) {return a.x + a.columnWidth / 2 - b.x - b.columnWidth / 2;}); + var newOrder = yColumn.data().sort(function(a, b) {return getter(a) - getter(b);}); newOrder.forEach(function(dd, i) { dd.xIndex = i; dd.x = d === dd ? dd.x : dd.xScale(dd); From 8830381908a28fcfa0b54130a5e5f6fa9b14c89d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:06:06 +0200 Subject: [PATCH 129/281] splitToCells extracted --- src/traces/table/plot.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 391098ec144..e33cf44be79 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -136,7 +136,6 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); renderColumnBlocks(gd, columnBlock.filter(cellsBlock), columnBlock); @@ -216,19 +215,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .remove(); var columnCell = columnCells.selectAll('.columnCell') - .data(function(d) { - var fromTo = rowFromTo(d); - return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { - return { - key: fromTo[0] + i, - column: d, - calcdata: d.calcdata, - page: d.page, - rowBlocks: d.rowBlocks, - value: v - }; - }); - }, gup.keyFun); + .data(splitToCells, gup.keyFun); columnCell.enter() .append('g') @@ -443,6 +430,20 @@ function splitToPanels(d) { return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo } +function splitToCells(d) { + var fromTo = rowFromTo(d); + return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { + return { + key: fromTo[0] + i, + column: d, + calcdata: d.calcdata, + page: d.page, + rowBlocks: d.rowBlocks, + value: v + }; + }); +} + function makeDragRow(cellsColumnBlock) { return function dragRow (d) { var calcdata = d.calcdata; From 2f39a4e91225cad72a3a68b42c25dff119319015 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:11:28 +0200 Subject: [PATCH 130/281] note --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e33cf44be79..d61b4913a98 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -339,6 +339,7 @@ function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} function rowFromTo(d) { var rowBlock = d.rowBlocks[d.page]; + // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; return [rowFrom, rowTo]; From 1f17d9332fbc0514dc4e6789141076c48cb4c06e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:22:58 +0200 Subject: [PATCH 131/281] reordered tricky functions --- src/traces/table/plot.js | 129 ++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d61b4913a98..01b729cca2b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -334,69 +334,6 @@ function headerBlock(d) {return d.type === 'header';} * The tricky parts */ -function lookup(d) {return d.rowBlocks[d.page];} -function lookupRow(l, i) {return l.rows[i - l.firstRowIndex];} - -function rowFromTo(d) { - var rowBlock = d.rowBlocks[d.page]; - // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 - var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; - var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; - return [rowFrom, rowTo]; -} - -function columnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); -} - -function rowOffset(rowBlocks, d, i) { - var l = lookup(d); - return rowAnchor(l, lookupRow(l, i)) + firstRowAnchor(rowBlocks, l) - d.column.anchor; -} - -function rowHeight(d) { - var l = lookup(d); - return lookupRow(l, d.key).rowHeight; -} - -function totalHeight(rowBlock) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - total += rowBlock.rows[i].rowHeight; - } - return total; -} - -function rowAnchor(rowBlock, row) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - if(rowBlock.rows[i] === row) break; - total += rowBlock.rows[i].rowHeight; - } - return total; -} - -function translateY(columCell) { - columCell - .attr('transform', function(d) { - var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); - return 'translate(' + 0 + ' ' + yOffset + ')'; - }); -} - -function setRowHeight(columnCell) { - columnCell.select('.cellRect').attr('height', rowHeight); -} - -function firstRowAnchor(rowBlocks, l) { - var total = 0; - for(var i = 0; i < rowBlocks.length; i++) { - if(rowBlocks[i] === l) break; - total += totalHeight(rowBlocks[i]); - } - return total; -} - function splitToPanels(d) { var headerPanel = extendFlat({}, d, { key: 'header', @@ -445,6 +382,22 @@ function splitToCells(d) { }); } +function totalHeight(rowBlock) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + total += rowBlock.rows[i].rowHeight; + } + return total; +} + +function rowFromTo(d) { + var rowBlock = d.rowBlocks[d.page]; + // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 + var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; + var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; + return [rowFrom, rowTo]; +} + function makeDragRow(cellsColumnBlock) { return function dragRow (d) { var calcdata = d.calcdata; @@ -504,7 +457,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); var columnCells = d3.select(element.parentNode.parentNode.parentNode); - var l = lookup(d); + var l = getBlock(d); var rowIndex = d.key - l.firstRowIndex; var box = element.parentNode.getBoundingClientRect(); @@ -541,3 +494,51 @@ function finalizeYPositionMaker(columnBlock, element, d) { } }; } + +function setRowHeight(columnCell) { + columnCell.select('.cellRect').attr('height', rowHeight); +} + +function columnBlockPositionY(columnBlock) { + columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); +} + +function translateY(columCell) { + columCell + .attr('transform', function(d) { + var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + return 'translate(' + 0 + ' ' + yOffset + ')'; + }); +} + +function rowOffset(rowBlocks, d, i) { + var l = getBlock(d); + return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l) - d.column.anchor; +} + +function rowAnchor(rowBlock, row) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + if(rowBlock.rows[i] === row) break; + total += rowBlock.rows[i].rowHeight; + } + return total; +} + +function firstRowAnchor(rowBlocks, l) { + var total = 0; + for(var i = 0; i < rowBlocks.length; i++) { + if(rowBlocks[i] === l) break; + total += totalHeight(rowBlocks[i]); + } + return total; +} + +function rowHeight(d) { + var l = getBlock(d); + return getRow(l, d.key).rowHeight; +} + +function getBlock(d) {return d.rowBlocks[d.page];} +function getRow(l, i) {return l.rows[i - l.firstRowIndex];} + From a76be5409e712e92a93c812f9acd645900ff90da Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:26:49 +0200 Subject: [PATCH 132/281] synchronousHeightAndPosition --- src/traces/table/plot.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 01b729cca2b..a71faba2102 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -288,8 +288,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - columnCell.call(setRowHeight); - translateY(columnCell); + synchronousHeightAndPosition(columnCell); svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); } @@ -495,6 +494,11 @@ function finalizeYPositionMaker(columnBlock, element, d) { }; } +function synchronousHeightAndPosition(columnCell) { + columnCell.call(setRowHeight); + translateY(columnCell); +} + function setRowHeight(columnCell) { columnCell.select('.cellRect').attr('height', rowHeight); } From 1daf7d51a0484f0e9040324790752a37fc6c4f50 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:29:08 +0200 Subject: [PATCH 133/281] simpl. --- src/traces/table/plot.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a71faba2102..8c82f6e0673 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -288,7 +288,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - synchronousHeightAndPosition(columnCell); + renderHeightAndPosition(columnCell); svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); } @@ -473,8 +473,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { columnBlock .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) .selectAll('.columnCell') - .call(setRowHeight) // height increasing stuff in the same row - .call(translateY); //downshifting other cells + .call(renderHeightAndPosition); //downshifting other cells } cellTextHolder @@ -494,9 +493,10 @@ function finalizeYPositionMaker(columnBlock, element, d) { }; } -function synchronousHeightAndPosition(columnCell) { - columnCell.call(setRowHeight); - translateY(columnCell); +function renderHeightAndPosition(columnCell) { + columnCell + .call(setRowHeight) + .call(translateY); } function setRowHeight(columnCell) { From 413fe2bfbb6424cb9f490e83b74d45566f35eed3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:32:15 +0200 Subject: [PATCH 134/281] removed a translateY --- src/traces/table/plot.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8c82f6e0673..e49727791c9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -484,12 +484,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { var yPosition = (rectBox.top - box.top + c.cellPad) return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); - - // translate all downstream cells - // if there's no increase, then the subsequent rows don't need to be pushed down - if(increase) { - translateY(columnCells.selectAll('.columnCell').filter(function(dd) {return dd.key > d.key;})) - } }; } From 382c9fdddd089d9d68ecf167dec7ba2c8ade2752 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:35:05 +0200 Subject: [PATCH 135/281] some function merge --- src/traces/table/plot.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e49727791c9..5e9b14804b8 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -489,26 +489,18 @@ function finalizeYPositionMaker(columnBlock, element, d) { function renderHeightAndPosition(columnCell) { columnCell - .call(setRowHeight) - .call(translateY); -} - -function setRowHeight(columnCell) { - columnCell.select('.cellRect').attr('height', rowHeight); + .attr('transform', function(d) { + var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + return 'translate(' + 0 + ' ' + yOffset + ')'; + }) + .select('.cellRect') + .attr('height', rowHeight); } function columnBlockPositionY(columnBlock) { columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); } -function translateY(columCell) { - columCell - .attr('transform', function(d) { - var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); - return 'translate(' + 0 + ' ' + yOffset + ')'; - }); -} - function rowOffset(rowBlocks, d, i) { var l = getBlock(d); return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l) - d.column.anchor; From 129796df4f81e4d0c27ead6bb85db7a58c75dc43 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 12:36:48 +0200 Subject: [PATCH 136/281] rename --- src/traces/table/plot.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5e9b14804b8..d302c43140c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -120,7 +120,7 @@ module.exports = function plot(gd, calcdata) { columnBlock .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) - .call(columnBlockPositionY); + .call(setColumnBlockPositionY); cellsColumnBlock .call(d3.behavior.drag() @@ -288,7 +288,7 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); - renderHeightAndPosition(columnCell); + setCellHeightAndPositionY(columnCell); svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); }); } @@ -471,9 +471,9 @@ function finalizeYPositionMaker(columnBlock, element, d) { l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; columnBlock - .call(columnBlockPositionY) // translate all downstream revolver column panels (naturally, max. 1 of 2) + .call(setColumnBlockPositionY) .selectAll('.columnCell') - .call(renderHeightAndPosition); //downshifting other cells + .call(setCellHeightAndPositionY); } cellTextHolder @@ -487,7 +487,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { }; } -function renderHeightAndPosition(columnCell) { +function setCellHeightAndPositionY(columnCell) { columnCell .attr('transform', function(d) { var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); @@ -497,7 +497,7 @@ function renderHeightAndPosition(columnCell) { .attr('height', rowHeight); } -function columnBlockPositionY(columnBlock) { +function setColumnBlockPositionY(columnBlock) { columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); } From e9fe02d53e89eefa4a24189ca76efbbc983b598c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 15:22:14 +0200 Subject: [PATCH 137/281] shuffle --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d302c43140c..fdc8414eaac 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -339,9 +339,9 @@ function splitToPanels(d) { type: 'header', anchor: 0, page: 0, + dragHandle: true, values: d.calcdata.headerCells.values[d.specIndex], rowBlocks: d.calcdata.headerRowBlocks, - dragHandle: true, calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) }); var revolverPanel1 = extendFlat({}, d, { @@ -355,9 +355,9 @@ function splitToPanels(d) { }); var revolverPanel2 = extendFlat({}, d, { key: 'cells2', + type: 'cells', anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place page: -1, - type: 'cells', dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks From 576c1d005be589b78dea639ea8b2fb7a5016b89a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 15:23:13 +0200 Subject: [PATCH 138/281] obsolete --- src/traces/table/plot.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fdc8414eaac..dda29b7a7d8 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -362,8 +362,6 @@ function splitToPanels(d) { values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks }); - revolverPanel1.otherPanel = revolverPanel2; - revolverPanel2.otherPanel = revolverPanel1; return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo } From d3f2d4929059091d4c459a7f4e6660f8e2cbb889 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 16:51:01 +0200 Subject: [PATCH 139/281] obsolete --- src/traces/table/calc.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 8bf4bddf81c..f58744fcf19 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -39,7 +39,6 @@ function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { anchorToRowBlock[currentAnchor] = currentBlock; currentBlock.key = blockCounter++; - currentBlock.firstRowAnchr = currentAnchor; currentBlock.firstRowIndex = currentFirstRowIndex; currentBlock.lastRowIndex = i; currentBlock = makeIdentity(); From 5d9bf133cb208b0ce21c1f08c949ee240a2b5761 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 16:58:58 +0200 Subject: [PATCH 140/281] simplifying firstRowAnchor --- src/traces/table/plot.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index dda29b7a7d8..7bf454538a1 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -406,9 +406,9 @@ function makeDragRow(cellsColumnBlock) { .attr('transform', function (d) { var rowBlocks = d.rowBlocks; var currentBlock = rowBlocks[d.page]; - var blockAnchors = rowBlocks.map(function (v) { - return firstRowAnchor(rowBlocks, v); - }); + var getAnchor = function(rowBlocks, page) { + return firstRowAnchor(rowBlocks, rowBlocks[page]) + } var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) { @@ -418,15 +418,15 @@ function makeDragRow(cellsColumnBlock) { var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { - if(d.page + 2 < blockAnchors.length) { + if(d.page + 2 < rowBlocks.length) { d.page += 2; - d.anchor = blockAnchors[d.page]; + d.anchor = getAnchor(rowBlocks, d.page);//blockAnchors[d.page]; anchorChanged = d.key; } } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; - d.anchor = blockAnchors[d.page]; + d.anchor = getAnchor(rowBlocks, d.page); //blockAnchors[d.page]; anchorChanged = d.key; } } From 75ace9f2abb1e25fa061009e0982a0e240470142 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 17:13:52 +0200 Subject: [PATCH 141/281] simplifying getting anchor --- src/traces/table/plot.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7bf454538a1..e6f76fbe773 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -406,27 +406,24 @@ function makeDragRow(cellsColumnBlock) { .attr('transform', function (d) { var rowBlocks = d.rowBlocks; var currentBlock = rowBlocks[d.page]; - var getAnchor = function(rowBlocks, page) { - return firstRowAnchor(rowBlocks, rowBlocks[page]) - } var lastBlock = rowBlocks[rowBlocks.length - 1]; var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) { return p + totalHeight(n) }, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(rowBlocks, lastBlock) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; + var bottom = firstRowAnchor(rowBlocks, lastBlock.key) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < rowBlocks.length) { d.page += 2; - d.anchor = getAnchor(rowBlocks, d.page);//blockAnchors[d.page]; + d.anchor = firstRowAnchor(rowBlocks, d.page);//blockAnchors[d.page]; anchorChanged = d.key; } } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; - d.anchor = getAnchor(rowBlocks, d.page); //blockAnchors[d.page]; + d.anchor = firstRowAnchor(rowBlocks, d.page); //blockAnchors[d.page]; anchorChanged = d.key; } } @@ -501,7 +498,7 @@ function setColumnBlockPositionY(columnBlock) { function rowOffset(rowBlocks, d, i) { var l = getBlock(d); - return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l) - d.column.anchor; + return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l.key) - d.column.anchor; } function rowAnchor(rowBlock, row) { @@ -513,10 +510,9 @@ function rowAnchor(rowBlock, row) { return total; } -function firstRowAnchor(rowBlocks, l) { +function firstRowAnchor(rowBlocks, page) { var total = 0; - for(var i = 0; i < rowBlocks.length; i++) { - if(rowBlocks[i] === l) break; + for(var i = 0; i <= page - 1; i++) { total += totalHeight(rowBlocks[i]); } return total; From 54bef008051bbe28b55061fc9ccd3e2a802f6ddb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 17:51:31 +0200 Subject: [PATCH 142/281] simpler bottom calculation; renamings --- src/traces/table/plot.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e6f76fbe773..52e24de5ffb 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -404,26 +404,23 @@ function makeDragRow(cellsColumnBlock) { var anchorChanged = false; cellsColumnBlock .attr('transform', function (d) { - var rowBlocks = d.rowBlocks; - var currentBlock = rowBlocks[d.page]; - var lastBlock = rowBlocks[rowBlocks.length - 1]; - var lastRow = lastBlock.rows[lastBlock.rows.length - 1]; - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) { - return p + totalHeight(n) - }, 0); + var blocks = d.rowBlocks; + var currentBlock = blocks[d.page]; + var lastBlock = blocks[blocks.length - 1]; + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + totalHeight(n)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(rowBlocks, lastBlock.key) + rowAnchor(lastBlock, lastRow) + lastRow.rowHeight - scrollHeight; + var bottom = firstRowAnchor(blocks, lastBlock.key + 1) - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { - if(d.page + 2 < rowBlocks.length) { + if(d.page + 2 < blocks.length) { d.page += 2; - d.anchor = firstRowAnchor(rowBlocks, d.page);//blockAnchors[d.page]; + d.anchor = firstRowAnchor(blocks, d.page); anchorChanged = d.key; } } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; - d.anchor = firstRowAnchor(rowBlocks, d.page); //blockAnchors[d.page]; + d.anchor = firstRowAnchor(blocks, d.page); anchorChanged = d.key; } } @@ -450,7 +447,6 @@ function makeDragRow(cellsColumnBlock) { function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); - var columnCells = d3.select(element.parentNode.parentNode.parentNode); var l = getBlock(d); var rowIndex = d.key - l.firstRowIndex; var box = element.parentNode.getBoundingClientRect(); From b5151c083a2a934060c611369c9c2eeb795eea0f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 17:53:32 +0200 Subject: [PATCH 143/281] minor simpl. --- src/traces/table/plot.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 52e24de5ffb..f12d2c4c118 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -406,10 +406,9 @@ function makeDragRow(cellsColumnBlock) { .attr('transform', function (d) { var blocks = d.rowBlocks; var currentBlock = blocks[d.page]; - var lastBlock = blocks[blocks.length - 1]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + totalHeight(n)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(blocks, lastBlock.key + 1) - scrollHeight; + var bottom = firstRowAnchor(blocks, blocks.length) - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { if(d.page + 2 < blocks.length) { From 635ec61c05582c6de655f4d90cf8e2f5df5dfd7c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 18:30:25 +0200 Subject: [PATCH 144/281] minor --- src/traces/table/plot.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f12d2c4c118..c9573189e81 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -347,7 +347,7 @@ function splitToPanels(d) { var revolverPanel1 = extendFlat({}, d, { key: 'cells1', type: 'cells', - anchor: 0, // will be mutated on scroll; points to current place + anchor: 0, page: 0, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -356,13 +356,14 @@ function splitToPanels(d) { var revolverPanel2 = extendFlat({}, d, { key: 'cells2', type: 'cells', - anchor: d.calcdata.rowBlocks[1] ? -totalHeight(d.calcdata.rowBlocks[1]) : 0, // will be mutated on scroll; points to current place + anchor: 0, page: -1, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks }); - return [revolverPanel1, revolverPanel2, headerPanel]; // order due to SVG using painter's algo + // order due to SVG using painter's algo: + return [revolverPanel1, revolverPanel2, headerPanel]; } function splitToCells(d) { @@ -427,7 +428,7 @@ function makeDragRow(cellsColumnBlock) { var yTranslate = d.anchor - scrollY; return 'translate(0 ' + yTranslate + ')'; - }); + })//.call(setColumnBlockPositionY); if(anchorChanged) { window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function () { From fbc1fb985870aa5b29b7ba7ea71d2c04c05c53e7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 19:13:15 +0200 Subject: [PATCH 145/281] get rid of a block translator --- src/traces/table/plot.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c9573189e81..22c582bb0c2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -119,8 +119,7 @@ module.exports = function plot(gd, calcdata) { var cellsColumnBlock = columnBlock.filter(cellsBlock); columnBlock - .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}) - .call(setColumnBlockPositionY); + .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}); cellsColumnBlock .call(d3.behavior.drag() @@ -428,7 +427,7 @@ function makeDragRow(cellsColumnBlock) { var yTranslate = d.anchor - scrollY; return 'translate(0 ' + yTranslate + ')'; - })//.call(setColumnBlockPositionY); + }); if(anchorChanged) { window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function () { @@ -462,7 +461,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; columnBlock - .call(setColumnBlockPositionY) .selectAll('.columnCell') .call(setCellHeightAndPositionY); } @@ -488,10 +486,6 @@ function setCellHeightAndPositionY(columnCell) { .attr('height', rowHeight); } -function setColumnBlockPositionY(columnBlock) { - columnBlock.attr('transform', function(d) {return 'translate(0 ' + d.anchor + ')';}); -} - function rowOffset(rowBlocks, d, i) { var l = getBlock(d); return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l.key) - d.column.anchor; From 05cbab9ae7f8cc102c5a89c3d8b78521d7ab3b12 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 23:05:11 +0200 Subject: [PATCH 146/281] tentative --- src/traces/table/plot.js | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 22c582bb0c2..7a9b31d4e2d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -476,29 +476,42 @@ function finalizeYPositionMaker(columnBlock, element, d) { }; } + + + + function setCellHeightAndPositionY(columnCell) { + + function rowOffset(rowBlocks, d, i) { + + function rowAnchor(rowBlock, row) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + if(rowBlock.rows[i] === row) break; + total += rowBlock.rows[i].rowHeight; + } + return total; + } + + + var l = getBlock(d); + return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l.key) - d.column.anchor; + } + columnCell .attr('transform', function(d) { - var yOffset = rowOffset(d.rowBlocks, d, d.key) + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + var rowOffs = rowOffset(d.rowBlocks, d, d.key); + var yOffset = rowOffs + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); return 'translate(' + 0 + ' ' + yOffset + ')'; }) .select('.cellRect') .attr('height', rowHeight); } -function rowOffset(rowBlocks, d, i) { - var l = getBlock(d); - return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l.key) - d.column.anchor; -} -function rowAnchor(rowBlock, row) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - if(rowBlock.rows[i] === row) break; - total += rowBlock.rows[i].rowHeight; - } - return total; -} + + + function firstRowAnchor(rowBlocks, page) { var total = 0; From 16497add5c3fbe2c1d6d5d173e3a9acfa211e897 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 23:07:40 +0200 Subject: [PATCH 147/281] tentative 2 --- src/traces/table/plot.js | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7a9b31d4e2d..8271bbd5251 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -482,25 +482,20 @@ function finalizeYPositionMaker(columnBlock, element, d) { function setCellHeightAndPositionY(columnCell) { - function rowOffset(rowBlocks, d, i) { - - function rowAnchor(rowBlock, row) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - if(rowBlock.rows[i] === row) break; - total += rowBlock.rows[i].rowHeight; - } - return total; + function rowAnchor(rowBlock, row) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + if(rowBlock.rows[i] === row) break; + total += rowBlock.rows[i].rowHeight; } - - - var l = getBlock(d); - return rowAnchor(l, getRow(l, i)) + firstRowAnchor(rowBlocks, l.key) - d.column.anchor; + return total; } columnCell .attr('transform', function(d) { - var rowOffs = rowOffset(d.rowBlocks, d, d.key); + + var l = getBlock(d); + var rowOffs = rowAnchor(l, getRow(l, d.key)) + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; var yOffset = rowOffs + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); return 'translate(' + 0 + ' ' + yOffset + ')'; }) From cb0d8f6069df47f5350622149699c151fb630bd5 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 23:14:03 +0200 Subject: [PATCH 148/281] tentative 3 --- src/traces/table/plot.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8271bbd5251..f1c6380943f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -482,20 +482,19 @@ function finalizeYPositionMaker(columnBlock, element, d) { function setCellHeightAndPositionY(columnCell) { - function rowAnchor(rowBlock, row) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - if(rowBlock.rows[i] === row) break; - total += rowBlock.rows[i].rowHeight; - } - return total; - } - columnCell .attr('transform', function(d) { var l = getBlock(d); - var rowOffs = rowAnchor(l, getRow(l, d.key)) + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; + var row = getRow(l, d.key) + + var rowAnchr = 0; + for(var i = 0; i < l.rows.length; i++) { + if(l.rows[i] === row) break; + rowAnchr += l.rows[i].rowHeight; + } + + var rowOffs = rowAnchr + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; var yOffset = rowOffs + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); return 'translate(' + 0 + ' ' + yOffset + ')'; }) From d4aca80c40a49f832942e45b017df151d0ff9c0b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 23:33:35 +0200 Subject: [PATCH 149/281] tentative 4 --- src/traces/table/plot.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f1c6380943f..11e0d17db27 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -488,14 +488,15 @@ function setCellHeightAndPositionY(columnCell) { var l = getBlock(d); var row = getRow(l, d.key) - var rowAnchr = 0; + var rowAnchor = 0; for(var i = 0; i < l.rows.length; i++) { if(l.rows[i] === row) break; - rowAnchr += l.rows[i].rowHeight; + rowAnchor += l.rows[i].rowHeight; } - var rowOffs = rowAnchr + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; - var yOffset = rowOffs + d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + var rowOffs = rowAnchor + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + var yOffset = rowOffs + headerHeight; return 'translate(' + 0 + ' ' + yOffset + ')'; }) .select('.cellRect') From 99f1444081cc2a3bfdfb273bb932555adec6a32e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 12 Sep 2017 23:52:34 +0200 Subject: [PATCH 150/281] tentative 5 --- src/traces/table/plot.js | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 11e0d17db27..bee55400842 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -379,14 +379,6 @@ function splitToCells(d) { }); } -function totalHeight(rowBlock) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - total += rowBlock.rows[i].rowHeight; - } - return total; -} - function rowFromTo(d) { var rowBlock = d.rowBlocks[d.page]; // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 @@ -406,11 +398,11 @@ function makeDragRow(cellsColumnBlock) { .attr('transform', function (d) { var blocks = d.rowBlocks; var currentBlock = blocks[d.page]; - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + totalHeight(n)}, 0); + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; var bottom = firstRowAnchor(blocks, blocks.length) - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(d.page < 0 || direction === 'down' && scrollY - d.anchor > totalHeight(currentBlock)) { + if(d.page < 0 || direction === 'down' && scrollY - d.anchor > rowsHeight(currentBlock, Infinity)) { if(d.page + 2 < blocks.length) { d.page += 2; d.anchor = firstRowAnchor(blocks, d.page); @@ -477,8 +469,13 @@ function finalizeYPositionMaker(columnBlock, element, d) { } - - +function rowsHeight(rowBlock, key) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { + total += rowBlock.rows[i].rowHeight; + } + return total; +} function setCellHeightAndPositionY(columnCell) { @@ -486,16 +483,10 @@ function setCellHeightAndPositionY(columnCell) { .attr('transform', function(d) { var l = getBlock(d); - var row = getRow(l, d.key) - - var rowAnchor = 0; - for(var i = 0; i < l.rows.length; i++) { - if(l.rows[i] === row) break; - rowAnchor += l.rows[i].rowHeight; - } + var rowAnchor = rowsHeight(l, d.key); var rowOffs = rowAnchor + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + totalHeight(n)}, 0); + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var yOffset = rowOffs + headerHeight; return 'translate(' + 0 + ' ' + yOffset + ')'; }) @@ -503,15 +494,10 @@ function setCellHeightAndPositionY(columnCell) { .attr('height', rowHeight); } - - - - - function firstRowAnchor(rowBlocks, page) { var total = 0; for(var i = 0; i <= page - 1; i++) { - total += totalHeight(rowBlocks[i]); + total += rowsHeight(rowBlocks[i], Infinity); } return total; } From 12c638ac35ba142d06d2930f279d346953fbbf3f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Sep 2017 00:43:25 +0200 Subject: [PATCH 151/281] tentative 6 --- src/traces/table/plot.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index bee55400842..2c42400816b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -469,14 +469,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { } -function rowsHeight(rowBlock, key) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { - total += rowBlock.rows[i].rowHeight; - } - return total; -} - function setCellHeightAndPositionY(columnCell) { columnCell @@ -491,7 +483,11 @@ function setCellHeightAndPositionY(columnCell) { return 'translate(' + 0 + ' ' + yOffset + ')'; }) .select('.cellRect') - .attr('height', rowHeight); + .attr('height', function(d) { + var l = getBlock(d); + return getRow(l, d.key).rowHeight; + } + ); } function firstRowAnchor(rowBlocks, page) { @@ -502,9 +498,12 @@ function firstRowAnchor(rowBlocks, page) { return total; } -function rowHeight(d) { - var l = getBlock(d); - return getRow(l, d.key).rowHeight; +function rowsHeight(rowBlock, key) { + var total = 0; + for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { + total += rowBlock.rows[i].rowHeight; + } + return total; } function getBlock(d) {return d.rowBlocks[d.page];} From 131ce57fdbaca3fd660a768059fdb4c72221e2c6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Sep 2017 15:04:13 +0200 Subject: [PATCH 152/281] prep for absolute panel layouting --- src/traces/table/plot.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2c42400816b..be74e1a59c0 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -393,7 +393,7 @@ function makeDragRow(cellsColumnBlock) { var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; if(!direction) return; calcdata.scrollY -= d3.event.dy; - var anchorChanged = false; + var anchorsChanged = []; cellsColumnBlock .attr('transform', function (d) { var blocks = d.rowBlocks; @@ -406,13 +406,13 @@ function makeDragRow(cellsColumnBlock) { if(d.page + 2 < blocks.length) { d.page += 2; d.anchor = firstRowAnchor(blocks, d.page); - anchorChanged = d.key; + anchorsChanged.push(d.key); } } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; d.anchor = firstRowAnchor(blocks, d.page); - anchorChanged = d.key; + anchorsChanged.push(d.key); } } @@ -420,15 +420,15 @@ function makeDragRow(cellsColumnBlock) { return 'translate(0 ' + yTranslate + ')'; }); - if(anchorChanged) { + if(anchorsChanged.length) { window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) { - return d.key === anchorChanged; + return anchorsChanged.indexOf(d.key) !== -1; }), cellsColumnBlock.filter(function (d) { - return d.key === anchorChanged; + return anchorsChanged.indexOf(d.key) !== -1; })); }); } @@ -477,7 +477,7 @@ function setCellHeightAndPositionY(columnCell) { var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); - var rowOffs = rowAnchor + firstRowAnchor(d.rowBlocks, l.key) - d.column.anchor; + var rowOffs = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - d.column.anchor; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var yOffset = rowOffs + headerHeight; return 'translate(' + 0 + ' ' + yOffset + ')'; From d902c49bde18c1782a4944b576c10c069219631a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Sep 2017 17:04:34 +0200 Subject: [PATCH 153/281] deleted d.anchor --- src/traces/table/plot.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index be74e1a59c0..34e5501cb74 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -336,7 +336,6 @@ function splitToPanels(d) { var headerPanel = extendFlat({}, d, { key: 'header', type: 'header', - anchor: 0, page: 0, dragHandle: true, values: d.calcdata.headerCells.values[d.specIndex], @@ -346,7 +345,6 @@ function splitToPanels(d) { var revolverPanel1 = extendFlat({}, d, { key: 'cells1', type: 'cells', - anchor: 0, page: 0, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -355,7 +353,6 @@ function splitToPanels(d) { var revolverPanel2 = extendFlat({}, d, { key: 'cells2', type: 'cells', - anchor: 0, page: -1, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -402,21 +399,20 @@ function makeDragRow(cellsColumnBlock) { var scrollHeight = d.calcdata.groupHeight - headerHeight; var bottom = firstRowAnchor(blocks, blocks.length) - scrollHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); - if(d.page < 0 || direction === 'down' && scrollY - d.anchor > rowsHeight(currentBlock, Infinity)) { + var dAnchor = firstRowAnchor(blocks, d.page); + if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(currentBlock, Infinity)) { if(d.page + 2 < blocks.length) { d.page += 2; - d.anchor = firstRowAnchor(blocks, d.page); anchorsChanged.push(d.key); } - } else if(direction === 'up' && d.anchor > scrollY + scrollHeight) { + } else if(direction === 'up' && dAnchor > scrollY + scrollHeight) { if(d.page - 2 >= 0) { d.page -= 2; - d.anchor = firstRowAnchor(blocks, d.page); anchorsChanged.push(d.key); } } - var yTranslate = d.anchor - scrollY; + var yTranslate = dAnchor - scrollY; return 'translate(0 ' + yTranslate + ')'; }); @@ -477,7 +473,7 @@ function setCellHeightAndPositionY(columnCell) { var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); - var rowOffs = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - d.column.anchor; + var rowOffs = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var yOffset = rowOffs + headerHeight; return 'translate(' + 0 + ' ' + yOffset + ')'; From ac7998abd2698c70819651bb617262810dadd0a3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Sep 2017 20:00:08 +0200 Subject: [PATCH 154/281] shuffle --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 34e5501cb74..e1204b6e40d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -397,8 +397,8 @@ function makeDragRow(cellsColumnBlock) { var currentBlock = blocks[d.page]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(blocks, blocks.length) - scrollHeight; - var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom, calcdata.scrollY)); + var bottom = firstRowAnchor(blocks, blocks.length); + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var dAnchor = firstRowAnchor(blocks, d.page); if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(currentBlock, Infinity)) { if(d.page + 2 < blocks.length) { From ed5219ff04c6997ddd4e34f803472c063033b83c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 13 Sep 2017 20:26:48 +0200 Subject: [PATCH 155/281] calculate and output currently visible blocks --- src/traces/table/plot.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e1204b6e40d..dd1c9bf8c40 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -384,6 +384,10 @@ function rowFromTo(d) { return [rowFrom, rowTo]; } +function overlap(a, b) { + return a[0] < b[1] && a[1] > b[0]; +} + function makeDragRow(cellsColumnBlock) { return function dragRow (d) { var calcdata = d.calcdata; @@ -400,6 +404,15 @@ function makeDragRow(cellsColumnBlock) { var bottom = firstRowAnchor(blocks, blocks.length); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var dAnchor = firstRowAnchor(blocks, d.page); + var pages = []; + for(var p = 0; p < blocks.length; p++) { + var pTop = firstRowAnchor(blocks, p); + var pBottom = pTop + rowsHeight(blocks[p], Infinity); + if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { + pages.push(p); + } + } + console.log('pages:', pages); if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(currentBlock, Infinity)) { if(d.page + 2 < blocks.length) { d.page += 2; From 4d344688c642345fa92cc86ac998f1b70f9d8dca Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 00:39:01 +0200 Subject: [PATCH 156/281] starting lifting --- src/traces/table/plot.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index dd1c9bf8c40..cd5029e60c9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -389,6 +389,8 @@ function overlap(a, b) { } function makeDragRow(cellsColumnBlock) { + var d = cellsColumnBlock[0][0].__data__; + var blocks = d.rowBlocks; return function dragRow (d) { var calcdata = d.calcdata; var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; @@ -397,7 +399,7 @@ function makeDragRow(cellsColumnBlock) { var anchorsChanged = []; cellsColumnBlock .attr('transform', function (d) { - var blocks = d.rowBlocks; + //var blocks = d.rowBlocks; var currentBlock = blocks[d.page]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; From 66043b286e4a61645fd6e20e173be48546c170c8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 00:42:50 +0200 Subject: [PATCH 157/281] starting lifting 2 --- src/traces/table/plot.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index cd5029e60c9..17470baf362 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -399,8 +399,6 @@ function makeDragRow(cellsColumnBlock) { var anchorsChanged = []; cellsColumnBlock .attr('transform', function (d) { - //var blocks = d.rowBlocks; - var currentBlock = blocks[d.page]; var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; var bottom = firstRowAnchor(blocks, blocks.length); @@ -415,7 +413,7 @@ function makeDragRow(cellsColumnBlock) { } } console.log('pages:', pages); - if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(currentBlock, Infinity)) { + if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(blocks[d.page], Infinity)) { if(d.page + 2 < blocks.length) { d.page += 2; anchorsChanged.push(d.key); From 5b966c7b5684cef7e0c8ee14fbfb520d949d145f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 00:46:58 +0200 Subject: [PATCH 158/281] starting lifting 3 --- src/traces/table/plot.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 17470baf362..6e7a1010c52 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -396,13 +396,13 @@ function makeDragRow(cellsColumnBlock) { var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; if(!direction) return; calcdata.scrollY -= d3.event.dy; + var bottom = firstRowAnchor(blocks, blocks.length); + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); + var scrollHeight = d.calcdata.groupHeight - headerHeight; + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var anchorsChanged = []; cellsColumnBlock .attr('transform', function (d) { - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); - var scrollHeight = d.calcdata.groupHeight - headerHeight; - var bottom = firstRowAnchor(blocks, blocks.length); - var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var dAnchor = firstRowAnchor(blocks, d.page); var pages = []; for(var p = 0; p < blocks.length; p++) { From 8c3354b5cdb2fa58331883c16f7fb4300d399826 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 00:56:08 +0200 Subject: [PATCH 159/281] starting lifting 4 --- src/traces/table/plot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6e7a1010c52..533ace11e61 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -391,8 +391,8 @@ function overlap(a, b) { function makeDragRow(cellsColumnBlock) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; + var calcdata = d.calcdata; return function dragRow (d) { - var calcdata = d.calcdata; var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; if(!direction) return; calcdata.scrollY -= d3.event.dy; From f1120328ae76b5e9a7a477ac5c6cbe6ebee65b4a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 02:01:25 +0200 Subject: [PATCH 160/281] starting lifting 5 --- src/traces/table/plot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 533ace11e61..6e4cd47e4ef 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -392,12 +392,13 @@ function makeDragRow(cellsColumnBlock) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; + var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; return function dragRow (d) { var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; if(!direction) return; calcdata.scrollY -= d3.event.dy; var bottom = firstRowAnchor(blocks, blocks.length); - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); + var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var anchorsChanged = []; From 3b6e9031d8f9ee98dbee922641a13241cc4161ca Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 02:09:01 +0200 Subject: [PATCH 161/281] starting lifting 6 --- src/traces/table/plot.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6e4cd47e4ef..7426ad95d98 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -393,6 +393,11 @@ function makeDragRow(cellsColumnBlock) { var blocks = d.rowBlocks; var calcdata = d.calcdata; var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; + + function calc(d, dyD3event) { + + } + return function dragRow (d) { var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; if(!direction) return; @@ -402,18 +407,20 @@ function makeDragRow(cellsColumnBlock) { var scrollHeight = d.calcdata.groupHeight - headerHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var anchorsChanged = []; + + var pages = []; + for(var p = 0; p < blocks.length; p++) { + var pTop = firstRowAnchor(blocks, p); + var pBottom = pTop + rowsHeight(blocks[p], Infinity); + if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { + pages.push(p); + } + } + console.log('pages:', pages); + cellsColumnBlock .attr('transform', function (d) { var dAnchor = firstRowAnchor(blocks, d.page); - var pages = []; - for(var p = 0; p < blocks.length; p++) { - var pTop = firstRowAnchor(blocks, p); - var pBottom = pTop + rowsHeight(blocks[p], Infinity); - if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { - pages.push(p); - } - } - console.log('pages:', pages); if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(blocks[d.page], Infinity)) { if(d.page + 2 < blocks.length) { d.page += 2; From bc47890c19bbd8ac9143f4fe5a589f1f2e5a5c63 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 02:37:14 +0200 Subject: [PATCH 162/281] good but jumpy at the beginning; also, not conservative (panels don't get reused) --- src/traces/table/plot.js | 43 ++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7426ad95d98..923c6bfaaa1 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -353,7 +353,7 @@ function splitToPanels(d) { var revolverPanel2 = extendFlat({}, d, { key: 'cells2', type: 'cells', - page: -1, + page: 0, dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks @@ -394,9 +394,7 @@ function makeDragRow(cellsColumnBlock) { var calcdata = d.calcdata; var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; - function calc(d, dyD3event) { - - } + var prevPages = [0, 0]; return function dragRow (d) { var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; @@ -416,38 +414,35 @@ function makeDragRow(cellsColumnBlock) { pages.push(p); } } - console.log('pages:', pages); + if(pages.length === 1) { + if(pages[0] === blocks.length - 1) { + pages.unshift(pages[0] - 1) + } else { + pages.push(pages[0] + 1); + } + } - cellsColumnBlock - .attr('transform', function (d) { - var dAnchor = firstRowAnchor(blocks, d.page); - if(d.page < 0 || direction === 'down' && scrollY - dAnchor > rowsHeight(blocks[d.page], Infinity)) { - if(d.page + 2 < blocks.length) { - d.page += 2; - anchorsChanged.push(d.key); - } - } else if(direction === 'up' && dAnchor > scrollY + scrollHeight) { - if(d.page - 2 >= 0) { - d.page -= 2; - anchorsChanged.push(d.key); - } - } - - var yTranslate = dAnchor - scrollY; + var processedPages = pages[0]; + cellsColumnBlock + .attr('transform', function (d, i) { + var dPage = processedPages + i; + d.page = dPage; + var yTranslate = firstRowAnchor(blocks, dPage) - scrollY; return 'translate(0 ' + yTranslate + ')'; }); - if(anchorsChanged.length) { + if(pages[0] !== prevPages[0] || pages[1] !== prevPages[1]) { window.clearTimeout(d.currentRepaint); d.currentRepaint = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) { - return anchorsChanged.indexOf(d.key) !== -1; + return true || anchorsChanged.indexOf(d.key) !== -1; }), cellsColumnBlock.filter(function (d) { - return anchorsChanged.indexOf(d.key) !== -1; + return true || anchorsChanged.indexOf(d.key) !== -1; })); }); + prevPages = pages.slice(); } } } From 1a2c5b0a125911388679a5627666eb7bb294044f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 02:40:14 +0200 Subject: [PATCH 163/281] minor --- src/traces/table/plot.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 923c6bfaaa1..d3750102e68 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -422,11 +422,9 @@ function makeDragRow(cellsColumnBlock) { } } - var processedPages = pages[0]; - cellsColumnBlock .attr('transform', function (d, i) { - var dPage = processedPages + i; + var dPage = pages[i]; d.page = dPage; var yTranslate = firstRowAnchor(blocks, dPage) - scrollY; return 'translate(0 ' + yTranslate + ')'; From c66a69ba196f2606bda678b32848bc720c6e7bd9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 02:52:36 +0200 Subject: [PATCH 164/281] no more jumps, overshoots, looks perfect! --- src/traces/table/plot.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d3750102e68..de95c08980b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -422,6 +422,11 @@ function makeDragRow(cellsColumnBlock) { } } + if(pages[0] % 2) { + // make phased out page jump by 2 while leaving stationary page intact + pages.reverse(); + } + cellsColumnBlock .attr('transform', function (d, i) { var dPage = pages[i]; @@ -434,13 +439,13 @@ function makeDragRow(cellsColumnBlock) { d.currentRepaint = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(function (d) { - return true || anchorsChanged.indexOf(d.key) !== -1; - }), cellsColumnBlock.filter(function (d) { - return true || anchorsChanged.indexOf(d.key) !== -1; + renderColumnBlocks(gd, cellsColumnBlock.filter(function (d, i) { + return pages[i] !== prevPages[i]; + }), cellsColumnBlock.filter(function (d, i) { + return pages[i] !== prevPages[i]; })); + prevPages = pages.slice(); }); - prevPages = pages.slice(); } } } From 36c3d23dd978436824e66d5cfb05c5fd6b1baaab Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 03:03:13 +0200 Subject: [PATCH 165/281] efficiency improv --- src/traces/table/plot.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index de95c08980b..322c7d4cb2a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -439,11 +439,8 @@ function makeDragRow(cellsColumnBlock) { d.currentRepaint = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - renderColumnBlocks(gd, cellsColumnBlock.filter(function (d, i) { - return pages[i] !== prevPages[i]; - }), cellsColumnBlock.filter(function (d, i) { - return pages[i] !== prevPages[i]; - })); + var toRerender = cellsColumnBlock.filter(function (d, i) {return pages[i] !== prevPages[i];}); + renderColumnBlocks(gd, toRerender, toRerender); prevPages = pages.slice(); }); } From 840955ebc245badd7a9a5fcbdbc0017734bbd5d2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 03:10:26 +0200 Subject: [PATCH 166/281] fewer rerenders --- src/traces/table/plot.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 322c7d4cb2a..19d60eb6dfe 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -337,6 +337,7 @@ function splitToPanels(d) { key: 'header', type: 'header', page: 0, + currentRepaint: [null, null], dragHandle: true, values: d.calcdata.headerCells.values[d.specIndex], rowBlocks: d.calcdata.headerRowBlocks, @@ -346,6 +347,7 @@ function splitToPanels(d) { key: 'cells1', type: 'cells', page: 0, + currentRepaint: [null, null], dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks @@ -354,6 +356,7 @@ function splitToPanels(d) { key: 'cells2', type: 'cells', page: 0, + currentRepaint: [null, null], dragHandle: false, values: d.calcdata.cells.values[d.specIndex], rowBlocks: d.calcdata.rowBlocks @@ -434,16 +437,22 @@ function makeDragRow(cellsColumnBlock) { var yTranslate = firstRowAnchor(blocks, dPage) - scrollY; return 'translate(0 ' + yTranslate + ')'; }); - if(pages[0] !== prevPages[0] || pages[1] !== prevPages[1]) { - window.clearTimeout(d.currentRepaint); - d.currentRepaint = window.setTimeout(function () { - // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes - // some repaints invisible ie. wasteful (DOM work blocks the main thread) - var toRerender = cellsColumnBlock.filter(function (d, i) {return pages[i] !== prevPages[i];}); - renderColumnBlocks(gd, toRerender, toRerender); - prevPages = pages.slice(); - }); + + function rerenderIfNeeded(revolverIndex) { + if(pages[revolverIndex] !== prevPages[revolverIndex]) { + window.clearTimeout(d.currentRepaint[revolverIndex]); + d.currentRepaint[revolverIndex] = window.setTimeout(function () { + // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes + // some repaints invisible ie. wasteful (DOM work blocks the main thread) + var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); + renderColumnBlocks(gd, toRerender, toRerender); + prevPages[revolverIndex] = pages[revolverIndex]; + }); + } } + + rerenderIfNeeded(0); + rerenderIfNeeded(1); } } From 6b2055d16dcb6100a902b38770c5ab725a1fbe9b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 13:53:33 +0200 Subject: [PATCH 167/281] cleanup --- src/traces/table/plot.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 19d60eb6dfe..a3b60d29f7f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -66,9 +66,7 @@ module.exports = function plot(gd, calcdata) { .classed('yColumn', true); yColumn - .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - - yColumn + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}) .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) .call(d3.behavior.drag() .origin(function(d) { @@ -116,11 +114,11 @@ module.exports = function plot(gd, calcdata) { .classed('columnBlock', true) .style('user-select', 'none'); - var cellsColumnBlock = columnBlock.filter(cellsBlock); - columnBlock .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}); + var cellsColumnBlock = columnBlock.filter(cellsBlock); + cellsColumnBlock .call(d3.behavior.drag() .origin(function(d) { @@ -143,9 +141,7 @@ module.exports = function plot(gd, calcdata) { scrollAreaClip.enter() .append(c.clipView ? 'g' : 'clipPath') - .classed('scrollAreaClip', true); - - scrollAreaClip + .classed('scrollAreaClip', true) .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') @@ -251,7 +247,9 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .attr('width', function(d) {return d.column.columnWidth;}) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) .attr('stroke', function(d) { - return c.clipView ? ({header: 'blue', cells1: 'red', cells2: 'green'})[d.column.key] : gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); + return c.clipView ? + ({header: 'blue', cells1: 'red', cells2: 'green'})[d.column.key] : + gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); }) .attr('fill', function(d) { return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); @@ -327,9 +325,8 @@ function easeColumn(selection, d, y) { function cellsBlock(d) {return d.type === 'cells';} function headerBlock(d) {return d.type === 'header';} - /** - * The tricky parts + * Revolver panel and cell contents layouting */ function splitToPanels(d) { @@ -407,7 +404,6 @@ function makeDragRow(cellsColumnBlock) { var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - var anchorsChanged = []; var pages = []; for(var p = 0; p < blocks.length; p++) { @@ -419,14 +415,14 @@ function makeDragRow(cellsColumnBlock) { } if(pages.length === 1) { if(pages[0] === blocks.length - 1) { - pages.unshift(pages[0] - 1) + pages.unshift(pages[0] - 1); } else { pages.push(pages[0] + 1); } } + // make phased out page jump by 2 while leaving stationary page intact if(pages[0] % 2) { - // make phased out page jump by 2 while leaving stationary page intact pages.reverse(); } From 7ea4faa074dd533b137c750387e0f5a4eb94e642 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 14:01:23 +0200 Subject: [PATCH 168/281] cleanup 2 --- src/traces/table/plot.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a3b60d29f7f..8040f4b4743 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -479,7 +479,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { var element = this; var box = element.parentNode.getBoundingClientRect(); var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); - var yPosition = (rectBox.top - box.top + c.cellPad) + var yPosition = (rectBox.top - box.top + c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); }; @@ -487,24 +487,20 @@ function finalizeYPositionMaker(columnBlock, element, d) { function setCellHeightAndPositionY(columnCell) { - columnCell .attr('transform', function(d) { - var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); - - var rowOffs = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); + var rowOffset = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); - var yOffset = rowOffs + headerHeight; + var yOffset = rowOffset + headerHeight; return 'translate(' + 0 + ' ' + yOffset + ')'; }) .select('.cellRect') .attr('height', function(d) { var l = getBlock(d); return getRow(l, d.key).rowHeight; - } - ); + }); } function firstRowAnchor(rowBlocks, page) { From c0918a30cfca11df4f8c0e537fa04f250d454105 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 14:04:07 +0200 Subject: [PATCH 169/281] cleanup 3 --- src/traces/table/plot.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8040f4b4743..c3035ed6727 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -434,21 +434,22 @@ function makeDragRow(cellsColumnBlock) { return 'translate(0 ' + yTranslate + ')'; }); - function rerenderIfNeeded(revolverIndex) { - if(pages[revolverIndex] !== prevPages[revolverIndex]) { - window.clearTimeout(d.currentRepaint[revolverIndex]); - d.currentRepaint[revolverIndex] = window.setTimeout(function () { - // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes - // some repaints invisible ie. wasteful (DOM work blocks the main thread) - var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); - renderColumnBlocks(gd, toRerender, toRerender); - prevPages[revolverIndex] = pages[revolverIndex]; - }); - } - } + // conditionally rerendering panel 0 and 1 + conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, 0); + conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, 1); + } +} - rerenderIfNeeded(0); - rerenderIfNeeded(1); +function conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, revolverIndex) { + if(pages[revolverIndex] !== prevPages[revolverIndex]) { + window.clearTimeout(d.currentRepaint[revolverIndex]); + d.currentRepaint[revolverIndex] = window.setTimeout(function () { + // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes + // some repaints invisible ie. wasteful (DOM work blocks the main thread) + var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); + renderColumnBlocks(gd, toRerender, toRerender); + prevPages[revolverIndex] = pages[revolverIndex]; + }); } } From f3418609a13dacf90dc686b35e9692dd15ee2a5c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 14:11:44 +0200 Subject: [PATCH 170/281] cleanup 4; removing obsolete data --- src/traces/table/calc.js | 4 +--- src/traces/table/plot.js | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index f58744fcf19..8deff999cdd 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -93,8 +93,7 @@ module.exports = function calc(gd, trace) { size: gd._fullLayout._size, width: groupWidth, height: groupHeight, - columnWidths: columnWidths, - columnOrder: columnOrder, // will be mutated on column move + columnOrder: columnOrder, // will be mutated on column move, todo use in callback groupHeight: groupHeight, rowBlocks: rowBlocks, headerRowBlocks: headerRowBlocks, @@ -118,7 +117,6 @@ module.exports = function calc(gd, trace) { }; }), - // these two are being phased out in favor of the new `columnOrder` attribute gdColumns: trace.header.values.map(function(d) {return d[0];}), gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}) }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c3035ed6727..361968545b2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -486,7 +486,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { }; } - function setCellHeightAndPositionY(columnCell) { columnCell .attr('transform', function(d) { @@ -495,13 +494,10 @@ function setCellHeightAndPositionY(columnCell) { var rowOffset = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var yOffset = rowOffset + headerHeight; - return 'translate(' + 0 + ' ' + yOffset + ')'; + return 'translate(0 ' + yOffset + ')'; }) .select('.cellRect') - .attr('height', function(d) { - var l = getBlock(d); - return getRow(l, d.key).rowHeight; - }); + .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); } function firstRowAnchor(rowBlocks, page) { From c506cca1cb57311e260d07123014cbe8c8ad0ac7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 14:16:07 +0200 Subject: [PATCH 171/281] cleanup 5: removing obsolete data --- src/traces/table/calc.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 8deff999cdd..eb5954528d2 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -100,7 +100,8 @@ module.exports = function calc(gd, trace) { scrollY: 0, // will be mutated on scroll cells: trace.cells, headerCells: trace.header, - rowHeights: rowHeights, + gdColumns: trace.header.values.map(function(d) {return d[0];}), + gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}), columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; @@ -115,10 +116,7 @@ module.exports = function calc(gd, trace) { calcdata: undefined, // initialized below columnWidth: columnWidths[i] }; - }), - - gdColumns: trace.header.values.map(function(d) {return d[0];}), - gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}) + }) }; calcdata.columns.forEach(function(col) { @@ -130,5 +128,7 @@ module.exports = function calc(gd, trace) { }; var xScale = function (d) { - return d.calcdata.columns.reduce(function(prev, next) {return next.xIndex < d.xIndex ? prev + next.columnWidth : prev}, 0); + return d.calcdata.columns.reduce(function(prev, next) { + return next.xIndex < d.xIndex ? prev + next.columnWidth : prev + }, 0); } From 4bdf092147f53815fd72fb98d9f5540d0701b46a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 14:26:07 +0200 Subject: [PATCH 172/281] cleanup 6: shuffles, renames --- src/traces/table/calc.js | 115 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index eb5954528d2..786ef1bae32 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -12,79 +12,30 @@ var c = require('./constants'); var wrap = require('../../lib/gup').wrap; var extendFlat = require('../../lib/extend').extendFlat; -function makeIdentity() { - return { - firstRowIndex: null, - lastRowIndex: null, - rows: [] - }; -} - -function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { - - var anchorToRowBlock = {}; - var currentRowHeight; - var currentAnchor = 0; - var currentBlockHeight = 0; - var currentBlock = makeIdentity(); - var currentFirstRowIndex = 0; - var blockCounter = 0; - for(var i = 0; i < rowHeights.length; i++) { - currentRowHeight = rowHeights[i]; - currentBlock.rows.push({ - rowIndex: i, - rowHeight: currentRowHeight - }); - currentBlockHeight += currentRowHeight; - if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { - anchorToRowBlock[currentAnchor] = currentBlock; - currentBlock.key = blockCounter++; - currentBlock.firstRowIndex = currentFirstRowIndex; - currentBlock.lastRowIndex = i; - currentBlock = makeIdentity(); - currentAnchor += currentBlockHeight; - currentFirstRowIndex = i + 1; - currentBlockHeight = 0; - } - } - - return anchorToRowBlock; -} - module.exports = function calc(gd, trace) { - var domain = trace.domain; var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); - - var columnWidths = trace.header.values.map(function(d, i) { - return Array.isArray(trace.columnwidth) ? - trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : - isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; - }); - - var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); - columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); - var headerRowHeights = trace.header.values[0].map(function() {return trace.header.height;}); var rowHeights = trace.cells.values[0].map(function() {return trace.cells.height;}); var headerHeight = headerRowHeights.reduce(function(a, b) {return a + b;}, 0); var scrollHeight = groupHeight - headerHeight; var minimumFillHeight = scrollHeight + c.uplift; - - function rb(anchorToRowBlock, auxiliary) { - var blockAnchorKeys = Object.keys(anchorToRowBlock); - return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}) - } - var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); - var headerRowBlocks = rb(anchorToHeaderRowBlock, []); - var rowBlocks = rb(anchorToRowBlock, headerRowBlocks); - + var headerRowBlocks = makeRowBlock(anchorToHeaderRowBlock, []); + var rowBlocks = makeRowBlock(anchorToRowBlock, headerRowBlocks); var uniqueKeys = {}; - var columnOrder = trace._fullInput.columnorder; + var columnWidths = trace.header.values.map(function(d, i) { + return Array.isArray(trace.columnwidth) ? + trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : + isFinite(trace.columnwidth) && trace.columnwidth !== null ? trace.columnwidth : 1; + }); + var totalColumnWidths = columnWidths.reduce(function(p, n) {return p + n;}, 0); + + // fit columns in the available vertical space as there's no vertical scrolling now + columnWidths = columnWidths.map(function(d) {return d / totalColumnWidths * groupWidth;}); var calcdata = { key: trace.index, @@ -132,3 +83,47 @@ var xScale = function (d) { return next.xIndex < d.xIndex ? prev + next.columnWidth : prev }, 0); } + +function makeRowBlock(anchorToRowBlock, auxiliary) { + var blockAnchorKeys = Object.keys(anchorToRowBlock); + return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}); +} + +function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { + + var anchorToRowBlock = {}; + var currentRowHeight; + var currentAnchor = 0; + var currentBlockHeight = 0; + var currentBlock = makeIdentity(); + var currentFirstRowIndex = 0; + var blockCounter = 0; + for(var i = 0; i < rowHeights.length; i++) { + currentRowHeight = rowHeights[i]; + currentBlock.rows.push({ + rowIndex: i, + rowHeight: currentRowHeight + }); + currentBlockHeight += currentRowHeight; + if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { + anchorToRowBlock[currentAnchor] = currentBlock; + currentBlock.key = blockCounter++; + currentBlock.firstRowIndex = currentFirstRowIndex; + currentBlock.lastRowIndex = i; + currentBlock = makeIdentity(); + currentAnchor += currentBlockHeight; + currentFirstRowIndex = i + 1; + currentBlockHeight = 0; + } + } + + return anchorToRowBlock; +} + +function makeIdentity() { + return { + firstRowIndex: null, + lastRowIndex: null, + rows: [] + }; +} From b7cacfed5af08a841d8907f056f5d4de4a05a11f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 18:18:29 +0200 Subject: [PATCH 173/281] adding mock; minor --- src/traces/table/plot.js | 3 +- test/image/mocks/table_latex.json | 142 +++++++++++++++++++++++++++ test/image/mocks/table_one_cell.json | 10 +- 3 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 test/image/mocks/table_latex.json diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 361968545b2..efa3d8aa2f3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -441,7 +441,8 @@ function makeDragRow(cellsColumnBlock) { } function conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, revolverIndex) { - if(pages[revolverIndex] !== prevPages[revolverIndex]) { + var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; + if(shouldComponentUpdate) { window.clearTimeout(d.currentRepaint[revolverIndex]); d.currentRepaint[revolverIndex] = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes diff --git a/test/image/mocks/table_latex.json b/test/image/mocks/table_latex.json new file mode 100644 index 00000000000..a67e19b482b --- /dev/null +++ b/test/image/mocks/table_latex.json @@ -0,0 +1,142 @@ +{ + "layout": { + "width": 600, + "height": 330 + 380 - 150, + "title": "Widget parameters and cost", + "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [20, 50, 50], + "columnorder": [0, 1, 2], + + "header": { + + "height": 20, // fixme for some reason it doesn't recognize arrays here + + "values": [ + ["Index" , "#"], + ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] + ].map(function(r) {return r.slice(0, 100)}).slice(0, 4), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 12, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "0 A" || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}) + + ].map(function(a) {return a.slice(0, 19)}).slice(0, 4), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fill": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "verdana", + "size": 12, + "color": ["black"] + } + } + }] +} diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index a67e19b482b..c0f1a4a6d46 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 600, + "width": 200, "height": 330 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 100)}).slice(0, 4), + ].map(function(r) {return r.slice(0, 1)}).slice(0, 1), "align": ["right"], "valign": "middle", @@ -69,7 +69,7 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "0 A" || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", @@ -105,7 +105,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 19)}).slice(0, 4), + ].map(function(a) {return a.slice(0, 1)}).slice(1, 2), "format": [ null @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 40, + "height": 10, "align": ["right"], "valign": ["bottom"], From 53a8316ad0929b8cd06e2f8f6cc366b9f17b4224 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 14 Sep 2017 18:54:48 +0200 Subject: [PATCH 174/281] baseline --- src/traces/table/constants.js | 1 + src/traces/table/plot.js | 16 ++++++++++++---- test/image/mocks/table_one_cell.json | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index f71ba7f9c24..606e8a9b385 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -12,6 +12,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, cellPad: 4, + latexMark: '$', uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index efa3d8aa2f3..29c4e21e3b1 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -273,10 +273,14 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .text(function(d) { var col = d.column.specIndex; var row = d.rowNumber; - var prefix = gridPick(d.calcdata.cells.prefix, col, row) || ''; - var suffix = gridPick(d.calcdata.cells.suffix, col, row) || ''; - var format = gridPick(d.calcdata.cells.format, col, row) || ''; - return prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; + var userSuppliedContent = d.value; + var latex = latexEh(userSuppliedContent); + var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; + var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; + var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; + var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; + var textToRender = prefixSuffixedText.replace(/ /g, '
'); + return textToRender; }) .each(function(d) { @@ -290,6 +294,10 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { }); } +function latexEh(content) { + return typeof content === 'string' && content[0] === c.latexMark && content[content.length - 1] === c.latexMark; +} + function columnMoved(gd, calcdata, i, indices) { var o = calcdata[i][0].gdColumnsOriginalOrder; calcdata[i][0].gdColumns.sort(function (a, b) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index c0f1a4a6d46..a277d30b4cc 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 200, + "width": 300, "height": 330 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} From 1e0aa1248d93c1066638fed906e3b63b4624b3b2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Sep 2017 00:55:53 +0200 Subject: [PATCH 175/281] baseline 2 for text wrapping --- src/traces/table/constants.js | 2 ++ src/traces/table/plot.js | 39 +++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 606e8a9b385..203c3fc15da 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -13,6 +13,8 @@ module.exports = { overdrag: 45, cellPad: 4, latexMark: '$', + wrapSplitCharacter: ' ', + wrapSpacer: ' ', uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 29c4e21e3b1..52b1b9bd136 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -269,6 +269,11 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .append('text') .classed('cellText', true); + cellText + .call(renderCellText, allColumnBlock, columnCell); +} + +function renderCellText(cellText, allColumnBlock, columnCell) { cellText .text(function(d) { var col = d.column.specIndex; @@ -279,7 +284,12 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; - var textToRender = prefixSuffixedText.replace(/ /g, '
'); + var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); + var textToRender = fragments.join('
') + "
"; + d.latex = latex; + d.wrappingNeeded = !latex; + d.fragments = fragments.map(function(f) {return {fragment:f, width: null};}) + d.fragments.push({fragment: c.wrapSpacer, width: null}) return textToRender; }) .each(function(d) { @@ -290,7 +300,9 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // finalize what's in the DOM Drawing.font(selection, d.font); setCellHeightAndPositionY(columnCell); - svgUtil.convertToTspans(selection, gd, finalizeYPositionMaker(allColumnBlock, element, d)); + + var renderCallback = d.wrappingNeeded ? wrapText : finalizeYPositionMaker; + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, d)); }); } @@ -462,6 +474,29 @@ function conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, revolve } } +function wrapText(columnBlock, element, d) { + var nextRenderCallback = finalizeYPositionMaker(columnBlock, element, d); + return function finalizeYPosition() { + var cellTextHolder = d3.select(element.parentNode); + cellTextHolder + .each(function(d) { + var fragments = d.fragments; + cellTextHolder.selectAll('tspan.line').each(function(dd, i) { + fragments[i].width = this.getComputedTextLength(); + }); + d.value = 'kjhdlk
jkelrjlk' + }); + + // the pre-wrapped text was rendered only for the text measurements + cellTextHolder.selectAll('tspan.line').remove(); + + // resupply text, now wrapped + //renderCellText(cellTextHolder.select('.cellText'), allColumnBlock, columnCell); + + nextRenderCallback(); + }; +} + function finalizeYPositionMaker(columnBlock, element, d) { return function finalizeYPosition() { var cellTextHolder = d3.select(element.parentNode); From 481b1932ea4c47b52a1e13a370fe950cc94a4c7b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Sep 2017 01:00:56 +0200 Subject: [PATCH 176/281] doing something... --- src/traces/table/plot.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 52b1b9bd136..b269eb5041c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -287,7 +287,7 @@ function renderCellText(cellText, allColumnBlock, columnCell) { var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); var textToRender = fragments.join('
') + "
"; d.latex = latex; - d.wrappingNeeded = !latex; + d.wrappingNeeded = !d.wrapped && !latex; d.fragments = fragments.map(function(f) {return {fragment:f, width: null};}) d.fragments.push({fragment: c.wrapSpacer, width: null}) return textToRender; @@ -484,14 +484,15 @@ function wrapText(columnBlock, element, d) { cellTextHolder.selectAll('tspan.line').each(function(dd, i) { fragments[i].width = this.getComputedTextLength(); }); - d.value = 'kjhdlk
jkelrjlk' + d.value = 'kjhdlk
jkelrjlk'; + d.wrapped = true; }); // the pre-wrapped text was rendered only for the text measurements cellTextHolder.selectAll('tspan.line').remove(); // resupply text, now wrapped - //renderCellText(cellTextHolder.select('.cellText'), allColumnBlock, columnCell); + renderCellText(cellTextHolder.select('.cellText'), columnBlock, d3.select(element.parentNode.parentNode)); nextRenderCallback(); }; From ac9dc0834ba9d3d1c71682051f00729008386495 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Sep 2017 20:28:59 +0200 Subject: [PATCH 177/281] tmp --- src/traces/table/plot.js | 4 ++-- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b269eb5041c..b29e1b869fa 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -379,7 +379,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2, headerPanel]; + return [revolverPanel1/*, revolverPanel2, headerPanel*/]; } function splitToCells(d) { @@ -484,7 +484,7 @@ function wrapText(columnBlock, element, d) { cellTextHolder.selectAll('tspan.line').each(function(dd, i) { fragments[i].width = this.getComputedTextLength(); }); - d.value = 'kjhdlk
jkelrjlk'; + d.value = 'kjhdlk
jkelrjlk
jkelrjlk
jkelrjlk
jkelrjlk
jkelrjlk
jkelrjlk
jkelrjlk'; d.wrapped = true; }); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index a277d30b4cc..7007687487a 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,7 +20,7 @@ "header": { - "height": 20, // fixme for some reason it doesn't recognize arrays here + "height": 60, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 10, + "height": 60, "align": ["right"], "valign": ["bottom"], From 11180ada80bedc3ad27109e96d0580b630389e75 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 15 Sep 2017 20:28:59 +0200 Subject: [PATCH 178/281] text wrapping works again --- src/traces/table/constants.js | 1 + src/traces/table/plot.js | 37 +++++++++++++++++++++++----- test/image/mocks/table_one_cell.json | 4 +-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 203c3fc15da..01b7bcfb65d 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -15,6 +15,7 @@ module.exports = { latexMark: '$', wrapSplitCharacter: ' ', wrapSpacer: ' ', + lineBreaker: '
', uplift: 5, columnTitleOffset: 28, columnExtentOffset: 10, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b269eb5041c..20f45c22af6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -284,12 +284,16 @@ function renderCellText(cellText, allColumnBlock, columnCell) { var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; - var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); - var textToRender = fragments.join('
') + "
"; d.latex = latex; d.wrappingNeeded = !d.wrapped && !latex; - d.fragments = fragments.map(function(f) {return {fragment:f, width: null};}) - d.fragments.push({fragment: c.wrapSpacer, width: null}) + var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); + var textToRender = d.wrappingNeeded ? fragments.join(c.lineBreaker) + c.lineBreaker + c.wrapSpacer : d.value; + if(d.wrappingNeeded) { + d.fragments = fragments.map(function (f) {return {text: f, width: null};}); + d.fragments.push({fragment: c.wrapSpacer, width: null}); + } else { + delete d.fragments; + } return textToRender; }) .each(function(d) { @@ -379,7 +383,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2, headerPanel]; + return [revolverPanel1/*, revolverPanel2, headerPanel*/]; } function splitToCells(d) { @@ -484,7 +488,28 @@ function wrapText(columnBlock, element, d) { cellTextHolder.selectAll('tspan.line').each(function(dd, i) { fragments[i].width = this.getComputedTextLength(); }); - d.value = 'kjhdlk
jkelrjlk'; + // last element is only for measuring the separator character, so it's ignored: + var separatorLength = fragments[fragments.length - 1].width; + var rest = fragments.slice(0, -1); + var currentRow = []; + var currentAddition, currentAdditionLength; + var currentRowLength = 0; + var rowLengthLimit = d.column.columnWidth; + d.value = ""; + while(rest.length) { + currentAddition = rest.shift(); + currentAdditionLength = currentAddition.width + separatorLength; + if(currentRowLength + currentAdditionLength > rowLengthLimit) { + d.value += c.lineBreaker + currentRow.join(c.wrapSpacer); + currentRow = []; + currentRowLength = 0; + } + currentRow.push(currentAddition.text); + currentRowLength += currentAdditionLength; + } + if(currentRowLength) { + d.value += c.lineBreaker + currentRow.join(c.wrapSpacer); + } d.wrapped = true; }); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index a277d30b4cc..7007687487a 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -20,7 +20,7 @@ "header": { - "height": 20, // fixme for some reason it doesn't recognize arrays here + "height": 60, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], @@ -114,7 +114,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 10, + "height": 60, "align": ["right"], "valign": ["bottom"], From ec17fb20ddc8b1e7a2754153f070d11e7af41563 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 19 Sep 2017 07:46:27 +0200 Subject: [PATCH 179/281] tmp --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 20f45c22af6..2620333230c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -500,7 +500,7 @@ function wrapText(columnBlock, element, d) { currentAddition = rest.shift(); currentAdditionLength = currentAddition.width + separatorLength; if(currentRowLength + currentAdditionLength > rowLengthLimit) { - d.value += c.lineBreaker + currentRow.join(c.wrapSpacer); + d.value += currentRow.join(c.wrapSpacer) + c.lineBreaker; currentRow = []; currentRowLength = 0; } @@ -508,7 +508,7 @@ function wrapText(columnBlock, element, d) { currentRowLength += currentAdditionLength; } if(currentRowLength) { - d.value += c.lineBreaker + currentRow.join(c.wrapSpacer); + d.value += currentRow.join(c.wrapSpacer); } d.wrapped = true; }); From 9e8b31b8cce748f2847963694891c2491d8432e2 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 21 Sep 2017 12:54:15 +0200 Subject: [PATCH 180/281] tmp --- src/traces/table/plot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b29e1b869fa..83f8a7113e4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -563,4 +563,3 @@ function rowsHeight(rowBlock, key) { function getBlock(d) {return d.rowBlocks[d.page];} function getRow(l, i) {return l.rows[i - l.firstRowIndex];} - From 1762d9ea518cd18b8a1be66dd2eaef62d9c7ca7e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 21 Sep 2017 21:43:13 +0200 Subject: [PATCH 181/281] wrapping such that preexisting `transform` is taken into account --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 01b7bcfb65d..a1a11789e05 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -11,7 +11,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, - cellPad: 4, + cellPad: 8, latexMark: '$', wrapSplitCharacter: ' ', wrapSpacer: ' ', diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2620333230c..dfac4519b0f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -305,7 +305,7 @@ function renderCellText(cellText, allColumnBlock, columnCell) { Drawing.font(selection, d.font); setCellHeightAndPositionY(columnCell); - var renderCallback = d.wrappingNeeded ? wrapText : finalizeYPositionMaker; + var renderCallback = d.wrappingNeeded ? wrapTextMaker : finalizeYPositionMaker; svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, d)); }); } @@ -478,9 +478,9 @@ function conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, revolve } } -function wrapText(columnBlock, element, d) { +function wrapTextMaker(columnBlock, element, d) { var nextRenderCallback = finalizeYPositionMaker(columnBlock, element, d); - return function finalizeYPosition() { + return function wrapText() { var cellTextHolder = d3.select(element.parentNode); cellTextHolder .each(function(d) { @@ -494,7 +494,7 @@ function wrapText(columnBlock, element, d) { var currentRow = []; var currentAddition, currentAdditionLength; var currentRowLength = 0; - var rowLengthLimit = d.column.columnWidth; + var rowLengthLimit = d.column.columnWidth - 2 * c.cellPad; d.value = ""; while(rest.length) { currentAddition = rest.shift(); @@ -548,9 +548,11 @@ function finalizeYPositionMaker(columnBlock, element, d) { cellTextHolder .attr('transform', function () { var element = this; - var box = element.parentNode.getBoundingClientRect(); + var columnCellElement = element.parentNode; + var box = columnCellElement.parentNode.getBoundingClientRect(); var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); - var yPosition = (rectBox.top - box.top + c.cellPad); + var currentTransform = element.transform.baseVal.consolidate(); + var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); }; From 8542a386fd336db0da757cedb242ff994c9e9cf7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 22 Sep 2017 01:13:45 +0200 Subject: [PATCH 182/281] properly pass on gd where needed --- src/traces/table/plot.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index dfac4519b0f..a5f0120684c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -125,7 +125,7 @@ module.exports = function plot(gd, calcdata) { d3.event.stopPropagation(); return d; }) - .on('drag', makeDragRow(cellsColumnBlock)) + .on('drag', makeDragRow(gd, cellsColumnBlock)) .on('dragend', function(d) { // fixme emit plotly notification }) @@ -270,10 +270,10 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .classed('cellText', true); cellText - .call(renderCellText, allColumnBlock, columnCell); + .call(renderCellText, allColumnBlock, columnCell, gd); } -function renderCellText(cellText, allColumnBlock, columnCell) { +function renderCellText(cellText, allColumnBlock, columnCell, gd) { cellText .text(function(d) { var col = d.column.specIndex; @@ -412,7 +412,7 @@ function overlap(a, b) { return a[0] < b[1] && a[1] > b[0]; } -function makeDragRow(cellsColumnBlock) { +function makeDragRow(gd, cellsColumnBlock) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; @@ -459,12 +459,12 @@ function makeDragRow(cellsColumnBlock) { }); // conditionally rerendering panel 0 and 1 - conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, 0); - conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, 1); + conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 0); + conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 1); } } -function conditionalPanelRerender(cellsColumnBlock, pages, prevPages, d, revolverIndex) { +function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, revolverIndex) { var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; if(shouldComponentUpdate) { window.clearTimeout(d.currentRepaint[revolverIndex]); From cce181656128cc74c03052ff4d527a49fee352c8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 00:38:32 +0200 Subject: [PATCH 183/281] finally, Firefox renders --- src/traces/table/plot.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a5f0120684c..759bab0f964 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -142,7 +142,7 @@ module.exports = function plot(gd, calcdata) { scrollAreaClip.enter() .append(c.clipView ? 'g' : 'clipPath') .classed('scrollAreaClip', true) - .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) + .attr('id', function(d) { return 'scrollAreaBottomClip_' + (c.clipView ? 'FirefoxSpoof_' : '') + d.key;}) var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') .data(gup.repeat, gup.keyFun); @@ -177,7 +177,7 @@ module.exports = function plot(gd, calcdata) { .classed('columnBoundaryClippath', true); columnBoundaryClippath - .attr('id', function(d) {return 'columnBoundaryClippath_' + d.specIndex;}); + .attr('id', function(d) {return 'columnBoundaryClippath_' + (c.clipView ? 'FirefoxSpoof_' : '') + d.specIndex;}); var columnBoundaryRect = columnBoundaryClippath.selectAll('.columnBoundaryRect') .data(gup.repeat, gup.keyFun); @@ -479,8 +479,10 @@ function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, rev } function wrapTextMaker(columnBlock, element, d) { + console.log(wrapTextMaker) var nextRenderCallback = finalizeYPositionMaker(columnBlock, element, d); return function wrapText() { + console.log(wrapText) var cellTextHolder = d3.select(element.parentNode); cellTextHolder .each(function(d) { From ae594ddeb640c920de6109a2b216d26c0ad3797e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 00:46:03 +0200 Subject: [PATCH 184/281] restored header --- src/traces/table/plot.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 759bab0f964..8de3b906383 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -383,7 +383,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1/*, revolverPanel2, headerPanel*/]; + return [revolverPanel1, revolverPanel2, headerPanel]; } function splitToCells(d) { @@ -479,10 +479,8 @@ function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, rev } function wrapTextMaker(columnBlock, element, d) { - console.log(wrapTextMaker) var nextRenderCallback = finalizeYPositionMaker(columnBlock, element, d); return function wrapText() { - console.log(wrapText) var cellTextHolder = d3.select(element.parentNode); cellTextHolder .each(function(d) { From cdaf961a9b92543e9717b6bf2bd8ab431d846d9a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 00:55:15 +0200 Subject: [PATCH 185/281] switching off clipView as it confuses FF --- src/traces/table/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index a1a11789e05..19526c64951 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -23,5 +23,5 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, - clipView: true + clipView: false }; From b39188d7d96fb294576294ea06bc892728f81790 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 00:59:11 +0200 Subject: [PATCH 186/281] avoid spoofing for FF; break clippath link instead at the user DOM node --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 19526c64951..a1a11789e05 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -23,5 +23,5 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, - clipView: false + clipView: true }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8de3b906383..73b106113a6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -56,7 +56,10 @@ module.exports = function plot(gd, calcdata) { tableControlView .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}) - .attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); + + if(!c.clipView) { + tableControlView.attr('clip-path', function (d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); + } var yColumn = tableControlView.selectAll('.yColumn') .data(function(vm) {return vm.columns;}, gup.keyFun); @@ -67,7 +70,6 @@ module.exports = function plot(gd, calcdata) { yColumn .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}) - .attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}) .call(d3.behavior.drag() .origin(function(d) { var movedColumn = d3.select(this); @@ -103,6 +105,10 @@ module.exports = function plot(gd, calcdata) { }) ); + if(!c.clipView) { + yColumn.attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}); + } + yColumn.exit() .remove(); @@ -142,7 +148,7 @@ module.exports = function plot(gd, calcdata) { scrollAreaClip.enter() .append(c.clipView ? 'g' : 'clipPath') .classed('scrollAreaClip', true) - .attr('id', function(d) { return 'scrollAreaBottomClip_' + (c.clipView ? 'FirefoxSpoof_' : '') + d.key;}) + .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') .data(gup.repeat, gup.keyFun); @@ -177,7 +183,7 @@ module.exports = function plot(gd, calcdata) { .classed('columnBoundaryClippath', true); columnBoundaryClippath - .attr('id', function(d) {return 'columnBoundaryClippath_' + (c.clipView ? 'FirefoxSpoof_' : '') + d.specIndex;}); + .attr('id', function(d) {return 'columnBoundaryClippath_' + d.specIndex;}); var columnBoundaryRect = columnBoundaryClippath.selectAll('.columnBoundaryRect') .data(gup.repeat, gup.keyFun); From 91b67e41058fdb726bed9919596ab5afb9c21b37 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 14:23:32 +0200 Subject: [PATCH 187/281] baseline for multirow wrapping --- src/traces/table/plot.js | 3 ++- test/image/mocks/table_one_cell.json | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 73b106113a6..c2426fb8608 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -389,7 +389,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2, headerPanel]; + return [revolverPanel1/*, revolverPanel2, headerPanel*/]; } function splitToCells(d) { @@ -542,6 +542,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); var increase = finalHeight - l.rows[rowIndex].rowHeight; + console.log('checking increase') if(increase) { // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 7007687487a..65b17c9d004 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,9 +1,9 @@ { "layout": { - "width": 300, - "height": 330 + 380 - 150, + "width": 400, + "height": 230 + 380 - 150, "title": "Widget parameters and cost", - "margin": {"t": 0 || 380, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, "data": [{ @@ -20,13 +20,13 @@ "header": { - "height": 60, // fixme for some reason it doesn't recognize arrays here + "height": 0, // fixme for some reason it doesn't recognize arrays here "values": [ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 1)}).slice(0, 1), + ].map(function(r) {return r.slice(0, 1)}).slice(1, 2), "align": ["right"], "valign": "middle", @@ -70,7 +70,9 @@ ].map(function(d, i) {return i}), [ "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "1AX
B
Plotly
CD", + "Hello1", + "Hello2", + //"1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", @@ -105,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 1)}).slice(1, 2), + ].map(function(a) {return [a[1], a[2]]}).slice(1, 2), "format": [ null @@ -114,7 +116,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 60, + "height": 50, "align": ["right"], "valign": ["bottom"], From 7af8966211c052604c9d881bccd3d89e0802fa2e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 17:30:57 +0200 Subject: [PATCH 188/281] avoid one unnecessary DOM subtree adjustment --- src/traces/table/plot.js | 8 ++------ test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c2426fb8608..3b1f95f1f62 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -139,7 +139,7 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); + //renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); renderColumnBlocks(gd, columnBlock.filter(cellsBlock), columnBlock); var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') @@ -484,8 +484,7 @@ function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, rev } } -function wrapTextMaker(columnBlock, element, d) { - var nextRenderCallback = finalizeYPositionMaker(columnBlock, element, d); +function wrapTextMaker(columnBlock, element) { return function wrapText() { var cellTextHolder = d3.select(element.parentNode); cellTextHolder @@ -524,8 +523,6 @@ function wrapTextMaker(columnBlock, element, d) { // resupply text, now wrapped renderCellText(cellTextHolder.select('.cellText'), columnBlock, d3.select(element.parentNode.parentNode)); - - nextRenderCallback(); }; } @@ -542,7 +539,6 @@ function finalizeYPositionMaker(columnBlock, element, d) { var finalHeight = Math.max(requiredHeight, l.rows[rowIndex].rowHeight); var increase = finalHeight - l.rows[rowIndex].rowHeight; - console.log('checking increase') if(increase) { // current row height increased l.rows[d.key - l.firstRowIndex].rowHeight = finalHeight; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 65b17c9d004..ed18ae2cf30 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return [a[1], a[2]]}).slice(1, 2), + ].map(function(a) {return [a[0]]}).slice(1, 2), "format": [ null From 998e61a8adc3dec471b08910ad78660d0da9d644 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 18:26:51 +0200 Subject: [PATCH 189/281] baseline for fixing overshifting --- test/image/mocks/table_one_cell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index ed18ae2cf30..65b17c9d004 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return [a[0]]}).slice(1, 2), + ].map(function(a) {return [a[1], a[2]]}).slice(1, 2), "format": [ null From 769654b84909c505d6972d46bc592e4ebaf10100 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 18:33:08 +0200 Subject: [PATCH 190/281] baseline for fixing overshifting 2 --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3b1f95f1f62..dc4cae9f337 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -291,7 +291,7 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; - d.wrappingNeeded = !d.wrapped && !latex; + d.wrappingNeeded = false && !d.wrapped && !latex; var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); var textToRender = d.wrappingNeeded ? fragments.join(c.lineBreaker) + c.lineBreaker + c.wrapSpacer : d.value; if(d.wrappingNeeded) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 65b17c9d004..01c9c3b6553 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -116,7 +116,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 50, + "height": 40, "align": ["right"], "valign": ["bottom"], From ff67893985a612ed993ffeb0bd3bf6f5d9bd3f68 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 23 Sep 2017 18:47:07 +0200 Subject: [PATCH 191/281] fixed multirow downshift problem --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index dc4cae9f337..b8faf8555f3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -291,7 +291,7 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; - d.wrappingNeeded = false && !d.wrapped && !latex; + d.wrappingNeeded = !d.wrapped && !latex; var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); var textToRender = d.wrappingNeeded ? fragments.join(c.lineBreaker) + c.lineBreaker + c.wrapSpacer : d.value; if(d.wrappingNeeded) { @@ -552,7 +552,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { .attr('transform', function () { var element = this; var columnCellElement = element.parentNode; - var box = columnCellElement.parentNode.getBoundingClientRect(); + var box = columnCellElement.getBoundingClientRect(); var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); From cfbcb21daf3be4dcf7147d523b71f93bcfad9c0c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 00:51:29 +0200 Subject: [PATCH 192/281] conditionalizing against markup with line breaks --- src/traces/table/plot.js | 13 +++++++++---- test/image/mocks/table_one_cell.json | 10 +++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b8faf8555f3..3ae4148f84f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -286,19 +286,24 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { var row = d.rowNumber; var userSuppliedContent = d.value; var latex = latexEh(userSuppliedContent); + var userBrokenText = userSuppliedContent.match(/
/i); var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; - d.wrappingNeeded = !d.wrapped && !latex; - var fragments = prefixSuffixedText.split(c.wrapSplitCharacter); - var textToRender = d.wrappingNeeded ? fragments.join(c.lineBreaker) + c.lineBreaker + c.wrapSpacer : d.value; + d.wrappingNeeded = !userBrokenText && !d.wrapped && !latex; + var textToRender; if(d.wrappingNeeded) { - d.fragments = fragments.map(function (f) {return {text: f, width: null};}); + var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/X
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "Hello2", //"1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "2AX
B
Plotly
CD", + "2AX
B
Plotly
CD", "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "3AX
B
Plotly
CD", "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return [a[1], a[2]]}).slice(1, 2), + ].map(function(a) {return [a[4]]}).slice(1, 2), "format": [ null From 1cf037e5fb9c2aa8032cdad8734055c7961ba036 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 00:58:32 +0200 Subject: [PATCH 193/281] very good single-column --- src/traces/table/plot.js | 4 ++-- test/image/mocks/table_one_cell.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3ae4148f84f..a29b7d3d106 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -139,7 +139,7 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - //renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); + renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); renderColumnBlocks(gd, columnBlock.filter(cellsBlock), columnBlock); var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') @@ -394,7 +394,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1/*, revolverPanel2, headerPanel*/]; + return [revolverPanel1, revolverPanel2, headerPanel]; } function splitToCells(d) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index a171de9b8c5..02213154de3 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 400, - "height": 330 + 380 - 150, + "height": 230 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, @@ -76,7 +76,7 @@ "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "2AX
B
Plotly
CD", "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "3AX
B
Plotly
CD", + "3AXB PlotlyCD", "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "4AX
B
Plotly
CD", "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return [a[4]]}).slice(1, 2), + ].map(function(a) {return a}).slice(1, 2), "format": [ null @@ -116,7 +116,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 40, + "height": 20, "align": ["right"], "valign": ["bottom"], From fa2a2a7264ab1429c2777b74e26ad754646832e7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 01:06:16 +0200 Subject: [PATCH 194/281] numbers ok; baseline for the issue of not downshifting next panel --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a29b7d3d106..04473b21639 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -286,7 +286,7 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { var row = d.rowNumber; var userSuppliedContent = d.value; var latex = latexEh(userSuppliedContent); - var userBrokenText = userSuppliedContent.match(/
/i); + var userBrokenText = (typeof userSuppliedContent !== 'string') || userSuppliedContent.match(/
/i); var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 02213154de3..e961f31570c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 1)}).slice(1, 2), + ].map(function(r) {return r.slice(0, 1)}).slice(0, 2), "align": ["right"], "valign": "middle", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a}).slice(1, 2), + ].map(function(a) {return a}).slice(0, 2), "format": [ null From 5b10f8ff2d19c0d38f5a1fedaea399a90defe922 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 01:21:37 +0200 Subject: [PATCH 195/281] splitting viewModel and render for columnBlock --- src/traces/table/plot.js | 13 +++++++++---- test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 04473b21639..cd9889c863a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -462,10 +462,15 @@ function makeDragRow(gd, cellsColumnBlock) { } cellsColumnBlock - .attr('transform', function (d, i) { - var dPage = pages[i]; - d.page = dPage; - var yTranslate = firstRowAnchor(blocks, dPage) - scrollY; + .each(function (d, i) { + // these values will also be needed when a block is translated again due to growing cell height + d.page = pages[i]; + d.scrollY = scrollY; + }); + + cellsColumnBlock + .attr('transform', function (d) { + var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; return 'translate(0 ' + yTranslate + ')'; }); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index e961f31570c..f4446318cac 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 1)}).slice(0, 2), + ].map(function(r) {return r.slice(0, 1)}).slice(1, 2), "align": ["right"], "valign": "middle", @@ -69,8 +69,8 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "Hello1", "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello1", "Hello2", //"1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a}).slice(0, 2), + ].map(function(a) {return a.slice(1)}).slice(1, 2), "format": [ null From 59a610865ca8ddb22bd93b5d67ec79c2f9673839 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 15:01:36 +0200 Subject: [PATCH 196/281] alternative take --- src/traces/table/plot.js | 10 +++++++--- test/image/mocks/table_one_cell.json | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index cd9889c863a..ea3a5080ae6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -431,10 +431,10 @@ function makeDragRow(gd, cellsColumnBlock) { var prevPages = [0, 0]; - return function dragRow (d) { - var direction = d3.event.dy < 0 ? 'down' : d3.event.dy > 0 ? 'up' : null; + function magic(d, dy) { + var direction = dy < 0 ? 'down' : dy > 0 ? 'up' : null; if(!direction) return; - calcdata.scrollY -= d3.event.dy; + calcdata.scrollY -= dy; var bottom = firstRowAnchor(blocks, blocks.length); var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); var scrollHeight = d.calcdata.groupHeight - headerHeight; @@ -478,6 +478,10 @@ function makeDragRow(gd, cellsColumnBlock) { conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 0); conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 1); } + + return function dragRow (d) { + magic(d, d3.event.dy); + } } function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, revolverIndex) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index f4446318cac..272cdcaa231 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,6 +1,6 @@ { "layout": { - "width": 400, + "width": 600, "height": 230 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 1)}).slice(1, 2), + ].map(function(r) {return r.slice(0, 2)}).slice(0, 3), "align": ["right"], "valign": "middle", @@ -69,8 +69,8 @@ "8AX
B
Plotly
CD", ].map(function(d, i) {return i}), [ - "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "Hello2", //"1AX
B
Plotly
CD", "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(1)}).slice(1, 2), + ].map(function(a) {return a.slice(0)}).slice(0, 3), "format": [ null From 38f5c9f359f2c6f24fb680f41c6fb57674deb188 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 16:54:16 +0200 Subject: [PATCH 197/281] alternative take 2 --- src/traces/table/plot.js | 94 ++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ea3a5080ae6..c5892cda09d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -423,64 +423,66 @@ function overlap(a, b) { return a[0] < b[1] && a[1] > b[0]; } -function makeDragRow(gd, cellsColumnBlock) { +function magic(gd, cellsColumnBlock, prevPages, dy) { + var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; - var prevPages = [0, 0]; - - function magic(d, dy) { - var direction = dy < 0 ? 'down' : dy > 0 ? 'up' : null; - if(!direction) return; - calcdata.scrollY -= dy; - var bottom = firstRowAnchor(blocks, blocks.length); - var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); - var scrollHeight = d.calcdata.groupHeight - headerHeight; - var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - - var pages = []; - for(var p = 0; p < blocks.length; p++) { - var pTop = firstRowAnchor(blocks, p); - var pBottom = pTop + rowsHeight(blocks[p], Infinity); - if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { - pages.push(p); - } + var direction = dy < 0 ? 'down' : dy > 0 ? 'up' : null; + if(!direction) return; + calcdata.scrollY -= dy; + var bottom = firstRowAnchor(blocks, blocks.length); + var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); + var scrollHeight = d.calcdata.groupHeight - headerHeight; + var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); + + var pages = []; + for(var p = 0; p < blocks.length; p++) { + var pTop = firstRowAnchor(blocks, p); + var pBottom = pTop + rowsHeight(blocks[p], Infinity); + if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { + pages.push(p); } - if(pages.length === 1) { - if(pages[0] === blocks.length - 1) { - pages.unshift(pages[0] - 1); - } else { - pages.push(pages[0] + 1); - } + } + if(pages.length === 1) { + if(pages[0] === blocks.length - 1) { + pages.unshift(pages[0] - 1); + } else { + pages.push(pages[0] + 1); } + } - // make phased out page jump by 2 while leaving stationary page intact - if(pages[0] % 2) { - pages.reverse(); - } + // make phased out page jump by 2 while leaving stationary page intact + if(pages[0] % 2) { + pages.reverse(); + } - cellsColumnBlock - .each(function (d, i) { - // these values will also be needed when a block is translated again due to growing cell height - d.page = pages[i]; - d.scrollY = scrollY; - }); + cellsColumnBlock + .each(function (d, i) { + // these values will also be needed when a block is translated again due to growing cell height + d.page = pages[i]; + d.scrollY = scrollY; + }); - cellsColumnBlock - .attr('transform', function (d) { - var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; - return 'translate(0 ' + yTranslate + ')'; - }); + cellsColumnBlock + .attr('transform', function (d) { + var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; + return 'translate(0 ' + yTranslate + ')'; + }); - // conditionally rerendering panel 0 and 1 - conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 0); - conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 1); - } + // conditionally rerendering panel 0 and 1 + conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 0); + conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 1); +} + +function makeDragRow(gd, cellsColumnBlock) { + + var prevPages = [0, 0]; - return function dragRow (d) { - magic(d, d3.event.dy); + return function dragRow () { + magic(gd, cellsColumnBlock, prevPages, d3.event.dy); } } From 1ab9af50a7b7b526fd317f734980b0c75f3d50f3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 17:16:24 +0200 Subject: [PATCH 198/281] alternative take 3 --- src/traces/table/calc.js | 1 + src/traces/table/plot.js | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 786ef1bae32..931760bcf31 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -53,6 +53,7 @@ module.exports = function calc(gd, trace) { headerCells: trace.header, gdColumns: trace.header.values.map(function(d) {return d[0];}), gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}), + prevPages: [0, 0], columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c5892cda09d..5733a0894f3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -365,10 +365,12 @@ function headerBlock(d) {return d.type === 'header';} */ function splitToPanels(d) { + var prevPages = [0, 0]; var headerPanel = extendFlat({}, d, { key: 'header', type: 'header', page: 0, + prevPages: prevPages, currentRepaint: [null, null], dragHandle: true, values: d.calcdata.headerCells.values[d.specIndex], @@ -379,6 +381,7 @@ function splitToPanels(d) { key: 'cells1', type: 'cells', page: 0, + prevPages: prevPages, currentRepaint: [null, null], dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -388,6 +391,7 @@ function splitToPanels(d) { key: 'cells2', type: 'cells', page: 0, + prevPages: prevPages, currentRepaint: [null, null], dragHandle: false, values: d.calcdata.cells.values[d.specIndex], @@ -423,7 +427,7 @@ function overlap(a, b) { return a[0] < b[1] && a[1] > b[0]; } -function magic(gd, cellsColumnBlock, prevPages, dy) { +function magic(gd, cellsColumnBlock, dy) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; @@ -473,16 +477,14 @@ function magic(gd, cellsColumnBlock, prevPages, dy) { }); // conditionally rerendering panel 0 and 1 - conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 0); - conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, 1); + conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 0); + conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 1); } function makeDragRow(gd, cellsColumnBlock) { - var prevPages = [0, 0]; - return function dragRow () { - magic(gd, cellsColumnBlock, prevPages, d3.event.dy); + magic(gd, cellsColumnBlock, d3.event.dy); } } From 5766916b7f46e940b371500e143fb867bea3d37e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 17:50:39 +0200 Subject: [PATCH 199/281] block bumping now works fine! --- src/traces/table/plot.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5733a0894f3..08735bf0f41 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -434,8 +434,6 @@ function magic(gd, cellsColumnBlock, dy) { var calcdata = d.calcdata; var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; - var direction = dy < 0 ? 'down' : dy > 0 ? 'up' : null; - if(!direction) return; calcdata.scrollY -= dy; var bottom = firstRowAnchor(blocks, blocks.length); var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); @@ -477,8 +475,10 @@ function magic(gd, cellsColumnBlock, dy) { }); // conditionally rerendering panel 0 and 1 - conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 0); - conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 1); + if(gd) { + conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 0); + conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 1); + } } function makeDragRow(gd, cellsColumnBlock) { @@ -564,6 +564,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { columnBlock .selectAll('.columnCell') .call(setCellHeightAndPositionY); + magic(null, columnBlock.filter(cellsBlock), 0); } cellTextHolder From 6ae80f2b33cf346a401a585cd1e21a78302be272 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 24 Sep 2017 22:38:34 +0200 Subject: [PATCH 200/281] restoring clipping --- src/traces/table/constants.js | 2 +- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index a1a11789e05..19526c64951 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -23,5 +23,5 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, - clipView: true + clipView: false }; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 272cdcaa231..ccc4501f600 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 230 + 380 - 150, + "height": 430 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, From e5ba612166d57bc1f5dfac4a866cfbfcfcfeea19 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 25 Sep 2017 01:07:09 +0200 Subject: [PATCH 201/281] rename --- src/traces/table/plot.js | 13 ++++++------- test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 08735bf0f41..28903ad86a7 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -316,7 +316,7 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { Drawing.font(selection, d.font); setCellHeightAndPositionY(columnCell); - var renderCallback = d.wrappingNeeded ? wrapTextMaker : finalizeYPositionMaker; + var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, d)); }); } @@ -427,7 +427,7 @@ function overlap(a, b) { return a[0] < b[1] && a[1] > b[0]; } -function magic(gd, cellsColumnBlock, dy) { +function updateBlockYPosition(gd, cellsColumnBlock, dy) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; @@ -482,9 +482,8 @@ function magic(gd, cellsColumnBlock, dy) { } function makeDragRow(gd, cellsColumnBlock) { - return function dragRow () { - magic(gd, cellsColumnBlock, d3.event.dy); + updateBlockYPosition(gd, cellsColumnBlock, d3.event.dy); } } @@ -544,8 +543,8 @@ function wrapTextMaker(columnBlock, element) { }; } -function finalizeYPositionMaker(columnBlock, element, d) { - return function finalizeYPosition() { +function updateYPositionMaker(columnBlock, element, d) { + return function updateYPosition() { var cellTextHolder = d3.select(element.parentNode); var l = getBlock(d); var rowIndex = d.key - l.firstRowIndex; @@ -564,7 +563,7 @@ function finalizeYPositionMaker(columnBlock, element, d) { columnBlock .selectAll('.columnCell') .call(setCellHeightAndPositionY); - magic(null, columnBlock.filter(cellsBlock), 0); + updateBlockYPosition(null, columnBlock.filter(cellsBlock), 0); } cellTextHolder diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index ccc4501f600..5e889b541f1 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 430 + 380 - 150, + "height": 250 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, From f18e729efe1864448de9e71532801851152ec37e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 25 Sep 2017 11:46:34 +0200 Subject: [PATCH 202/281] tmp --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 28903ad86a7..c19bd3835bb 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -17,6 +17,7 @@ var svgUtil = require('../../lib/svg_text_utils'); var raiseToTop = require('../../lib').raiseToTop; var cancelEeaseColumn = require('../../lib').cancelTransition; + module.exports = function plot(gd, calcdata) { if(c.clipView) { From 56699e996c190bffd5bee8e05afdc769d7245ef6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 25 Sep 2017 18:30:37 +0200 Subject: [PATCH 203/281] optical test for OS X native like scrollbar --- src/traces/table/constants.js | 1 + src/traces/table/plot.js | 40 +++++++++++++++++++++++++--- test/image/mocks/table_one_cell.json | 2 +- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 19526c64951..028afa1f5e8 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -23,5 +23,6 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, + scrollbarWidth: 9, clipView: false }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c19bd3835bb..c44633899ef 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -17,7 +17,6 @@ var svgUtil = require('../../lib/svg_text_utils'); var raiseToTop = require('../../lib').raiseToTop; var cancelEeaseColumn = require('../../lib').cancelTransition; - module.exports = function plot(gd, calcdata) { if(c.clipView) { @@ -53,7 +52,8 @@ module.exports = function plot(gd, calcdata) { tableControlView.enter() .append('g') .classed('tableControlView', true) - .style('box-sizing', 'content-box'); + .style('box-sizing', 'content-box') + .call(renderScrollbarKit); tableControlView .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}) @@ -149,7 +149,7 @@ module.exports = function plot(gd, calcdata) { scrollAreaClip.enter() .append(c.clipView ? 'g' : 'clipPath') .classed('scrollAreaClip', true) - .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}) + .attr('id', function(d) { return 'scrollAreaBottomClip_' + d.key;}); var scrollAreaClipRect = scrollAreaClip.selectAll('.scrollAreaClipRect') .data(gup.repeat, gup.keyFun); @@ -202,6 +202,40 @@ module.exports = function plot(gd, calcdata) { .attr('height', function(d) {return d.calcdata.height + c.uplift;}); }; +function renderScrollbarKit(tableControlView) { + + var scrollbarKit = tableControlView.selectAll('.scrollbarKit') + .data(gup.repeat, gup.keyFun); + + scrollbarKit.enter() + .append('g') + .classed('scrollbarKit', true) + .attr('transform', function(d) {return 'translate(' + (d.width + c.scrollbarWidth) + ' 0)';}); + + var scrollbar = scrollbarKit.selectAll('.scrollbar') + .data(gup.repeat, gup.keyFun); + + scrollbar.enter() + .append('g') + .classed('scrollbar', true); + + + var scrollbarGlyph = scrollbar.selectAll('.scrollbarGlyph') + .data(gup.repeat, gup.keyFun); + + scrollbarGlyph.enter() + .append('line') + .classed('scrollbarGlyph', true) + .attr('stroke', 'black') + .attr('stroke-opacity', 0.4) + .attr('stroke-width', c.scrollbarWidth) + .attr('stroke-linecap', 'round'); + + scrollbarGlyph + .attr('y1', 100) + .attr('y2', 250); +} + function renderColumnBlocks(gd, columnBlock, allColumnBlock) { // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 5e889b541f1..2e7276012cc 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 250 + 380 - 150, + "height": 200 + 250 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, From 0755456aadf346d9fbe688a07d89523702944af9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 25 Sep 2017 19:21:45 +0200 Subject: [PATCH 204/281] baseline for making scrollbar reflect position and coverage --- src/traces/table/constants.js | 3 ++- src/traces/table/plot.js | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 028afa1f5e8..fa70b49a248 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -23,6 +23,7 @@ module.exports = { transitionDuration: 100, releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, - scrollbarWidth: 9, + scrollbarWidth: 8, + scrollbarOffset: 5, clipView: false }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c44633899ef..d469122089c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -210,7 +210,7 @@ function renderScrollbarKit(tableControlView) { scrollbarKit.enter() .append('g') .classed('scrollbarKit', true) - .attr('transform', function(d) {return 'translate(' + (d.width + c.scrollbarWidth) + ' 0)';}); + .attr('transform', function(d) {return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' 0)';}); var scrollbar = scrollbarKit.selectAll('.scrollbar') .data(gup.repeat, gup.keyFun); @@ -219,7 +219,6 @@ function renderScrollbarKit(tableControlView) { .append('g') .classed('scrollbar', true); - var scrollbarGlyph = scrollbar.selectAll('.scrollbarGlyph') .data(gup.repeat, gup.keyFun); From 4f70c4f05ce5bbfffc462d3b962555268b235543 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 25 Sep 2017 23:48:06 +0200 Subject: [PATCH 205/281] piping enough data through to enable scrollbar rerendering --- src/traces/table/plot.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d469122089c..a5dc0132f28 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -140,8 +140,8 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - renderColumnBlocks(gd, columnBlock.filter(headerBlock), columnBlock); - renderColumnBlocks(gd, columnBlock.filter(cellsBlock), columnBlock); + renderColumnBlocks(gd, tableControlView, columnBlock.filter(headerBlock), columnBlock); + renderColumnBlocks(gd, tableControlView, columnBlock.filter(cellsBlock), columnBlock); var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') .data(gup.repeat, gup.keyFun); @@ -231,11 +231,11 @@ function renderScrollbarKit(tableControlView) { .attr('stroke-linecap', 'round'); scrollbarGlyph - .attr('y1', 100) - .attr('y2', 250); + .attr('y1', function(d) {return 100}) + .attr('y2', 120 + Math.random() * 150); } -function renderColumnBlocks(gd, columnBlock, allColumnBlock) { +function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization @@ -310,10 +310,10 @@ function renderColumnBlocks(gd, columnBlock, allColumnBlock) { .classed('cellText', true); cellText - .call(renderCellText, allColumnBlock, columnCell, gd); + .call(renderCellText, tableControlView, allColumnBlock, columnCell, gd); } -function renderCellText(cellText, allColumnBlock, columnCell, gd) { +function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, gd) { cellText .text(function(d) { var col = d.column.specIndex; @@ -351,7 +351,7 @@ function renderCellText(cellText, allColumnBlock, columnCell, gd) { setCellHeightAndPositionY(columnCell); var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; - svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, d)); + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); }); } @@ -535,7 +535,7 @@ function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, rev } } -function wrapTextMaker(columnBlock, element) { +function wrapTextMaker(columnBlock, element, tableControlView) { return function wrapText() { var cellTextHolder = d3.select(element.parentNode); cellTextHolder @@ -573,11 +573,11 @@ function wrapTextMaker(columnBlock, element) { cellTextHolder.selectAll('tspan.line').remove(); // resupply text, now wrapped - renderCellText(cellTextHolder.select('.cellText'), columnBlock, d3.select(element.parentNode.parentNode)); + renderCellText(cellTextHolder.select('.cellText'), tableControlView, columnBlock, d3.select(element.parentNode.parentNode)); }; } -function updateYPositionMaker(columnBlock, element, d) { +function updateYPositionMaker(columnBlock, element, tableControlView, d) { return function updateYPosition() { var cellTextHolder = d3.select(element.parentNode); var l = getBlock(d); @@ -597,6 +597,10 @@ function updateYPositionMaker(columnBlock, element, d) { columnBlock .selectAll('.columnCell') .call(setCellHeightAndPositionY); + if(d.column.key === 'header') { + // if the header increased in height, the scrollbar has to be pushed downward to the scrollable area + renderScrollbarKit(tableControlView); + } updateBlockYPosition(null, columnBlock.filter(cellsBlock), 0); } From ac7c2b155a4ab6195895328df4991411b74ee1db Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 00:06:02 +0200 Subject: [PATCH 206/281] abstracting out data for scrollbar rerendering --- src/traces/table/plot.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a5dc0132f28..a3d31771848 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -231,8 +231,12 @@ function renderScrollbarKit(tableControlView) { .attr('stroke-linecap', 'round'); scrollbarGlyph - .attr('y1', function(d) {return 100}) - .attr('y2', 120 + Math.random() * 150); + .attr('y1', function(d) { + return headerHeight(d) + c.scrollbarWidth / 2; + }) + .attr('y2', function(d) { + return d.groupHeight - c.scrollbarWidth / 2; + }); } function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { @@ -461,17 +465,20 @@ function overlap(a, b) { return a[0] < b[1] && a[1] > b[0]; } +function headerHeight(d) { + var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; + return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); +} + function updateBlockYPosition(gd, cellsColumnBlock, dy) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; - var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; calcdata.scrollY -= dy; var bottom = firstRowAnchor(blocks, blocks.length); - var headerHeight = headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); - var scrollHeight = d.calcdata.groupHeight - headerHeight; + var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); var pages = []; From 16eaee9b83d1000192cf4d2ffd42a9eee2c35e74 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 16:12:24 +0200 Subject: [PATCH 207/281] properly sized scrollbar even for a short row --- src/traces/table/plot.js | 42 ++++++++++++++++++++++------ test/image/mocks/table_one_cell.json | 2 +- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a3d31771848..7be6187f765 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -210,7 +210,11 @@ function renderScrollbarKit(tableControlView) { scrollbarKit.enter() .append('g') .classed('scrollbarKit', true) - .attr('transform', function(d) {return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' 0)';}); + + scrollbarKit + .attr('transform', function(d) { + return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' ' + headerHeight(d) + ')'; + }); var scrollbar = scrollbarKit.selectAll('.scrollbar') .data(gup.repeat, gup.keyFun); @@ -219,7 +223,14 @@ function renderScrollbarKit(tableControlView) { .append('g') .classed('scrollbar', true); - var scrollbarGlyph = scrollbar.selectAll('.scrollbarGlyph') + var scrollbarSlider = scrollbar.selectAll('.scrollbarSlider') + .data(gup.repeat, gup.keyFun); + + scrollbarSlider.enter() + .append('g') + .classed('scrollbarSlider', true); + + var scrollbarGlyph = scrollbarSlider.selectAll('.scrollbarGlyph') .data(gup.repeat, gup.keyFun); scrollbarGlyph.enter() @@ -232,10 +243,15 @@ function renderScrollbarKit(tableControlView) { scrollbarGlyph .attr('y1', function(d) { - return headerHeight(d) + c.scrollbarWidth / 2; + return c.scrollbarWidth / 2; }) .attr('y2', function(d) { - return d.groupHeight - c.scrollbarWidth / 2; + var blocks = d.rowBlocks; + var totalHeight = firstRowAnchor2(blocks, blocks.length) + rowsHeight(blocks[blocks.length - 1], Infinity); + var scrollableAreaHeight = d.groupHeight - headerHeight(d); + var currentlyVisibleHeight = Math.min(totalHeight, scrollableAreaHeight); + var ratio = currentlyVisibleHeight / totalHeight; + return ratio * (currentlyVisibleHeight - c.scrollbarWidth / 2); }); } @@ -604,11 +620,13 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { columnBlock .selectAll('.columnCell') .call(setCellHeightAndPositionY); - if(d.column.key === 'header') { - // if the header increased in height, the scrollbar has to be pushed downward to the scrollable area - renderScrollbarKit(tableControlView); - } + updateBlockYPosition(null, columnBlock.filter(cellsBlock), 0); + + // if d.column.type === 'header', then the scrollbar has to be pushed downward to the scrollable area + // if d.column.type === 'cells', it can still be relevant if total scrolling content height is less than the + // scrollable window, as increases to row heights may need scrollbar updates + renderScrollbarKit(tableControlView); } cellTextHolder @@ -646,6 +664,14 @@ function firstRowAnchor(rowBlocks, page) { return total; } +function firstRowAnchor2(rowBlocks, page) { + var total = 0; + for(var i = 0; i < page - 1; i++) { + total += rowsHeight(rowBlocks[i], Infinity); + } + return total; +} + function rowsHeight(rowBlock, key) { var total = 0; for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 2e7276012cc..2816152a23c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0)}).slice(0, 3), + ].map(function(a) {return a.slice(0, 20)}).slice(0, 3), "format": [ null From 5039a81b9b0701287315a9d9c14f6453f15cac68 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 18:50:32 +0200 Subject: [PATCH 208/281] perfect scroll bar in one direction --- src/traces/table/constants.js | 2 ++ src/traces/table/plot.js | 47 +++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index fa70b49a248..7bcbc2d998d 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -25,5 +25,7 @@ module.exports = { releaseTransitionDuration: 300, scrollbarWidth: 8, scrollbarOffset: 5, + scrollbarHideDelay: 1000, + scrollbarHideDuration: 1000, clipView: false }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7be6187f765..00b213c6d47 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -132,7 +132,7 @@ module.exports = function plot(gd, calcdata) { d3.event.stopPropagation(); return d; }) - .on('drag', makeDragRow(gd, cellsColumnBlock)) + .on('drag', makeDragRow(gd, tableControlView, cellsColumnBlock)) .on('dragend', function(d) { // fixme emit plotly notification }) @@ -204,6 +204,11 @@ module.exports = function plot(gd, calcdata) { function renderScrollbarKit(tableControlView) { + function calcTotalHeight(d) { + var blocks = d.rowBlocks; + return firstRowAnchor2(blocks, blocks.length) + rowsHeight(blocks[blocks.length - 1], Infinity); + } + var scrollbarKit = tableControlView.selectAll('.scrollbarKit') .data(gup.repeat, gup.keyFun); @@ -213,7 +218,20 @@ function renderScrollbarKit(tableControlView) { scrollbarKit .attr('transform', function(d) { - return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' ' + headerHeight(d) + ')'; + var scrollY = d.scrollY; + + var totalHeight = calcTotalHeight(d); + var scrollableAreaHeight = d.groupHeight - headerHeight(d); + var currentlyVisibleHeight = Math.min(totalHeight, scrollableAreaHeight); + var ratio = currentlyVisibleHeight / totalHeight; + var barLength = ratio * currentlyVisibleHeight; + + var effectiveScrollBarWiggleRoom = currentlyVisibleHeight - barLength; + var effectiveScrollWiggleRoom = totalHeight - scrollableAreaHeight; + var topY = (scrollY / effectiveScrollWiggleRoom) * effectiveScrollBarWiggleRoom; + + var yPosition = headerHeight(d) + topY; + return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' ' + yPosition + ')'; }); var scrollbar = scrollbarKit.selectAll('.scrollbar') @@ -237,7 +255,6 @@ function renderScrollbarKit(tableControlView) { .append('line') .classed('scrollbarGlyph', true) .attr('stroke', 'black') - .attr('stroke-opacity', 0.4) .attr('stroke-width', c.scrollbarWidth) .attr('stroke-linecap', 'round'); @@ -246,13 +263,22 @@ function renderScrollbarKit(tableControlView) { return c.scrollbarWidth / 2; }) .attr('y2', function(d) { - var blocks = d.rowBlocks; - var totalHeight = firstRowAnchor2(blocks, blocks.length) + rowsHeight(blocks[blocks.length - 1], Infinity); + var totalHeight = calcTotalHeight(d); var scrollableAreaHeight = d.groupHeight - headerHeight(d); var currentlyVisibleHeight = Math.min(totalHeight, scrollableAreaHeight); var ratio = currentlyVisibleHeight / totalHeight; - return ratio * (currentlyVisibleHeight - c.scrollbarWidth / 2); - }); + var barLength = ratio * currentlyVisibleHeight; + return barLength - c.scrollbarWidth / 2; + }) + .attr('stroke-opacity', 0.4) + + // cancel transition: possible pending (also, delayed) transition + scrollbarGlyph + .transition().delay(0).duration(0); + + scrollbarGlyph + .transition().delay(c.scrollbarHideDelay).duration(c.scrollbarHideDuration) + .attr('stroke-opacity', 0); } function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { @@ -486,7 +512,7 @@ function headerHeight(d) { return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); } -function updateBlockYPosition(gd, cellsColumnBlock, dy) { +function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; @@ -535,12 +561,13 @@ function updateBlockYPosition(gd, cellsColumnBlock, dy) { if(gd) { conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 0); conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 1); + renderScrollbarKit(tableControlView); } } -function makeDragRow(gd, cellsColumnBlock) { +function makeDragRow(gd, tableControlView, cellsColumnBlock) { return function dragRow () { - updateBlockYPosition(gd, cellsColumnBlock, d3.event.dy); + updateBlockYPosition(gd, cellsColumnBlock, d3.event.dy, tableControlView); } } From 48ca142a124b1767acb4f83db444bd8ed2b30e37 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 20:07:43 +0200 Subject: [PATCH 209/281] d.scrollbarState --- src/traces/table/calc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 931760bcf31..d3843eddf72 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -54,6 +54,7 @@ module.exports = function calc(gd, trace) { gdColumns: trace.header.values.map(function(d) {return d[0];}), gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}), prevPages: [0, 0], + scrollbarState: {}, columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; From 840c06417f111484496a54f8d540025116f47be4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 20:13:01 +0200 Subject: [PATCH 210/281] avoiding multiple calculations --- src/traces/table/plot.js | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 00b213c6d47..13f77fe0eba 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -217,21 +217,21 @@ function renderScrollbarKit(tableControlView) { .classed('scrollbarKit', true) scrollbarKit + .each(function(d) { + var s = d.scrollbarState; + s.totalHeight = calcTotalHeight(d); + s.scrollableAreaHeight = d.groupHeight - headerHeight(d); + s.currentlyVisibleHeight = Math.min(s.totalHeight, s.scrollableAreaHeight); + s.ratio = s.currentlyVisibleHeight / s.totalHeight; + s.barLength = s.ratio * s.currentlyVisibleHeight; + s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; + s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; + s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; + s.yPosition = headerHeight(d) + s.topY; + }) .attr('transform', function(d) { - var scrollY = d.scrollY; - - var totalHeight = calcTotalHeight(d); - var scrollableAreaHeight = d.groupHeight - headerHeight(d); - var currentlyVisibleHeight = Math.min(totalHeight, scrollableAreaHeight); - var ratio = currentlyVisibleHeight / totalHeight; - var barLength = ratio * currentlyVisibleHeight; - - var effectiveScrollBarWiggleRoom = currentlyVisibleHeight - barLength; - var effectiveScrollWiggleRoom = totalHeight - scrollableAreaHeight; - var topY = (scrollY / effectiveScrollWiggleRoom) * effectiveScrollBarWiggleRoom; - - var yPosition = headerHeight(d) + topY; - return 'translate(' + (d.width + c.scrollbarWidth / 2 + c.scrollbarOffset) + ' ' + yPosition + ')'; + var xPosition = d.width + c.scrollbarWidth / 2 + c.scrollbarOffset; + return 'translate(' + xPosition + ' ' + d.scrollbarState.yPosition + ')'; }); var scrollbar = scrollbarKit.selectAll('.scrollbar') @@ -263,12 +263,7 @@ function renderScrollbarKit(tableControlView) { return c.scrollbarWidth / 2; }) .attr('y2', function(d) { - var totalHeight = calcTotalHeight(d); - var scrollableAreaHeight = d.groupHeight - headerHeight(d); - var currentlyVisibleHeight = Math.min(totalHeight, scrollableAreaHeight); - var ratio = currentlyVisibleHeight / totalHeight; - var barLength = ratio * currentlyVisibleHeight; - return barLength - c.scrollbarWidth / 2; + return d.scrollbarState.barLength - c.scrollbarWidth / 2; }) .attr('stroke-opacity', 0.4) From 78a8ac79f494176b6486d02850da68adf12b5d1a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 20:49:18 +0200 Subject: [PATCH 211/281] baseline for making the scrollbar interactive --- src/traces/table/constants.js | 3 ++- src/traces/table/plot.js | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 7bcbc2d998d..4f4f275576b 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -24,8 +24,9 @@ module.exports = { releaseTransitionEase: 'elastic', releaseTransitionDuration: 300, scrollbarWidth: 8, + scrollbarCaptureWidth: 18, scrollbarOffset: 5, scrollbarHideDelay: 1000, scrollbarHideDuration: 1000, - clipView: false + clipView: true }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 13f77fe0eba..5d81f543a0c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -256,16 +256,14 @@ function renderScrollbarKit(tableControlView) { .classed('scrollbarGlyph', true) .attr('stroke', 'black') .attr('stroke-width', c.scrollbarWidth) - .attr('stroke-linecap', 'round'); + .attr('stroke-linecap', 'round') + .attr('y1', c.scrollbarWidth / 2); scrollbarGlyph - .attr('y1', function(d) { - return c.scrollbarWidth / 2; - }) .attr('y2', function(d) { return d.scrollbarState.barLength - c.scrollbarWidth / 2; }) - .attr('stroke-opacity', 0.4) + .attr('stroke-opacity', 0.4); // cancel transition: possible pending (also, delayed) transition scrollbarGlyph @@ -274,6 +272,23 @@ function renderScrollbarKit(tableControlView) { scrollbarGlyph .transition().delay(c.scrollbarHideDelay).duration(c.scrollbarHideDuration) .attr('stroke-opacity', 0); + + var scrollbarCaptureZone = scrollbarSlider.selectAll('.scrollbarCaptureZone') + .data(gup.repeat, gup.keyFun); + + scrollbarCaptureZone.enter() + .append('line') + .classed('scrollbarCaptureZone', true) + .attr('stroke', 'red') + .attr('stroke-width', c.scrollbarCaptureWidth) + .attr('stroke-linecap', 'square') + .attr('stroke-opacity', c.clipView ? 0.5 : 0) + .attr('y1', c.scrollbarCaptureWidth / 2); + + scrollbarCaptureZone + .attr('y2', function(d) { + return d.scrollbarState.barLength - c.scrollbarCaptureWidth / 2; + }); } function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { From 126e93da1e20fa76f4314fe6873d6b8865782623 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 21:12:54 +0200 Subject: [PATCH 212/281] drag event logged --- src/traces/table/plot.js | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5d81f543a0c..2b4636473b6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -283,7 +283,47 @@ function renderScrollbarKit(tableControlView) { .attr('stroke-width', c.scrollbarCaptureWidth) .attr('stroke-linecap', 'square') .attr('stroke-opacity', c.clipView ? 0.5 : 0) - .attr('y1', c.scrollbarCaptureWidth / 2); + .attr('y1', c.scrollbarCaptureWidth / 2) + .call(d3.behavior.drag() + .origin(function(d) { + console.log('drag started') + return d; + var movedColumn = d3.select(this); + easeColumn(movedColumn, d, -c.uplift); + raiseToTop(this); + return d; + }) + .on('drag', function(d) { + console.log('drag') + return + var movedColumn = d3.select(this); + var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;} + d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); + var newOrder = yColumn.data().sort(function(a, b) {return getter(a) - getter(b);}); + newOrder.forEach(function(dd, i) { + dd.xIndex = i; + dd.x = d === dd ? dd.x : dd.xScale(dd); + }) + + yColumn.filter(function(dd) {return d !== dd;}) + .transition() + .ease(c.transitionEase) + .duration(c.transitionDuration) + .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); + movedColumn + .call(cancelEeaseColumn) + .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); + }) + .on('dragend', function(d) { + console.log('drag ended') + return + var movedColumn = d3.select(this); + var p = d.calcdata; + d.x = d.xScale(d); + easeColumn(movedColumn, d, 0); + columnMoved(gd, calcdata, p.key, p.columns.map(function(dd) {return dd.xIndex;})); + }) + ); scrollbarCaptureZone .attr('y2', function(d) { From 1ce53dc23abd1629040c2874939892801373f45f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 22:38:17 +0200 Subject: [PATCH 213/281] scrollbar starts to control --- src/traces/table/calc.js | 2 +- src/traces/table/plot.js | 34 +++++++++------------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index d3843eddf72..0cbce03b5f7 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -54,7 +54,7 @@ module.exports = function calc(gd, trace) { gdColumns: trace.header.values.map(function(d) {return d[0];}), gdColumnsOriginalOrder: trace.header.values.map(function(d) {return d[0];}), prevPages: [0, 0], - scrollbarState: {}, + scrollbarState: {scrollbarScrollInProgress: false}, columns: trace.header.values.map(function(label, i) { var foundKey = uniqueKeys[label]; uniqueKeys[label] = (foundKey || 0) + 1; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2b4636473b6..839174ed2c4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -132,7 +132,7 @@ module.exports = function plot(gd, calcdata) { d3.event.stopPropagation(); return d; }) - .on('drag', makeDragRow(gd, tableControlView, cellsColumnBlock)) + .on('drag', makeDragRow(gd, tableControlView, -1)) .on('dragend', function(d) { // fixme emit plotly notification }) @@ -287,35 +287,18 @@ function renderScrollbarKit(tableControlView) { .call(d3.behavior.drag() .origin(function(d) { console.log('drag started') + d3.event.stopPropagation(); + d.scrollbarState.scrollbarScrollInProgress = true; return d; var movedColumn = d3.select(this); easeColumn(movedColumn, d, -c.uplift); raiseToTop(this); return d; }) - .on('drag', function(d) { - console.log('drag') - return - var movedColumn = d3.select(this); - var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;} - d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); - var newOrder = yColumn.data().sort(function(a, b) {return getter(a) - getter(b);}); - newOrder.forEach(function(dd, i) { - dd.xIndex = i; - dd.x = d === dd ? dd.x : dd.xScale(dd); - }) - - yColumn.filter(function(dd) {return d !== dd;}) - .transition() - .ease(c.transitionEase) - .duration(c.transitionDuration) - .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - movedColumn - .call(cancelEeaseColumn) - .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); - }) + .on('drag', makeDragRow(gd, tableControlView, 7)) .on('dragend', function(d) { console.log('drag ended') + d.scrollbarState.scrollbarScrollInProgress = false; return var movedColumn = d3.select(this); var p = d.calcdata; @@ -568,7 +551,7 @@ function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { var blocks = d.rowBlocks; var calcdata = d.calcdata; - calcdata.scrollY -= dy; + calcdata.scrollY += dy; var bottom = firstRowAnchor(blocks, blocks.length); var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); @@ -615,9 +598,10 @@ function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { } } -function makeDragRow(gd, tableControlView, cellsColumnBlock) { +function makeDragRow(gd, tableControlView, multiplier) { return function dragRow () { - updateBlockYPosition(gd, cellsColumnBlock, d3.event.dy, tableControlView); + var cellsColumnBlock = tableControlView.selectAll('.columnBlock').filter(cellsBlock); + updateBlockYPosition(gd, cellsColumnBlock, multiplier * d3.event.dy, tableControlView); } } From b0ecdb47780dab5e927d3a1d346da7fb7a3cff74 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 23:38:50 +0200 Subject: [PATCH 214/281] proper scrollbar drag with mock multiplier --- src/traces/table/plot.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 839174ed2c4..c977c41cbf4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -227,11 +227,11 @@ function renderScrollbarKit(tableControlView) { s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; - s.yPosition = headerHeight(d) + s.topY; + s.dragMultiplier = 5.5; }) .attr('transform', function(d) { var xPosition = d.width + c.scrollbarWidth / 2 + c.scrollbarOffset; - return 'translate(' + xPosition + ' ' + d.scrollbarState.yPosition + ')'; + return 'translate(' + xPosition + ' ' + headerHeight(d) + ')'; }); var scrollbar = scrollbarKit.selectAll('.scrollbar') @@ -248,6 +248,11 @@ function renderScrollbarKit(tableControlView) { .append('g') .classed('scrollbarSlider', true); + scrollbarSlider + .attr('transform', function(d) { + return 'translate(0 ' + d.scrollbarState.topY + ')'; + }); + var scrollbarGlyph = scrollbarSlider.selectAll('.scrollbarGlyph') .data(gup.repeat, gup.keyFun); @@ -273,7 +278,7 @@ function renderScrollbarKit(tableControlView) { .transition().delay(c.scrollbarHideDelay).duration(c.scrollbarHideDuration) .attr('stroke-opacity', 0); - var scrollbarCaptureZone = scrollbarSlider.selectAll('.scrollbarCaptureZone') + var scrollbarCaptureZone = scrollbar.selectAll('.scrollbarCaptureZone') .data(gup.repeat, gup.keyFun); scrollbarCaptureZone.enter() @@ -283,7 +288,7 @@ function renderScrollbarKit(tableControlView) { .attr('stroke-width', c.scrollbarCaptureWidth) .attr('stroke-linecap', 'square') .attr('stroke-opacity', c.clipView ? 0.5 : 0) - .attr('y1', c.scrollbarCaptureWidth / 2) + .attr('y1', 0) .call(d3.behavior.drag() .origin(function(d) { console.log('drag started') @@ -295,7 +300,7 @@ function renderScrollbarKit(tableControlView) { raiseToTop(this); return d; }) - .on('drag', makeDragRow(gd, tableControlView, 7)) + .on('drag', makeDragRow(gd, tableControlView)) .on('dragend', function(d) { console.log('drag ended') d.scrollbarState.scrollbarScrollInProgress = false; @@ -310,7 +315,7 @@ function renderScrollbarKit(tableControlView) { scrollbarCaptureZone .attr('y2', function(d) { - return d.scrollbarState.barLength - c.scrollbarCaptureWidth / 2; + return d.scrollbarState.scrollableAreaHeight; }); } @@ -598,8 +603,9 @@ function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { } } -function makeDragRow(gd, tableControlView, multiplier) { +function makeDragRow(gd, tableControlView, optionalMultiplier) { return function dragRow () { + var multiplier = optionalMultiplier || tableControlView.node().__data__.scrollbarState.dragMultiplier var cellsColumnBlock = tableControlView.selectAll('.columnBlock').filter(cellsBlock); updateBlockYPosition(gd, cellsColumnBlock, multiplier * d3.event.dy, tableControlView); } From 88ce78a94c42e10b68c6118165425035c8604d8b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 26 Sep 2017 23:50:17 +0200 Subject: [PATCH 215/281] plugging in real pixel to virtual document ratio --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 4f4f275576b..1fbfbbdb65f 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -28,5 +28,5 @@ module.exports = { scrollbarOffset: 5, scrollbarHideDelay: 1000, scrollbarHideDuration: 1000, - clipView: true + clipView: false }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c977c41cbf4..98c70a9ce8e 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -227,7 +227,7 @@ function renderScrollbarKit(tableControlView) { s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; - s.dragMultiplier = 5.5; + s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; }) .attr('transform', function(d) { var xPosition = d.width + c.scrollbarWidth / 2 + c.scrollbarOffset; From cea920055dff741b07f679c2e4516a7cb8e964a5 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 27 Sep 2017 00:25:42 +0200 Subject: [PATCH 216/281] hover induces the scrollbar --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 98c70a9ce8e..e380a41e9af 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -53,6 +53,7 @@ module.exports = function plot(gd, calcdata) { .append('g') .classed('tableControlView', true) .style('box-sizing', 'content-box') + .on('mousemove', function() {tableControlView.call(renderScrollbarKit);}) .call(renderScrollbarKit); tableControlView From 46ae7926341f7abafddce140639d110be51cd25b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 27 Sep 2017 00:27:09 +0200 Subject: [PATCH 217/281] cut copypasta --- src/traces/table/plot.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e380a41e9af..42016008aa5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -292,25 +292,13 @@ function renderScrollbarKit(tableControlView) { .attr('y1', 0) .call(d3.behavior.drag() .origin(function(d) { - console.log('drag started') d3.event.stopPropagation(); d.scrollbarState.scrollbarScrollInProgress = true; return d; - var movedColumn = d3.select(this); - easeColumn(movedColumn, d, -c.uplift); - raiseToTop(this); - return d; }) .on('drag', makeDragRow(gd, tableControlView)) .on('dragend', function(d) { - console.log('drag ended') - d.scrollbarState.scrollbarScrollInProgress = false; - return - var movedColumn = d3.select(this); - var p = d.calcdata; - d.x = d.xScale(d); - easeColumn(movedColumn, d, 0); - columnMoved(gd, calcdata, p.key, p.columns.map(function(dd) {return dd.xIndex;})); + // fixme emit Plotly event }) ); From 1ef0050aaa6cae2fe5ad0df686edcab4141fefd3 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Wed, 27 Sep 2017 16:09:19 +0200 Subject: [PATCH 218/281] tmp --- src/traces/table/plot.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 42016008aa5..632fdbae14c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -228,6 +228,7 @@ function renderScrollbarKit(tableControlView) { s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; + s.bottomY = s.topY + s.barLength; s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; }) .attr('transform', function(d) { @@ -287,17 +288,32 @@ function renderScrollbarKit(tableControlView) { .classed('scrollbarCaptureZone', true) .attr('stroke', 'red') .attr('stroke-width', c.scrollbarCaptureWidth) - .attr('stroke-linecap', 'square') + .attr('stroke-linecap', 'butt') .attr('stroke-opacity', c.clipView ? 0.5 : 0) .attr('y1', 0) + .on('mousedown', function(d) { + var y = d3.event.y; + var bbox = this.getBoundingClientRect(); + var s = d.scrollbarState; + var pixelVal = y - bbox.top; + if(s.topY <= pixelVal && pixelVal <= s.bottomY) { + console.log('on glyph!') + } else { + console.log('should jump!') + makeDragRow(gd, tableControlView) // now makeDragRow depends on d3.event.y and multiplier; move these out + } + //console.log('mousedown', bbox.top, bbox.bottom, y, scale(y)) + }) .call(d3.behavior.drag() .origin(function(d) { + //console.log('drag started') d3.event.stopPropagation(); d.scrollbarState.scrollbarScrollInProgress = true; return d; }) .on('drag', makeDragRow(gd, tableControlView)) .on('dragend', function(d) { + //console.log('drag ended') // fixme emit Plotly event }) ); From 82461090179b1c7c6308aa09ca6547688616468f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 01:45:47 +0200 Subject: [PATCH 219/281] perfect scroll jump behavior --- src/traces/table/plot.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 632fdbae14c..7c902ec0107 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -296,11 +296,11 @@ function renderScrollbarKit(tableControlView) { var bbox = this.getBoundingClientRect(); var s = d.scrollbarState; var pixelVal = y - bbox.top; + var inverseScale = d3.scale.linear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true); if(s.topY <= pixelVal && pixelVal <= s.bottomY) { - console.log('on glyph!') + //console.log('on glyph!') } else { - console.log('should jump!') - makeDragRow(gd, tableControlView) // now makeDragRow depends on d3.event.y and multiplier; move these out + makeDragRow(gd, tableControlView, null, inverseScale(pixelVal - s.barLength / 2))(d); } //console.log('mousedown', bbox.top, bbox.bottom, y, scale(y)) }) @@ -461,7 +461,7 @@ function columnMoved(gd, calcdata, i, indices) { function gridPick(spec, col, row) { if(Array.isArray(spec)) { - const column = spec[Math.min(col, spec.length - 1)]; + var column = spec[Math.min(col, spec.length - 1)]; if(Array.isArray(column)) { return column[Math.min(row, column.length - 1)]; } else { @@ -555,13 +555,12 @@ function headerHeight(d) { return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); } -function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { +function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; - calcdata.scrollY += dy; var bottom = firstRowAnchor(blocks, blocks.length); var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); @@ -608,11 +607,13 @@ function updateBlockYPosition(gd, cellsColumnBlock, dy, tableControlView) { } } -function makeDragRow(gd, tableControlView, optionalMultiplier) { +function makeDragRow(gd, tableControlView, optionalMultiplier, optionalPosition) { return function dragRow () { - var multiplier = optionalMultiplier || tableControlView.node().__data__.scrollbarState.dragMultiplier + var d = tableControlView.node().__data__; + var multiplier = optionalMultiplier || d.scrollbarState.dragMultiplier; + d.scrollY = optionalPosition === void(0) ? d.scrollY + multiplier * d3.event.dy : optionalPosition; var cellsColumnBlock = tableControlView.selectAll('.columnBlock').filter(cellsBlock); - updateBlockYPosition(gd, cellsColumnBlock, multiplier * d3.event.dy, tableControlView); + updateBlockYPosition(gd, cellsColumnBlock, tableControlView); } } From 2533b85864cb0dd0c1d7ed6ea6321e269e8775f4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 02:11:14 +0200 Subject: [PATCH 220/281] mousewheel --- src/traces/table/plot.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7c902ec0107..e6cf97d7d65 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -54,6 +54,10 @@ module.exports = function plot(gd, calcdata) { .classed('tableControlView', true) .style('box-sizing', 'content-box') .on('mousemove', function() {tableControlView.call(renderScrollbarKit);}) + .on('mousewheel', function(d) { + d3.event.preventDefault(); + makeDragRow(gd, tableControlView, null, d.scrollY + d3.event.deltaY)(d); + }) .call(renderScrollbarKit); tableControlView @@ -77,6 +81,8 @@ module.exports = function plot(gd, calcdata) { var movedColumn = d3.select(this); easeColumn(movedColumn, d, -c.uplift); raiseToTop(this); + d.calcdata.columnDragInProgress = true; + renderScrollbarKit(tableControlView); return d; }) .on('drag', function(d) { @@ -102,6 +108,7 @@ module.exports = function plot(gd, calcdata) { var movedColumn = d3.select(this); var p = d.calcdata; d.x = d.xScale(d); + d.calcdata.columnDragInProgress = false; easeColumn(movedColumn, d, 0); columnMoved(gd, calcdata, p.key, p.columns.map(function(dd) {return dd.xIndex;})); }) @@ -270,7 +277,7 @@ function renderScrollbarKit(tableControlView) { .attr('y2', function(d) { return d.scrollbarState.barLength - c.scrollbarWidth / 2; }) - .attr('stroke-opacity', 0.4); + .attr('stroke-opacity', function(d) {return d.columnDragInProgress ? 0 : 0.4}); // cancel transition: possible pending (also, delayed) transition scrollbarGlyph From e19b6e7e65ff2a185a55bb4856b5ea5ad14df7a7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 15:26:44 +0200 Subject: [PATCH 221/281] test case --- test/image/mocks/table_one_cell.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 2816152a23c..d0b193fd5b7 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 200 + 250 + 380 - 150, + "height": 250 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 2)}).slice(0, 3), + ].map(function(r) {return r.slice(0, 2)}).slice(0, 2), "align": ["right"], "valign": "middle", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a) {return a.slice(0, 20)}).slice(0, 3), + ].map(function(a, i) {return a.map(function(d, j) {return i ? 'Col2 ' + (i * a.length + j) : i * a.length + j})}).slice(0, 2), "format": [ null From 9603cb154519d0b8c38ab75651fbc8bfe3bd7052 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 19:34:01 +0200 Subject: [PATCH 222/281] fixing revolver regression (flat selection, had 1x4 elements instead of 2x2) --- src/traces/table/plot.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e6cf97d7d65..378e1ea493a 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -608,8 +608,8 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { // conditionally rerendering panel 0 and 1 if(gd) { - conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 0); - conditionalPanelRerender(gd, cellsColumnBlock, pages, d.prevPages, d, 1); + conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 0); + conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 1); renderScrollbarKit(tableControlView); } } @@ -619,22 +619,22 @@ function makeDragRow(gd, tableControlView, optionalMultiplier, optionalPosition) var d = tableControlView.node().__data__; var multiplier = optionalMultiplier || d.scrollbarState.dragMultiplier; d.scrollY = optionalPosition === void(0) ? d.scrollY + multiplier * d3.event.dy : optionalPosition; - var cellsColumnBlock = tableControlView.selectAll('.columnBlock').filter(cellsBlock); + var cellsColumnBlock = tableControlView.selectAll('.yColumn').selectAll('.columnBlock').filter(cellsBlock); updateBlockYPosition(gd, cellsColumnBlock, tableControlView); } } -function conditionalPanelRerender(gd, cellsColumnBlock, pages, prevPages, d, revolverIndex) { +function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, prevPages, d, revolverIndex) { var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; if(shouldComponentUpdate) { - window.clearTimeout(d.currentRepaint[revolverIndex]); - d.currentRepaint[revolverIndex] = window.setTimeout(function () { + //window.clearTimeout(d.currentRepaint[revolverIndex]); + //d.currentRepaint[revolverIndex] = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); - renderColumnBlocks(gd, toRerender, toRerender); + renderColumnBlocks(gd, tableControlView, toRerender, toRerender); prevPages[revolverIndex] = pages[revolverIndex]; - }); + //}); } } From 32b5aa6db97a52df91b1e59477ee733144669ee7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 21:52:04 +0200 Subject: [PATCH 223/281] mock update --- test/image/mocks/table_one_cell.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index d0b193fd5b7..d46df748430 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 2)}).slice(0, 2), + ].map(function(r) {return r.slice(0, 2)}).slice(0, 3), "align": ["right"], "valign": "middle", @@ -107,7 +107,7 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a, i) {return a.map(function(d, j) {return i ? 'Col2 ' + (i * a.length + j) : i * a.length + j})}).slice(0, 2), + ].map(function(a, i) {return a.map(function(d, j) {return i ? d : i * a.length + j})}).slice(0, 3), "format": [ null From 92e35eb05fcb16ff891d31631ed788d8ae9e7d47 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Thu, 28 Sep 2017 22:05:01 +0200 Subject: [PATCH 224/281] minor fix - avoid scrollbar butt crop; minimum bar length for Fitts law --- src/traces/table/constants.js | 1 + src/traces/table/plot.js | 4 ++-- test/image/mocks/table_one_cell.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 1fbfbbdb65f..e8631543c97 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -17,6 +17,7 @@ module.exports = { wrapSpacer: ' ', lineBreaker: '
', uplift: 5, + goldenRatio: 1.618, columnTitleOffset: 28, columnExtentOffset: 10, transitionEase: 'cubic-out', diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 378e1ea493a..c6d7f678430 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -231,10 +231,10 @@ function renderScrollbarKit(tableControlView) { s.scrollableAreaHeight = d.groupHeight - headerHeight(d); s.currentlyVisibleHeight = Math.min(s.totalHeight, s.scrollableAreaHeight); s.ratio = s.currentlyVisibleHeight / s.totalHeight; - s.barLength = s.ratio * s.currentlyVisibleHeight; + s.barLength = Math.max(s.ratio * s.currentlyVisibleHeight, c.goldenRatio * c.scrollbarWidth); s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; - s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; + s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom ; s.bottomY = s.topY + s.barLength; s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; }) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index d46df748430..2f16ceccd7f 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -3,7 +3,7 @@ "width": 600, "height": 250 + 380 - 150, "title": "Widget parameters and cost", - "margin": {"t": 0 || 280, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0|| 280, "r": 60, "b": 54, "l": 60} }, "data": [{ From eb8c110a87f8ede3c0126ee36e0ca3446c9eb745 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 12:28:23 +0200 Subject: [PATCH 225/281] performance baseline --- src/traces/table/plot.js | 40 +++++++++++++++++----------- test/image/mocks/table_one_cell.json | 39 +++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c6d7f678430..fd1450d6e19 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -388,7 +388,7 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber); }) .attr('fill', function(d) { - return gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber); + return d.calcdata.cells.fill ? gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber) : 'none'; }); var cellTextHolder = columnCell.selectAll('.cellTextHolder') @@ -444,10 +444,10 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, // finalize what's in the DOM Drawing.font(selection, d.font); - setCellHeightAndPositionY(columnCell); + setCellHeightAndPositionY(columnCell); // fixme this is first perf bottleneck var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; - svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); // fixme (not) this is third perf bottleneck }); } @@ -562,8 +562,22 @@ function headerHeight(d) { return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); } -function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { +function heavy(blocks, scrollY, scrollHeight) { + // fixme this is the first perf bottleneck + var pages = []; + for(var p = 0; p < blocks.length; p++) { + var pTop = firstRowAnchor(blocks, p); + var pBottom = pTop + rowsHeight(blocks[p], Infinity); + if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { + pages.push(p); + } + } + + return pages; +} +function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { + // fixme this function is THE performance hotspot var d = cellsColumnBlock[0][0].__data__; var blocks = d.rowBlocks; var calcdata = d.calcdata; @@ -572,14 +586,7 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - var pages = []; - for(var p = 0; p < blocks.length; p++) { - var pTop = firstRowAnchor(blocks, p); - var pBottom = pTop + rowsHeight(blocks[p], Infinity); - if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { - pages.push(p); - } - } + var pages = heavy(blocks, scrollY, scrollHeight); if(pages.length === 1) { if(pages[0] === blocks.length - 1) { pages.unshift(pages[0] - 1); @@ -627,14 +634,14 @@ function makeDragRow(gd, tableControlView, optionalMultiplier, optionalPosition) function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, prevPages, d, revolverIndex) { var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; if(shouldComponentUpdate) { - //window.clearTimeout(d.currentRepaint[revolverIndex]); - //d.currentRepaint[revolverIndex] = window.setTimeout(function () { + window.clearTimeout(d.currentRepaint[revolverIndex]); + d.currentRepaint[revolverIndex] = window.setTimeout(function () { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); renderColumnBlocks(gd, tableControlView, toRerender, toRerender); prevPages[revolverIndex] = pages[revolverIndex]; - //}); + }); } } @@ -682,6 +689,7 @@ function wrapTextMaker(columnBlock, element, tableControlView) { function updateYPositionMaker(columnBlock, element, tableControlView, d) { return function updateYPosition() { + if(d.settledY) return; var cellTextHolder = d3.select(element.parentNode); var l = getBlock(d); var rowIndex = d.key - l.firstRowIndex; @@ -719,6 +727,8 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; }); + + d.settledY = true; }; } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 2f16ceccd7f..db4d5cf1723 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 600, - "height": 250 + 380 - 150, + "height": 550 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0|| 280, "r": 60, "b": 54, "l": 60} }, @@ -26,7 +26,7 @@ ["Index" , "#"], ["Column 2" , "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 2)}).slice(0, 3), + ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), "align": ["right"], "valign": "middle", @@ -107,7 +107,36 @@ "x8AX
B
Plotly
CD", ].map(function(d, i) {return d}) - ].map(function(a, i) {return a.map(function(d, j) {return i ? d : i * a.length + j})}).slice(0, 3), + ].map(function(a, i) {return a + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + + .map(function(d, i) {return i} ) + + }).slice(0, 1), "format": [ null @@ -116,7 +145,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 20, + "height": 40, "align": ["right"], "valign": ["bottom"], @@ -128,7 +157,7 @@ "width": 1 }, - "fill": { + "fille": { "color": [ ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] ] From 00815ba25eca7b503f3a64491a083b7fda8dbe83 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 12:54:46 +0200 Subject: [PATCH 226/281] manual inlining 1 --- src/traces/table/plot.js | 9 ++++++++- test/image/mocks/table_one_cell.json | 29 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index fd1450d6e19..f8c1430f910 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -564,10 +564,16 @@ function headerHeight(d) { function heavy(blocks, scrollY, scrollHeight) { // fixme this is the first perf bottleneck + var pages = []; for(var p = 0; p < blocks.length; p++) { var pTop = firstRowAnchor(blocks, p); - var pBottom = pTop + rowsHeight(blocks[p], Infinity); + var rowBlock = blocks[p]; + var rowsHeight = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + rowsHeight += rowBlock.rows[i].rowHeight; + } + var pBottom = pTop + rowsHeight; if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { pages.push(p); } @@ -733,6 +739,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function setCellHeightAndPositionY(columnCell) { + // fixme second perf bottleneck columnCell .attr('transform', function(d) { var l = getBlock(d); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index db4d5cf1723..e6d491b61b3 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -108,6 +108,13 @@ ].map(function(d, i) {return d}) ].map(function(a, i) {return a + + //25k + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) @@ -125,6 +132,14 @@ .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + + //25k + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) @@ -133,8 +148,20 @@ .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) + + - .map(function(d, i) {return i} ) + .map(function(d, i) {return i} ) }).slice(0, 1), From b37a8a2756e26e37fac4b4e16517fa1677c347d4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 13:07:04 +0200 Subject: [PATCH 227/281] manual inlining 2 --- src/traces/table/plot.js | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f8c1430f910..d01d3053230 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -567,16 +567,29 @@ function heavy(blocks, scrollY, scrollHeight) { var pages = []; for(var p = 0; p < blocks.length; p++) { - var pTop = firstRowAnchor(blocks, p); - var rowBlock = blocks[p]; - var rowsHeight = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { + var pTop = 0; + for(var j = 0; j <= p - 1; j++) { + + var rowsHeight = 0; + var rowBlock = blocks[j]; + for(var i = 0; i < rowBlock.rows.length; i++) { + rowsHeight += rowBlock.rows[i].rowHeight; + } + + pTop += rowsHeight; + } + rowBlock = blocks[p]; + rowsHeight = 0; + for(i = 0; i < rowBlock.rows.length; i++) { rowsHeight += rowBlock.rows[i].rowHeight; } var pBottom = pTop + rowsHeight; - if(overlap([scrollY, scrollY + scrollHeight], [pTop, pBottom])) { + var windowTop = scrollY; + var windowBottom = windowTop + scrollHeight; + if(windowTop < pBottom && windowBottom > pTop) { pages.push(p); } + //if(pages.length > 1) break; // fixme uncomment this nice final optimization } return pages; @@ -753,12 +766,12 @@ function setCellHeightAndPositionY(columnCell) { .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); } -function firstRowAnchor(rowBlocks, page) { - var total = 0; - for(var i = 0; i <= page - 1; i++) { - total += rowsHeight(rowBlocks[i], Infinity); +function firstRowAnchor(blocks, p) { + var pTop = 0; + for(var i = 0; i <= p - 1; i++) { + pTop += rowsHeight(blocks[i], Infinity); } - return total; + return pTop; } function firstRowAnchor2(rowBlocks, page) { From be8fc72325427e71f51e70f20a341db7ea842231 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 15:19:54 +0200 Subject: [PATCH 228/281] manual inlining 3 --- src/traces/table/plot.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index d01d3053230..c80b4eb959c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -566,28 +566,30 @@ function heavy(blocks, scrollY, scrollHeight) { // fixme this is the first perf bottleneck var pages = []; - for(var p = 0; p < blocks.length; p++) { + for(var blockIndex = 0; blockIndex < blocks.length; blockIndex++) { + var pTop = 0; - for(var j = 0; j <= p - 1; j++) { + for(var j = 0; j < blockIndex; j++) { var rowsHeight = 0; var rowBlock = blocks[j]; for(var i = 0; i < rowBlock.rows.length; i++) { rowsHeight += rowBlock.rows[i].rowHeight; } - pTop += rowsHeight; } - rowBlock = blocks[p]; + + rowBlock = blocks[blockIndex]; rowsHeight = 0; for(i = 0; i < rowBlock.rows.length; i++) { rowsHeight += rowBlock.rows[i].rowHeight; } + var pBottom = pTop + rowsHeight; var windowTop = scrollY; var windowBottom = windowTop + scrollHeight; if(windowTop < pBottom && windowBottom > pTop) { - pages.push(p); + pages.push(blockIndex); } //if(pages.length > 1) break; // fixme uncomment this nice final optimization } From 282dd0a8c3feb6c51862631998345347b766b783 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 15:34:25 +0200 Subject: [PATCH 229/281] manual inlining 3 - optimized (linear rather than quadratic) --- src/traces/table/plot.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c80b4eb959c..5892a82351f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -566,23 +566,20 @@ function heavy(blocks, scrollY, scrollHeight) { // fixme this is the first perf bottleneck var pages = []; + var pTop = 0; for(var blockIndex = 0; blockIndex < blocks.length; blockIndex++) { - var pTop = 0; - for(var j = 0; j < blockIndex; j++) { - - var rowsHeight = 0; - var rowBlock = blocks[j]; - for(var i = 0; i < rowBlock.rows.length; i++) { - rowsHeight += rowBlock.rows[i].rowHeight; + if(blockIndex) { + var pastBlockRows = blocks[blockIndex - 1].rows; + for(var i = 0; i < pastBlockRows.length; i++) { + pTop += pastBlockRows[i].rowHeight; } - pTop += rowsHeight; } - rowBlock = blocks[blockIndex]; - rowsHeight = 0; - for(i = 0; i < rowBlock.rows.length; i++) { - rowsHeight += rowBlock.rows[i].rowHeight; + var blockRows = blocks[blockIndex].rows; + var rowsHeight = 0; + for(i = 0; i < blockRows.length; i++) { + rowsHeight += blockRows[i].rowHeight; } var pBottom = pTop + rowsHeight; @@ -591,7 +588,7 @@ function heavy(blocks, scrollY, scrollHeight) { if(windowTop < pBottom && windowBottom > pTop) { pages.push(blockIndex); } - //if(pages.length > 1) break; // fixme uncomment this nice final optimization + //if(pages.length > 1) break; // fixme uncomment this nice final optimization; put it in `for` condition } return pages; From 940a41da8fedbbc54c8cb4b16567225951aab75f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 15:54:09 +0200 Subject: [PATCH 230/281] halve the calculations in heavy --- src/traces/table/plot.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5892a82351f..2c676379e6c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -569,16 +569,9 @@ function heavy(blocks, scrollY, scrollHeight) { var pTop = 0; for(var blockIndex = 0; blockIndex < blocks.length; blockIndex++) { - if(blockIndex) { - var pastBlockRows = blocks[blockIndex - 1].rows; - for(var i = 0; i < pastBlockRows.length; i++) { - pTop += pastBlockRows[i].rowHeight; - } - } - var blockRows = blocks[blockIndex].rows; var rowsHeight = 0; - for(i = 0; i < blockRows.length; i++) { + for(var i = 0; i < blockRows.length; i++) { rowsHeight += blockRows[i].rowHeight; } @@ -588,6 +581,7 @@ function heavy(blocks, scrollY, scrollHeight) { if(windowTop < pBottom && windowBottom > pTop) { pages.push(blockIndex); } + pTop += rowsHeight; //if(pages.length > 1) break; // fixme uncomment this nice final optimization; put it in `for` condition } From c252e17ee9c8d9f3843520dc63617bfe19cefdbc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 16:19:24 +0200 Subject: [PATCH 231/281] reshuffling --- src/traces/table/plot.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 2c676379e6c..44df23a0405 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -745,13 +745,12 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function setCellHeightAndPositionY(columnCell) { - // fixme second perf bottleneck columnCell .attr('transform', function(d) { + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); var rowOffset = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var yOffset = rowOffset + headerHeight; return 'translate(0 ' + yOffset + ')'; }) @@ -761,7 +760,7 @@ function setCellHeightAndPositionY(columnCell) { function firstRowAnchor(blocks, p) { var pTop = 0; - for(var i = 0; i <= p - 1; i++) { + for(var i = 0; i < p; i++) { pTop += rowsHeight(blocks[i], Infinity); } return pTop; From d50216e06562c99057311b6361072901a2d1ce7f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 16:23:40 +0200 Subject: [PATCH 232/281] getting rid of expensive rowOffset --- src/traces/table/plot.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 44df23a0405..32ce70ef0f5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -750,26 +750,25 @@ function setCellHeightAndPositionY(columnCell) { var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); - var rowOffset = firstRowAnchor(d.rowBlocks, l.key) + rowAnchor - firstRowAnchor(d.rowBlocks, d.page); - var yOffset = rowOffset + headerHeight; + var yOffset = rowAnchor + headerHeight; return 'translate(0 ' + yOffset + ')'; }) .select('.cellRect') .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); } -function firstRowAnchor(blocks, p) { - var pTop = 0; - for(var i = 0; i < p; i++) { - pTop += rowsHeight(blocks[i], Infinity); +function firstRowAnchor(blocks, page) { + var total = 0; + for(var i = 0; i < page; i++) { + total += rowsHeight(blocks[i], Infinity); } - return pTop; + return total; } -function firstRowAnchor2(rowBlocks, page) { +function firstRowAnchor2(blocks, page) { var total = 0; for(var i = 0; i < page - 1; i++) { - total += rowsHeight(rowBlocks[i], Infinity); + total += rowsHeight(blocks[i], Infinity); } return total; } From 213e9c3e3dffd456be458e0749d64720a43008a0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 16:24:28 +0200 Subject: [PATCH 233/281] deleted redundant function --- src/traces/table/plot.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 32ce70ef0f5..ac651c176ae 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -214,7 +214,7 @@ function renderScrollbarKit(tableControlView) { function calcTotalHeight(d) { var blocks = d.rowBlocks; - return firstRowAnchor2(blocks, blocks.length) + rowsHeight(blocks[blocks.length - 1], Infinity); + return firstRowAnchor(blocks, blocks.length - 1) + rowsHeight(blocks[blocks.length - 1], Infinity); } var scrollbarKit = tableControlView.selectAll('.scrollbarKit') @@ -765,14 +765,6 @@ function firstRowAnchor(blocks, page) { return total; } -function firstRowAnchor2(blocks, page) { - var total = 0; - for(var i = 0; i < page - 1; i++) { - total += rowsHeight(blocks[i], Infinity); - } - return total; -} - function rowsHeight(rowBlock, key) { var total = 0; for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { From 5800a3422b294975e9dc844ff649f44848e4b0bb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 16:29:22 +0200 Subject: [PATCH 234/281] mock with 1m rows --- test/image/mocks/table_one_cell.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index e6d491b61b3..2742bf412b6 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -49,7 +49,7 @@ "cells": { - "values": [ + "values": [Array.from(Array(1000000).keys())] || [ [ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", From 3045336651eb19e5c8569989c6bebf48097c60f8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 17:08:25 +0200 Subject: [PATCH 235/281] reversing loop --- src/traces/table/plot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ac651c176ae..f877eebbade 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -759,7 +759,7 @@ function setCellHeightAndPositionY(columnCell) { function firstRowAnchor(blocks, page) { var total = 0; - for(var i = 0; i < page; i++) { + for(var i = page - 1; i >=0 ; i--) { total += rowsHeight(blocks[i], Infinity); } return total; From fbba640c68ecc50903452de0a921c90ab7b9153c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 21:23:29 +0200 Subject: [PATCH 236/281] caching allRowsHeight --- src/traces/table/plot.js | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f877eebbade..16ecf76f597 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -553,28 +553,30 @@ function rowFromTo(d) { return [rowFrom, rowTo]; } -function overlap(a, b) { - return a[0] < b[1] && a[1] > b[0]; -} - function headerHeight(d) { var headerBlocks = d.rowBlocks[0].auxiliaryBlocks; return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); } -function heavy(blocks, scrollY, scrollHeight) { - // fixme this is the first perf bottleneck +function paginate(blocks, scrollY, scrollHeight) { var pages = []; var pTop = 0; + for(var blockIndex = 0; blockIndex < blocks.length; blockIndex++) { - var blockRows = blocks[blockIndex].rows; + var block = blocks[blockIndex]; + //block.allRowsHeight = undefined; + var blockRows = block.rows; var rowsHeight = 0; for(var i = 0; i < blockRows.length; i++) { rowsHeight += blockRows[i].rowHeight; } + // caching allRowsHeight on the block - it's safe as this function is always called from within the code part + // that handles increases to row heights + block.allRowsHeight = rowsHeight; + var pBottom = pTop + rowsHeight; var windowTop = scrollY; var windowBottom = windowTop + scrollHeight; @@ -582,7 +584,10 @@ function heavy(blocks, scrollY, scrollHeight) { pages.push(blockIndex); } pTop += rowsHeight; - //if(pages.length > 1) break; // fixme uncomment this nice final optimization; put it in `for` condition + + // fixme uncomment this nice final optimization; put it in `for` condition - caveat, currently the + // block.allRowsHeight relies on being invalidated, so enabling this opt may not be safe + //if(pages.length > 1) break; } return pages; @@ -598,7 +603,7 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - var pages = heavy(blocks, scrollY, scrollHeight); + var pages = paginate(blocks, scrollY, scrollHeight); if(pages.length === 1) { if(pages[0] === blocks.length - 1) { pages.unshift(pages[0] - 1); @@ -760,7 +765,7 @@ function setCellHeightAndPositionY(columnCell) { function firstRowAnchor(blocks, page) { var total = 0; for(var i = page - 1; i >=0 ; i--) { - total += rowsHeight(blocks[i], Infinity); + total += allRowsHeight(blocks[i]); } return total; } @@ -773,6 +778,19 @@ function rowsHeight(rowBlock, key) { return total; } +function allRowsHeight(rowBlock) { + var cached = rowBlock.allRowsHeight; + if(cached !== void(0)) { + return cached; + } + var total = 0; + for(var i = 0; i < rowBlock.rows.length; i++) { + total += rowBlock.rows[i].rowHeight; + } + rowBlock.allRowsHeight = total; + return total; +} + function getBlock(d) {return d.rowBlocks[d.page];} function getRow(l, i) {return l.rows[i - l.firstRowIndex];} From 01bfa79511f60609309bb6389b52a851ad9b1b14 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 21:57:50 +0200 Subject: [PATCH 237/281] bypass wrappingNeeded if text contains no separating characters (space) --- src/traces/table/plot.js | 11 ++++++++++- test/image/mocks/table_one_cell.json | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 16ecf76f597..728f27b01f1 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -422,7 +422,7 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; - d.wrappingNeeded = !userBrokenText && !d.wrapped && !latex; + d.wrappingNeeded = !userBrokenText && !d.wrapped && !latex && prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1; var textToRender; if(d.wrappingNeeded) { var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], - ["Column 3" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"] - ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), + ["C0" , "#"], + ["C1" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C2" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C3" , "#" || "#"], + ["C4" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C5" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C6" , "#" || "#"], + ["C7" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C8" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C9" , "#" || "#"] + ].map(function(r) {return r.slice(0, 2)}).slice(0, 10), "align": ["right"], "valign": "middle", @@ -49,7 +56,7 @@ "cells": { - "values": [Array.from(Array(1000000).keys())] || [ + "values": [Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys())] || [ [ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", From 2dbcc7fa473188fff386fd72ba2c2b63ce180045 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 21:59:28 +0200 Subject: [PATCH 238/281] baseline for avoiding getBoundingClientRect --- src/traces/table/plot.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 728f27b01f1..c867bc7e0c3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -444,10 +444,10 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, // finalize what's in the DOM Drawing.font(selection, d.font); - setCellHeightAndPositionY(columnCell); // fixme this is first perf bottleneck + setCellHeightAndPositionY(columnCell); var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; - svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); // fixme (not) this is third perf bottleneck + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); }); } @@ -710,6 +710,8 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var cellTextHolder = d3.select(element.parentNode); var l = getBlock(d); var rowIndex = d.key - l.firstRowIndex; + + // fixme perf bottleneck var box = element.parentNode.getBoundingClientRect(); var renderedHeight = box.height; From 473b3df361ac3bdebeed84e60152fac03afed07c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Fri, 29 Sep 2017 23:59:18 +0200 Subject: [PATCH 239/281] avoid wrapping if not needed --- src/traces/table/plot.js | 20 +++++++++++--------- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index c867bc7e0c3..32f5b6a5b44 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -417,12 +417,17 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, var userSuppliedContent = d.value; var latex = latexEh(userSuppliedContent); var userBrokenText = (typeof userSuppliedContent !== 'string') || userSuppliedContent.match(/
/i); + var userBrokenText2 = (typeof userSuppliedContent === 'string') && userSuppliedContent.match(/
/i); var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; - d.wrappingNeeded = !userBrokenText && !d.wrapped && !latex && prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1; + var hasWrapSplitCharacter; + var hwsc = function(prefixSuffixedText) {return prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1;}; + d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hwsc(prefixSuffixedText)); + d.cellHeightMayIncrease = !d.wrapped && (userBrokenText2 || latex || (hasWrapSplitCharacter === void(0) ? hwsc(prefixSuffixedText) : hasWrapSplitCharacter)); + if(d.cellHeightMayIncrease) debugger var textToRender; if(d.wrappingNeeded) { var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/X
B
Plotly
CD", From 0230f031b680872aa539d1d0ceee7d6200895589 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 01:01:35 +0200 Subject: [PATCH 240/281] baseline --- src/traces/table/plot.js | 3 + test/image/mocks/table_one_cell.json | 91 +++++++++------------------- 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 32f5b6a5b44..78bd305d418 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -738,6 +738,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { renderScrollbarKit(tableControlView); } + // fixme speed bottleneck esp. the getBoundingClientRect 66% cellTextHolder .attr('transform', function () { var element = this; @@ -754,6 +755,8 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function setCellHeightAndPositionY(columnCell) { + // fixme speed bottleneck esp. the getBoundingClientRect 15% + // fixme also, initial load is freaking slow columnCell .attr('transform', function(d) { var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 3274042aadc..341bcd51c75 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,7 +1,7 @@ { "layout": { "width": 800, - "height": 550 + 380 - 150, + "height": 950 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0|| 280, "r": 60, "b": 54, "l": 60} }, @@ -16,24 +16,34 @@ }, "columnwidth": [30], - "columnorder": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + "columnorder": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "header": { "height": 30, // fixme for some reason it doesn't recognize arrays here "values": [ - ["C0" , "#"], - ["C1" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], - ["C2" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], - ["C3" , "#" || "#"], - ["C4" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], - ["C5" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], - ["C6" , "#" || "#"], - ["C7" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], - ["C8" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], - ["C9" , "#" || "#"] - ].map(function(r) {return r.slice(0, 2)}).slice(0, 10), + ["C00" , "#"], + ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 20), "align": ["right"], "valign": "middle", @@ -56,7 +66,11 @@ "cells": { - "values": [Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys())] || [ + "values": [ + Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), + Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), + ] + .slice(0, 20) || [ [ "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "1AX
B
Plotly
CD", @@ -118,55 +132,6 @@ //25k .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - - //25k - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - .concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a).concat(a) - - .map(function(d, i) {return i} ) From b7a2ed5d06d33e6344f5a34e951f4c510b034230 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 09:31:06 +0200 Subject: [PATCH 241/281] baseline 2 --- src/traces/table/plot.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 78bd305d418..1935ee73d0f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -744,7 +744,9 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var element = this; var columnCellElement = element.parentNode; var box = columnCellElement.getBoundingClientRect(); + window.monfera++ var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); + window.monfera++ var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; @@ -755,7 +757,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function setCellHeightAndPositionY(columnCell) { - // fixme speed bottleneck esp. the getBoundingClientRect 15% + // fixme speed bottleneck 15% // fixme also, initial load is freaking slow columnCell .attr('transform', function(d) { From 4df9fd46c15e708a0f800b116674aeb073c934c4 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 10:03:52 +0200 Subject: [PATCH 242/281] avoiding getBoundingClientRect; baseline for 'empty last row' issue --- src/traces/table/plot.js | 22 ++++++++++++---------- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 1935ee73d0f..8892107d6f2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -740,16 +740,18 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { // fixme speed bottleneck esp. the getBoundingClientRect 66% cellTextHolder - .attr('transform', function () { - var element = this; - var columnCellElement = element.parentNode; - var box = columnCellElement.getBoundingClientRect(); - window.monfera++ - var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); - window.monfera++ - var currentTransform = element.transform.baseVal.consolidate(); - var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - return 'translate(' + c.cellPad + ' ' + yPosition + ')'; + .attr('transform', function (d) { + if(d.cellHeightMayIncrease) { + var element = this; + var columnCellElement = element.parentNode; + var box = columnCellElement.getBoundingClientRect(); + var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); + var currentTransform = element.transform.baseVal.consolidate(); + var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); + return 'translate(' + c.cellPad + ' ' + yPosition + ')'; + } else { + return 'translate(' + c.cellPad + ' ' + -c.cellPad + ')'; + } }); d.settledY = true; diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 341bcd51c75..6037be68a29 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -1,9 +1,9 @@ { "layout": { "width": 800, - "height": 950 + 380 - 150, + "height": 750 + 380 - 150, "title": "Widget parameters and cost", - "margin": {"t": 0|| 280, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} }, "data": [{ From 10cf0582b2bf5dd02d204beca2efce463beaf5b0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 10:32:02 +0200 Subject: [PATCH 243/281] fixes: - updateBlockYPosition called on initial render - if there may not be increase, use 'hanging' - always render 2nd panel (handle single-page things later) --- src/traces/table/plot.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 8892107d6f2..f0c25a46728 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -208,6 +208,8 @@ module.exports = function plot(gd, calcdata) { columnBoundaryRect .attr('width', function(d) {return d.columnWidth;}) .attr('height', function(d) {return d.calcdata.height + c.uplift;}); + + updateBlockYPosition(gd, cellsColumnBlock, tableControlView); }; function renderScrollbarKit(tableControlView) { @@ -442,6 +444,9 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, } return textToRender; }) + .attr('alignment-baseline', function(d) { + return d.cellHeightMayIncrease ? null : 'hanging'; + }) .each(function(d) { var element = this; @@ -525,7 +530,7 @@ function splitToPanels(d) { var revolverPanel2 = extendFlat({}, d, { key: 'cells2', type: 'cells', - page: 0, + page: 1, prevPages: prevPages, currentRepaint: [null, null], dragHandle: false, @@ -563,7 +568,7 @@ function headerHeight(d) { return headerBlocks.reduce(function (p, n) {return p + rowsHeight(n, Infinity)}, 0); } -function paginate(blocks, scrollY, scrollHeight) { +function findPagesAndCacheHeights(blocks, scrollY, scrollHeight) { var pages = []; var pTop = 0; @@ -608,7 +613,7 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { var scrollHeight = d.calcdata.groupHeight - headerHeight(d); var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - var pages = paginate(blocks, scrollY, scrollHeight); + var pages = findPagesAndCacheHeights(blocks, scrollY, scrollHeight); if(pages.length === 1) { if(pages[0] === blocks.length - 1) { pages.unshift(pages[0] - 1); @@ -750,7 +755,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; } else { - return 'translate(' + c.cellPad + ' ' + -c.cellPad + ')'; + return 'translate(' + c.cellPad + ' ' + c.cellPad + ')'; } }); From d7fc0a4cfcec499904e43c4948a64fc0470b0109 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 11:07:25 +0200 Subject: [PATCH 244/281] don't show scrollbars and north/south arrow if table is not tall enough; fix the condition when table is exactly as high as the scroll space (div by 0) --- src/traces/table/plot.js | 12 ++++++++---- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f0c25a46728..ccb69df4a2d 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -130,7 +130,9 @@ module.exports = function plot(gd, calcdata) { .style('user-select', 'none'); columnBlock - .style('cursor', function(d) {return d.dragHandle ? 'ew-resize' : 'ns-resize';}); + .style('cursor', function(d) { + return d.dragHandle ? 'ew-resize' : d.calcdata.scrollbarState.barWiggleRoom ? 'ns-resize' : 'default'; + }); var cellsColumnBlock = columnBlock.filter(cellsBlock); @@ -235,8 +237,8 @@ function renderScrollbarKit(tableControlView) { s.ratio = s.currentlyVisibleHeight / s.totalHeight; s.barLength = Math.max(s.ratio * s.currentlyVisibleHeight, c.goldenRatio * c.scrollbarWidth); s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; - s.wiggleRoom = s.totalHeight - s.scrollableAreaHeight; - s.topY = (d.scrollY / s.wiggleRoom) * s.barWiggleRoom ; + s.wiggleRoom = Math.max(0, s.totalHeight - s.scrollableAreaHeight); + s.topY = s.barWiggleRoom === 0 ? 0 : (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; s.bottomY = s.topY + s.barLength; s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; }) @@ -279,7 +281,9 @@ function renderScrollbarKit(tableControlView) { .attr('y2', function(d) { return d.scrollbarState.barLength - c.scrollbarWidth / 2; }) - .attr('stroke-opacity', function(d) {return d.columnDragInProgress ? 0 : 0.4}); + .attr('stroke-opacity', function(d) { + return d.columnDragInProgress || !d.scrollbarState.barWiggleRoom ? 0 : 0.4 + }); // cancel transition: possible pending (also, delayed) transition scrollbarGlyph diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 6037be68a29..18eb4cfc97c 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -67,8 +67,8 @@ "cells": { "values": [ - Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), - Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), + Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()), + Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()), ] .slice(0, 20) || [ [ From 7a4a21e5e58f30b30e457983223173cdf56d4da8 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 11:08:19 +0200 Subject: [PATCH 245/281] restored 100 rows in mock --- src/traces/table/plot.js | 2 -- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ccb69df4a2d..68cf672f6c6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -747,7 +747,6 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { renderScrollbarKit(tableControlView); } - // fixme speed bottleneck esp. the getBoundingClientRect 66% cellTextHolder .attr('transform', function (d) { if(d.cellHeightMayIncrease) { @@ -769,7 +768,6 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { function setCellHeightAndPositionY(columnCell) { // fixme speed bottleneck 15% - // fixme also, initial load is freaking slow columnCell .attr('transform', function(d) { var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 18eb4cfc97c..6037be68a29 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -67,8 +67,8 @@ "cells": { "values": [ - Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()), - Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()),Array.from(Array(10).keys()), + Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), + Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), ] .slice(0, 20) || [ [ From 9328dff999634c8dc776ca6ccf3654d8bae00194 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 11:51:08 +0200 Subject: [PATCH 246/281] calling setCellHeightAndPositionY in bulk --- src/traces/table/plot.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 68cf672f6c6..eb1dbc97238 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -458,11 +458,11 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, // finalize what's in the DOM Drawing.font(selection, d.font); - setCellHeightAndPositionY(columnCell); var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); - }); + }) + columnCell.call(setCellHeightAndPositionY); } function latexEh(content) { @@ -768,6 +768,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { function setCellHeightAndPositionY(columnCell) { // fixme speed bottleneck 15% + window.monfera++ columnCell .attr('transform', function(d) { var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); @@ -776,7 +777,7 @@ function setCellHeightAndPositionY(columnCell) { var yOffset = rowAnchor + headerHeight; return 'translate(0 ' + yOffset + ')'; }) - .select('.cellRect') + .selectAll('.cellRect') .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); } From 4e5bcf6adb51d4b21b7a6b8e8382d8de97c6d1bb Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 12:08:32 +0200 Subject: [PATCH 247/281] eschewing convertToTspans if not need (though: formatting is now lost) --- src/traces/table/plot.js | 7 ++++++- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index eb1dbc97238..3cc2605b670 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -429,6 +429,7 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; d.latex = latex; + d.mayHaveMarkup = (typeof userSuppliedContent === 'string') && userSuppliedContent.match(/[<>]/); var hasWrapSplitCharacter; var hwsc = function(prefixSuffixedText) {return prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1;}; d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hwsc(prefixSuffixedText)); @@ -460,7 +461,11 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, Drawing.font(selection, d.font); var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; - svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); + if(d.mayHaveMarkup || d.wrappingNeeded || d.latex) { + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); + } else { + // renderCallback(allColumnBlock, element, tableControlView, d); + } }) columnCell.call(setCellHeightAndPositionY); } diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 6037be68a29..7fdc6cda045 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -67,8 +67,8 @@ "cells": { "values": [ - Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), - Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()),Array.from(Array(100).keys()), + Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()), + Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()), ] .slice(0, 20) || [ [ From 89e1984f015696be265b5337281d5c18274646f0 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 12:37:09 +0200 Subject: [PATCH 248/281] baseline for renderColumnBlocks perf hotspot --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 3cc2605b670..b859d84caa6 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -338,6 +338,7 @@ function renderScrollbarKit(tableControlView) { } function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { + // fixme this perf hotspot // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization From efc388da9d75025d7c19e822765bb77428a8fa01 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 12:40:51 +0200 Subject: [PATCH 249/281] broke up monolithic renderColumnBlock --- src/traces/table/plot.js | 58 +++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b859d84caa6..264be680d89 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -361,6 +361,38 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { columnCell.exit().remove(); + columnCell + .call(setFont); + + var cellRect = columnCell.selectAll('.cellRect') + .data(gup.repeat, gup.keyFun); + + cellRect.enter() + .append('rect') + .classed('cellRect', true); + + cellRect + .call(renderRect); + + var cellTextHolder = columnCell.selectAll('.cellTextHolder') + .data(gup.repeat, gup.keyFun); + + cellTextHolder.enter() + .append('g') + .classed('cellTextHolder', true); + + var cellText = cellTextHolder.selectAll('.cellText') + .data(gup.repeat, gup.keyFun); + + cellText.enter() + .append('text') + .classed('cellText', true); + + cellText + .call(renderCellText, tableControlView, allColumnBlock, columnCell, gd); +} + +function setFont(columnCell) { columnCell .each(function(d, i) { var spec = d.calcdata.cells.font; @@ -378,14 +410,9 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i) d.font = font; }); +} - var cellRect = columnCell.selectAll('.cellRect') - .data(gup.repeat, gup.keyFun); - - cellRect.enter() - .append('rect') - .classed('cellRect', true); - +function renderRect(cellRect) { cellRect .attr('width', function(d) {return d.column.columnWidth;}) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) @@ -397,23 +424,6 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { .attr('fill', function(d) { return d.calcdata.cells.fill ? gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber) : 'none'; }); - - var cellTextHolder = columnCell.selectAll('.cellTextHolder') - .data(gup.repeat, gup.keyFun); - - cellTextHolder.enter() - .append('g') - .classed('cellTextHolder', true); - - var cellText = cellTextHolder.selectAll('.cellText') - .data(gup.repeat, gup.keyFun); - - cellText.enter() - .append('text') - .classed('cellText', true); - - cellText - .call(renderCellText, tableControlView, allColumnBlock, columnCell, gd); } function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, gd) { From 6292da76ff667b6f7d632fd2fbf9eac7e6e073bc Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 12:52:13 +0200 Subject: [PATCH 250/281] removed unneeded font spec (there were two places setting font) --- src/traces/table/plot.js | 1 - test/image/mocks/table_one_cell.json | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 264be680d89..ee4a29f80a2 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -469,7 +469,6 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, var selection = d3.select(element); // finalize what's in the DOM - Drawing.font(selection, d.font); var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; if(d.mayHaveMarkup || d.wrappingNeeded || d.latex) { diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 7fdc6cda045..73f5aa68266 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -59,7 +59,7 @@ "font": { "family": "Arial", - "size": 12, + "size": 18, "color": "white" } }, @@ -163,8 +163,8 @@ }, "font": { - "family": "verdana", - "size": 12, + "family": "Courier", + "size": 15, "color": ["black"] } } From 45ae34315d72fc793c64a322f5b5cd81b602a51f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 12:58:10 +0200 Subject: [PATCH 251/281] moved setCellHeightAndPositionY outside renderCellText (became peer) --- src/traces/table/plot.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index ee4a29f80a2..534210ddd2b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -389,7 +389,10 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { .classed('cellText', true); cellText - .call(renderCellText, tableControlView, allColumnBlock, columnCell, gd); + .call(renderCellText, tableControlView, allColumnBlock, gd); + + // doing this at the end when text, and text stlying are set + columnCell.call(setCellHeightAndPositionY); } function setFont(columnCell) { @@ -426,7 +429,7 @@ function renderRect(cellRect) { }); } -function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, gd) { +function renderCellText(cellText, tableControlView, allColumnBlock, gd) { cellText .text(function(d) { var col = d.column.specIndex; @@ -476,8 +479,7 @@ function renderCellText(cellText, tableControlView, allColumnBlock, columnCell, } else { // renderCallback(allColumnBlock, element, tableControlView, d); } - }) - columnCell.call(setCellHeightAndPositionY); + }); } function latexEh(content) { @@ -729,7 +731,8 @@ function wrapTextMaker(columnBlock, element, tableControlView) { cellTextHolder.selectAll('tspan.line').remove(); // resupply text, now wrapped - renderCellText(cellTextHolder.select('.cellText'), tableControlView, columnBlock, d3.select(element.parentNode.parentNode)); + renderCellText(cellTextHolder.select('.cellText'), tableControlView, columnBlock); + d3.select(element.parentNode.parentNode).call(setCellHeightAndPositionY); }; } window.monfera = 0 From f85beb6d3e1cc746582b66641bb6018b4d94d700 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 13:59:24 +0200 Subject: [PATCH 252/281] switching to direct calls (shows up better on perf profiling) --- src/traces/table/plot.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 534210ddd2b..f7233023313 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -361,8 +361,7 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { columnCell.exit().remove(); - columnCell - .call(setFont); + setFont(columnCell); var cellRect = columnCell.selectAll('.cellRect') .data(gup.repeat, gup.keyFun); @@ -371,8 +370,7 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { .append('rect') .classed('cellRect', true); - cellRect - .call(renderRect); + renderRect(cellRect); var cellTextHolder = columnCell.selectAll('.cellTextHolder') .data(gup.repeat, gup.keyFun); @@ -388,11 +386,10 @@ function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { .append('text') .classed('cellText', true); - cellText - .call(renderCellText, tableControlView, allColumnBlock, gd); + renderCellText(cellText, tableControlView, allColumnBlock, gd); // doing this at the end when text, and text stlying are set - columnCell.call(setCellHeightAndPositionY); + setCellHeightAndPositionY(columnCell); } function setFont(columnCell) { From bd10e57d33ca831a31cbddf3b463255aabd570d7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 14:00:10 +0200 Subject: [PATCH 253/281] rename --- src/traces/table/plot.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index f7233023313..a220badfa8b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -150,8 +150,8 @@ module.exports = function plot(gd, calcdata) { // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) // but blocks are _entered_ the way they are due to painter's algo (header on top) - renderColumnBlocks(gd, tableControlView, columnBlock.filter(headerBlock), columnBlock); - renderColumnBlocks(gd, tableControlView, columnBlock.filter(cellsBlock), columnBlock); + renderColumnCellTree(gd, tableControlView, columnBlock.filter(headerBlock), columnBlock); + renderColumnCellTree(gd, tableControlView, columnBlock.filter(cellsBlock), columnBlock); var scrollAreaClip = tableControlView.selectAll('.scrollAreaClip') .data(gup.repeat, gup.keyFun); @@ -337,7 +337,7 @@ function renderScrollbarKit(tableControlView) { }); } -function renderColumnBlocks(gd, tableControlView, columnBlock, allColumnBlock) { +function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) { // fixme this perf hotspot // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization @@ -684,7 +684,7 @@ function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); - renderColumnBlocks(gd, tableControlView, toRerender, toRerender); + renderColumnCellTree(gd, tableControlView, toRerender, toRerender); prevPages[revolverIndex] = pages[revolverIndex]; }); } From 8037a25933e4f6f6fa543a17f8a48df0abacd02a Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 14:07:47 +0200 Subject: [PATCH 254/281] extracted out some functions --- src/traces/table/plot.js | 58 +++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index a220badfa8b..6bd8ecf71c7 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -342,6 +342,33 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) // this is performance critical code as scrolling calls it on every revolver switch // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization + var columnCells = renderColumnCells(columnBlock); + + var columnCell = renderColumnCell(columnCells); + + setFont(columnCell); + + var cellRect = renderCellRect(columnCell); + + renderRect(cellRect); + + var cellTextHolder = renderCellTextHolder(columnCell); + + var cellText = cellTextHolder.selectAll('.cellText') + .data(gup.repeat, gup.keyFun); + + cellText.enter() + .append('text') + .classed('cellText', true); + + populateCellText(cellText, tableControlView, allColumnBlock, gd); + + // doing this at the end when text, and text stlying are set + setCellHeightAndPositionY(columnCell); +} + +function renderColumnCells(columnBlock) { + var columnCells = columnBlock.selectAll('.columnCells') .data(gup.repeat, gup.keyFun); @@ -352,6 +379,11 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) columnCells.exit() .remove(); + return columnCells; +} + +function renderColumnCell(columnCells) { + var columnCell = columnCells.selectAll('.columnCell') .data(splitToCells, gup.keyFun); @@ -361,7 +393,10 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) columnCell.exit().remove(); - setFont(columnCell); + return columnCell; +} + +function renderCellRect(columnCell) { var cellRect = columnCell.selectAll('.cellRect') .data(gup.repeat, gup.keyFun); @@ -370,7 +405,10 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) .append('rect') .classed('cellRect', true); - renderRect(cellRect); + return cellRect; +} + +function renderCellTextHolder(columnCell) { var cellTextHolder = columnCell.selectAll('.cellTextHolder') .data(gup.repeat, gup.keyFun); @@ -379,17 +417,7 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) .append('g') .classed('cellTextHolder', true); - var cellText = cellTextHolder.selectAll('.cellText') - .data(gup.repeat, gup.keyFun); - - cellText.enter() - .append('text') - .classed('cellText', true); - - renderCellText(cellText, tableControlView, allColumnBlock, gd); - - // doing this at the end when text, and text stlying are set - setCellHeightAndPositionY(columnCell); + return cellTextHolder; } function setFont(columnCell) { @@ -426,7 +454,7 @@ function renderRect(cellRect) { }); } -function renderCellText(cellText, tableControlView, allColumnBlock, gd) { +function populateCellText(cellText, tableControlView, allColumnBlock, gd) { cellText .text(function(d) { var col = d.column.specIndex; @@ -728,7 +756,7 @@ function wrapTextMaker(columnBlock, element, tableControlView) { cellTextHolder.selectAll('tspan.line').remove(); // resupply text, now wrapped - renderCellText(cellTextHolder.select('.cellText'), tableControlView, columnBlock); + populateCellText(cellTextHolder.select('.cellText'), tableControlView, columnBlock); d3.select(element.parentNode.parentNode).call(setCellHeightAndPositionY); }; } From a33d979627d646c53855d55160accd02d2a4125d Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 14:08:31 +0200 Subject: [PATCH 255/281] rename --- src/traces/table/plot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6bd8ecf71c7..522ded03c36 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -350,7 +350,7 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) var cellRect = renderCellRect(columnCell); - renderRect(cellRect); + sizeAndStyleRect(cellRect); var cellTextHolder = renderCellTextHolder(columnCell); @@ -440,7 +440,7 @@ function setFont(columnCell) { }); } -function renderRect(cellRect) { +function sizeAndStyleRect(cellRect) { cellRect .attr('width', function(d) {return d.column.columnWidth;}) .attr('stroke-width', function(d) {return d.cellBorderWidth;}) From 3f27ea140dbecaedbdbb7197cd167e646c137c53 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sat, 30 Sep 2017 14:10:09 +0200 Subject: [PATCH 256/281] extracted out more --- src/traces/table/plot.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 522ded03c36..6de5eb57b8b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -354,12 +354,7 @@ function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) var cellTextHolder = renderCellTextHolder(columnCell); - var cellText = cellTextHolder.selectAll('.cellText') - .data(gup.repeat, gup.keyFun); - - cellText.enter() - .append('text') - .classed('cellText', true); + var cellText = renderCellText(cellTextHolder); populateCellText(cellText, tableControlView, allColumnBlock, gd); @@ -408,6 +403,18 @@ function renderCellRect(columnCell) { return cellRect; } +function renderCellText(cellTextHolder) { + + var cellText = cellTextHolder.selectAll('.cellText') + .data(gup.repeat, gup.keyFun); + + cellText.enter() + .append('text') + .classed('cellText', true); + + return cellText; +} + function renderCellTextHolder(columnCell) { var cellTextHolder = columnCell.selectAll('.cellTextHolder') From 51be19d746e3e60d28483f1207caeab57debaa6c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 1 Oct 2017 02:13:32 +0200 Subject: [PATCH 257/281] fantastic speedup due to not having to exit cells, only update --- src/traces/table/plot.js | 19 ++++++------------- test/image/mocks/table_one_cell.json | 4 ++-- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 6de5eb57b8b..b30446a6368 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -118,8 +118,7 @@ module.exports = function plot(gd, calcdata) { yColumn.attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}); } - yColumn.exit() - .remove(); + //yColumn.exit().remove(); var columnBlock = yColumn.selectAll('.columnBlock') .data(splitToPanels, gup.keyFun); @@ -371,30 +370,25 @@ function renderColumnCells(columnBlock) { .append('g') .classed('columnCells', true); - columnCells.exit() - .remove(); - return columnCells; } function renderColumnCell(columnCells) { var columnCell = columnCells.selectAll('.columnCell') - .data(splitToCells, gup.keyFun); + .data(splitToCells, function(d) {return d.keyWithinBlock;}); columnCell.enter() .append('g') .classed('columnCell', true); - columnCell.exit().remove(); - return columnCell; } function renderCellRect(columnCell) { var cellRect = columnCell.selectAll('.cellRect') - .data(gup.repeat, gup.keyFun); + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); cellRect.enter() .append('rect') @@ -406,7 +400,7 @@ function renderCellRect(columnCell) { function renderCellText(cellTextHolder) { var cellText = cellTextHolder.selectAll('.cellText') - .data(gup.repeat, gup.keyFun); + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); cellText.enter() .append('text') @@ -418,7 +412,7 @@ function renderCellText(cellTextHolder) { function renderCellTextHolder(columnCell) { var cellTextHolder = columnCell.selectAll('.cellTextHolder') - .data(gup.repeat, gup.keyFun); + .data(gup.repeat, function(d) {return d.keyWithinBlock;}); cellTextHolder.enter() .append('g') @@ -598,6 +592,7 @@ function splitToCells(d) { var fromTo = rowFromTo(d); return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { return { + keyWithinBlock: /*fromTo[0] + */i, key: fromTo[0] + i, column: d, calcdata: d.calcdata, @@ -817,8 +812,6 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function setCellHeightAndPositionY(columnCell) { - // fixme speed bottleneck 15% - window.monfera++ columnCell .attr('transform', function(d) { var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell.json index 73f5aa68266..aa8b106c9bc 100644 --- a/test/image/mocks/table_one_cell.json +++ b/test/image/mocks/table_one_cell.json @@ -67,8 +67,8 @@ "cells": { "values": [ - Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()), - Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()),Array.from(Array(1000).keys()), + Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()), + Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()),Array.from(Array(1000000).keys()), ] .slice(0, 20) || [ [ From bfa59688250cb56e3ffb75fdccfb6a083091ed66 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Sun, 1 Oct 2017 02:15:21 +0200 Subject: [PATCH 258/281] minor --- src/traces/table/plot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b30446a6368..7c16c379ffd 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -624,7 +624,6 @@ function findPagesAndCacheHeights(blocks, scrollY, scrollHeight) { for(var blockIndex = 0; blockIndex < blocks.length; blockIndex++) { var block = blocks[blockIndex]; - //block.allRowsHeight = undefined; var blockRows = block.rows; var rowsHeight = 0; for(var i = 0; i < blockRows.length; i++) { From cb5dec87af14e322ef502aaa4835db980dd82b77 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 12:04:38 +0200 Subject: [PATCH 259/281] baseline for fixing latex regression --- src/traces/table/plot.js | 3 +- test/image/mocks/table_one_cell_latex.json | 169 ++++++++++++++++++ .../mocks/table_one_cell_linebroken.json | 169 ++++++++++++++++++ ...ne_cell.json => table_one_cell_plain.json} | 0 test/image/mocks/table_one_cell_styled.json | 169 ++++++++++++++++++ 5 files changed, 509 insertions(+), 1 deletion(-) create mode 100644 test/image/mocks/table_one_cell_latex.json create mode 100644 test/image/mocks/table_one_cell_linebroken.json rename test/image/mocks/{table_one_cell.json => table_one_cell_plain.json} (100%) create mode 100644 test/image/mocks/table_one_cell_styled.json diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7c16c379ffd..4216d25defe 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -474,7 +474,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { var hwsc = function(prefixSuffixedText) {return prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1;}; d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hwsc(prefixSuffixedText)); d.cellHeightMayIncrease = !d.wrapped && (userBrokenText2 || latex || (hasWrapSplitCharacter === void(0) ? hwsc(prefixSuffixedText) : hasWrapSplitCharacter)); - if(d.cellHeightMayIncrease) debugger + //if(d.cellHeightMayIncrease) debugger var textToRender; if(d.wrappingNeeded) { var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 18, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello2", + //"1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AXB PlotlyCD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + "$\\begin{eqnarray*} \\cos 1\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 3\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 4\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 5\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 6\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 7\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 8\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 9\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 10\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 11\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 12\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 13\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 14\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 15\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "$\\begin{eqnarray*} \\cos 16\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + //"x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}) + + ].filter(function(d,i) {return i === 2}), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fille": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "Courier", + "size": 15, + "color": ["black"] + } + } + }] +} diff --git a/test/image/mocks/table_one_cell_linebroken.json b/test/image/mocks/table_one_cell_linebroken.json new file mode 100644 index 00000000000..bf7afa8b03c --- /dev/null +++ b/test/image/mocks/table_one_cell_linebroken.json @@ -0,0 +1,169 @@ +{ + "layout": { + "width": 800, + "height": 0.2 * 750 + 380 - 150, + "title": "Widget parameters and cost", + "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [30], + "columnorder": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + + "header": { + + "height": 30, // fixme for some reason it doesn't recognize arrays here + + "values": [ + ["C00" , "#"], + ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 18, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello2", + //"1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AXB PlotlyCD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "x1AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "x2AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "x3AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "x4AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "x5AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "x6AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "x7AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", + "x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}) + + ].filter(function(d,i) {return i === 2}), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fille": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "Courier", + "size": 15, + "color": ["black"] + } + } + }] +} diff --git a/test/image/mocks/table_one_cell.json b/test/image/mocks/table_one_cell_plain.json similarity index 100% rename from test/image/mocks/table_one_cell.json rename to test/image/mocks/table_one_cell_plain.json diff --git a/test/image/mocks/table_one_cell_styled.json b/test/image/mocks/table_one_cell_styled.json new file mode 100644 index 00000000000..bf7afa8b03c --- /dev/null +++ b/test/image/mocks/table_one_cell_styled.json @@ -0,0 +1,169 @@ +{ + "layout": { + "width": 800, + "height": 0.2 * 750 + 380 - 150, + "title": "Widget parameters and cost", + "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [30], + "columnorder": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + + "header": { + + "height": 30, // fixme for some reason it doesn't recognize arrays here + + "values": [ + ["C00" , "#"], + ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 18, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello2", + //"1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AXB PlotlyCD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "x1AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "x2AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "x3AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "x4AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "x5AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "x6AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "x7AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", + "x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}) + + ].filter(function(d,i) {return i === 2}), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fille": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "Courier", + "size": 15, + "color": ["black"] + } + } + }] +} From ae10de6da2ebb50ce9b9589e0037f71a4a0e0d73 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 13:07:58 +0200 Subject: [PATCH 260/281] hmm doesn't reproduce --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell_latex.json | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index e8631543c97..4b945386176 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -29,5 +29,5 @@ module.exports = { scrollbarOffset: 5, scrollbarHideDelay: 1000, scrollbarHideDuration: 1000, - clipView: false + clipView: true }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 4216d25defe..471450cff1b 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -585,7 +585,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2, headerPanel]; + return [revolverPanel1, revolverPanel2/*, headerPanel*/]; } function splitToCells(d) { diff --git a/test/image/mocks/table_one_cell_latex.json b/test/image/mocks/table_one_cell_latex.json index df6b94a2678..3feee33886e 100644 --- a/test/image/mocks/table_one_cell_latex.json +++ b/test/image/mocks/table_one_cell_latex.json @@ -1,7 +1,7 @@ { "layout": { "width": 800, - "height": 0.2 * 750 + 380 - 150, + "height": 0 * 750 + 380 - 210, "title": "Widget parameters and cost", "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} }, @@ -20,7 +20,7 @@ "header": { - "height": 30, // fixme for some reason it doesn't recognize arrays here + "height": 0, // fixme for some reason it doesn't recognize arrays here "values": [ ["C00" , "#"], @@ -130,7 +130,7 @@ "$\\begin{eqnarray*} \\cos 15\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "$\\begin{eqnarray*} \\cos 16\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", //"x8AX
B
Plotly
CD", - ].map(function(d, i) {return d}) + ].map(function(d, i) {return d}).filter(function(d, i) {return i < 2;}) ].filter(function(d,i) {return i === 2}), @@ -141,7 +141,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 40, + "height": 46, "align": ["right"], "valign": ["bottom"], From 406708427b512d95a3032603c5ec261c5f01413f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 13:21:43 +0200 Subject: [PATCH 261/281] minimal repro of issue --- test/image/mocks/table_one_cell_latex.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/image/mocks/table_one_cell_latex.json b/test/image/mocks/table_one_cell_latex.json index 3feee33886e..46faeee7e50 100644 --- a/test/image/mocks/table_one_cell_latex.json +++ b/test/image/mocks/table_one_cell_latex.json @@ -130,7 +130,7 @@ "$\\begin{eqnarray*} \\cos 15\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "$\\begin{eqnarray*} \\cos 16\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", //"x8AX
B
Plotly
CD", - ].map(function(d, i) {return d}).filter(function(d, i) {return i < 2;}) + ].map(function(d, i) {return d}).filter(function(d, i) {return i < 4;}) ].filter(function(d,i) {return i === 2}), @@ -141,7 +141,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 46, + "height": 30, "align": ["right"], "valign": ["bottom"], From d3dffc0d5210edffe34aad282ec17f0e85abd735 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 13:52:02 +0200 Subject: [PATCH 262/281] minor --- src/traces/table/plot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 471450cff1b..0f0a5aba0a9 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -126,6 +126,7 @@ module.exports = function plot(gd, calcdata) { columnBlock.enter() .append('g') .classed('columnBlock', true) + .attr('id', function(d) {return d.key;}) .style('user-select', 'none'); columnBlock From a04fd845f17b5847618ccb24d50152b9d363a1ae Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 17:25:41 +0200 Subject: [PATCH 263/281] avoiding double render loop on 1st render --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 9 ++++++++- test/image/mocks/table_one_cell_latex.json | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index 4b945386176..e8631543c97 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -29,5 +29,5 @@ module.exports = { scrollbarOffset: 5, scrollbarHideDelay: 1000, scrollbarHideDuration: 1000, - clipView: true + clipView: false }; diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 0f0a5aba0a9..9bb44c37bb5 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -211,7 +211,7 @@ module.exports = function plot(gd, calcdata) { .attr('width', function(d) {return d.columnWidth;}) .attr('height', function(d) {return d.calcdata.height + c.uplift;}); - updateBlockYPosition(gd, cellsColumnBlock, tableControlView); + updateBlockYPosition(null, cellsColumnBlock, tableControlView); }; function renderScrollbarKit(tableControlView) { @@ -371,6 +371,9 @@ function renderColumnCells(columnBlock) { .append('g') .classed('columnCells', true); + columnCells.exit() + .remove(); + return columnCells; } @@ -383,6 +386,9 @@ function renderColumnCell(columnCells) { .append('g') .classed('columnCell', true); + columnCell.exit() + .remove(); + return columnCell; } @@ -594,6 +600,7 @@ function splitToCells(d) { return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { return { keyWithinBlock: /*fromTo[0] + */i, + //keyWithinBlock: fromTo[0] + i, key: fromTo[0] + i, column: d, calcdata: d.calcdata, diff --git a/test/image/mocks/table_one_cell_latex.json b/test/image/mocks/table_one_cell_latex.json index 46faeee7e50..c55a70731d5 100644 --- a/test/image/mocks/table_one_cell_latex.json +++ b/test/image/mocks/table_one_cell_latex.json @@ -1,7 +1,7 @@ { "layout": { "width": 800, - "height": 0 * 750 + 380 - 210, + "height": 0.1 * 750 + 380 - 210, "title": "Widget parameters and cost", "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} }, @@ -130,7 +130,7 @@ "$\\begin{eqnarray*} \\cos 15\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "$\\begin{eqnarray*} \\cos 16\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", //"x8AX
B
Plotly
CD", - ].map(function(d, i) {return d}).filter(function(d, i) {return i < 4;}) + ].map(function(d, i) {return d}).filter(function(d, i) {return i < 400;}) ].filter(function(d,i) {return i === 2}), @@ -141,7 +141,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 30, + "height": 60, "align": ["right"], "valign": ["bottom"], From 2c87828fb21f4b1bbe9ae9a7d4ecf75e730be4bd Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 17:39:41 +0200 Subject: [PATCH 264/281] busting keys for async render calls --- src/traces/table/plot.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 9bb44c37bb5..14284a7ac61 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -598,9 +598,16 @@ function splitToPanels(d) { function splitToCells(d) { var fromTo = rowFromTo(d); return d.values.slice(fromTo[0], fromTo[1]).map(function(v, i) { + // By keeping identical key, a DOM node removal, creation and addition is spared, important when visible + // grid has a lot of elements (quadratic with xcol/ycol count). + // But it has to be busted when `svgUtil.convertToTspans` is used as it reshapes cell subtrees asynchronously, + // and by that time the user may have scrolled away, resulting in stale overwrites. The real solution will be + // to turn `svgUtil.convertToTspans` into a cancelable request, in which case no key busting is needed. + var buster = (typeof v === 'string') && v.match(/[<$>]/) ? '_keybuster_' + Math.random() : ''; return { - keyWithinBlock: /*fromTo[0] + */i, - //keyWithinBlock: fromTo[0] + i, + // keyWithinBlock: /*fromTo[0] + */i, // optimized future version - no busting + // keyWithinBlock: fromTo[0] + i, // initial always-unoptimized version - janky scrolling with 5+ columns + keyWithinBlock: i + buster, // current compromise: regular content is very fast; async content is possible key: fromTo[0] + i, column: d, calcdata: d.calcdata, From 9179e844b539563e1d0c0ab3e530148f4aab269e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 18:08:37 +0200 Subject: [PATCH 265/281] mock update; reactivating header column --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell_plain.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 14284a7ac61..03c14b13a2c 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -592,7 +592,7 @@ function splitToPanels(d) { rowBlocks: d.calcdata.rowBlocks }); // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2/*, headerPanel*/]; + return [revolverPanel1, revolverPanel2, headerPanel]; } function splitToCells(d) { diff --git a/test/image/mocks/table_one_cell_plain.json b/test/image/mocks/table_one_cell_plain.json index aa8b106c9bc..5ec59bfd397 100644 --- a/test/image/mocks/table_one_cell_plain.json +++ b/test/image/mocks/table_one_cell_plain.json @@ -1,6 +1,6 @@ { "layout": { - "width": 800, + "width": 1400, "height": 750 + 380 - 150, "title": "Widget parameters and cost", "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} @@ -156,9 +156,9 @@ "width": 1 }, - "fille": { + "fill": { "color": [ - ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + Array.from(Array(1000000).keys()).map(function(d, i) {return i % 2 ? "#c6dbef" : "#9ecae1"}) ] }, From 3309f288ed852c0ff3c510cdb48c3d504377c194 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 18:11:00 +0200 Subject: [PATCH 266/281] mock update for latex: also showing an increased-height header --- test/image/mocks/table_one_cell_latex.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/image/mocks/table_one_cell_latex.json b/test/image/mocks/table_one_cell_latex.json index c55a70731d5..06e20c178d2 100644 --- a/test/image/mocks/table_one_cell_latex.json +++ b/test/image/mocks/table_one_cell_latex.json @@ -1,7 +1,7 @@ { "layout": { "width": 800, - "height": 0.1 * 750 + 380 - 210, + "height": 0.2 * 750 + 380 - 210, "title": "Widget parameters and cost", "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} }, @@ -20,10 +20,10 @@ "header": { - "height": 0, // fixme for some reason it doesn't recognize arrays here + "height": 20, // fixme for some reason it doesn't recognize arrays here "values": [ - ["C00" , "#"], + ["C00" , "$\\begin{eqnarray*} \\cos 0\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], ["C03" , "#" || "#"], From b7d140ed4bb11b9bb09558eab8377f6274f3cd30 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 18:13:03 +0200 Subject: [PATCH 267/281] mock update for linebroken: also showing an increased-height header --- test/image/mocks/table_one_cell_linebroken.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell_linebroken.json b/test/image/mocks/table_one_cell_linebroken.json index bf7afa8b03c..25ab3b9b107 100644 --- a/test/image/mocks/table_one_cell_linebroken.json +++ b/test/image/mocks/table_one_cell_linebroken.json @@ -23,7 +23,7 @@ "height": 30, // fixme for some reason it doesn't recognize arrays here "values": [ - ["C00" , "#"], + ["C00" , "0AX
B
Plotly
CD"], ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], ["C03" , "#" || "#"], From 54b319f02970dfcb226eeda2eefd18f828ac6b2f Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 18:15:19 +0200 Subject: [PATCH 268/281] mock update for styled --- test/image/mocks/table_one_cell_styled.json | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/image/mocks/table_one_cell_styled.json b/test/image/mocks/table_one_cell_styled.json index bf7afa8b03c..4e5fc2ccf95 100644 --- a/test/image/mocks/table_one_cell_styled.json +++ b/test/image/mocks/table_one_cell_styled.json @@ -107,29 +107,29 @@ ].map(function(d, i) {return d}), [ //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x1AX
B
Plotly
CD", - "x1AX
B
Plotly
CD", + "x1AXB PlotlyCD", + "x1AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x2AX
B
Plotly
CD", - "x2AX
B
Plotly
CD", + "x2AXB PlotlyCD", + "x2AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x3AX
B
Plotly
CD", - "x3AX
B
Plotly
CD", + "x3AXB PlotlyCD", + "x3AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x4AX
B
Plotly
CD", - "x4AX
B
Plotly
CD", + "x4AXB PlotlyCD", + "x4AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x5AX
B
Plotly
CD", - "x5AX
B
Plotly
CD", + "x5AXB PlotlyCD", + "x5AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x6AX
B
Plotly
CD", - "x6AX
B
Plotly
CD", + "x6AXB PlotlyCD", + "x6AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x7AX
B
Plotly
CD", - "x7AX
B
Plotly
CD", + "x7AXB PlotlyCD", + "x7AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", - "x8AX
B
Plotly
CD", - "x8AX
B
Plotly
CD", + "x8AXB PlotlyCD", + "x8AXB PlotlyCD", ].map(function(d, i) {return d}) ].filter(function(d,i) {return i === 2}), @@ -141,7 +141,7 @@ //"prefix": ["#"], //"suffix": ["cell"], - "height": 40, + "height": 20, "align": ["right"], "valign": ["bottom"], From c32141f64103e6485dde7ab4f5cf1767f11574e7 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 18:55:21 +0200 Subject: [PATCH 269/281] just because it's wrapped, it may still need a height increase --- src/traces/table/plot.js | 4 ++-- test/image/mocks/table_one_cell_styled.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 03c14b13a2c..7a14d45d2cd 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -480,8 +480,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { var hasWrapSplitCharacter; var hwsc = function(prefixSuffixedText) {return prefixSuffixedText.indexOf(c.wrapSplitCharacter) !== -1;}; d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hwsc(prefixSuffixedText)); - d.cellHeightMayIncrease = !d.wrapped && (userBrokenText2 || latex || (hasWrapSplitCharacter === void(0) ? hwsc(prefixSuffixedText) : hasWrapSplitCharacter)); - //if(d.cellHeightMayIncrease) debugger + d.cellHeightMayIncrease = userBrokenText2 || latex || d.mayHaveMarkup || (hasWrapSplitCharacter === void(0) ? hwsc(prefixSuffixedText) : hasWrapSplitCharacter); var textToRender; if(d.wrappingNeeded) { var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/X
B
Plotly
CD"], + ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 1), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 18, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello2", + //"1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AXB PlotlyCD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "x1AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "x2AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "x3AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "x4AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "x5AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "x6AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "x7AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", + "x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}) + + ].filter(function(d,i) {return i === 1}), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fille": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "Courier", + "size": 15, + "color": ["black"] + } + } + }] +} From a13accb8e35a867cb380ab67088a210f74ceff1b Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 19:02:55 +0200 Subject: [PATCH 271/281] added mock for mixed content --- .../table_multicolumn_mixed_content.json | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 test/image/mocks/table_multicolumn_mixed_content.json diff --git a/test/image/mocks/table_multicolumn_mixed_content.json b/test/image/mocks/table_multicolumn_mixed_content.json new file mode 100644 index 00000000000..210071dcccb --- /dev/null +++ b/test/image/mocks/table_multicolumn_mixed_content.json @@ -0,0 +1,169 @@ +{ + "layout": { + "width": 800, + "height": 0.2 * 750 + 380 - 150, + "title": "Widget parameters and cost", + "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} + }, + + "data": [{ + + "type": "table", + + "domain": { + "x": [0.05, 0.95], + "y": [0, 1] + }, + + "columnwidth": [30], + "columnorder": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + + "header": { + + "height": 30, // fixme for some reason it doesn't recognize arrays here + + "values": [ + ["C00" , "0AX
B
Plotly
CD"], + ["C01" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C02" , "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C03" , "#" || "#"], + ["C04" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C05" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C06" , "#" || "#"], + ["C07" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C08" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C09" , "#" || "#"], + ["C10" , "#"], + ["C11" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C12" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C13" , "#" || "#"], + ["C14" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C15" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C16" , "#" || "#"], + ["C17" , "#" || "ASDF
GHJKLWW" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$" || "1AX
B
Plotly
CD"], + ["C18" , "#" || "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1 \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$"], + ["C19" , "#" || "#"], + ].map(function(r) {return r.slice(0, 2)}).slice(0, 3), + + "align": ["right"], + "valign": "middle", + + "line": { + "color": "lightgray", + "width": 0.5 + }, + + "fill": { + "color": "grey" + }, + + "font": { + "family": "Arial", + "size": 18, + "color": "white" + } + }, + + "cells": { + + "values": [ + [ + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "1AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return i}), + [ + "Hello1", + "Try-hard bushwick irony humblebrag activated charcoal, thundercats air plant drinking vinegar knausgaard stumptown normcore readymade af prism. Master cleanse pork belly mumblecore, godard 8-bit wolf mlkshk dreamcatcher narwhal kickstarter williamsburg hoodie meh tumblr brunch." || "$\\begin{eqnarray*} 1*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "Hello2", + //"1AX
B
Plotly
CD", + "$\\begin{eqnarray*} 2*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "2AX
B
Plotly
CD", + "$\\begin{eqnarray*} 3*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "3AXB PlotlyCD", + "$\\begin{eqnarray*} 4*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "4AX
B
Plotly
CD", + "$\\begin{eqnarray*} 5*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "5AX
B
Plotly
CD", + "$\\begin{eqnarray*} 6*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "6AX
B
Plotly
CD", + "$\\begin{eqnarray*} 7*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "7AX
B
Plotly
CD", + "$\\begin{eqnarray*} 8*\\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "8AX
B
Plotly
CD", + ].map(function(d, i) {return d}), + [ + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x1AX
B
Plotly
CD", + "x1AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x2AX
B
Plotly
CD", + "x2AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x3AX
B
Plotly
CD", + "x3AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x4AX
B
Plotly
CD", + "x4AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x5AX
B
Plotly
CD", + "x5AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x6AX
B
Plotly
CD", + "x6AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x7AX
B
Plotly
CD", + "x7AX
B
Plotly
CD", + //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", + "x8AX
B
Plotly
CD", + "x8AX
B
Plotly
CD", + ].map(function(d, i) {return d}).slice(0, 16) + + ].filter(function(d,i) {return i < 4}), + + "format": [ + null + ], + + //"prefix": ["#"], + //"suffix": ["cell"], + + "height": 40, + + "align": ["right"], + "valign": ["bottom"], + + "line": { + "color": [ + "grey" + ], + "width": 1 + }, + + "fille": { + "color": [ + ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] + ] + }, + + "font": { + "family": "Courier", + "size": 15, + "color": ["black"] + } + } + }] +} From 303ba176ede9566b8d6d21ed20cefc01dd6a146c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 22:09:49 +0200 Subject: [PATCH 272/281] basic cell adjustment for cellPad --- src/traces/table/plot.js | 21 +++++-------------- .../table_multicolumn_mixed_content.json | 2 +- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 7a14d45d2cd..4cf50f071f3 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -310,23 +310,18 @@ function renderScrollbarKit(tableControlView) { var s = d.scrollbarState; var pixelVal = y - bbox.top; var inverseScale = d3.scale.linear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true); - if(s.topY <= pixelVal && pixelVal <= s.bottomY) { - //console.log('on glyph!') - } else { + if(!(s.topY <= pixelVal && pixelVal <= s.bottomY)) { makeDragRow(gd, tableControlView, null, inverseScale(pixelVal - s.barLength / 2))(d); } - //console.log('mousedown', bbox.top, bbox.bottom, y, scale(y)) }) .call(d3.behavior.drag() .origin(function(d) { - //console.log('drag started') d3.event.stopPropagation(); d.scrollbarState.scrollbarScrollInProgress = true; return d; }) .on('drag', makeDragRow(gd, tableControlView)) .on('dragend', function(d) { - //console.log('drag ended') // fixme emit Plotly event }) ); @@ -509,7 +504,9 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { if(d.mayHaveMarkup || d.wrappingNeeded || d.latex) { svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); } else { - // renderCallback(allColumnBlock, element, tableControlView, d); + d3.select(element.parentNode) + // basic cell adjustment - compliance with `cellPad` + .attr('transform', function (d) {return 'translate(' + c.cellPad + ' ' + c.cellPad + ')';}); } }); } @@ -817,8 +814,6 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); return 'translate(' + c.cellPad + ' ' + yPosition + ')'; - } else { - return 'translate(' + c.cellPad + ' ' + c.cellPad + ')'; } }); @@ -867,13 +862,7 @@ function allRowsHeight(rowBlock) { total += rowBlock.rows[i].rowHeight; } rowBlock.allRowsHeight = total; -/* - if(cached !== void(0)) { - if(cached !== total) console.log('allRowsHeight mismatch'); - } else { - //console.log('cache miss') - } -*/ + return total; } diff --git a/test/image/mocks/table_multicolumn_mixed_content.json b/test/image/mocks/table_multicolumn_mixed_content.json index 210071dcccb..8e2d671d88f 100644 --- a/test/image/mocks/table_multicolumn_mixed_content.json +++ b/test/image/mocks/table_multicolumn_mixed_content.json @@ -126,7 +126,7 @@ "x6AX
B
Plotly
CD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "x7AX
B
Plotly
CD", - "x7AX
B
Plotly
CD", + "x7AXB PlotlyCD", //"$\\begin{eqnarray*} \\cos 2\\theta & = & \\cos^2 \\theta - \\sin^2 \\theta \\\\ & = & 2 \\cos^2 \\theta - 1. \\end{eqnarray*}$", "x8AX
B
Plotly
CD", "x8AX
B
Plotly
CD", From 0f6fe97f8846b6de346b7bdde19f021e937db31c Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 22:38:04 +0200 Subject: [PATCH 273/281] latex check --- src/traces/table/constants.js | 2 +- src/traces/table/plot.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/traces/table/constants.js b/src/traces/table/constants.js index e8631543c97..9746babad1d 100644 --- a/src/traces/table/constants.js +++ b/src/traces/table/constants.js @@ -12,7 +12,7 @@ module.exports = { maxDimensionCount: 60, overdrag: 45, cellPad: 8, - latexMark: '$', + latexCheck: /^\$.*\$$/, wrapSplitCharacter: ' ', wrapSpacer: ' ', lineBreaker: '
', diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 4cf50f071f3..b9815a99f00 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -463,7 +463,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { var col = d.column.specIndex; var row = d.rowNumber; var userSuppliedContent = d.value; - var latex = latexEh(userSuppliedContent); + var latex = isLatex(userSuppliedContent); var userBrokenText = (typeof userSuppliedContent !== 'string') || userSuppliedContent.match(/
/i); var userBrokenText2 = (typeof userSuppliedContent === 'string') && userSuppliedContent.match(/
/i); var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; @@ -511,8 +511,8 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { }); } -function latexEh(content) { - return typeof content === 'string' && content[0] === c.latexMark && content[content.length - 1] === c.latexMark; +function isLatex(content) { + return typeof content === 'string' && content.match(c.latexCheck); } function columnMoved(gd, calcdata, i, indices) { From 9f27d6053ddeac86a89366fb36c3c5c6042e60ee Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 22:44:43 +0200 Subject: [PATCH 274/281] xPosition extracted --- src/traces/table/plot.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index b9815a99f00..399cb2b4aa4 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -506,7 +506,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { } else { d3.select(element.parentNode) // basic cell adjustment - compliance with `cellPad` - .attr('transform', function (d) {return 'translate(' + c.cellPad + ' ' + c.cellPad + ')';}); + .attr('transform', function (d) {return 'translate(' + xPosition(d) + ' ' + c.cellPad + ')';}); } }); } @@ -805,22 +805,26 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } cellTextHolder - .attr('transform', function (d) { - if(d.cellHeightMayIncrease) { - var element = this; - var columnCellElement = element.parentNode; - var box = columnCellElement.getBoundingClientRect(); - var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); - var currentTransform = element.transform.baseVal.consolidate(); - var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - return 'translate(' + c.cellPad + ' ' + yPosition + ')'; - } + .attr('transform', function () { + // this code block is only invoked for items where d.cellHeightMayIncrease is truthy + var element = this; + var columnCellElement = element.parentNode; + var box = columnCellElement.getBoundingClientRect(); + var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); + var currentTransform = element.transform.baseVal.consolidate(); + var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); + return 'translate(' + xPosition(d) + ' ' + yPosition + ')'; }); d.settledY = true; }; } +function xPosition(d) { + //debugger + return c.cellPad; +} + function setCellHeightAndPositionY(columnCell) { columnCell .attr('transform', function(d) { From 7c180e4b51566833190e5229d301367934d64fc6 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 23:49:58 +0200 Subject: [PATCH 275/281] alignment works again for plain mode --- src/traces/table/plot.js | 22 +++++++++++++++++----- test/image/mocks/table_one_cell_plain.json | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 399cb2b4aa4..37d011f575f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -506,7 +506,14 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { } else { d3.select(element.parentNode) // basic cell adjustment - compliance with `cellPad` - .attr('transform', function (d) {return 'translate(' + xPosition(d) + ' ' + c.cellPad + ')';}); + .attr('transform', function (d) {return 'translate(' + xPosition(d) + ' ' + c.cellPad + ')';}) + .attr('text-anchor', function(d) { + return ({ + left: 'start', + center: 'middle', + right: 'end' + })[d.align]; + }); } }); } @@ -813,16 +820,21 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - return 'translate(' + xPosition(d) + ' ' + yPosition + ')'; + //if(box.width !== rectBox.width) debugger; + return 'translate(' + xPosition(d, box.width) + ' ' + yPosition + ')'; }); d.settledY = true; }; } -function xPosition(d) { - //debugger - return c.cellPad; +function xPosition(d, optionalWidth) { + // fixme optimize + return ({ + left: c.cellPad, + center: (d.column.columnWidth - (optionalWidth || 0)) / 2, + right: d.column.columnWidth - (optionalWidth || 0) - c.cellPad + })[d.align]; } function setCellHeightAndPositionY(columnCell) { diff --git a/test/image/mocks/table_one_cell_plain.json b/test/image/mocks/table_one_cell_plain.json index 5ec59bfd397..d7db3b6658b 100644 --- a/test/image/mocks/table_one_cell_plain.json +++ b/test/image/mocks/table_one_cell_plain.json @@ -3,7 +3,7 @@ "width": 1400, "height": 750 + 380 - 150, "title": "Widget parameters and cost", - "margin": {"t": 0|| 80, "r": 60, "b": 54, "l": 60} + "margin": {"t": 0|| 80, "r": 20, "b": 54, "l": 20} }, "data": [{ @@ -11,7 +11,7 @@ "type": "table", "domain": { - "x": [0.05, 0.95], + "x": [0, 1], "y": [0, 1] }, From 64f39d8e658246e72a01ba6c761eef0461bde736 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Mon, 2 Oct 2017 23:53:41 +0200 Subject: [PATCH 276/281] alignment works again for plain mode - optimized --- src/traces/table/plot.js | 13 ++++++------- test/image/mocks/table_one_cell_plain.json | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 37d011f575f..1501733998f 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -820,7 +820,6 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - //if(box.width !== rectBox.width) debugger; return 'translate(' + xPosition(d, box.width) + ' ' + yPosition + ')'; }); @@ -829,12 +828,12 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } function xPosition(d, optionalWidth) { - // fixme optimize - return ({ - left: c.cellPad, - center: (d.column.columnWidth - (optionalWidth || 0)) / 2, - right: d.column.columnWidth - (optionalWidth || 0) - c.cellPad - })[d.align]; + switch(d.align) { + case 'left': return c.cellPad; + case 'right': return d.column.columnWidth - (optionalWidth || 0) - c.cellPad; + case 'center': return (d.column.columnWidth - (optionalWidth || 0)) / 2; + default: return c.cellPad; + } } function setCellHeightAndPositionY(columnCell) { diff --git a/test/image/mocks/table_one_cell_plain.json b/test/image/mocks/table_one_cell_plain.json index d7db3b6658b..c3917f4179f 100644 --- a/test/image/mocks/table_one_cell_plain.json +++ b/test/image/mocks/table_one_cell_plain.json @@ -146,7 +146,7 @@ "height": 40, - "align": ["right"], + "align": [["center", "right"], "left", "center", "right"], "valign": ["bottom"], "line": { From e7d279bf186fa0ca4af6d9501117ff1092693b61 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 3 Oct 2017 00:06:09 +0200 Subject: [PATCH 277/281] alignment works for styled mode --- src/traces/table/plot.js | 2 +- test/image/mocks/table_one_cell_styled.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 1501733998f..5567480c564 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -820,7 +820,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { var rectBox = d3.select(element.parentNode).select('.cellRect').node().getBoundingClientRect(); var currentTransform = element.transform.baseVal.consolidate(); var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - return 'translate(' + xPosition(d, box.width) + ' ' + yPosition + ')'; + return 'translate(' + xPosition(d, d3.select(element.parentNode).select('.cellTextHolder').node().getBoundingClientRect().width) + ' ' + yPosition + ')'; }); d.settledY = true; diff --git a/test/image/mocks/table_one_cell_styled.json b/test/image/mocks/table_one_cell_styled.json index 1de8453191d..e2c95f75a82 100644 --- a/test/image/mocks/table_one_cell_styled.json +++ b/test/image/mocks/table_one_cell_styled.json @@ -143,7 +143,7 @@ "height": 20, - "align": ["right"], + "align": ["center"], "valign": ["bottom"], "line": { From 7f7e377e3482dc1b448c656252fe86768465954e Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 3 Oct 2017 00:09:09 +0200 Subject: [PATCH 278/281] bench for textwrap quickscroll test --- test/image/mocks/table_one_cell_textwrap.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/table_one_cell_textwrap.json b/test/image/mocks/table_one_cell_textwrap.json index a7b1a039942..7c4802ddd0b 100644 --- a/test/image/mocks/table_one_cell_textwrap.json +++ b/test/image/mocks/table_one_cell_textwrap.json @@ -153,7 +153,7 @@ "width": 1 }, - "fille": { + "fill": { "color": [ ["#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1", "#c6dbef", "#9ecae1"] ] From 22a0a9772b18bc3a5c8fff0ef359b929b062e7d9 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 3 Oct 2017 00:19:20 +0200 Subject: [PATCH 279/281] avoid running into unpainted lines --- src/traces/table/plot.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 5567480c564..e409a57b909 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -55,8 +55,12 @@ module.exports = function plot(gd, calcdata) { .style('box-sizing', 'content-box') .on('mousemove', function() {tableControlView.call(renderScrollbarKit);}) .on('mousewheel', function(d) { + if(d.scrollbarState.wheeling) return; + d.scrollbarState.wheeling = true; + d3.event.stopPropagation(); d3.event.preventDefault(); makeDragRow(gd, tableControlView, null, d.scrollY + d3.event.deltaY)(d); + d.scrollbarState.wheeling = false; }) .call(renderScrollbarKit); @@ -779,7 +783,7 @@ function wrapTextMaker(columnBlock, element, tableControlView) { d3.select(element.parentNode.parentNode).call(setCellHeightAndPositionY); }; } -window.monfera = 0 + function updateYPositionMaker(columnBlock, element, tableControlView, d) { return function updateYPosition() { if(d.settledY) return; From 26b61004c42900832da348f61656a01e3bc17f79 Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 3 Oct 2017 00:54:54 +0200 Subject: [PATCH 280/281] lint --- src/traces/table/attributes.js | 1 - src/traces/table/base_plot.js | 1 - src/traces/table/calc.js | 4 +- src/traces/table/defaults.js | 2 +- src/traces/table/plot.js | 61 +++++++++---------- .../mocks/gl2d_parcoords_very_large.json | 2 +- 6 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/traces/table/attributes.js b/src/traces/table/attributes.js index 0dc975c2282..d3539862da2 100644 --- a/src/traces/table/attributes.js +++ b/src/traces/table/attributes.js @@ -9,7 +9,6 @@ 'use strict'; var annAttrs = require('../../components/annotations/attributes'); -var fontAttrs = require('../../plots/font_attributes'); var extendFlat = require('../../lib/extend').extendFlat; module.exports = { diff --git a/src/traces/table/base_plot.js b/src/traces/table/base_plot.js index 901128aa9b7..c68e3de2dbd 100644 --- a/src/traces/table/base_plot.js +++ b/src/traces/table/base_plot.js @@ -8,7 +8,6 @@ 'use strict'; -var d3 = require('d3'); var Plots = require('../../plots/plots'); var tablePlot = require('./plot'); diff --git a/src/traces/table/calc.js b/src/traces/table/calc.js index 0cbce03b5f7..a2fc81bb524 100644 --- a/src/traces/table/calc.js +++ b/src/traces/table/calc.js @@ -80,9 +80,9 @@ module.exports = function calc(gd, trace) { return wrap(calcdata); }; -var xScale = function (d) { +function xScale(d) { return d.calcdata.columns.reduce(function(prev, next) { - return next.xIndex < d.xIndex ? prev + next.columnWidth : prev + return next.xIndex < d.xIndex ? prev + next.columnWidth : prev; }, 0); } diff --git a/src/traces/table/defaults.js b/src/traces/table/defaults.js index 2ae1ee8ae26..78ddd608a44 100644 --- a/src/traces/table/defaults.js +++ b/src/traces/table/defaults.js @@ -21,7 +21,7 @@ function defaultColumnOrder(traceIn, coerce) { oneStepped.push(i); } coerce('columnorder', oneStepped); -}; +} module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { function coerce(attr, dflt) { diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index e409a57b909..953a7af4634 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -65,11 +65,11 @@ module.exports = function plot(gd, calcdata) { .call(renderScrollbarKit); tableControlView - .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}) + .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}); - if(!c.clipView) { - tableControlView.attr('clip-path', function (d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); - } + if(!c.clipView) { + tableControlView.attr('clip-path', function(d) {return 'url(#scrollAreaBottomClip_' + d.key + ')';}); + } var yColumn = tableControlView.selectAll('.yColumn') .data(function(vm) {return vm.columns;}, gup.keyFun); @@ -91,13 +91,13 @@ module.exports = function plot(gd, calcdata) { }) .on('drag', function(d) { var movedColumn = d3.select(this); - var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;} + var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;}; d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); var newOrder = yColumn.data().sort(function(a, b) {return getter(a) - getter(b);}); newOrder.forEach(function(dd, i) { dd.xIndex = i; dd.x = d === dd ? dd.x : dd.xScale(dd); - }) + }); yColumn.filter(function(dd) {return d !== dd;}) .transition() @@ -122,8 +122,6 @@ module.exports = function plot(gd, calcdata) { yColumn.attr('clip-path', function(d) {return 'url(#columnBoundaryClippath_' + d.specIndex + ')';}); } - //yColumn.exit().remove(); - var columnBlock = yColumn.selectAll('.columnBlock') .data(splitToPanels, gup.keyFun); @@ -147,7 +145,7 @@ module.exports = function plot(gd, calcdata) { return d; }) .on('drag', makeDragRow(gd, tableControlView, -1)) - .on('dragend', function(d) { + .on('dragend', function() { // fixme emit plotly notification }) ); @@ -230,7 +228,7 @@ function renderScrollbarKit(tableControlView) { scrollbarKit.enter() .append('g') - .classed('scrollbarKit', true) + .classed('scrollbarKit', true); scrollbarKit .each(function(d) { @@ -286,7 +284,7 @@ function renderScrollbarKit(tableControlView) { return d.scrollbarState.barLength - c.scrollbarWidth / 2; }) .attr('stroke-opacity', function(d) { - return d.columnDragInProgress || !d.scrollbarState.barWiggleRoom ? 0 : 0.4 + return d.columnDragInProgress || !d.scrollbarState.barWiggleRoom ? 0 : 0.4; }); // cancel transition: possible pending (also, delayed) transition @@ -325,7 +323,7 @@ function renderScrollbarKit(tableControlView) { return d; }) .on('drag', makeDragRow(gd, tableControlView)) - .on('dragend', function(d) { + .on('dragend', function() { // fixme emit Plotly event }) ); @@ -442,7 +440,7 @@ function setFont(columnCell) { d.rowNumber = d.key; d.align = gridPick(d.calcdata.cells.align, col, i); d.valign = gridPick(d.calcdata.cells.valign, col, i); - d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i) + d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i); d.font = font; }); } @@ -484,8 +482,8 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { if(d.wrappingNeeded) { var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/ 1) break; + // if(pages.length > 1) break; } return pages; @@ -697,14 +695,14 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { } cellsColumnBlock - .each(function (d, i) { + .each(function(d, i) { // these values will also be needed when a block is translated again due to growing cell height d.page = pages[i]; d.scrollY = scrollY; }); cellsColumnBlock - .attr('transform', function (d) { + .attr('transform', function(d) { var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; return 'translate(0 ' + yTranslate + ')'; }); @@ -718,23 +716,23 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { } function makeDragRow(gd, tableControlView, optionalMultiplier, optionalPosition) { - return function dragRow () { + return function dragRow() { var d = tableControlView.node().__data__; var multiplier = optionalMultiplier || d.scrollbarState.dragMultiplier; d.scrollY = optionalPosition === void(0) ? d.scrollY + multiplier * d3.event.dy : optionalPosition; var cellsColumnBlock = tableControlView.selectAll('.yColumn').selectAll('.columnBlock').filter(cellsBlock); updateBlockYPosition(gd, cellsColumnBlock, tableControlView); - } + }; } function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, prevPages, d, revolverIndex) { var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; if(shouldComponentUpdate) { window.clearTimeout(d.currentRepaint[revolverIndex]); - d.currentRepaint[revolverIndex] = window.setTimeout(function () { + d.currentRepaint[revolverIndex] = window.setTimeout(function() { // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes // some repaints invisible ie. wasteful (DOM work blocks the main thread) - var toRerender = cellsColumnBlock.filter(function (d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); + var toRerender = cellsColumnBlock.filter(function(d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); renderColumnCellTree(gd, tableControlView, toRerender, toRerender); prevPages[revolverIndex] = pages[revolverIndex]; }); @@ -757,7 +755,7 @@ function wrapTextMaker(columnBlock, element, tableControlView) { var currentAddition, currentAdditionLength; var currentRowLength = 0; var rowLengthLimit = d.column.columnWidth - 2 * c.cellPad; - d.value = ""; + d.value = ''; while(rest.length) { currentAddition = rest.shift(); currentAdditionLength = currentAddition.width + separatorLength; @@ -816,7 +814,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { } cellTextHolder - .attr('transform', function () { + .attr('transform', function() { // this code block is only invoked for items where d.cellHeightMayIncrease is truthy var element = this; var columnCellElement = element.parentNode; @@ -843,7 +841,7 @@ function xPosition(d, optionalWidth) { function setCellHeightAndPositionY(columnCell) { columnCell .attr('transform', function(d) { - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity)}, 0); + var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity);}, 0); var l = getBlock(d); var rowAnchor = rowsHeight(l, d.key); var yOffset = rowAnchor + headerHeight; @@ -855,7 +853,7 @@ function setCellHeightAndPositionY(columnCell) { function firstRowAnchor(blocks, page) { var total = 0; - for(var i = page - 1; i >=0 ; i--) { + for(var i = page - 1; i >= 0; i--) { total += allRowsHeight(blocks[i]); } return total; @@ -887,4 +885,3 @@ function allRowsHeight(rowBlock) { function getBlock(d) {return d.rowBlocks[d.page];} function getRow(l, i) {return l.rows[i - l.firstRowIndex];} - diff --git a/test/image/mocks/gl2d_parcoords_very_large.json b/test/image/mocks/gl2d_parcoords_very_large.json index 360c5a59e35..5be3f4bbf7a 100644 --- a/test/image/mocks/gl2d_parcoords_very_large.json +++ b/test/image/mocks/gl2d_parcoords_very_large.json @@ -91,4 +91,4 @@ } ] }] -}; \ No newline at end of file +} From dd1c2214670928f00afb3ab2ea0ff2a68d3c5cad Mon Sep 17 00:00:00 2001 From: Robert Monfera Date: Tue, 3 Oct 2017 01:01:56 +0200 Subject: [PATCH 281/281] propagated gd to where it's needed --- src/traces/table/plot.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 953a7af4634..a98339dbc21 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -53,7 +53,7 @@ module.exports = function plot(gd, calcdata) { .append('g') .classed('tableControlView', true) .style('box-sizing', 'content-box') - .on('mousemove', function() {tableControlView.call(renderScrollbarKit);}) + .on('mousemove', function() {tableControlView.call(renderScrollbarKit, gd);}) .on('mousewheel', function(d) { if(d.scrollbarState.wheeling) return; d.scrollbarState.wheeling = true; @@ -62,7 +62,7 @@ module.exports = function plot(gd, calcdata) { makeDragRow(gd, tableControlView, null, d.scrollY + d3.event.deltaY)(d); d.scrollbarState.wheeling = false; }) - .call(renderScrollbarKit); + .call(renderScrollbarKit, gd); tableControlView .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}); @@ -86,7 +86,7 @@ module.exports = function plot(gd, calcdata) { easeColumn(movedColumn, d, -c.uplift); raiseToTop(this); d.calcdata.columnDragInProgress = true; - renderScrollbarKit(tableControlView); + renderScrollbarKit(tableControlView, gd); return d; }) .on('drag', function(d) { @@ -216,7 +216,7 @@ module.exports = function plot(gd, calcdata) { updateBlockYPosition(null, cellsColumnBlock, tableControlView); }; -function renderScrollbarKit(tableControlView) { +function renderScrollbarKit(tableControlView, gd) { function calcTotalHeight(d) { var blocks = d.rowBlocks; @@ -504,7 +504,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { var renderCallback = d.wrappingNeeded ? wrapTextMaker : updateYPositionMaker; if(d.mayHaveMarkup || d.wrappingNeeded || d.latex) { - svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, d)); + svgUtil.convertToTspans(selection, gd, renderCallback(allColumnBlock, element, tableControlView, gd, d)); } else { d3.select(element.parentNode) // basic cell adjustment - compliance with `cellPad` @@ -711,7 +711,7 @@ function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { if(gd) { conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 0); conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 1); - renderScrollbarKit(tableControlView); + renderScrollbarKit(tableControlView, gd); } } @@ -782,7 +782,7 @@ function wrapTextMaker(columnBlock, element, tableControlView) { }; } -function updateYPositionMaker(columnBlock, element, tableControlView, d) { +function updateYPositionMaker(columnBlock, element, tableControlView, gd, d) { return function updateYPosition() { if(d.settledY) return; var cellTextHolder = d3.select(element.parentNode); @@ -810,7 +810,7 @@ function updateYPositionMaker(columnBlock, element, tableControlView, d) { // if d.column.type === 'header', then the scrollbar has to be pushed downward to the scrollable area // if d.column.type === 'cells', it can still be relevant if total scrolling content height is less than the // scrollable window, as increases to row heights may need scrollbar updates - renderScrollbarKit(tableControlView); + renderScrollbarKit(tableControlView, gd); } cellTextHolder