Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cad8e06

Browse filesBrowse files
authored
Merge pull request #1965 from apalchys/tickformatstops
add 'tickformatstops'
2 parents 9af3036 + 0e6747f commit cad8e06
Copy full SHA for cad8e06

File tree

11 files changed

+483
-6
lines changed
Filter options

11 files changed

+483
-6
lines changed

‎src/components/colorbar/attributes.js

Copy file name to clipboardExpand all lines: src/components/colorbar/attributes.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ module.exports = overrideAll({
166166
}),
167167
tickangle: axesAttrs.tickangle,
168168
tickformat: axesAttrs.tickformat,
169+
tickformatstops: axesAttrs.tickformatstops,
169170
tickprefix: axesAttrs.tickprefix,
170171
showtickprefix: axesAttrs.showtickprefix,
171172
ticksuffix: axesAttrs.ticksuffix,

‎src/plots/cartesian/axes.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/axes.js
+75-4Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ function tickTextObj(ax, x, text) {
12321232

12331233
function formatDate(ax, out, hover, extraPrecision) {
12341234
var tr = ax._tickround,
1235-
fmt = (hover && ax.hoverformat) || ax.tickformat;
1235+
fmt = (hover && ax.hoverformat) || axes.getTickFormat(ax);
12361236

12371237
if(extraPrecision) {
12381238
// second or sub-second precision: extra always shows max digits.
@@ -1288,7 +1288,8 @@ function formatDate(ax, out, hover, extraPrecision) {
12881288

12891289
function formatLog(ax, out, hover, extraPrecision, hideexp) {
12901290
var dtick = ax.dtick,
1291-
x = out.x;
1291+
x = out.x,
1292+
tickformat = ax.tickformat;
12921293

12931294
if(hideexp === 'never') {
12941295
// If this is a hover label, then we must *never* hide the exponent
@@ -1302,7 +1303,7 @@ function formatLog(ax, out, hover, extraPrecision, hideexp) {
13021303

13031304
if(extraPrecision && ((typeof dtick !== 'string') || dtick.charAt(0) !== 'L')) dtick = 'L3';
13041305

1305-
if(ax.tickformat || (typeof dtick === 'string' && dtick.charAt(0) === 'L')) {
1306+
if(tickformat || (typeof dtick === 'string' && dtick.charAt(0) === 'L')) {
13061307
out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision);
13071308
}
13081309
else if(isNumeric(dtick) || ((dtick.charAt(0) === 'D') && (Lib.mod(x + 0.01, 1) < 0.1))) {
@@ -1397,7 +1398,7 @@ function numFormat(v, ax, fmtoverride, hover) {
13971398
tickRound = ax._tickround,
13981399
exponentFormat = fmtoverride || ax.exponentformat || 'B',
13991400
exponent = ax._tickexponent,
1400-
tickformat = ax.tickformat,
1401+
tickformat = axes.getTickFormat(ax),
14011402
separatethousands = ax.separatethousands;
14021403

14031404
// special case for hover: set exponent just for this value, and
@@ -1498,6 +1499,76 @@ function numFormat(v, ax, fmtoverride, hover) {
14981499
return v;
14991500
}
15001501

1502+
axes.getTickFormat = function(ax) {
1503+
var i;
1504+
1505+
function convertToMs(dtick) {
1506+
return typeof dtick !== 'string' ? dtick : Number(dtick.replace('M', '')) * ONEAVGMONTH;
1507+
}
1508+
1509+
function compareLogTicks(left, right) {
1510+
var priority = ['L', 'D'];
1511+
if(typeof left === typeof right) {
1512+
if(typeof left === 'number') {
1513+
return left - right;
1514+
} else {
1515+
var leftPriority = priority.indexOf(left.charAt(0));
1516+
var rightPriority = priority.indexOf(right.charAt(0));
1517+
if(leftPriority === rightPriority) {
1518+
return Number(left.replace(/(L|D)/g, '')) - Number(right.replace(/(L|D)/g, ''));
1519+
} else {
1520+
return leftPriority - rightPriority;
1521+
}
1522+
}
1523+
} else {
1524+
return typeof left === 'number' ? 1 : -1;
1525+
}
1526+
}
1527+
1528+
function isProperStop(dtick, range, convert) {
1529+
var convertFn = convert || function(x) { return x;};
1530+
var leftDtick = range[0];
1531+
var rightDtick = range[1];
1532+
return ((!leftDtick && typeof leftDtick !== 'number') || convertFn(leftDtick) <= convertFn(dtick)) &&
1533+
((!rightDtick && typeof rightDtick !== 'number') || convertFn(rightDtick) >= convertFn(dtick));
1534+
}
1535+
1536+
function isProperLogStop(dtick, range) {
1537+
var isLeftDtickNull = range[0] === null;
1538+
var isRightDtickNull = range[1] === null;
1539+
var isDtickInRangeLeft = compareLogTicks(dtick, range[0]) >= 0;
1540+
var isDtickInRangeRight = compareLogTicks(dtick, range[1]) <= 0;
1541+
return (isLeftDtickNull || isDtickInRangeLeft) && (isRightDtickNull || isDtickInRangeRight);
1542+
}
1543+
1544+
var tickstop;
1545+
if(ax.tickformatstops && ax.tickformatstops.length > 0) {
1546+
switch(ax.type) {
1547+
case 'date':
1548+
case 'linear': {
1549+
for(i = 0; i < ax.tickformatstops.length; i++) {
1550+
if(isProperStop(ax.dtick, ax.tickformatstops[i].dtickrange, convertToMs)) {
1551+
tickstop = ax.tickformatstops[i];
1552+
break;
1553+
}
1554+
}
1555+
break;
1556+
}
1557+
case 'log': {
1558+
for(i = 0; i < ax.tickformatstops.length; i++) {
1559+
if(isProperLogStop(ax.dtick, ax.tickformatstops[i].dtickrange)) {
1560+
tickstop = ax.tickformatstops[i];
1561+
break;
1562+
}
1563+
}
1564+
break;
1565+
}
1566+
default:
1567+
}
1568+
}
1569+
return tickstop ? tickstop.value : ax.tickformat;
1570+
};
1571+
15011572
axes.subplotMatch = /^x([0-9]*)y([0-9]*)$/;
15021573

15031574
// getSubplots - extract all combinations of axes we need to make plots for

‎src/plots/cartesian/layout_attributes.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/layout_attributes.js
+28Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,34 @@ module.exports = {
492492
'*%H~%M~%S.%2f* would display *09~15~23.46*'
493493
].join(' ')
494494
},
495+
tickformatstops: {
496+
_isLinkedToArray: 'tickformatstop',
497+
498+
dtickrange: {
499+
valType: 'info_array',
500+
role: 'info',
501+
items: [
502+
{valType: 'any', editType: 'ticks'},
503+
{valType: 'any', editType: 'ticks'}
504+
],
505+
editType: 'ticks',
506+
description: [
507+
'range [*min*, *max*], where *min*, *max* - dtick values',
508+
'which describe some zoom level, it is possible to omit *min*',
509+
'or *max* value by passing *null*'
510+
].join(' ')
511+
},
512+
value: {
513+
valType: 'string',
514+
dflt: '',
515+
role: 'style',
516+
editType: 'ticks',
517+
description: [
518+
'string - dtickformat for described zoom level, the same as *tickformat*'
519+
].join(' ')
520+
},
521+
editType: 'ticks'
522+
},
495523
hoverformat: {
496524
valType: 'string',
497525
dflt: '',

‎src/plots/cartesian/tick_label_defaults.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/tick_label_defaults.js
+25-1Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
'use strict';
1111

1212
var Lib = require('../../lib');
13-
13+
var layoutAttributes = require('./layout_attributes');
1414

1515
/**
1616
* options: inherits font, outerTicks, noHover from axes.handleAxisDefaults
@@ -40,6 +40,7 @@ module.exports = function handleTickLabelDefaults(containerIn, containerOut, coe
4040

4141
if(axType !== 'category') {
4242
var tickFormat = coerce('tickformat');
43+
tickformatstopsDefaults(containerIn, containerOut);
4344
if(!tickFormat && axType !== 'date') {
4445
coerce('showexponent', showAttrDflt);
4546
coerce('exponentformat');
@@ -80,3 +81,26 @@ function getShowAttrDflt(containerIn) {
8081
return containerIn[showAttrs[0]];
8182
}
8283
}
84+
85+
function tickformatstopsDefaults(tickformatIn, tickformatOut) {
86+
var valuesIn = tickformatIn.tickformatstops;
87+
var valuesOut = tickformatOut.tickformatstops = [];
88+
89+
if(!Array.isArray(valuesIn)) return;
90+
91+
var valueIn, valueOut;
92+
93+
function coerce(attr, dflt) {
94+
return Lib.coerce(valueIn, valueOut, layoutAttributes.tickformatstops, attr, dflt);
95+
}
96+
97+
for(var i = 0; i < valuesIn.length; i++) {
98+
valueIn = valuesIn[i];
99+
valueOut = {};
100+
101+
coerce('dtickrange');
102+
coerce('value');
103+
104+
valuesOut.push(valueOut);
105+
}
106+
}

‎src/plots/gl3d/layout/axis_attributes.js

Copy file name to clipboardExpand all lines: src/plots/gl3d/layout/axis_attributes.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ module.exports = overrideAll({
101101
exponentformat: axesAttrs.exponentformat,
102102
separatethousands: axesAttrs.separatethousands,
103103
tickformat: axesAttrs.tickformat,
104+
tickformatstops: axesAttrs.tickformatstops,
104105
hoverformat: axesAttrs.hoverformat,
105106
// lines and grids
106107
showline: axesAttrs.showline,

‎src/plots/ternary/layout/axis_attributes.js

Copy file name to clipboardExpand all lines: src/plots/ternary/layout/axis_attributes.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module.exports = {
3939
tickfont: axesAttrs.tickfont,
4040
tickangle: axesAttrs.tickangle,
4141
tickformat: axesAttrs.tickformat,
42+
tickformatstops: axesAttrs.tickformatstops,
4243
hoverformat: axesAttrs.hoverformat,
4344
// lines and grids
4445
showline: extendFlat({}, axesAttrs.showline, {dflt: true}),

‎src/traces/carpet/axis_attributes.js

Copy file name to clipboardExpand all lines: src/traces/carpet/axis_attributes.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
var fontAttrs = require('../../plots/font_attributes');
1212
var colorAttrs = require('../../components/color/attributes');
13+
var axesAttrs = require('../../plots/cartesian/layout_attributes');
14+
var overrideAll = require('../../plot_api/edit_types').overrideAll;
1315

1416
module.exports = {
1517
color: {
@@ -290,6 +292,7 @@ module.exports = {
290292
'*%H~%M~%S.%2f* would display *09~15~23.46*'
291293
].join(' ')
292294
},
295+
tickformatstops: overrideAll(axesAttrs.tickformatstops, 'calc', 'from-root'),
293296
categoryorder: {
294297
valType: 'enumerated',
295298
values: [

‎tasks/util/strict_d3.js

Copy file name to clipboardExpand all lines: tasks/util/strict_d3.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var pathToStrictD3Module = path.join(
66
constants.pathToImageTest,
77
'strict-d3.js'
88
);
9-
109
/**
1110
* Transform `require('d3')` expressions to `require(/path/to/strict-d3.js)`
1211
*/
@@ -18,6 +17,8 @@ module.exports = transformTools.makeRequireTransform('requireTransform',
1817
var pathOut;
1918

2019
if(pathIn === 'd3' && opts.file !== pathToStrictD3Module) {
20+
// JSON.stringify: fix npm-scripts for windows users, for whom
21+
// path has \ in it, without stringify that turns into control chars.
2122
pathOut = 'require(' + JSON.stringify(pathToStrictD3Module) + ')';
2223
}
2324

28.3 KB
Loading

‎test/image/mocks/tickformatstops.json

Copy file name to clipboard
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"data": [
3+
{
4+
"x": ["2005-01","2005-02","2005-03","2005-04","2005-05","2005-06","2005-07"],
5+
"y": [-20,10,-5,0,5,-10,20]
6+
}
7+
],
8+
"layout": {
9+
"xaxis": {
10+
"tickformatstops": [
11+
{
12+
"dtickrange": [null, 1000],
13+
"value": "%H:%M:%S.%L ms"
14+
},
15+
{
16+
"dtickrange": [1000, 60000],
17+
"value": "%H:%M:%S s"
18+
},
19+
{
20+
"dtickrange": [60000, 3600000],
21+
"value": "%H:%M m"
22+
},
23+
{
24+
"dtickrange": [3600000, 86400000],
25+
"value": "%H:%M h"
26+
},
27+
{
28+
"dtickrange": [86400000, 604800000],
29+
"value": "%e. %b d"
30+
},
31+
{
32+
"dtickrange": [604800000, "M1"],
33+
"value": "%e. %b w"
34+
},
35+
{
36+
"dtickrange": ["M1", "M12"],
37+
"value": "%b '%y M"
38+
},
39+
{
40+
"dtickrange": ["M12", null],
41+
"value": "%Y Y"
42+
}
43+
]
44+
}
45+
}
46+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.