From 7fb8266810a402c3e394a99774a84f34d9d2bf1e Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 24 Jul 2020 15:58:21 -0400 Subject: [PATCH 1/6] apply latest d3-time-format in plotly.js --- package-lock.json | 13 +++++++++++++ package.json | 1 + src/lib/dates.js | 2 +- src/lib/index.js | 3 ++- src/plots/cartesian/set_convert.js | 3 ++- src/plots/plots.js | 3 ++- test/jasmine/tests/axes_test.js | 3 ++- test/jasmine/tests/localize_test.js | 3 ++- 8 files changed, 25 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11fcb19be53..cbe39237fd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2482,6 +2482,19 @@ "d3-path": "1" } }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz", + "integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==", + "requires": { + "d3-time": "1" + } + }, "d3-timer": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", diff --git a/package.json b/package.json index 875885a4576..7b2092835a9 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "d3-force": "^1.2.1", "d3-hierarchy": "^1.1.9", "d3-interpolate": "^1.4.0", + "d3-time-format": "^2.2.3", "delaunay-triangulate": "^1.1.6", "es6-promise": "^4.2.8", "fast-isnumeric": "^1.1.4", diff --git a/src/lib/dates.js b/src/lib/dates.js index 52ca20433e1..8b81836c195 100644 --- a/src/lib/dates.js +++ b/src/lib/dates.js @@ -25,7 +25,7 @@ var EPOCHJD = constants.EPOCHJD; var Registry = require('../registry'); -var utcFormat = d3.time.format.utc; +var utcFormat = require('d3-time-format').utcFormat; var DATETIME_REGEXP = /^\s*(-?\d\d\d\d|\d\d)(-(\d?\d)(-(\d?\d)([ Tt]([01]?\d|2[0-3])(:([0-5]\d)(:([0-5]\d(\.\d+)?))?(Z|z|[+\-]\d\d(:?\d\d)?)?)?)?)?)?\s*$/m; // special regex for chinese calendars to support yyyy-mmi-dd etc for intercalary months diff --git a/src/lib/index.js b/src/lib/index.js index 331c5dbefb4..12e059909f6 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var utcFormat = require('d3-time-format').utcFormat; var isNumeric = require('fast-isnumeric'); var numConstants = require('../constants/numerical'); @@ -1082,7 +1083,7 @@ function templateFormatString(string, labels, d3locale) { } if(format[0] === '|') { - fmt = d3locale ? d3locale.timeFormat.utc : d3.time.format.utc; + fmt = d3locale ? d3locale.utcFormat : utcFormat; var ms = lib.dateTime2ms(value); value = lib.formatDate(ms, format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''), false, fmt); } diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index 508d3731b00..45cdee77175 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var utcFormat = require('d3-time-format').utcFormat; var isNumeric = require('fast-isnumeric'); var Lib = require('../../lib'); @@ -954,7 +955,7 @@ module.exports = function setConvert(ax, fullLayout) { // Fall back on default format for dummy axes that don't care about formatting var locale = fullLayout._d3locale; if(ax.type === 'date') { - ax._dateFormat = locale ? locale.timeFormat.utc : d3.time.format.utc; + ax._dateFormat = locale ? locale.utcFormat : utcFormat; ax._extraFormat = fullLayout._extraFormat; } // occasionally we need _numFormat to pass through diff --git a/src/plots/plots.js b/src/plots/plots.js index 9fad0247f05..62a7522a75b 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var timeFormatLocale = require('d3-time-format').timeFormatLocale; var isNumeric = require('fast-isnumeric'); var Registry = require('../registry'); @@ -723,7 +724,7 @@ function getFormatter(formatObj, separators) { formatObj.decimal = separators.charAt(0); formatObj.thousands = separators.charAt(1); - return d3.locale(formatObj); + return timeFormatLocale(formatObj); } function fillMetaTextHelpers(newFullData, newFullLayout) { diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 5c19984ce9e..f9c7b2a347c 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1,5 +1,6 @@ var Plotly = require('@lib/index'); var d3 = require('d3'); +var utcFormat = require('d3-time-format').utcFormat; var Plots = require('@src/plots/plots'); var Lib = require('@src/lib'); @@ -5206,7 +5207,7 @@ function getZoomOutButton(gd) { } function getFormatter(format) { - return d3.time.format.utc(format); + return utcFormat(format); } describe('Test Axes.getTickformat', function() { diff --git a/test/jasmine/tests/localize_test.js b/test/jasmine/tests/localize_test.js index 92d2d0f556b..c4b1ea92088 100644 --- a/test/jasmine/tests/localize_test.js +++ b/test/jasmine/tests/localize_test.js @@ -3,6 +3,7 @@ var _ = Lib._; var Registry = require('@src/registry'); var d3 = require('d3'); +var utcFormat = require('d3-time-format').utcFormat; var Plotly = require('@lib'); var createGraphDiv = require('../assets/create_graph_div'); @@ -236,7 +237,7 @@ describe('localization', function() { expect(firstYLabel()).toBe('0~5'); var d0 = new Date(0); // thursday, Jan 1 1970 (UTC) // sanity check that d0 is what we think... - expect(d3.time.format.utc('%a %b %A %B')(d0)).toBe('Thu Jan Thursday January'); + expect(utcFormat('%a %b %A %B')(d0)).toBe('Thu Jan Thursday January'); // full names were not overridden, so fall back on english expect(gd._fullLayout.xaxis._dateFormat('%a %b %A %B')(d0)).toBe('t !1 Thursday January'); }) From c3e3f545d45593ec6724142f93b1a5c1d8a0f025 Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 24 Jul 2020 17:33:42 -0400 Subject: [PATCH 2/6] apply latest d3-format in plotly.js --- package-lock.json | 5 +++++ package.json | 1 + src/components/drawing/index.js | 3 ++- src/lib/index.js | 4 ++-- src/plots/cartesian/dragbox.js | 5 +++-- src/plots/cartesian/set_convert.js | 3 ++- src/traces/parcoords/parcoords.js | 5 +++-- src/traces/sankey/plot.js | 9 +++++---- src/traces/table/plot.js | 3 ++- 9 files changed, 25 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index cbe39237fd3..83d2a25b01f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2451,6 +2451,11 @@ "d3-timer": "1" } }, + "d3-format": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.4.tgz", + "integrity": "sha512-TWks25e7t8/cqctxCmxpUuzZN11QxIA7YrMbram94zMQ0PXjE4LVIMe/f6a4+xxL8HQ3OsAFULOINQi1pE62Aw==" + }, "d3-hierarchy": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", diff --git a/package.json b/package.json index 7b2092835a9..c11d98ebee3 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "country-regex": "^1.1.0", "d3": "^3.5.17", "d3-force": "^1.2.1", + "d3-format": "^1.4.4", "d3-hierarchy": "^1.1.9", "d3-interpolate": "^1.4.0", "d3-time-format": "^2.2.3", diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index d8f99f96535..273e8217679 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -10,6 +10,7 @@ 'use strict'; var d3 = require('d3'); +var numberFormat = require('d3-format').format; var isNumeric = require('fast-isnumeric'); var tinycolor = require('tinycolor2'); @@ -275,7 +276,7 @@ function makePointPath(symbolNumber, r) { var HORZGRADIENT = {x1: 1, x2: 0, y1: 0, y2: 0}; var VERTGRADIENT = {x1: 0, x2: 0, y1: 1, y2: 0}; -var stopFormatter = d3.format('~.1f'); +var stopFormatter = numberFormat('~f'); var gradientInfo = { radial: {node: 'radialGradient'}, radialreversed: {node: 'radialGradient', reversed: true}, diff --git a/src/lib/index.js b/src/lib/index.js index 12e059909f6..37bd910929a 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -8,7 +8,7 @@ 'use strict'; -var d3 = require('d3'); +var numberFormat = require('d3-format').format; var utcFormat = require('d3-time-format').utcFormat; var isNumeric = require('fast-isnumeric'); @@ -1078,7 +1078,7 @@ function templateFormatString(string, labels, d3locale) { if(format) { var fmt; if(format[0] === ':') { - fmt = d3locale ? d3locale.numberFormat : d3.format; + fmt = numberFormat; value = fmt(format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''))(value); } diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 573362f0047..63d42bc6de3 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var numberFormat = require('d3-format').format; var tinycolor = require('tinycolor2'); var supportsPassive = require('has-passive-events'); @@ -983,11 +984,11 @@ function getEndText(ax, end) { return initialVal; } else if(ax.type === 'log') { dig = Math.ceil(Math.max(0, -Math.log(diff) / Math.LN10)) + 3; - return d3.format('.' + dig + 'g')(Math.pow(10, initialVal)); + return numberFormat('.' + dig + 'g')(Math.pow(10, initialVal)); } else { // linear numeric (or category... but just show numbers here) dig = Math.floor(Math.log(Math.abs(initialVal)) / Math.LN10) - Math.floor(Math.log(diff) / Math.LN10) + 4; - return d3.format('.' + String(dig) + 'g')(initialVal); + return numberFormat('.' + String(dig) + 'g')(initialVal); } } diff --git a/src/plots/cartesian/set_convert.js b/src/plots/cartesian/set_convert.js index 45cdee77175..2d34c2ad629 100644 --- a/src/plots/cartesian/set_convert.js +++ b/src/plots/cartesian/set_convert.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var numberFormat = require('d3-format').format; var utcFormat = require('d3-time-format').utcFormat; var isNumeric = require('fast-isnumeric'); @@ -961,7 +962,7 @@ module.exports = function setConvert(ax, fullLayout) { // occasionally we need _numFormat to pass through // even though it won't be needed by this axis ax._separators = fullLayout.separators; - ax._numFormat = locale ? locale.numberFormat : d3.format; + ax._numFormat = numberFormat; // and for bar charts and box plots: reset forced minimum tick spacing delete ax._minDtick; diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index d314f9ad4c8..4dfc01edbdc 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var numberFormat = require('d3-format').format; var rgba = require('color-rgba'); var Axes = require('../../plots/cartesian/axes'); @@ -85,7 +86,7 @@ function domainScale(height, padding, dimension, tickvals, ticktext) { var extent = dimensionExtent(dimension); if(tickvals) { return d3.scale.ordinal() - .domain(tickvals.map(toText(d3.format(dimension.tickformat), ticktext))) + .domain(tickvals.map(toText(numberFormat(dimension.tickformat), ticktext))) .range(tickvals .map(function(d) { var unitVal = (d - extent[0]) / (extent[1] - extent[0]); @@ -272,7 +273,7 @@ function viewModel(state, callbacks, model) { // ensure ticktext and tickvals have same length if(!Array.isArray(ticktext) || !ticktext.length) { - ticktext = tickvals.map(d3.format(dimension.tickformat)); + ticktext = tickvals.map(numberFormat(dimension.tickformat)); } else if(ticktext.length > tickvals.length) { ticktext = ticktext.slice(0, tickvals.length); } else if(tickvals.length > ticktext.length) { diff --git a/src/traces/sankey/plot.js b/src/traces/sankey/plot.js index d85a2da7b7b..be066ebcaae 100644 --- a/src/traces/sankey/plot.js +++ b/src/traces/sankey/plot.js @@ -9,6 +9,7 @@ 'use strict'; var d3 = require('d3'); +var numberFormat = require('d3-format').format; var render = require('./render'); var Fx = require('../../components/fx'); var Color = require('../../components/color'); @@ -200,7 +201,7 @@ module.exports = function plot(gd, calcData) { link.fullData = link.trace; obj = d.link.trace.link; var hoverCenter = hoverCenterPosition(link); - var hovertemplateLabels = {valueLabel: d3.format(d.valueFormat)(link.value) + d.valueSuffix}; + var hovertemplateLabels = {valueLabel: numberFormat(d.valueFormat)(link.value) + d.valueSuffix}; hoverItems.push({ x: hoverCenter[0], @@ -210,7 +211,7 @@ module.exports = function plot(gd, calcData) { link.label || '', sourceLabel + link.source.label, targetLabel + link.target.label, - link.concentrationscale ? concentrationLabel + d3.format('%0.2f')(link.flow.labelConcentration) : '' + link.concentrationscale ? concentrationLabel + numberFormat('%0.2f')(link.flow.labelConcentration) : '' ].filter(renderableValuePresent).join('
'), color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(link.color, 1), borderColor: castHoverOption(obj, 'bordercolor'), @@ -289,14 +290,14 @@ module.exports = function plot(gd, calcData) { var hoverCenterX1 = boundingBox.right + 2 - rootBBox.left; var hoverCenterY = boundingBox.top + boundingBox.height / 4 - rootBBox.top; - var hovertemplateLabels = {valueLabel: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix}; + var hovertemplateLabels = {valueLabel: numberFormat(d.valueFormat)(d.node.value) + d.valueSuffix}; d.node.fullData = d.node.trace; var tooltip = Fx.loneHover({ x0: hoverCenterX0, x1: hoverCenterX1, y: hoverCenterY, - name: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix, + name: numberFormat(d.valueFormat)(d.node.value) + d.valueSuffix, text: [ d.node.label, incomingLabel + d.node.targetLinks.length, diff --git a/src/traces/table/plot.js b/src/traces/table/plot.js index 9b2bddbed9f..f28b0d99a01 100644 --- a/src/traces/table/plot.js +++ b/src/traces/table/plot.js @@ -10,6 +10,7 @@ var c = require('./constants'); var d3 = require('d3'); +var numberFormat = require('d3-format').format; var gup = require('../../lib/gup'); var Drawing = require('../../components/drawing'); var svgUtil = require('../../lib/svg_text_utils'); @@ -534,7 +535,7 @@ function populateCellText(cellText, tableControlView, allColumnBlock, gd) { 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 prefixSuffixedText = prefix + (format ? numberFormat(format)(d.value) : d.value) + suffix; var hasWrapSplitCharacter; d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hasWrapCharacter(prefixSuffixedText)); From eafc956207fea66bf0d3cc5da3f900bea4d6a21a Mon Sep 17 00:00:00 2001 From: archmoj Date: Fri, 24 Jul 2020 19:16:40 -0400 Subject: [PATCH 3/6] update doc links for d3 formatters --- src/constants/docs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants/docs.js b/src/constants/docs.js index 72e06e9af84..d3138ffef2c 100644 --- a/src/constants/docs.js +++ b/src/constants/docs.js @@ -9,6 +9,6 @@ 'use strict'; module.exports = { - FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format', - DATE_FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format' + FORMAT_LINK: 'https://github.com/d3/d3-format#format', + DATE_FORMAT_LINK: 'https://github.com/d3/d3-time-format#locale_format' }; From c35aac5b695f0393439cc295c0e1f4f159617ba8 Mon Sep 17 00:00:00 2001 From: archmoj Date: Mon, 27 Jul 2020 10:10:18 -0400 Subject: [PATCH 4/6] need to change indicator delta auto default format --- src/traces/indicator/defaults.js | 2 +- test/jasmine/tests/indicator_test.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/traces/indicator/defaults.js b/src/traces/indicator/defaults.js index 717f99984c8..2b6b14c4b3e 100644 --- a/src/traces/indicator/defaults.js +++ b/src/traces/indicator/defaults.js @@ -64,7 +64,7 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) { } coerce('delta.reference', traceOut.value); coerce('delta.relative'); - coerce('delta.valueformat', traceOut.delta.relative ? '2%' : ''); + coerce('delta.valueformat', traceOut.delta.relative ? '.0%' : ''); coerce('delta.increasing.symbol'); coerce('delta.increasing.color'); coerce('delta.decreasing.symbol'); diff --git a/test/jasmine/tests/indicator_test.js b/test/jasmine/tests/indicator_test.js index 4bc28714830..1d65f57ec20 100644 --- a/test/jasmine/tests/indicator_test.js +++ b/test/jasmine/tests/indicator_test.js @@ -48,7 +48,7 @@ describe('Indicator defaults', function() { it('defaults to displaying relative changes in percentage', function() { var out = _supply({type: 'indicator', mode: 'delta', delta: {relative: true}, value: 1}); - expect(out.delta.valueformat).toBe('2%'); + expect(out.delta.valueformat).toBe('.0%'); }); it('should not ignore empty valueformat', function() { @@ -164,7 +164,7 @@ describe('Indicator plot', function() { Plotly.newPlot(gd, [{ type: 'indicator', value: 500, - number: {valueformat: '0.f'} + number: {valueformat: '~f'} }], {width: 400, height: 400}) .then(function() { checkNumbersScale(1, 'initialy at normal scale'); @@ -185,7 +185,7 @@ describe('Indicator plot', function() { Plotly.newPlot(gd, [{ type: 'indicator', value: 1, - number: {valueformat: '0.f'} + number: {valueformat: '~f'} }], {width: 400, height: 400}) .then(function() { checkNumbersScale(1, 'initialy at normal scale'); @@ -208,7 +208,7 @@ describe('Indicator plot', function() { type: 'indicator', mode: 'number+delta', value: 1, - number: {valueformat: '0.f'} + number: {valueformat: '~f'} }; figure[numberType] = {font: {size: 100}}; Plotly.newPlot(gd, [figure], {width: 400, height: 400}) From a53c750231ca038e6dfd508b60a9e1d24e5a95b2 Mon Sep 17 00:00:00 2001 From: archmoj Date: Mon, 27 Jul 2020 12:10:06 -0400 Subject: [PATCH 5/6] need to change 0.f formatter in the mock --- test/image/mocks/texttemplate_scatter.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image/mocks/texttemplate_scatter.json b/test/image/mocks/texttemplate_scatter.json index 3fff2e746f4..132aa727211 100644 --- a/test/image/mocks/texttemplate_scatter.json +++ b/test/image/mocks/texttemplate_scatter.json @@ -17,7 +17,7 @@ "Toronto", "Vancouver" ], - "texttemplate": "%{text}: (%{lon:.0f}, %{lat:0.f}): %{customdata:.2s}", + "texttemplate": "%{text}: (%{lon:.0f}, %{lat:~f}): %{customdata:.2s}", "textposition": "top center", "customdata": [1780000, 2930000, 675218], "geo": "geo" From e3934d3f87657b9474f1ce34b1eb5e9d8a9f7ea6 Mon Sep 17 00:00:00 2001 From: archmoj Date: Mon, 27 Jul 2020 12:29:26 -0400 Subject: [PATCH 6/6] need to change localize test --- test/jasmine/tests/localize_test.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/jasmine/tests/localize_test.js b/test/jasmine/tests/localize_test.js index c4b1ea92088..d787c83fea4 100644 --- a/test/jasmine/tests/localize_test.js +++ b/test/jasmine/tests/localize_test.js @@ -307,15 +307,10 @@ describe('localization', function() { .then(function() { expect(firstYLabel()).toBe('0p5'); - return Plotly.relayout(gd, {'yaxis.tickformat': '.3f'}); - }) - .then(function() { - expect(firstYLabel()).toBe('0p500'); - return Plotly.relayout(gd, {separators: null}); }) .then(function() { - expect(firstYLabel()).toBe('0D500'); + expect(firstYLabel()).toBe('0D5'); }) .catch(failTest) .then(done);