From 9caf482f01af4e6b0a954fdc7527490e68ac5ab8 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Tue, 3 Aug 2021 13:02:17 -0400 Subject: [PATCH 01/15] Simply trying to force all strings to be categories Meaning even "40" gets interpreted as the string "40", a category named "40". --- src/plots/cartesian/set_convert.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index 31a274811c8..4590f910c17 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -6,6 +6,7 @@ var Lib = require('../../lib'); var numberFormat = Lib.numberFormat; var isNumeric = require('fast-isnumeric'); + var cleanNumber = Lib.cleanNumber; var ms2DateTime = Lib.ms2DateTime; var dateTime2ms = Lib.dateTime2ms; @@ -178,8 +179,8 @@ module.exports = function setConvert(ax, fullLayout) { if(isNumeric(v)) return +v; } - function getRangePosition(v) { - return isNumeric(v) ? +v : getCategoryIndex(v); + function getRangePositionForCategory(v) { + return (typeof v !== 'string') ? v : getCategoryIndex(v); } // include 2 fractional digits on pixel, for PDF zooming etc @@ -313,12 +314,12 @@ module.exports = function setConvert(ax, fullLayout) { ax.d2r = ax.d2l_noadd = getCategoryPosition; ax.r2c = function(v) { - var index = getRangePosition(v); + var index = getRangePositionForCategory(v); return index !== undefined ? index : ax.fraction2r(0.5); }; ax.l2r = ax.c2r = ensureNumber; - ax.r2l = getRangePosition; + ax.r2l = getRangePositionForCategory; ax.d2p = function(v) { return ax.l2p(ax.r2c(v)); }; ax.p2d = function(px) { return getCategoryName(p2l(px)); }; From 536e6e951afb0c4ba4131d9461d4b54a1eb1ef9b Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Thu, 5 Aug 2021 17:28:07 -0400 Subject: [PATCH 02/15] Added notes for clarification needs in the tests --- src/plots/cartesian/axis_autotype.js | 1 + test/jasmine/tests/axes_test.js | 13 ++++++++++++- test/jasmine/tests/plot_api_test.js | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/plots/cartesian/axis_autotype.js b/src/plots/cartesian/axis_autotype.js index 8186caf7839..09b4c52f2e8 100644 --- a/src/plots/cartesian/axis_autotype.js +++ b/src/plots/cartesian/axis_autotype.js @@ -10,6 +10,7 @@ var isDateTime = Lib.isDateTime; var cleanNumber = Lib.cleanNumber; var round = Math.round; +// Determines a type for an axis based on the contents of array. module.exports = function autoType(array, calendar, opts) { var a = array; diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 0c336d948fa..af8ec9d9229 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -338,7 +338,14 @@ describe('Test axes', function() { }); }); + /* TODO: These tests don't actually test if the numeric strings are + * indeed converted or not... */ describe('autotype disable/enable converting numeric strings', function() { + /* TODO: The test description doesn't totally reflect what it is + * testing: here the test is to determine that setting + * autotypenumbers: 'strict' on the yaxis forces yaxis.type to be + * 'category', that's it. + */ it('should disable converting numeric strings using axis.autotypenumbers', function() { layoutIn = { xaxis: {}, @@ -381,7 +388,11 @@ describe('Test axes', function() { expect(layoutOut.yaxis.type).toBe('category'); }); - it('should autotype date having more dates with & without strict autotypenumbers', function() { + /* TODO: Should not the opposite also be tested? Namely that data + * having fewer dates gets forced to 'category' (that's consitent + * with the previous test). + */ + it('should autotype data having more dates with & without strict autotypenumbers', function() { layoutIn = { xaxis: {}, yaxis: { autotypenumbers: 'strict' } diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 4b79a98133a..d9729d1c1ac 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -269,6 +269,8 @@ describe('Test plot api', function() { .then(done, done.fail); }); + // TODO: Make this test work for the case where categories are numeric + // strings it('annotations, shapes and images linked to category axes should update properly on zoom/pan', function(done) { var jsLogo = 'https://images.plot.ly/language-icons/api-home/js-logo.png'; From 5fc0adecbcc55ef39bedd77ea8e924fd73532e58 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Fri, 6 Aug 2021 09:29:01 -0400 Subject: [PATCH 03/15] possibly break on call to getRangePositionForCategory --- src/plots/cartesian/set_convert.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index 4590f910c17..7e9465f0cdd 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -180,6 +180,7 @@ module.exports = function setConvert(ax, fullLayout) { } function getRangePositionForCategory(v) { + //debugger; return (typeof v !== 'string') ? v : getCategoryIndex(v); } From 69ea57c7ae86cde8996400001e68332a4eec8de3 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Mon, 9 Aug 2021 16:02:32 -0400 Subject: [PATCH 04/15] Numeric categories in SVG paths intepreted as indices This is because SVG paths are always strings, so there is no practical way of indicating a number was meant and not a numeric string when specifying SVG paths (sure they could be wrapped in escaped quotes but not today). So when a number is encountered in an SVG (i.e., it is a numeric string), then it is converted to a number so that it is interpreted as an index into layout.categoriesarray. --- src/components/shapes/draw.js | 4 ++++ src/components/shapes/helpers.js | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 06050ca72c5..4c311bb5a72 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -613,6 +613,10 @@ function getPathString(gd, options) { if(type === 'path') { if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); + // the SVG path is always a string, so for categories numeric strings + // are always converted to numbers when seen in a SVG path + if(xa && xa.type === 'category') x2p = helpers.castNumericStringsToNumbers(x2p); + if(ya && ya.type === 'category') y2p = helpers.castNumericStringsToNumbers(y2p); return convertPath(options, x2p, y2p); } diff --git a/src/components/shapes/helpers.js b/src/components/shapes/helpers.js index ca03b9aa935..76ef81ae70c 100644 --- a/src/components/shapes/helpers.js +++ b/src/components/shapes/helpers.js @@ -4,6 +4,8 @@ var constants = require('./constants'); var Lib = require('../../lib'); +var isNumeric = require('fast-isnumeric'); + // special position conversion functions... category axis positions can't be // specified by their data values, because they don't make a continuous mapping. // so these have to be specified in terms of the category serial numbers, @@ -32,6 +34,12 @@ exports.encodeDate = function(convertToDate) { return function(v) { return convertToDate(v).replace(' ', '_'); }; }; +exports.castNumericStringsToNumbers = function(convertToPx) { + return function(v) { + return convertToPx(isNumeric(v) ? Number(v) : v); + }; +}; + exports.extractPathCoords = function(path, paramsToUse) { var extractedCoordinates = []; From bf90246f8a13612d4c92faa44e85d694c6dfba34 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Mon, 9 Aug 2021 17:19:25 -0400 Subject: [PATCH 05/15] Original shapes test now passing --- src/components/shapes/calc_autorange.js | 1 + src/components/shapes/draw.js | 74 ++++++++++++------------- src/components/shapes/helpers.js | 1 + 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/components/shapes/calc_autorange.js b/src/components/shapes/calc_autorange.js index 7892bceb12f..69d95cce10f 100644 --- a/src/components/shapes/calc_autorange.js +++ b/src/components/shapes/calc_autorange.js @@ -93,6 +93,7 @@ function shapeBounds(ax, v0, v1, path, paramsToUse) { var val; if(ax.type === 'date') convertVal = helpers.decodeDate(convertVal); + if(ax.type === 'category') convertVal = helpers.castNumericStringsToNumbers(convertVal); for(i = 0; i < segments.length; i++) { segment = segments[i]; diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 4c311bb5a72..ef1fa8c744a 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -383,27 +383,44 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe removeVisualCues(shapeLayer); } - function moveShape(dx, dy) { - if(shapeOptions.type === 'path') { - var noOp = function(coord) { return coord; }; - var moveX = noOp; - var moveY = noOp; + // Compute moveX or moveY, ax is xa or ya, p2xy is p2x or p2y, xy2p is x2p + // or y2p, dxy is dx or dy + function computeMove(ax, p2xy, xy2p, dxy) { + var move = function(xy) { return p2xy(xy2p(xy) + dxy); }; + if(ax && ax.type === 'date') { + move = helpers.encodeDate(move); + } + if(ax && ax.type === 'category') { + move = function(xy) { + return p2xy(helpers.castNumericStringsToNumbers(xy2p)(xy) + dxy); + }; + } + return move; + } - if(xPixelSized) { - modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); - } else { - moveX = function moveX(x) { return p2x(x2p(x) + dx); }; - if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); - } + function doPathMoveOrResize(dx, dy) { + var noOp = function(coord) { return coord; }; + var moveX = noOp; + var moveY = noOp; - if(yPixelSized) { - modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); - } else { - moveY = function moveY(y) { return p2y(y2p(y) + dy); }; - if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); - } + if(xPixelSized) { + modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); + } else { + moveX = computeMove(xa, p2x, x2p, dx); + } + + if(yPixelSized) { + modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); + } else { + moveY = computeMove(ya, p2y, y2p, dy); + } + + modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); + } - modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); + function moveShape(dx, dy) { + if(shapeOptions.type === 'path') { + doPathMoveOrResize(dx, dy); } else { if(xPixelSized) { modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); @@ -426,26 +443,7 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe function resizeShape(dx, dy) { if(isPath) { - // TODO: implement path resize, don't forget to update dragMode code - var noOp = function(coord) { return coord; }; - var moveX = noOp; - var moveY = noOp; - - if(xPixelSized) { - modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); - } else { - moveX = function moveX(x) { return p2x(x2p(x) + dx); }; - if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); - } - - if(yPixelSized) { - modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); - } else { - moveY = function moveY(y) { return p2y(y2p(y) + dy); }; - if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); - } - - modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); + doPathMoveOrResize(dx, dy); } else if(isLine) { if(dragMode === 'resize-over-start-point') { var newX0 = x0 + dx; diff --git a/src/components/shapes/helpers.js b/src/components/shapes/helpers.js index 76ef81ae70c..02a3dd1f531 100644 --- a/src/components/shapes/helpers.js +++ b/src/components/shapes/helpers.js @@ -74,6 +74,7 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType) { }; if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); + if(axis.type === 'category') dataToPixel = exports.castNumericStringsToNumbers(dataToPixel); } } else if(isVertical) { dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; From b60fe186965b9bdffa6405e6243a6ab677aea07d Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Tue, 10 Aug 2021 08:45:03 -0400 Subject: [PATCH 06/15] linting --- src/plots/cartesian/set_convert.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index 7e9465f0cdd..4590f910c17 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -180,7 +180,6 @@ module.exports = function setConvert(ax, fullLayout) { } function getRangePositionForCategory(v) { - //debugger; return (typeof v !== 'string') ? v : getCategoryIndex(v); } From 89cbf1188c091dce26b669e03c2b9e72f2074339 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Tue, 10 Aug 2021 11:59:14 -0400 Subject: [PATCH 07/15] we cannot cast numeric strings to numbers in getDataToPixel This made the dragging "jump" when categories were named numeric strings as the strings were all of a sudden interpreted as indices. Lets see if we can't make the pesky shapes test pass some other way. --- src/components/shapes/helpers.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/shapes/helpers.js b/src/components/shapes/helpers.js index 02a3dd1f531..76ef81ae70c 100644 --- a/src/components/shapes/helpers.js +++ b/src/components/shapes/helpers.js @@ -74,7 +74,6 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType) { }; if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); - if(axis.type === 'category') dataToPixel = exports.castNumericStringsToNumbers(dataToPixel); } } else if(isVertical) { dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; From b3896a2a3156e54328abc5989be8e69ad11477bc Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Tue, 10 Aug 2021 16:36:51 -0400 Subject: [PATCH 08/15] Simplification of dataToPixel code Unfortunately the drag bug is back... --- src/components/shapes/draw.js | 40 ++++++++------------------------ src/components/shapes/helpers.js | 19 ++++++++++++--- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index ef1fa8c744a..7b5a4799f10 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -206,8 +206,8 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe var xRefType = Axes.getRefType(shapeOptions.xref); var ya = Axes.getFromId(gd, shapeOptions.yref); var yRefType = Axes.getRefType(shapeOptions.yref); - var x2p = helpers.getDataToPixel(gd, xa, false, xRefType); - var y2p = helpers.getDataToPixel(gd, ya, true, yRefType); + var x2p = helpers.getDataToPixel(gd, xa, false, xRefType, helpers.keyIfDefined(xa,'type')); + var y2p = helpers.getDataToPixel(gd, ya, true, yRefType, helpers.keyIfDefined(ya,'type')); var p2x = helpers.getPixelToData(gd, xa, false, xRefType); var p2y = helpers.getPixelToData(gd, ya, true, yRefType); @@ -392,7 +392,7 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe } if(ax && ax.type === 'category') { move = function(xy) { - return p2xy(helpers.castNumericStringsToNumbers(xy2p)(xy) + dxy); + return p2xy(xy2p(xy) + dxy); }; } return move; @@ -585,36 +585,16 @@ function getPathString(gd, options) { var gs = gd._fullLayout._size; var x2r, x2p, y2r, y2p; var x0, x1, y0, y1; + var x2pDecoSelect, y2pDecoSelect; - if(xa) { - if(xRefType === 'domain') { - x2p = function(v) { return xa._offset + xa._length * v; }; - } else { - x2r = helpers.shapePositionToRange(xa); - x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); }; - } - } else { - x2p = function(v) { return gs.l + gs.w * v; }; - } - - if(ya) { - if(yRefType === 'domain') { - y2p = function(v) { return ya._offset + ya._length * (1 - v); }; - } else { - y2r = helpers.shapePositionToRange(ya); - y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); }; - } - } else { - y2p = function(v) { return gs.t + gs.h * (1 - v); }; + if(type === 'path') { + x2pDecoSelect = helpers.keyIfDefined(xa,'type'); + y2pDecoSelect = helpers.keyIfDefined(ya,'type'); } + x2p = helpers.getDataToPixel(gd,xa,false,xRefType,x2pDecoSelect); + y2p = helpers.getDataToPixel(gd,ya,true,yRefType,y2pDecoSelect); - if(type === 'path') { - if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); - if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); - // the SVG path is always a string, so for categories numeric strings - // are always converted to numbers when seen in a SVG path - if(xa && xa.type === 'category') x2p = helpers.castNumericStringsToNumbers(x2p); - if(ya && ya.type === 'category') y2p = helpers.castNumericStringsToNumbers(y2p); + if (type === 'path') { return convertPath(options, x2p, y2p); } diff --git a/src/components/shapes/helpers.js b/src/components/shapes/helpers.js index 76ef81ae70c..7e9121f8210 100644 --- a/src/components/shapes/helpers.js +++ b/src/components/shapes/helpers.js @@ -57,9 +57,18 @@ exports.extractPathCoords = function(path, paramsToUse) { return extractedCoordinates; }; -exports.getDataToPixel = function(gd, axis, isVertical, refType) { +exports.getDataToPixel = function(gd, axis, isVertical, refType, d2pDecoSelect) { var gs = gd._fullLayout._size; var dataToPixel; + var d2pDecorator; + var d2pDecos = { + date: exports.decodeDate, + category: exports.castNumericStringsToNumbers + }; + d2pDecorator = d2pDecos[d2pDecoSelect]; + if (d2pDecorator === undefined) { + d2pDecorator = function (f) { return f; } + } if(axis) { if(refType === 'domain') { @@ -73,7 +82,6 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType) { return axis._offset + axis.r2p(d2r(v, true)); }; - if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); } } else if(isVertical) { dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; @@ -81,7 +89,7 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType) { dataToPixel = function(v) { return gs.l + gs.w * v; }; } - return dataToPixel; + return d2pDecorator(dataToPixel); }; exports.getPixelToData = function(gd, axis, isVertical, opt) { @@ -153,3 +161,8 @@ exports.makeOptionsAndPlotinfo = function(gd, index) { plotinfo: plotinfo }; }; + +exports.keyIfDefined = function (o,k) { + if (o !== undefined) { return o[k]; } + return undefined; +} From 8ac107adf701ddb0e21a3be5b73382a9c3ebafe4 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Wed, 11 Aug 2021 13:27:38 -0400 Subject: [PATCH 09/15] have to make special case for category axis in shapes test This keeps the tests passing and the correct behaviour when categories are numeric strings. --- src/components/shapes/draw.js | 40 +++++++++++++++++++++++-------- src/components/shapes/helpers.js | 19 +++------------ test/jasmine/tests/shapes_test.js | 4 ++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 7b5a4799f10..ef1fa8c744a 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -206,8 +206,8 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe var xRefType = Axes.getRefType(shapeOptions.xref); var ya = Axes.getFromId(gd, shapeOptions.yref); var yRefType = Axes.getRefType(shapeOptions.yref); - var x2p = helpers.getDataToPixel(gd, xa, false, xRefType, helpers.keyIfDefined(xa,'type')); - var y2p = helpers.getDataToPixel(gd, ya, true, yRefType, helpers.keyIfDefined(ya,'type')); + var x2p = helpers.getDataToPixel(gd, xa, false, xRefType); + var y2p = helpers.getDataToPixel(gd, ya, true, yRefType); var p2x = helpers.getPixelToData(gd, xa, false, xRefType); var p2y = helpers.getPixelToData(gd, ya, true, yRefType); @@ -392,7 +392,7 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe } if(ax && ax.type === 'category') { move = function(xy) { - return p2xy(xy2p(xy) + dxy); + return p2xy(helpers.castNumericStringsToNumbers(xy2p)(xy) + dxy); }; } return move; @@ -585,16 +585,36 @@ function getPathString(gd, options) { var gs = gd._fullLayout._size; var x2r, x2p, y2r, y2p; var x0, x1, y0, y1; - var x2pDecoSelect, y2pDecoSelect; - if(type === 'path') { - x2pDecoSelect = helpers.keyIfDefined(xa,'type'); - y2pDecoSelect = helpers.keyIfDefined(ya,'type'); + if(xa) { + if(xRefType === 'domain') { + x2p = function(v) { return xa._offset + xa._length * v; }; + } else { + x2r = helpers.shapePositionToRange(xa); + x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); }; + } + } else { + x2p = function(v) { return gs.l + gs.w * v; }; + } + + if(ya) { + if(yRefType === 'domain') { + y2p = function(v) { return ya._offset + ya._length * (1 - v); }; + } else { + y2r = helpers.shapePositionToRange(ya); + y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); }; + } + } else { + y2p = function(v) { return gs.t + gs.h * (1 - v); }; } - x2p = helpers.getDataToPixel(gd,xa,false,xRefType,x2pDecoSelect); - y2p = helpers.getDataToPixel(gd,ya,true,yRefType,y2pDecoSelect); - if (type === 'path') { + if(type === 'path') { + if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); + if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); + // the SVG path is always a string, so for categories numeric strings + // are always converted to numbers when seen in a SVG path + if(xa && xa.type === 'category') x2p = helpers.castNumericStringsToNumbers(x2p); + if(ya && ya.type === 'category') y2p = helpers.castNumericStringsToNumbers(y2p); return convertPath(options, x2p, y2p); } diff --git a/src/components/shapes/helpers.js b/src/components/shapes/helpers.js index 7e9121f8210..76ef81ae70c 100644 --- a/src/components/shapes/helpers.js +++ b/src/components/shapes/helpers.js @@ -57,18 +57,9 @@ exports.extractPathCoords = function(path, paramsToUse) { return extractedCoordinates; }; -exports.getDataToPixel = function(gd, axis, isVertical, refType, d2pDecoSelect) { +exports.getDataToPixel = function(gd, axis, isVertical, refType) { var gs = gd._fullLayout._size; var dataToPixel; - var d2pDecorator; - var d2pDecos = { - date: exports.decodeDate, - category: exports.castNumericStringsToNumbers - }; - d2pDecorator = d2pDecos[d2pDecoSelect]; - if (d2pDecorator === undefined) { - d2pDecorator = function (f) { return f; } - } if(axis) { if(refType === 'domain') { @@ -82,6 +73,7 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType, d2pDecoSelect) return axis._offset + axis.r2p(d2r(v, true)); }; + if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); } } else if(isVertical) { dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; @@ -89,7 +81,7 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType, d2pDecoSelect) dataToPixel = function(v) { return gs.l + gs.w * v; }; } - return d2pDecorator(dataToPixel); + return dataToPixel; }; exports.getPixelToData = function(gd, axis, isVertical, opt) { @@ -161,8 +153,3 @@ exports.makeOptionsAndPlotinfo = function(gd, index) { plotinfo: plotinfo }; }; - -exports.keyIfDefined = function (o,k) { - if (o !== undefined) { return o[k]; } - return undefined; -} diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index ed72199334d..e21dbbcba83 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -1516,6 +1516,10 @@ describe('Test shapes', function() { var ya = Axes.getFromId(gd, layoutShape.yref); var x2p = helpers.getDataToPixel(gd, xa); var y2p = helpers.getDataToPixel(gd, ya, true); + // This is required to match what src/components/shapes/draw.js does for + // category axes, so the test is done correctly. + if (xa && xa.type == 'category') { x2p = helpers.castNumericStringsToNumbers(x2p); } + if (ya && ya.type == 'category') { y2p = helpers.castNumericStringsToNumbers(y2p); } var initialPath = layoutShape.path; var initialCoordinates = getPathCoordinates(initialPath, x2p, y2p); From 536e51365a186287340b1776b3312771ac5b8211 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Wed, 11 Aug 2021 17:54:01 -0400 Subject: [PATCH 10/15] numeric-string-categories mock, shapes_test linting --- .../mocks/numeric-string-categories.json | 72 +++++++++++++++++++ test/jasmine/tests/shapes_test.js | 4 +- 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 test/image/mocks/numeric-string-categories.json diff --git a/test/image/mocks/numeric-string-categories.json b/test/image/mocks/numeric-string-categories.json new file mode 100644 index 00000000000..5401b4a20fe --- /dev/null +++ b/test/image/mocks/numeric-string-categories.json @@ -0,0 +1,72 @@ +{ +"data":[{ + "x": ["3", "1", "5", "2", "4", "6"], + "y": ["6","7","8","2","3","4"] + }], +"layout":{ + "xaxis": { + "type": "category", + "categoryarray": ["1", "2", "3", "4", "5", "6"] + }, + "yaxis": { + "type": "category" + }, + "shapes": [ + { + "type": "rect", + "x0": "2", + "x1": "4", + "y0": 3.5, + "y1": 4.5, + "line": {"color": "blue"} + }, + { + "type": "rect", + "x0": 0.5, + "x1": 1.5, + "y0": "3", + "y1": "4", + "line": {"color": "red"} + }, + { + "type": "rect", + "x0": 2, + "x1": 4, + "y0": "0", + "y1": "4", + "line": {"color": "green"} + }, + { + "type": "rect", + "x0": "4", + "x1": "7", + "y0": 3, + "y1": 4, + "line": {"color": "yellow"} + }, + { + "type": "path", + "path": "M0,5.5L3,4.5L1,3Z", + "line": {"color": "orange"} + }, + { + "type": "line", + "x0": 0.5, + "x1": 0.5, + "y0": 0, + "y1": 1, + "xref": "x domain", + "yref": "y domain" + }, + { + "type": "line", + "y0": 0.5, + "y1": 0.5, + "x0": 0, + "x1": 1, + "xref": "x domain", + "yref": "y domain" + } + ] + } +} diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index e21dbbcba83..8db397f972d 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -1518,8 +1518,8 @@ describe('Test shapes', function() { var y2p = helpers.getDataToPixel(gd, ya, true); // This is required to match what src/components/shapes/draw.js does for // category axes, so the test is done correctly. - if (xa && xa.type == 'category') { x2p = helpers.castNumericStringsToNumbers(x2p); } - if (ya && ya.type == 'category') { y2p = helpers.castNumericStringsToNumbers(y2p); } + if(xa && xa.type === 'category') { x2p = helpers.castNumericStringsToNumbers(x2p); } + if(ya && ya.type === 'category') { y2p = helpers.castNumericStringsToNumbers(y2p); } var initialPath = layoutShape.path; var initialCoordinates = getPathCoordinates(initialPath, x2p, y2p); From 0b48de5d91712c99c6373ed8b9d14d2559bde750 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Thu, 12 Aug 2021 09:48:58 -0400 Subject: [PATCH 11/15] Added numeric-string-categories baseline image --- .../baselines/numeric-string-categories.png | Bin 0 -> 35395 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/image/baselines/numeric-string-categories.png diff --git a/test/image/baselines/numeric-string-categories.png b/test/image/baselines/numeric-string-categories.png new file mode 100644 index 0000000000000000000000000000000000000000..3214dcea3438706e4e0773d79b63cc02bec4a606 GIT binary patch literal 35395 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

m2u(xCN>X z)C%JnEoMl>1)EnXS3>B3!ZytEp9a#U9}gqe)Oe@<;KJmLbT*TBdXHM><(KfTx8lS-_VjiFnN2KD*@XHk5b8gTvRG|aJe3jNTIzB}DK%KqCIU3pumS_E5L&uON&i;|jUh;X)@sF05x z|Lh}(2*+NY*8<9gu9ppYL7=Fut?eg=3UtuSj5UxA#?m+s1jQ<+PEp9A?ZJgj#F7gL zb^g)_Yfp;-V{3Be$WS9KUZCDO@EN*M=9|J)gl#eq*QZM;UL;JWUx81NqV#8YdHXO7 zEuh95b7R{#8LvITlrynLZ}%gPb|MBoKH?Rtn&l}iFQ1stEoeZykA_7>oua5gKLB4F zoE!6=9wPi|#2(bSN94tT;;n3<=8ytVcdy6&Vt*`+-F6|YjUu-7{8SVr2=>$q_wT%9 zh-VV<_!{vL`YEJetnF-bV{m^*fJs&TZ%Kwr4Qlid3jG2QnUA>iXx}NmAM$PQaSD#D zcDEgRZ+WDW(X$%F>kB6hg>MRhYxPQ05SX*EFnIslf-2>aY-2?N^*r^#!+Y&pVcDX%Y9>~ z)jv$2YdPS+MIU+3k$Z2AsC4kxV`9mkVYjxodBw#$ojGHu_%fn&7eQ(Z<3MvrgH-J* z6>qS+x%nq)v}u(~_P3In8uYc}o7((1>bHB5r_ZwxuA#OeaQUt0`~-W}Rz6b`6Zg`J zrta}iM9=Qmv>+;NNP~@Vg%y=doy!hiWg5M@dgW}j3~Qk;w(5rszIQZU{4S22kBV}J zTsa!(=wmeE^qERkLus~hr54APb%Aq#jHJu~B-yii zrX|w1M$P@~Tm{-H>U5at+@s2Nm^+`obyZXRG9#b0J1G-1ORFg)iUKhPF6! z^R+R?PT#wUO=(@1Sj8OqTAQ3)c|N$i(-*Vw`ZH^z*-3hgG}6sN5agfS;Oo?Bd5O;u z{#tC++J!;|CqQeNQw}$>irkirn99Ex0bUA%x>69-DfW4S2oGP-o;ZgT*7GV&6BjAv zso>6*>+P1AR?qXcEib%)dO4)h5OKMl^YP6$3FnvGY6=TZ6!dd8&b6K`a#WuyT^hXl zGpl?R@Q$*p-i_hxAGa}HRD%qI9zdcCrS{wT{D(?B#{*2nJGI<-3x=MSG2MvgLg*PS zs(Go|wf78u(}zPS!?g~JoGsiu@7z-oDCMaPZFRnxIJvK+&_ABEOy#hGM*9Ejp8Wc%%`g)SPCC-{+U5HC%^Z zaxqGI^kfLh%@BwgX|{TxIt&P^;Jf@k9o;fvRli>5slJA>eKP?5+rujgvSc zTU%D)vM59Q8B|MMTuRDfBt21cT8y`my4*QETFUJ9z^UPRPeDXg6G#jCg`CuL<2%r` zHsOP*8h(WHDPe))nd|q`vPr-NH2%ITT5j$90J1poJZDHe=W|i9P9?{nyW)fPfT@p$ z|0@OHlmr^Z%B5KvNOOD)HS*du;mc*I`o|-Ogc2DUcH?PdsM|IIOzvlS-LlIXvcNMr ze3bJKCilaiSeYpG(*3alX`KL`lTuj2vVZi&~$xQfW%)hjNFfAY??ChGtNs=f zf_mGc6^_%FdZ_(9N>laWMD1wMTI-Dq4@kai6Ye;f#d>%^mTS*JOB+ z#s|$hUV1AmKHgvq|)xr7)-3o}zu{SUOQi z>2t&z!>KpfB&ow+l-*Q3cRwnD)XU#Jibn-iAgbC+a=PvJ@Iy`)wp0RLU}xEmyt89n z6w6V%t>ddFe7R&@vp7J{o;)v|TYo0qT=A}av4rHJZjc-sNL{(2dipT|Ikat7_FE)! zA;h6jfehbbBnQ-Z8brPjJ*f-htt{K1oOpZlfJ;C35{yhqQ~U~!Kh7xIkxQUVZ|Re4 z20O4J=Sy{0cu1!UXWrNH+(oMxfFLk~~2oogIsPbalN9~7gn;%pC@(;Ffluz(Vz_I%f>!F<%62)xLgfL(Yv7-*^syAyV zZ-s%VqC)B)BjQPBKi#GxJu04$= z2%5G$su@)5@r>Jt>0GqM4lS3pfsg-xHi-A#FTwACS7 zp1-Cs)>wUj_~Lbp3{*wlh|$xCPc1#ZW0{kEy0`npjW6$A#M5F`O8svyJ;`h>o%a{C z(zm5B)i=0iM_~|X%SSG1by`qV)Q)lDcyZ*{qDkrSrGX;JE8C*JZujckS8&U6+j|H3 z^xvXZlGkfSD+d%f{kCz|Y!L~AC2lK`wDFA(YU1jPuTRaac)!(4$jNg)jHiWsS8F}X zg|s(xgrmZ1Lfc3SD4r9ar-2a7k`}PLppz_|TfDeGY>(X>d^G!dQNgWyp*v@4p5p$x z`qD(KCsbH`wB6G6$YUALUlli?JEOKmjTDhgbMEwzMVhl<=Ina5ofzi|;G?Frb& zU61)Zyw_rUec_-vKU+?Af*t8(Zu_u>m2ueO=DIGT+e*=y{ZMpD$QyH zFJGBKOpyZY9nBed1r7J1ulzC60`&URf6On5(C5CaXj$^Wd?7*tnX+u$qWYuM*{x(rz#QmD|zN2c*IFJc;q%$Ar0FG5U^<;ztV)!VpK z?8y}A_~@aH+mN2%a~qtTDJ7(RF$~2Y^6HJ9Uy7IRO$=OK68ct0?a7T$Y_6<~2oM-? zqGUNSPNk8*fuq56GaIR1g^A9^y<{C1C4_`j%s(Z(9>EdQ-`{_V_v_?V>iL+V@sYKF z#SW68N;wIM^WV>u(Rt|@w+wGyRk<{r(Kk(Uw%UMCZOQvS4P^K`@p##E1a@fkI&5j6 zy6FYB>a8se(fGwD$zvxAp4%_;6(KT6_Ey5fJ4DN>tZ&CLC)TbjYQ&ajoH>(~RPhm* ztE2#IIO9XGv;2NtiStYl(|d0hY|Yw5gf zpX4uFH^5taYYsb9j9MfuFs1s{?$^&CsvJ=9Zt`8zBvq0~6GJ8Km=B9uE1qxfB^cit zj*t4<-W+8FM=kG)y^22x<-Rt4D2HSf8{K^eX0&K}UlnG0qV`I(h_Q8NA7f4m%y z1`=Z=NABM6;NHPp&leYmJdRWuRG*2NPgR$7c-xZQS?cVJ&-UBiOf4_4j6C$qqr8am zHSkHJ)M6VcbO5gOJOUeZy!=_=phL3}V_C~WK-%T(zU7B*LdfK&kscZ48L9l})IJ@D za?RmL%tUTlQTemGuU2TTAj-?G|28RLx4#@oR;rEcTRgb%7i|N(<~E~+h#_~aEp|C> zy6CK#L^XSj47a_p6AU98$z@^Pu{j|#L?WL=NDCZp{`)>~?-Iz;X-?)%!z`0v9^8xH zEG^iKc;;rOo3q*Rs7$KgGiiu9E5vo4n^L=5&uqytO1Xs=>;z6?I4V{FY2U~>US_$% zBZ*w_f2T+ZM{&Bu^rMM*G4f?+i+Anqw>g*@Vlb8Y9hpOSWjNE*(;PKA%*vGC%)d19 zixKp>fHc1HS&xSckE<0fRTv0H{NUC+g`9%GNWBNRZ_Xd}6cZC*FEP~SX{66N8F z5nZm2xB)be*Iep28G@w>`M#JvAFeQ?8r^wZr7rAiUa*T@Ror=&kVP6ZdeB*l#=5(=yfIim>M{8E_YGnho(Es@}JS1Y13X(8tW&E26KJ(+cw zNzCvxyHIwXb5Hi>b#KoLNY+=031G`hu?46q!UCcmKjuU(1X;cmB!$x0tyYqZhv|xX zx1SM1dU<>6L6%tM9ljIENmM{#j@fxRAF%0{+_Bee_GpM>My8j9va@rrUwK>VNujSw zbvpxptjRwSpP#pPhpw6FUGCN)mQ3AK>yT5R(p5T3j&E;U z9RVOQhZ|82An0$91|@u6Q&Z!-kXO-h`r`TX+zFQ)qF5b2)~iq*`|2c$2;ilQkNe^x z=ir$#1WrZcbW_up#K*llibO9MMqf1}ZOzLDxPBwM&y?21{doQbLO5zm{U?Ou?I(kG30_RVIi%3n0iC6lFV2L= z5aN;1DTAi;n>5vZmY>~TcPX)NLX>^rk?kE98+fHy%+OpCwROwVVBV%9{~h9+U^#ez zXZUqF3aFohoFnJ;cB$3~zx~M(J^%4>3r<=M*1i3F#oaF5LpLKDxo6zNPYtq7(eY6k zd7H(>HTA}3)rcC!*a}qZ#7tE;|0ne2V^!hRnfz#j@6TgD_4dA+6H)GyA|u5QSOPu+;XA2)Vv?6W|?XtBWWKz zd`KyL;?Z~Rx5$i9m-+dqT_O`VjDSvCje}VtCqa_CfkDim)PZzK$UVm)i|_Wj^y#{t zsb=mQUcO370nNwl?CrJJ#9pP7LL+0?SXtMVx4lMj$)yz)OdfGKi@3w>=whgoi|SZK z{=+x`n$G7|;1Z_qoOY`m2M2oipk~8-VPyu(0=F`0?{=FT!(uNCtl6jsi28wltb%|1 zSU(Jpko?|kTCvBvb>(`8Oelgk(ZVbIMT=aWmx>#^{LF#I>H*YLY{jotLVPgxpm8eO zAsC?`zI=rT;J(KZWV^b?)~ed1Hed77mP>0;Nq3#zG`T9lI8{S?pDAg9a8&&S7oz@S zWfjG^t4g;Y8yuxjA`Lh@<4r1tL{=!`=JLnMlRbG&YgtCNoDey}rHEl%_c277?#U@v zKcdy&r6`rk}`u?L%TRi1l!Z&o`sIjM=nj!ykPVr0*D~#B^)w{eRIgFc{Gwfy`Ly>BW$hl?wK?sye#pxw5*dzQGf%M$>DXb8(}X(ho7q;v~AKWtSvxb&r>c5+dze zflr(StnCk<9i%zlo^sfUU0H$XG-6(i8W44qu{_4#Rr98_+zY`_s=2i zv7dllyJ-Jy5Pf9A(YK9(2^%lmW8;)L#s`DB8L6t6qH;-rPo~<+vAI-XMok zYO)|LjkWH_UZ7V3bql0W*h2~xRTu^B^KHOxR`WX(OG;=kgVBTE++_voh7RN&IalGl zFn2}geEd+Zt;V-YJ-i6TUr~&g<(>Iyjel@h-jiT9MUDKKQ-1Djv7I zBKVGpth&J~l%Md8gkxg~#EC0-5a$K2y%hRl3e#OUTuy}Gs&oCSa3E@ns>u7c3^jTZ zS9bAuJ?)$vDK!0~u4d4G>^`+9Y)3lif^cm*#+$0BOy9gmXQ& zco5}Q{|4$z^i=mm=*Q)5Z5!%(_r#5E@JahHi+SbEsx>zxJ67H^jWa3Eyrut4R1A*t z-*W-11W)Gvv2h!&F<`u3c{Y7LT4HN*@W~v0Yb9cN}`-qowJg(_CfJJMqtfuG|QVNKr8{ zq%m7oq3T~A&fycw18}@J36)++rhuH zH+ClrOcZS_J;AsrnOUAc_P7j?}pjk0pDSSMX?c9EPi(TZS4~1-kb>D#zi1N{qcfUx)edKK3L+ zF3@MKn3EPj@9O}Tnl!P&Ksmk{DC`yhj%!T%M>1~2*GJtqNrD=twlTGJK5K1T@|TlQ z2TOMOt$7DNjYB$jdvDx2cMfSxbMrkB4d%uwBV{<2QJH?804}AESSS8_j7UXnT3zRd z$&gV4UX7xI)TS&!>snx#T=%%1jey`{VH52w#tI@0{O2jQusg~PwiuAX&{<= zd{e40%_mZgdHAp+v^soh>i}I0j#+LJW<9RFWqP4XmJHIT$Gzl`w=AIe#s4@B#{bzh z_9xh&=N0Bo@CvSXUBq07)YPyu=a8&q*4yedkZmoS>#{D3%6nfc^5<ii*GrX!?{r zG(jzq71k1d!>8EesOtsUtRwZ=+OwaS#GrI&Dt}?N zW28`NlhCl|SVqmWiI09fgn$Pnp;}8C%uc^GCY~GN7T9wUA+yaHTeqk%F6y^4x%FA% z!j;H`mu`NWr4_9xcQ3CaH!0Mhwi}_fD$F7DC&m1Gh=LDaJJS;ny5G3@9aVXCMVpx( zTa7^3xcQ;PA9RTNeY91no>g};sV4&-d9d;$9nfgb!zkfW($#t^$}mknTQB?}R&a6y z-QTLBpdzK3N=K`!ZMAj4D&G*xP)i4cD%^so-)wA&@q%WuZsiGp9m3&1FzBCCNlE)G zGpd!T6M`tkJ=>QrSy^etg?F6xb#%YA{Iw#~uuRjzAOlUJsRo>7`3(@n;1!0yxlhsp z!VLnXj92W?fzK7*I==yoKmc!#y&tPx&Q#PzcF1?b?L)aNIje1M%S2}2J5T-#1mPtp zKsRPOhX5w47aSOn9pY*gFT2`#e#z-*7%6HzLR2Zu+s_`JWe4)WAPUH7|2h$uM&Ly0 zDA_pU6cF9t!3upA4xUnjY**x0>FIlx;i?~*#(@a1l*s(YR0#fKDsuP7+mDoo<_?A- zONW^ea{Wh1qX&J{C*!u$scT@vmF(|Yxm%|3K}6Vpm^I=C@Ksk#7jPTG4|e;+3iD5N zK=$4Z8yl8onfWfv#g>I8ERHF^WF8MASd$f^`Fo`Ehg2AZl&Qw$R?EHLpXW3s`LOV` zB+k*byhy-jes~z=7UCFK{t`fY`J4Z+#>Q*FY;^N+`!nu-)YQ7}e!0TJQ}1GyD&s~0 z=YL4jaT6>mZPODA8qAY1Hgpj7$}wgx5Ofk4y>L{7S?W_N+){)cbUDkEch%E5mh6UR zE_ffUR)NhvU7@swLSMIb@!Nboxsl2=w_LyxkXVW*1E>GXrkU)RT{X(Eq>cW4>k9b= zR{2O)$X#yd@#mMI=mK&qYX{^E0~sExfQEEY^1nuTij+y{R)BD>U8y_!$qy|j80``2 zCzD_|UEJ0|9hbKh)vq7MKIMVevaA&UL+%kL7;n$YM335(11f`*ES^#WK`5haYu-28@0wtjro5 zx%MuvkY6I$Kh~AP1hyW+(X$L)vGA~4;P#l0k-sc`;S$jfV0&vi-qrU^D-a$Y#_4D? z{B8#V(V)E>9F5-S07xLTaKjetYs@QBkOp~mx`<~P{ z;p*p#E2;QkONXWym=45NrOzoaA{SEPTV-e#>Fk$=xkr36ztW_M; ztjHTTJSw)<;S|J;7%wVnjV$x+oNPqtgeRFt) zpjIl?HJFl;@ox{5;Gv%7?hSYaX|Hkl!$_#_dcqn=^MKsWGcx$XK2EI&`)ng?NDP-c z?FF1_wNiE6+-99u#ETBn(#+hOm*%sf3)NF8w_VjtU8kApxDoX`)juLIi92lIXQY_i z@uJeu*Q>Blb3c@+dvi5rQ>=1lA~f_gdpiwWilxJ*#UFU%(P1eOT?g&fmEWQUvBH++ z;eMCfdtK=- zVp`~1So=j(Q6!HtPiX(81>L-?uTQrze@OUW65crBGVf2NXZ znw@=*FVu0yEmgDzQL!o?5fy$^RaH&T&)3Px$r0&}bJbyhEID7icroT;@HvJ3@Y>0> z;H6*{cVAd$#i(Wm)i{P&5$r0Tii*x>=jU(XrGu*p z?CtIC-vs#6v~+Y@Lg)m}#AqBf2+fBc&1mofiZzxs`YOM6&(349sPPOgY(7ijAbb1k zVbwxD-NA(Aqd7lVOiWDF664*r)Wpa0)K|P$LuSZMC%lega-(YTJDg#dW93i~otr#* zR3u_A>Qh}}D<7t&sTmq)XKO2%^GauZ7R7N;m1gGm@twdYRPt=Rjig3U< zcYP~%$6kDD-|SmkGi{#77N^%Al-$(8%Ls-JKt1>onTq;Pe5O_q2|mfb7JHuZ-)i&#jUo>K!O7kH<{W)PI zD-BzP$8j1+H3{KwO0e;971NT(opRevq2jfIo12@(4|@1LzRNgNYy4$cp3k+Vxn|*P zoYBG^#zs@@t1Lm-hFlKy1S)WAbpF@7iuhM}fNO7)2Wrz`Y}>yn&jeSH_9SxRz&#iP zqW_=&gMB>ggjdq>e~b13U2%bQf!eH_%MT)V&VGbdI6B^x4eiVa}eIgffvpN z;r^d;!T$ybIQ@4U$QSr?5fG3KsVgh$|DPN54DoR;0z%TO1jlHeTzv>gagit$T>!x! zA37-#0EQfSn&!zLpB3>v!8Vj%(4quC^4o`>P5^22#Mft*i^CPVwb(%MCIDxAD3iz9 zUj|#Hl4=XFB`F75$*>8s_{79lF~Wu|ASIF?jYdyX@F8_;-B%#HKj=y|H>b+Hx64Ra_rKzG47`F=Y8)GAU zH_~XW1lk7%UV9(mM&oQ!eEM_iwWZK!;vk+v=BJbi#az2<=-v%{^RoLig?(62msJ@ZfvfYzNa}aS|3(Xp}WfV1nV_EuFK#g$O!_iu_asMX<(WmHY_g2H&HHO_U0`lXc z4r9-QJ_S(A3!0jmI)7y_giVBERX>}S%tB+Y$jDf^xb))MgXD3Vu_7Uk$E*_Pz;Aqv z+1T1@S)FXO>P(g^cA3-L?ah*(?h6pU41&$6Ub_Y@TF5YxUEceSW8HyU!RKn&>b>FS zS2wo=QoQw+YqlZG%*>J7H7h=AsnkBt%*0jok3@~jVg9+D`=A^K$x6HZkR>Kh|Lk;) z!rNn8!=s0>qhc!hM5fiajUL@rkj*NZYgoW|u+$Ae^7}#T@81jRderka5^8F%u0=+8 zD}xN!cdy%W5SghLcfLjVp4sDRwvk_tU)#eHr`$&AjCwBQVLV-z&T`0k(vM$!ujJce zUr=+q7KdKxwtDgQ zdyiNvyZgwvE0dJth^-`9vFCA@il|PX<;Tf8&Via&-5WjvS@|(~;}(#M>x@w0Y55j5 zSy4{ADMD4gRNX5?KU}AH$qPIgc!;j*!=>tqo3#1y-(>B0&LEtgnp%$wN;7^%MM(+cXnUC<&_X5MVh&Qc)ZNXNcE<6r zTBj<>2D$AKUf`J}qZaCh3oVp3=+2hBsN4A}u6#7>+cf9{Q#f3W=oy!Qout9orgF-{ zZq#mMhm37c3zGSVAHabPW$lKk?;E1OYMu@#ehcPn`PkAt&&coQ0>!f5R^D*-Kfl<=5;Q zUU2^oXavW-X|BS2KHU@i1J9mZ#UH)qTxQ9j->?gO4HkghCShpm@81W|u$lMC|0edE qTlk;F{@8c_+hhMbmH*dpamYEDF&1Bxtv5*k{-~?yDCb`@_y2!x(oo3& literal 0 HcmV?d00001 From e9901c23b8d9fa4be01d29c40ca47e000439272a Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Fri, 13 Aug 2021 17:31:53 -0400 Subject: [PATCH 12/15] Added numeric categories tests to shapes_test --- test/jasmine/assets/numeric_category.js | 105 ++++++++++++++++++++++++ test/jasmine/tests/shapes_test.js | 27 ++++++ 2 files changed, 132 insertions(+) create mode 100644 test/jasmine/assets/numeric_category.js diff --git a/test/jasmine/assets/numeric_category.js b/test/jasmine/assets/numeric_category.js new file mode 100644 index 00000000000..225211e16c1 --- /dev/null +++ b/test/jasmine/assets/numeric_category.js @@ -0,0 +1,105 @@ +'use strict'; + +var Plotly = require('../../../lib/index'); +var d3SelectAll = require('../../strict-d3').selectAll; +var drag = require('../assets/drag'); + +module.exports.shapeColors = [ + 'red', + 'green', + 'blue', + 'yellow', + 'orange', +]; + +module.exports.shapeColorTab = { + red: 'rgb(255, 0, 0)', + green: 'rgb(0, 128, 0)', + blue: 'rgb(0, 0, 255)', + yellow: 'rgb(255, 255, 0)', + orange: 'rgb(255, 165, 0)' +}; + +function createDesc(xcats, ycats) { + return 'x is specified as ' + xcats + ', y is specified as ' + ycats; +} + +module.exports.shapeColorTestDesc = { + red: createDesc('indices', 'numeric strings'), + green: createDesc('indices', 'numeric string categories, one of which is missing'), + blue: createDesc('string categories', 'indices'), + yellow: createDesc('numeric string categories, one of which is missing', 'indices'), + orange: createDesc('(path) indices', '(path) indices'), +}; + +function keepMthOfNShapes(shapes, nshapes, m) { + var oneShape = shapes[m]; + var tailShapes = shapes.slice(nshapes); + return [oneShape].concat(tailShapes); +} + +module.exports.plotMthShape = function(gd, m) { + var mock; + mock = require('../../image/mocks/numeric-string-categories.json'); + mock.config = {editable: true}; + mock.layout.shapes = keepMthOfNShapes(mock.layout.shapes, mock.layout.shapes.length, m); + var promise = Plotly.newPlot(gd, mock); + return promise; +}; + +module.exports.plotColoredShape = function(gd, color) { + var mock = require('../../image/mocks/numeric-string-categories.json'); + var m; + mock.layout.shapes.forEach(function(e, i) { + if(e && e.line && e.line.color === color) { m = i; } + }); + return module.exports.plotMthShape(gd, m); +}; + +module.exports.getShapeByColor = function(color) { + var rgbColor = module.exports.shapeColorTab[color]; + var shapeNode = d3SelectAll('.shapelayer path[style*="stroke: ' + rgbColor + '"]').node(); + return shapeNode; +}; + +module.exports.dragShapeByColor = function(color, dx, dy) { + var shapeNode = module.exports.getShapeByColor(color); + return drag({node: shapeNode, dpos: [dx, dy]}); +}; + +module.exports.bboxChange = function(fromBBox, toBBox) { + var ret = { + dx: toBBox.x - fromBBox.x, + dy: toBBox.y - fromBBox.y, + dwidth: toBBox.width - fromBBox.width, + dheight: toBBox.height - fromBBox.height, + }; + return ret; +}; + +// Returns a promise that resolves with an object that looks like: +// { +// dx: ... // change in horizontal shape position +// dy: ... // change in vertical shape position +// dwidth: ... // change in shape width +// dheight: ... // change in shape height +// } +module.exports.testDragShapeByColor = function(gd, shapeColor, dx, dy) { + var startBBox, endBBox; + // Plot the shape with the specified color + var promise = module.exports.plotColoredShape(gd, shapeColor).then(function() { + // get the bounding box of the shape with the specified color + var shapeNode = module.exports.getShapeByColor(shapeColor); + startBBox = shapeNode.getBoundingClientRect(); + // drag that shape + return module.exports.dragShapeByColor(shapeColor, dx, dy); + }).then(function() { + // get the new bounding box of the shape + var shapeNode = module.exports.getShapeByColor(shapeColor); + endBBox = shapeNode.getBoundingClientRect(); + return module.exports.bboxChange(startBBox, endBBox); + }); + return promise; +}; + +module.exports.d3SelectAll = d3SelectAll; diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index 8db397f972d..644cd4fc069 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -12,6 +12,8 @@ var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var drag = require('../assets/drag'); +var numericCategory = require('../assets/numeric_category'); + var customAssertions = require('../assets/custom_assertions'); var assertElemRightTo = customAssertions.assertElemRightTo; @@ -1649,3 +1651,28 @@ describe('Test shapes', function() { return coordinates; } }); + +fdescribe('Numeric string categories', function() { + 'use strict'; + + var gd; var dx = 100; var dy = 100; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + numericCategory.shapeColors.forEach(function(color) { + it('should correctly drag shapes where ' + numericCategory.shapeColorTestDesc[color], + function(done) { + var promise = numericCategory.testDragShapeByColor(gd, color, dx, dy); + promise.then(function(dbbox) { + expect(dbbox.dx).toBeCloseTo(dx); + expect(dbbox.dy).toBeCloseTo(dy); + expect(dbbox.dwidth).toBeCloseTo(0); + expect(dbbox.dheight).toBeCloseTo(0); + }).then(done); + }); + }); +}); From e8277a91ed05d4303d7e6119e8bd2ef6f0a02ba1 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Mon, 16 Aug 2021 09:41:47 -0400 Subject: [PATCH 13/15] removed fdescribe (!) good thing there's a test for this (bad thing that that is jasmine's way of running one test) --- test/jasmine/tests/shapes_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index 644cd4fc069..24e1d7d47d5 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -1652,7 +1652,7 @@ describe('Test shapes', function() { } }); -fdescribe('Numeric string categories', function() { +describe('Numeric string categories', function() { 'use strict'; var gd; var dx = 100; var dy = 100; From b53aa49b5c5fd67049bf17524b28e69b3d38e561 Mon Sep 17 00:00:00 2001 From: Nicholas Esterer Date: Mon, 16 Aug 2021 11:48:00 -0400 Subject: [PATCH 14/15] Added baselines for images and annotations with numeric string categories. --- ...tations-with-numeric-string-categories.png | Bin 0 -> 29608 bytes .../images-with-numeric-string-categories.png | Bin 0 -> 35044 bytes ...shapes-with-numeric-string-categories.png} | Bin ...ations-with-numeric-string-categories.json | 57 ++++++++++++ ...images-with-numeric-string-categories.json | 86 ++++++++++++++++++ ...hapes-with-numeric-string-categories.json} | 0 6 files changed, 143 insertions(+) create mode 100644 test/image/baselines/annotations-with-numeric-string-categories.png create mode 100644 test/image/baselines/images-with-numeric-string-categories.png rename test/image/baselines/{numeric-string-categories.png => shapes-with-numeric-string-categories.png} (100%) create mode 100644 test/image/mocks/annotations-with-numeric-string-categories.json create mode 100644 test/image/mocks/images-with-numeric-string-categories.json rename test/image/mocks/{numeric-string-categories.json => shapes-with-numeric-string-categories.json} (100%) diff --git a/test/image/baselines/annotations-with-numeric-string-categories.png b/test/image/baselines/annotations-with-numeric-string-categories.png new file mode 100644 index 0000000000000000000000000000000000000000..4c2f376905b0baccbde9feaaa8f684d421f9bf16 GIT binary patch literal 29608 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 literal 0 HcmV?d00001 diff --git a/test/image/baselines/images-with-numeric-string-categories.png b/test/image/baselines/images-with-numeric-string-categories.png new file mode 100644 index 0000000000000000000000000000000000000000..a63767c9828f8f284664b0315e8e1aa30bc4e540 GIT binary patch literal 35044 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 Date: Thu, 9 Sep 2021 17:01:01 -0400 Subject: [PATCH 15/15] mock json linting --- ...ations-with-numeric-string-categories.json | 133 ++++++++++------- ...images-with-numeric-string-categories.json | 64 +++++--- ...shapes-with-numeric-string-categories.json | 138 +++++++++--------- 3 files changed, 190 insertions(+), 145 deletions(-) diff --git a/test/image/mocks/annotations-with-numeric-string-categories.json b/test/image/mocks/annotations-with-numeric-string-categories.json index ddd311ecbfb..d7b9fe5778b 100644 --- a/test/image/mocks/annotations-with-numeric-string-categories.json +++ b/test/image/mocks/annotations-with-numeric-string-categories.json @@ -1,57 +1,80 @@ { -"data":[{ - "x": ["3", "1", "5", "2", "4", "6"], - "y": ["6","7","8","2","3","4"] - }], -"layout":{ - "xaxis": { - "type": "category", - "categoryarray": ["1", "2", "3", "4", "5", "6"] - }, - "yaxis": { - "type": "category" - }, - "annotations": [ - { - "text": "A", - "x": "2", - "y": 3.5 - }, - { - "text": "B", - "x": 0.5, - "y": "3" - }, - { - "text": "C", - "x": 2, - "y": "0" - }, - { - "text": "D", - "x": "7", - "y": 3 - } - ], - "shapes": [ - { - "type": "line", - "x0": 0.5, - "x1": 0.5, - "y0": 0, - "y1": 1, - "xref": "x domain", - "yref": "y domain" - }, - { - "type": "line", - "y0": 0.5, - "y1": 0.5, - "x0": 0, - "x1": 1, - "xref": "x domain", - "yref": "y domain" - } - ] + "data": [ + { + "x": [ + "3", + "1", + "5", + "2", + "4", + "6" + ], + "y": [ + "6", + "7", + "8", + "2", + "3", + "4" + ] + } + ], + "layout": { + "xaxis": { + "type": "category", + "categoryarray": [ + "1", + "2", + "3", + "4", + "5", + "6" + ] + }, + "yaxis": { + "type": "category" + }, + "annotations": [ + { + "text": "A", + "x": "2", + "y": 3.5 + }, + { + "text": "B", + "x": 0.5, + "y": "3" + }, + { + "text": "C", + "x": 2, + "y": "0" + }, + { + "text": "D", + "x": "7", + "y": 3 } -} + ], + "shapes": [ + { + "type": "line", + "x0": 0.5, + "x1": 0.5, + "y0": 0, + "y1": 1, + "xref": "x domain", + "yref": "y domain" + }, + { + "type": "line", + "y0": 0.5, + "y1": 0.5, + "x0": 0, + "x1": 1, + "xref": "x domain", + "yref": "y domain" + } + ] + } +} \ No newline at end of file diff --git a/test/image/mocks/images-with-numeric-string-categories.json b/test/image/mocks/images-with-numeric-string-categories.json index 4a928044462..be74404da0e 100644 --- a/test/image/mocks/images-with-numeric-string-categories.json +++ b/test/image/mocks/images-with-numeric-string-categories.json @@ -1,17 +1,40 @@ { - "data":[{ - "x": ["3", "1", "5", "2", "4", "6"], - "y": ["6","7","8","2","3","4"] - }], - "layout":{ - "xaxis": { - "type": "category", - "categoryarray": ["1", "2", "3", "4", "5", "6"] - }, - "yaxis": { - "type": "category" - }, - "images": [ + "data": [ + { + "x": [ + "3", + "1", + "5", + "2", + "4", + "6" + ], + "y": [ + "6", + "7", + "8", + "2", + "3", + "4" + ] + } + ], + "layout": { + "xaxis": { + "type": "category", + "categoryarray": [ + "1", + "2", + "3", + "4", + "5", + "6" + ] + }, + "yaxis": { + "type": "category" + }, + "images": [ { "source": "https://images.plot.ly/language-icons/api-home/js-logo.png", "xref": "x", @@ -47,9 +70,9 @@ "xanchor": "left", "yanchor": "top", "opacity": 0.8 - }, - {"source": "https://images.plot.ly/language-icons/api-home/js-logo.png", + { + "source": "https://images.plot.ly/language-icons/api-home/js-logo.png", "xref": "x", "yref": "y", "sizex": 1, @@ -59,10 +82,9 @@ "xanchor": "left", "yanchor": "top", "opacity": 1 - } - ], - "shapes": [ + ], + "shapes": [ { "type": "line", "x0": 0.5, @@ -81,6 +103,6 @@ "xref": "x domain", "yref": "y domain" } - ] - } -} + ] + } +} \ No newline at end of file diff --git a/test/image/mocks/shapes-with-numeric-string-categories.json b/test/image/mocks/shapes-with-numeric-string-categories.json index 5401b4a20fe..82c209dfd32 100644 --- a/test/image/mocks/shapes-with-numeric-string-categories.json +++ b/test/image/mocks/shapes-with-numeric-string-categories.json @@ -1,72 +1,72 @@ { -"data":[{ - "x": ["3", "1", "5", "2", "4", "6"], - "y": ["6","7","8","2","3","4"] - }], -"layout":{ - "xaxis": { - "type": "category", - "categoryarray": ["1", "2", "3", "4", "5", "6"] - }, - "yaxis": { - "type": "category" - }, - "shapes": [ - { - "type": "rect", - "x0": "2", - "x1": "4", - "y0": 3.5, - "y1": 4.5, - "line": {"color": "blue"} - }, - { - "type": "rect", - "x0": 0.5, - "x1": 1.5, - "y0": "3", - "y1": "4", - "line": {"color": "red"} - }, - { - "type": "rect", - "x0": 2, - "x1": 4, - "y0": "0", - "y1": "4", - "line": {"color": "green"} - }, - { - "type": "rect", - "x0": "4", - "x1": "7", - "y0": 3, - "y1": 4, - "line": {"color": "yellow"} - }, - { - "type": "path", - "path": "M0,5.5L3,4.5L1,3Z", - "line": {"color": "orange"} - }, - { - "type": "line", - "x0": 0.5, - "x1": 0.5, - "y0": 0, - "y1": 1, - "xref": "x domain", - "yref": "y domain" - }, - { - "type": "line", - "y0": 0.5, - "y1": 0.5, - "x0": 0, - "x1": 1, - "xref": "x domain", - "yref": "y domain" - } - ] + "data":[{ + "x": ["3", "1", "5", "2", "4", "6"], + "y": ["6","7","8","2","3","4"] + }], + "layout":{ + "xaxis": { + "type": "category", + "categoryarray": ["1", "2", "3", "4", "5", "6"] + }, + "yaxis": { + "type": "category" + }, + "shapes": [ + { + "type": "rect", + "x0": "2", + "x1": "4", + "y0": 3.5, + "y1": 4.5, + "line": {"color": "blue"} + }, + { + "type": "rect", + "x0": 0.5, + "x1": 1.5, + "y0": "3", + "y1": "4", + "line": {"color": "red"} + }, + { + "type": "rect", + "x0": 2, + "x1": 4, + "y0": "0", + "y1": "4", + "line": {"color": "green"} + }, + { + "type": "rect", + "x0": "4", + "x1": "7", + "y0": 3, + "y1": 4, + "line": {"color": "yellow"} + }, + { + "type": "path", + "path": "M0,5.5L3,4.5L1,3Z", + "line": {"color": "orange"} + }, + { + "type": "line", + "x0": 0.5, + "x1": 0.5, + "y0": 0, + "y1": 1, + "xref": "x domain", + "yref": "y domain" + }, + { + "type": "line", + "y0": 0.5, + "y1": 0.5, + "x0": 0, + "x1": 1, + "xref": "x domain", + "yref": "y domain" } + ] + } }