diff --git a/src/components/colorbar/attributes.js b/src/components/colorbar/attributes.js index 9ded21dd822..1a01bc2646d 100644 --- a/src/components/colorbar/attributes.js +++ b/src/components/colorbar/attributes.js @@ -167,6 +167,7 @@ module.exports = { showtickprefix: axesAttrs.showtickprefix, ticksuffix: axesAttrs.ticksuffix, showticksuffix: axesAttrs.showticksuffix, + separatethousands: axesAttrs.separatethousands, exponentformat: axesAttrs.exponentformat, showexponent: axesAttrs.showexponent, title: { diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js index 3d287532a51..e8a91d78ffc 100644 --- a/src/components/colorbar/draw.js +++ b/src/components/colorbar/draw.js @@ -158,6 +158,7 @@ module.exports = function draw(gd, id) { tickangle: opts.tickangle, tickformat: opts.tickformat, exponentformat: opts.exponentformat, + separatethousands: opts.separatethousands, showexponent: opts.showexponent, showtickprefix: opts.showtickprefix, tickprefix: opts.tickprefix, diff --git a/src/lib/index.js b/src/lib/index.js index e2b0a6f8f95..1c32a168686 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -581,15 +581,21 @@ lib.objectFromPath = function(path, value) { * // returns '2016' * * @example + * lib.numSeparate(3000, '.,', true); + * // returns '3,000' + * + * @example * lib.numSeparate(1234.56, '|,') * // returns '1,234|56' * * @param {string|number} value the value to be converted * @param {string} separators string of decimal, then thousands separators + * @param {boolean} separatethousands boolean, 4-digit integers are separated if true * * @return {string} the value that has been separated */ -lib.numSeparate = function(value, separators) { +lib.numSeparate = function(value, separators, separatethousands) { + if(!separatethousands) separatethousands = false; if(typeof separators !== 'string' || separators.length === 0) { throw new Error('Separator string required for formatting!'); @@ -608,7 +614,7 @@ lib.numSeparate = function(value, separators) { x2 = x.length > 1 ? decimalSep + x[1] : ''; // Years are ignored for thousands separators - if(thouSep && (x.length > 1 || x1.length > 4)) { + if(thouSep && (x.length > 1 || x1.length > 4 || separatethousands)) { while(thousandsRe.test(x1)) { x1 = x1.replace(thousandsRe, '$1' + thouSep + '$2'); } diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index d6ffb8cc97f..8e574fe49e9 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1092,7 +1092,8 @@ function numFormat(v, ax, fmtoverride, hover) { tickRound = ax._tickround, exponentFormat = fmtoverride || ax.exponentformat || 'B', exponent = ax._tickexponent, - tickformat = ax.tickformat; + tickformat = ax.tickformat, + separatethousands = ax.separatethousands; // special case for hover: set exponent just for this value, and // add a couple more digits of precision over tick labels @@ -1156,7 +1157,7 @@ function numFormat(v, ax, fmtoverride, hover) { if(dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ''); } // insert appropriate decimal point and thousands separator - v = Lib.numSeparate(v, ax._gd._fullLayout.separators); + v = Lib.numSeparate(v, ax._gd._fullLayout.separators, separatethousands); } // add exponent diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index b4c4d134bc3..a0e44874bd6 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -310,6 +310,14 @@ module.exports = { 'If *B*, 1B.' ].join(' ') }, + separatethousands: { + valType: 'boolean', + dflt: false, + role: 'style', + description: [ + 'If "true", even 4-digit integers are separated' + ].join(' ') + }, tickformat: { valType: 'string', dflt: '', diff --git a/src/plots/cartesian/tick_label_defaults.js b/src/plots/cartesian/tick_label_defaults.js index 9d5a83d67a1..148368cb6b4 100644 --- a/src/plots/cartesian/tick_label_defaults.js +++ b/src/plots/cartesian/tick_label_defaults.js @@ -43,6 +43,7 @@ module.exports = function handleTickLabelDefaults(containerIn, containerOut, coe if(!tickFormat && axType !== 'date') { coerce('showexponent', showAttrDflt); coerce('exponentformat'); + coerce('separatethousands'); } } } diff --git a/src/plots/gl3d/layout/axis_attributes.js b/src/plots/gl3d/layout/axis_attributes.js index 6c948c1c1cb..faad75ece28 100644 --- a/src/plots/gl3d/layout/axis_attributes.js +++ b/src/plots/gl3d/layout/axis_attributes.js @@ -98,6 +98,7 @@ module.exports = { showticksuffix: axesAttrs.showticksuffix, showexponent: axesAttrs.showexponent, exponentformat: axesAttrs.exponentformat, + separatethousands: axesAttrs.separatethousands, tickformat: axesAttrs.tickformat, hoverformat: axesAttrs.hoverformat, // lines and grids diff --git a/src/plots/ternary/layout/axis_attributes.js b/src/plots/ternary/layout/axis_attributes.js index 42b00778682..8ceb94f5771 100644 --- a/src/plots/ternary/layout/axis_attributes.js +++ b/src/plots/ternary/layout/axis_attributes.js @@ -35,6 +35,7 @@ module.exports = { ticksuffix: axesAttrs.ticksuffix, showexponent: axesAttrs.showexponent, exponentformat: axesAttrs.exponentformat, + separatethousands: axesAttrs.separatethousands, tickfont: axesAttrs.tickfont, tickangle: axesAttrs.tickangle, tickformat: axesAttrs.tickformat, diff --git a/test/image/baselines/axislabel_separatethousands.png b/test/image/baselines/axislabel_separatethousands.png new file mode 100644 index 00000000000..d3af4c99e6d Binary files /dev/null and b/test/image/baselines/axislabel_separatethousands.png differ diff --git a/test/image/mocks/axislabel_separatethousands.json b/test/image/mocks/axislabel_separatethousands.json new file mode 100644 index 00000000000..2a853d23aab --- /dev/null +++ b/test/image/mocks/axislabel_separatethousands.json @@ -0,0 +1,15 @@ +{ + "data": [ + { + "x": [1000, 2000, 3000, 4000], + "y": [1000, 1500, 2000, 10000], + "type": "scatter" + } + ], + "layout": { + "yaxis": { + "exponentformat": "none", + "separatethousands": true + } + } +} diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index 76d0dff5b1e..16361f79cae 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -1315,6 +1315,10 @@ describe('Test lib.js:', function() { expect(Lib.numSeparate(2016, '.,')).toBe('2016'); }); + it('should work even for 4-digit integer if third argument is true', function() { + expect(Lib.numSeparate(3000, '.,', true)).toBe('3,000'); + }); + it('should work for multiple thousands', function() { expect(Lib.numSeparate(1000000000, '.,')).toBe('1,000,000,000'); });