diff --git a/src/traces/parcats/calc.js b/src/traces/parcats/calc.js index d52bbc4fca7..70b8f8a277f 100644 --- a/src/traces/parcats/calc.js +++ b/src/traces/parcats/calc.js @@ -17,11 +17,6 @@ var filterUnique = require('../../lib/filter_unique.js'); var Drawing = require('../../components/drawing'); var Lib = require('../../lib'); - -function visible(dimension) { return !('visible' in dimension) || dimension.visible; } - -// Exports -// ======= /** * Create a wrapped ParcatsModel object from trace * @@ -31,24 +26,18 @@ function visible(dimension) { return !('visible' in dimension) || dimension.visi * @return {Array.} */ module.exports = function calc(gd, trace) { + var visibleDims = Lib.filterVisible(trace.dimensions); - // Process inputs - // -------------- - if(trace.dimensions.filter(visible).length === 0) { - // No visible dimensions specified. Nothing to compute - return []; - } + if(visibleDims.length === 0) return []; - // Compute unique information - // -------------------------- - // UniqueInfo per dimension - var uniqueInfoDims = trace.dimensions.filter(visible).map(function(dim) { + var uniqueInfoDims = visibleDims.map(function(dim) { var categoryValues; if(dim.categoryorder === 'trace') { // Use order of first occurrence in trace categoryValues = null; } else if(dim.categoryorder === 'array') { - // Use categories specified in `categoryarray` first, then add extra to the end in trace order + // Use categories specified in `categoryarray` first, + // then add extra to the end in trace order categoryValues = dim.categoryarray; } else { // Get all categories up front so we can order them @@ -61,8 +50,6 @@ module.exports = function calc(gd, trace) { return getUniqueInfo(dim.values, categoryValues); }); - // Process counts - // -------------- var counts, count, totalCount; @@ -72,13 +59,9 @@ module.exports = function calc(gd, trace) { counts = [trace.counts]; } - // Validate dimension display order - // -------------------------------- - validateDimensionDisplayInds(trace); + validateDimensionDisplayInds(visibleDims); - // Validate category display order - // ------------------------------- - trace.dimensions.filter(visible).forEach(function(dim, dimInd) { + visibleDims.forEach(function(dim, dimInd) { validateCategoryProperties(dim, uniqueInfoDims[dimInd]); }); @@ -111,7 +94,7 @@ module.exports = function calc(gd, trace) { // Number of values and counts // --------------------------- - var numValues = trace.dimensions.filter(visible)[0].values.length; + var numValues = visibleDims[0].values.length; // Build path info // --------------- @@ -155,12 +138,8 @@ module.exports = function calc(gd, trace) { updatePathModel(pathModels[pathKey], valueInd, count); } - // Build categories info - // --------------------- - - // Array of DimensionModel objects - var dimensionModels = trace.dimensions.filter(visible).map(function(di, i) { - return createDimensionModel(i, di._index, di.displayindex, di.label, totalCount); + var dimensionModels = visibleDims.map(function(di, i) { + return createDimensionModel(i, di._index, di._displayindex, di.label, totalCount); }); @@ -174,8 +153,8 @@ module.exports = function calc(gd, trace) { var cats = dimensionModels[d].categories; if(cats[catInd] === undefined) { - var catValue = trace.dimensions[containerInd].categoryarray[catInd]; - var catLabel = trace.dimensions[containerInd].ticktext[catInd]; + var catValue = trace.dimensions[containerInd]._categoryarray[catInd]; + var catLabel = trace.dimensions[containerInd]._ticktext[catInd]; cats[catInd] = createCategoryModel(d, catInd, catValue, catLabel); } @@ -216,7 +195,6 @@ module.exports = function calc(gd, trace) { */ function createParcatsModel(dimensions, paths, count) { var maxCats = dimensions - .filter(visible) .map(function(d) {return d.categories.length;}) .reduce(function(v1, v2) {return Math.max(v1, v2);}); return {dimensions: dimensions, paths: paths, trace: undefined, maxCats: maxCats, count: count}; @@ -456,43 +434,47 @@ function getUniqueInfo(values, uniqueValues) { /** * Validate the requested display order for the dimensions. - * If the display order is a permutation of 0 through dimensions.length - 1 then leave it alone. Otherwise, repalce - * the display order with the dimension order + * If the display order is a permutation of 0 through dimensions.length - 1, link to _displayindex + * Otherwise, replace the display order with the dimension order * @param {Object} trace */ -function validateDimensionDisplayInds(trace) { - var displayInds = trace.dimensions.filter(visible).map(function(dim) {return dim.displayindex;}); - if(!isRangePermutation(displayInds)) { - trace.dimensions.filter(visible).forEach(function(dim, i) { - dim.displayindex = i; - }); +function validateDimensionDisplayInds(visibleDims) { + var displayInds = visibleDims.map(function(d) { return d.displayindex; }); + var i; + + if(isRangePermutation(displayInds)) { + for(i = 0; i < visibleDims.length; i++) { + visibleDims[i]._displayindex = visibleDims[i].displayindex; + } + } else { + for(i = 0; i < visibleDims.length; i++) { + visibleDims[i]._displayindex = i; + } } } /** - * Validate the requested display order for the dimensions. - * If the display order is a permutation of 0 through dimensions.length - 1 then leave it alone. Otherwise, repalce - * the display order with the dimension order + * Update category properties based on the unique values found for this dimension * @param {Object} dim * @param {UniqueInfo} uniqueInfoDim */ function validateCategoryProperties(dim, uniqueInfoDim) { // Update categoryarray - dim.categoryarray = uniqueInfoDim.uniqueValues; + dim._categoryarray = uniqueInfoDim.uniqueValues; // Handle ticktext if(dim.ticktext === null || dim.ticktext === undefined) { - dim.ticktext = []; + dim._ticktext = []; } else { // Shallow copy to avoid modifying input array - dim.ticktext = dim.ticktext.slice(); + dim._ticktext = dim.ticktext.slice(); } // Extend ticktext with elements from uniqueInfoDim.uniqueValues - for(var i = dim.ticktext.length; i < uniqueInfoDim.uniqueValues.length; i++) { - dim.ticktext.push(uniqueInfoDim.uniqueValues[i]); + for(var i = dim._ticktext.length; i < uniqueInfoDim.uniqueValues.length; i++) { + dim._ticktext.push(uniqueInfoDim.uniqueValues[i]); } } diff --git a/test/image/baselines/parcats_bad-displayindex.png b/test/image/baselines/parcats_bad-displayindex.png new file mode 100644 index 00000000000..1b02d451a15 Binary files /dev/null and b/test/image/baselines/parcats_bad-displayindex.png differ diff --git a/test/image/mocks/parcats_bad-displayindex.json b/test/image/mocks/parcats_bad-displayindex.json new file mode 100644 index 00000000000..f8ab51ab978 --- /dev/null +++ b/test/image/mocks/parcats_bad-displayindex.json @@ -0,0 +1,17 @@ +{ + "data": [ + {"type": "parcats", + "dimensions": [ + {"label": "One", "values": [1, 1, 2, 1, 2, 1, 1, 2, 1], + "displayindex": 1, "categoryarray": [1, 2], "ticktext": ["One", "Two"]}, + {"label": "Two", "values": ["A", "B", "A", "B", "C", "C", "A", "B", "C"], + "displayindex": 2, "categoryarray": ["B", "A", "C"]}, + {"label": "Three", "values": [11, 11, 11, 11, 11, 11, 11, 11, 11], "displayindex": 1}]} + ], + "layout": { + "height": 602, + "width": 592, + "margin": { + "l": 40, "r": 40, "t": 50, "b": 40 + }} +} diff --git a/test/jasmine/assets/mock_lists.js b/test/jasmine/assets/mock_lists.js index c54d91a4e00..2b0a4e8f61f 100644 --- a/test/jasmine/assets/mock_lists.js +++ b/test/jasmine/assets/mock_lists.js @@ -27,6 +27,7 @@ var svgMockList = [ ['range_selector_style', require('@mocks/range_selector_style.json')], ['range_slider_multiple', require('@mocks/range_slider_multiple.json')], ['sankey_energy', require('@mocks/sankey_energy.json')], + ['parcats_bad-displayindex', require('@mocks/parcats_bad-displayindex.json')], ['scattercarpet', require('@mocks/scattercarpet.json')], ['shapes', require('@mocks/shapes.json')], ['splom_iris', require('@mocks/splom_iris.json')], diff --git a/test/jasmine/tests/drawing_test.js b/test/jasmine/tests/drawing_test.js index 414f2239b26..257e074e3eb 100644 --- a/test/jasmine/tests/drawing_test.js +++ b/test/jasmine/tests/drawing_test.js @@ -363,7 +363,7 @@ describe('Drawing', function() { 'width', 'left', 'right' ].forEach(function(dim) { // give larger dimensions some extra tolerance - var tol = Math.max(expected[dim] / 10, 3); + var tol = Math.max(expected[dim] / 10, 3.5); expect(actual[dim]).toBeWithin(expected[dim], tol, dim); }); } diff --git a/test/jasmine/tests/parcats_test.js b/test/jasmine/tests/parcats_test.js index 6fc5070ba53..c4c3fb92873 100644 --- a/test/jasmine/tests/parcats_test.js +++ b/test/jasmine/tests/parcats_test.js @@ -723,7 +723,6 @@ describe('Drag to reordered dimensions', function() { Plotly.newPlot(gd, mock) .then(function() { - console.log(gd.data); restyleCallback = jasmine.createSpy('restyleCallback'); gd.on('plotly_restyle', restyleCallback); @@ -1229,9 +1228,6 @@ describe('Click events', function() { /** @type {ParcatsViewModel} */ var parcatsViewModel = d3.select('g.trace.parcats').datum(); - console.log(gd.data[0]); - console.log(parcatsViewModel.hoverinfoItems); - gd.on('plotly_click', function(data) { clickData = data; }); diff --git a/test/jasmine/tests/pie_test.js b/test/jasmine/tests/pie_test.js index 2880a514f5b..24c85e494e1 100644 --- a/test/jasmine/tests/pie_test.js +++ b/test/jasmine/tests/pie_test.js @@ -198,8 +198,8 @@ describe('Pie traces:', function() { expect(title.size()).toBe(1); var titlePos = getClientPosition('g.titletext'); var pieCenterPos = getClientPosition('g.trace'); - expect(Math.abs(titlePos[0] - pieCenterPos[0])).toBeLessThan(2); - expect(Math.abs(titlePos[1] - pieCenterPos[1])).toBeLessThan(2); + expect(Math.abs(titlePos[0] - pieCenterPos[0])).toBeLessThan(4); + expect(Math.abs(titlePos[1] - pieCenterPos[1])).toBeLessThan(4); }) .catch(failTest) .then(done); @@ -229,15 +229,15 @@ describe('Pie traces:', function() { var pieBox = d3.select('g.trace').node().getBoundingClientRect(); var radius = 0.1 * Math.min(pieBox.width / 2, pieBox.height / 2); var pieCenterPos = getClientPosition('g.trace'); - // unfortunately boundingClientRect is inaccurate and so we allow an error of 2 + // unfortunately boundingClientRect is inaccurate and so we allow an error of 3 expect(_verifyPointInCircle(titleBox.left, titleBox.top, pieCenterPos, radius)) - .toBeLessThan(2); + .toBeLessThan(3); expect(_verifyPointInCircle(titleBox.right, titleBox.top, pieCenterPos, radius)) - .toBeLessThan(2); + .toBeLessThan(3); expect(_verifyPointInCircle(titleBox.left, titleBox.bottom, pieCenterPos, radius)) - .toBeLessThan(2); + .toBeLessThan(3); expect(_verifyPointInCircle(titleBox.right, titleBox.bottom, pieCenterPos, radius)) - .toBeLessThan(2); + .toBeLessThan(3); }) .catch(failTest) .then(done); diff --git a/test/jasmine/tests/sliders_test.js b/test/jasmine/tests/sliders_test.js index ff3851ca24d..5438273dbd4 100644 --- a/test/jasmine/tests/sliders_test.js +++ b/test/jasmine/tests/sliders_test.js @@ -334,13 +334,13 @@ describe('sliders interactions', function() { d3.select(gd).selectAll('.slider-group').each(function(d, i) { var sliderBB = this.getBoundingClientRect(); var gdBB = gd.getBoundingClientRect(); + if(i === 0) { expect(sliderBB.left - gdBB.left) - .toBeWithin(12, 3, 'left: ' + msg); - } - else { + .toBeWithin(12, 5.1, 'left: ' + msg); + } else { expect(gdBB.bottom - sliderBB.bottom) - .toBeWithin(8, 3, 'bottom: ' + msg); + .toBeWithin(8, 5.1, 'bottom: ' + msg); } }); }