From 8d6861f4f65389ce716d2aa9561e92260fbb4a13 Mon Sep 17 00:00:00 2001 From: daniele99 Date: Thu, 24 Oct 2024 07:10:14 +0200 Subject: [PATCH 1/8] Add "SI extended" to display numbers in the full SI unit range (10^-30 to 10^30) --- src/plots/cartesian/axes.js | 24 +++++++++++++++++++----- src/plots/cartesian/layout_attributes.js | 2 +- src/traces/carpet/axis_attributes.js | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 90f7b288de5..cc09e1a04bf 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1558,7 +1558,8 @@ function autoTickRound(ax) { var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); var minexponent = ax.minexponent === undefined ? 3 : ax.minexponent; if(Math.abs(rangeexp) > minexponent) { - if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) { + if((isSIFormat(ax.exponentformat) && ax.exponentformat !== 'SI extended' && !beyondSI(rangeexp)) || + (isSIFormat(ax.exponentformat) && ax.exponentformat === 'SI extended' && !beyondSIExtended(rangeexp))) { ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); } else ax._tickexponent = rangeexp; } @@ -1904,7 +1905,8 @@ function formatLog(ax, out, hover, extraPrecision, hideexp) { var p = Math.round(x); var absP = Math.abs(p); var exponentFormat = ax.exponentformat; - if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && beyondSI(p))) { + if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(p)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(p))) { if(p === 0) out.text = 1; else if(p === 1) out.text = '10'; else out.text = '10' + (p > 1 ? '' : MINUS_SIGN) + absP + ''; @@ -2049,8 +2051,11 @@ function num2frac(num) { // also automatically switch to sci. notation var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; +// extending SI prefixes +var SIPREFIXES_EXTENDED = ['q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q']; + function isSIFormat(exponentFormat) { - return exponentFormat === 'SI' || exponentFormat === 'B'; + return exponentFormat === 'SI' || exponentFormat === 'SI extended' || exponentFormat === 'B'; } // are we beyond the range of common SI prefixes? @@ -2064,6 +2069,10 @@ function beyondSI(exponent) { return exponent > 14 || exponent < -15; } +function beyondSIExtended(exponent) { + return exponent > 32 || exponent < -32; +} + function numFormat(v, ax, fmtoverride, hover) { var isNeg = v < 0; // max number of digits past decimal point to show @@ -2139,7 +2148,8 @@ function numFormat(v, ax, fmtoverride, hover) { // add exponent if(exponent && exponentFormat !== 'hide') { - if(isSIFormat(exponentFormat) && beyondSI(exponent)) exponentFormat = 'power'; + if((isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(exponent)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(exponent))) exponentFormat = 'power'; var signedExponent; if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; @@ -2153,7 +2163,11 @@ function numFormat(v, ax, fmtoverride, hover) { } else if(exponentFormat === 'B' && exponent === 9) { v += 'B'; } else if(isSIFormat(exponentFormat)) { - v += SIPREFIXES[exponent / 3 + 5]; + if(exponentFormat !== 'SI extended') { + v += SIPREFIXES[exponent / 3 + 5]; + } else if(exponentFormat === 'SI extended') { + v += SIPREFIXES_EXTENDED[exponent / 3 + 10]; + } } } diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 32afc99457a..4b314b4453c 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -897,7 +897,7 @@ module.exports = { }, exponentformat: { valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], + values: ['none', 'e', 'E', 'power', 'SI', 'B', 'SI extended'], dflt: 'B', editType: 'ticks', description: [ diff --git a/src/traces/carpet/axis_attributes.js b/src/traces/carpet/axis_attributes.js index 688f1a11a50..95583ddda30 100644 --- a/src/traces/carpet/axis_attributes.js +++ b/src/traces/carpet/axis_attributes.js @@ -234,7 +234,7 @@ module.exports = { }, exponentformat: { valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], + values: ['none', 'e', 'E', 'power', 'SI', 'B', 'SI extended'], dflt: 'B', editType: 'calc', description: [ From c0ec8912f8b18e03bc62134794abca280aed4d02 Mon Sep 17 00:00:00 2001 From: daniele99 Date: Thu, 24 Oct 2024 07:11:24 +0200 Subject: [PATCH 2/8] Modify 20.json mock and relative baseline to show the new "SI extended" mode --- test/image/baselines/20.png | Bin 93063 -> 76587 bytes test/image/mocks/20.json | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/image/baselines/20.png b/test/image/baselines/20.png index 32da2fb249a23555551a7a6238452646041349fb..05cc733bd2520de8c790299ff9650c2430b571dd 100644 GIT binary patch literal 76587 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%0DW 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 diff --git a/test/image/mocks/20.json b/test/image/mocks/20.json index b2601cef1b7..078f4d66429 100644 --- a/test/image/mocks/20.json +++ b/test/image/mocks/20.json @@ -8,7 +8,7 @@ }, { "x": [2, 3, 4], - "y": [40, 50, 60], + "y": [4000000000000, 5000000000000, 6000000000000], "name": "yaxis2 data", "yaxis": "y2", "type": "scatter" @@ -36,7 +36,7 @@ }, { "x": [6, 7, 8], - "y": [4000000, 5000000, 6000000], + "y": [400000000000000000000000000000000, 500000000000000000000000000000000, 600000000000000000000000000000000], "name": "yaxis6 data", "yaxis": "y6", "type": "scatter" @@ -111,6 +111,7 @@ "tickfont": { "color": "#ff7f0e" }, + "exponentformat": "SI", "linecolor": "rgba(255,127,14,0.4)", "linewidth": 6, "anchor": "free", @@ -189,7 +190,7 @@ "tickfont": { "color": "#8c564b" }, - "exponentformat": "SI", + "exponentformat": "SI extended", "linecolor": "rgba(140,86,75,0.5)", "anchor": "free", "side": "right", From d78cfc10d2ab08376883fc21a7b432b0effb508d Mon Sep 17 00:00:00 2001 From: daniele99 Date: Thu, 24 Oct 2024 20:40:32 +0200 Subject: [PATCH 3/8] Fix bottom limit of exponent and add comments for the new "SI extended" feature --- src/plots/cartesian/axes.js | 2 +- src/plots/cartesian/layout_attributes.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index cc09e1a04bf..914e111f8db 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -2070,7 +2070,7 @@ function beyondSI(exponent) { } function beyondSIExtended(exponent) { - return exponent > 32 || exponent < -32; + return exponent > 32 || exponent < -30; } function numFormat(v, ax, fmtoverride, hover) { diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 4b314b4453c..a55c3821854 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -908,7 +908,12 @@ module.exports = { 'If *E*, 1E+9.', 'If *power*, 1x10^9 (with 9 in a super script).', 'If *SI*, 1G.', - 'If *B*, 1B.' + 'If *B*, 1B.', + + '*SI* uses prefixes from "femto" f (10^-15) to "tera" T (10^12).', + '*SI extended* covers instead the full SI range from "quecto" q (10^-30) to "quetta" Q (10^30).', + 'If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule', + 'will automatically be switched to the power notation.' ].join(' ') }, minexponent: { From 15fa0ba3c0495fbf18a1d0b603460c53e85d9bb4 Mon Sep 17 00:00:00 2001 From: Alex Hsu Date: Wed, 15 Oct 2025 14:13:52 -0400 Subject: [PATCH 4/8] Fix formatting using biome --- src/plots/cartesian/axes.js | 7807 +++++++++++++++++------------------ test/image/mocks/20.json | 5 +- 2 files changed, 3714 insertions(+), 4098 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index ee7a2caa8b9..662bb39791f 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -1,21 +1,21 @@ -"use strict"; +'use strict'; -var d3 = require("@plotly/d3"); -var isNumeric = require("fast-isnumeric"); -var Plots = require("../../plots/plots"); +var d3 = require('@plotly/d3'); +var isNumeric = require('fast-isnumeric'); +var Plots = require('../../plots/plots'); -var Registry = require("../../registry"); -var Lib = require("../../lib"); +var Registry = require('../../registry'); +var Lib = require('../../lib'); var strTranslate = Lib.strTranslate; -var svgTextUtils = require("../../lib/svg_text_utils"); -var Titles = require("../../components/titles"); -var Color = require("../../components/color"); -var Drawing = require("../../components/drawing"); +var svgTextUtils = require('../../lib/svg_text_utils'); +var Titles = require('../../components/titles'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); -var axAttrs = require("./layout_attributes"); -var cleanTicks = require("./clean_ticks"); +var axAttrs = require('./layout_attributes'); +var cleanTicks = require('./clean_ticks'); -var constants = require("../../constants/numerical"); +var constants = require('../../constants/numerical'); var ONEMAXYEAR = constants.ONEMAXYEAR; var ONEAVGYEAR = constants.ONEAVGYEAR; var ONEMINYEAR = constants.ONEMINYEAR; @@ -36,21 +36,21 @@ var ONEMICROSEC = constants.ONEMICROSEC; var MINUS_SIGN = constants.MINUS_SIGN; var BADNUM = constants.BADNUM; -var ZERO_PATH = { K: "zeroline" }; -var GRID_PATH = { K: "gridline", L: "path" }; -var MINORGRID_PATH = { K: "minor-gridline", L: "path" }; -var TICK_PATH = { K: "tick", L: "path" }; -var TICK_TEXT = { K: "tick", L: "text" }; +var ZERO_PATH = { K: 'zeroline' }; +var GRID_PATH = { K: 'gridline', L: 'path' }; +var MINORGRID_PATH = { K: 'minor-gridline', L: 'path' }; +var TICK_PATH = { K: 'tick', L: 'path' }; +var TICK_TEXT = { K: 'tick', L: 'text' }; var MARGIN_MAPPING = { - width: ["x", "r", "l", "xl", "xr"], - height: ["y", "t", "b", "yt", "yb"], - right: ["r", "xr"], - left: ["l", "xl"], - top: ["t", "yt"], - bottom: ["b", "yb"], + width: ['x', 'r', 'l', 'xl', 'xr'], + height: ['y', 't', 'b', 'yt', 'yb'], + right: ['r', 'xr'], + left: ['l', 'xl'], + top: ['t', 'yt'], + bottom: ['b', 'yb'] }; -var alignmentConstants = require("../../constants/alignment"); +var alignmentConstants = require('../../constants/alignment'); var MID_SHIFT = alignmentConstants.MID_SHIFT; var CAP_SHIFT = alignmentConstants.CAP_SHIFT; var LINE_SPACING = alignmentConstants.LINE_SPACING; @@ -58,12 +58,12 @@ var OPPOSITE_SIDE = alignmentConstants.OPPOSITE_SIDE; var TEXTPAD = 3; -var axes = (module.exports = {}); +var axes = module.exports = {}; -axes.setConvert = require("./set_convert"); -var autoType = require("./axis_autotype"); +axes.setConvert = require('./set_convert'); +var autoType = require('./axis_autotype'); -var axisIds = require("./axis_ids"); +var axisIds = require('./axis_ids'); var idSort = axisIds.idSort; var isLinked = axisIds.isLinked; @@ -76,14 +76,17 @@ axes.listIds = axisIds.listIds; axes.getFromId = axisIds.getFromId; axes.getFromTrace = axisIds.getFromTrace; -var autorange = require("./autorange"); +var autorange = require('./autorange'); axes.getAutoRange = autorange.getAutoRange; axes.findExtremes = autorange.findExtremes; var epsilon = 0.0001; function expandRange(range) { - var delta = (range[1] - range[0]) * epsilon; - return [range[0] - delta, range[1] + delta]; + var delta = (range[1] - range[0]) * epsilon; + return [ + range[0] - delta, + range[1] + delta + ]; } /* @@ -97,46 +100,28 @@ function expandRange(range) { * extraOption: aside from existing axes with this letter, what non-axis value is allowed? * Only required if it's different from `dflt` */ -axes.coerceRef = function ( - containerIn, - containerOut, - gd, - attr, - dflt, - extraOption -) { - var axLetter = attr.charAt(attr.length - 1); - var axlist = gd._fullLayout._subplots[axLetter + "axis"]; - var refAttr = attr + "ref"; - var attrDef = {}; - - if (!dflt) - dflt = - axlist[0] || - (typeof extraOption === "string" ? extraOption : extraOption[0]); - if (!extraOption) extraOption = dflt; - axlist = axlist.concat( - axlist.map(function (x) { - return x + " domain"; - }) - ); - - // data-ref annotations are not supported in gl2d yet - - attrDef[refAttr] = { - valType: "enumerated", - values: axlist.concat( - extraOption - ? typeof extraOption === "string" - ? [extraOption] - : extraOption - : [] - ), - dflt: dflt, - }; - - // xref, yref - return Lib.coerce(containerIn, containerOut, attrDef, refAttr); +axes.coerceRef = function(containerIn, containerOut, gd, attr, dflt, extraOption) { + var axLetter = attr.charAt(attr.length - 1); + var axlist = gd._fullLayout._subplots[axLetter + 'axis']; + var refAttr = attr + 'ref'; + var attrDef = {}; + + if(!dflt) dflt = axlist[0] || (typeof extraOption === 'string' ? extraOption : extraOption[0]); + if(!extraOption) extraOption = dflt; + axlist = axlist.concat(axlist.map(function(x) { return x + ' domain'; })); + + // data-ref annotations are not supported in gl2d yet + + attrDef[refAttr] = { + valType: 'enumerated', + values: axlist.concat(extraOption ? + (typeof extraOption === 'string' ? [extraOption] : extraOption) : + []), + dflt: dflt + }; + + // xref, yref + return Lib.coerce(containerIn, containerOut, attrDef, refAttr); }; /* @@ -147,21 +132,11 @@ axes.coerceRef = function ( * ar: the axis reference string * */ -axes.getRefType = function (ar) { - if (ar === undefined) { - return ar; - } - if (ar === "paper") { - return "paper"; - } - if (ar === "pixel") { - return "pixel"; - } - if (/( domain)$/.test(ar)) { - return "domain"; - } else { - return "range"; - } +axes.getRefType = function(ar) { + if(ar === undefined) { return ar; } + if(ar === 'paper') { return 'paper'; } + if(ar === 'pixel') { return 'pixel'; } + if(/( domain)$/.test(ar)) { return 'domain'; } else { return 'range'; } }; /* @@ -186,424 +161,396 @@ axes.getRefType = function (ar) { * - for date axes: JS Dates or milliseconds, and convert to date strings * - for other types: coerce them to numbers */ -axes.coercePosition = function (containerOut, gd, coerce, axRef, attr, dflt) { - var cleanPos, pos; - var axRefType = axes.getRefType(axRef); - if (axRefType !== "range") { - cleanPos = Lib.ensureNumber; - pos = coerce(attr, dflt); - } else { - var ax = axes.getFromId(gd, axRef); - dflt = ax.fraction2r(dflt); - pos = coerce(attr, dflt); - cleanPos = ax.cleanPos; - } - containerOut[attr] = cleanPos(pos); +axes.coercePosition = function(containerOut, gd, coerce, axRef, attr, dflt) { + var cleanPos, pos; + var axRefType = axes.getRefType(axRef); + if(axRefType !== 'range') { + cleanPos = Lib.ensureNumber; + pos = coerce(attr, dflt); + } else { + var ax = axes.getFromId(gd, axRef); + dflt = ax.fraction2r(dflt); + pos = coerce(attr, dflt); + cleanPos = ax.cleanPos; + } + containerOut[attr] = cleanPos(pos); }; -axes.cleanPosition = function (pos, gd, axRef) { - var cleanPos = - axRef === "paper" || axRef === "pixel" - ? Lib.ensureNumber - : axes.getFromId(gd, axRef).cleanPos; +axes.cleanPosition = function(pos, gd, axRef) { + var cleanPos = (axRef === 'paper' || axRef === 'pixel') ? + Lib.ensureNumber : + axes.getFromId(gd, axRef).cleanPos; - return cleanPos(pos); + return cleanPos(pos); }; -axes.redrawComponents = function (gd, axIds) { - axIds = axIds ? axIds : axes.listIds(gd); +axes.redrawComponents = function(gd, axIds) { + axIds = axIds ? axIds : axes.listIds(gd); - var fullLayout = gd._fullLayout; + var fullLayout = gd._fullLayout; - function _redrawOneComp(moduleName, methodName, stashName, shortCircuit) { - var method = Registry.getComponentMethod(moduleName, methodName); - var stash = {}; + function _redrawOneComp(moduleName, methodName, stashName, shortCircuit) { + var method = Registry.getComponentMethod(moduleName, methodName); + var stash = {}; - for (var i = 0; i < axIds.length; i++) { - var ax = fullLayout[axes.id2name(axIds[i])]; - var indices = ax[stashName]; + for(var i = 0; i < axIds.length; i++) { + var ax = fullLayout[axes.id2name(axIds[i])]; + var indices = ax[stashName]; - for (var j = 0; j < indices.length; j++) { - var ind = indices[j]; + for(var j = 0; j < indices.length; j++) { + var ind = indices[j]; - if (!stash[ind]) { - method(gd, ind); - stash[ind] = 1; - // once is enough for images (which doesn't use the `i` arg anyway) - if (shortCircuit) return; + if(!stash[ind]) { + method(gd, ind); + stash[ind] = 1; + // once is enough for images (which doesn't use the `i` arg anyway) + if(shortCircuit) return; + } + } } - } } - } - // annotations and shapes 'draw' method is slow, - // use the finer-grained 'drawOne' method instead - _redrawOneComp("annotations", "drawOne", "_annIndices"); - _redrawOneComp("shapes", "drawOne", "_shapeIndices"); - _redrawOneComp("images", "draw", "_imgIndices", true); - _redrawOneComp("selections", "drawOne", "_selectionIndices"); + // annotations and shapes 'draw' method is slow, + // use the finer-grained 'drawOne' method instead + _redrawOneComp('annotations', 'drawOne', '_annIndices'); + _redrawOneComp('shapes', 'drawOne', '_shapeIndices'); + _redrawOneComp('images', 'draw', '_imgIndices', true); + _redrawOneComp('selections', 'drawOne', '_selectionIndices'); }; -var getDataConversions = (axes.getDataConversions = function ( - gd, - trace, - target, - targetArray -) { - var ax; - - // If target points to an axis, use the type we already have for that - // axis to find the data type. Otherwise use the values to autotype. - var d2cTarget = - target === "x" || target === "y" || target === "z" ? target : targetArray; - - // In the case of an array target, make a mock data array - // and call supplyDefaults to the data type and - // setup the data-to-calc method. - if (Lib.isArrayOrTypedArray(d2cTarget)) { - ax = { - type: autoType(targetArray, undefined, { - autotypenumbers: gd._fullLayout.autotypenumbers, - }), - _categories: [], - }; - axes.setConvert(ax); +var getDataConversions = axes.getDataConversions = function(gd, trace, target, targetArray) { + var ax; + + // If target points to an axis, use the type we already have for that + // axis to find the data type. Otherwise use the values to autotype. + var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ? + target : + targetArray; + + // In the case of an array target, make a mock data array + // and call supplyDefaults to the data type and + // setup the data-to-calc method. + if(Lib.isArrayOrTypedArray(d2cTarget)) { + ax = { + type: autoType(targetArray, undefined, { + autotypenumbers: gd._fullLayout.autotypenumbers + }), + _categories: [] + }; + axes.setConvert(ax); - // build up ax._categories (usually done during ax.makeCalcdata() - if (ax.type === "category") { - for (var i = 0; i < targetArray.length; i++) { - ax.d2c(targetArray[i]); - } + // build up ax._categories (usually done during ax.makeCalcdata() + if(ax.type === 'category') { + for(var i = 0; i < targetArray.length; i++) { + ax.d2c(targetArray[i]); + } + } + } else { + ax = axes.getFromTrace(gd, trace, d2cTarget); } - } else { - ax = axes.getFromTrace(gd, trace, d2cTarget); - } - // if 'target' has corresponding axis - // -> use setConvert method - if (ax) return { d2c: ax.d2c, c2d: ax.c2d }; + // if 'target' has corresponding axis + // -> use setConvert method + if(ax) return {d2c: ax.d2c, c2d: ax.c2d}; - // special case for 'ids' - // -> cast to String - if (d2cTarget === "ids") return { d2c: toString, c2d: toString }; + // special case for 'ids' + // -> cast to String + if(d2cTarget === 'ids') return {d2c: toString, c2d: toString}; - // otherwise (e.g. numeric-array of 'marker.color' or 'marker.size') - // -> cast to Number + // otherwise (e.g. numeric-array of 'marker.color' or 'marker.size') + // -> cast to Number - return { d2c: toNum, c2d: toNum }; -}); + return {d2c: toNum, c2d: toNum}; +}; -function toNum(v) { - return +v; -} -function toString(v) { - return String(v); -} +function toNum(v) { return +v; } +function toString(v) { return String(v); } -axes.getDataToCoordFunc = function (gd, trace, target, targetArray) { - return getDataConversions(gd, trace, target, targetArray).d2c; +axes.getDataToCoordFunc = function(gd, trace, target, targetArray) { + return getDataConversions(gd, trace, target, targetArray).d2c; }; // get counteraxis letter for this axis (name or id) // this can also be used as the id for default counter axis -axes.counterLetter = function (id) { - var axLetter = id.charAt(0); - if (axLetter === "x") return "y"; - if (axLetter === "y") return "x"; +axes.counterLetter = function(id) { + var axLetter = id.charAt(0); + if(axLetter === 'x') return 'y'; + if(axLetter === 'y') return 'x'; }; // incorporate a new minimum difference and first tick into // forced // note that _forceTick0 is linearized, so needs to be turned into // a range value for setting tick0 -axes.minDtick = function (ax, newDiff, newFirst, allow) { - // doesn't make sense to do forced min dTick on log or category axes, - // and the plot itself may decide to cancel (ie non-grouped bars) - if (["log", "category", "multicategory"].indexOf(ax.type) !== -1 || !allow) { - ax._minDtick = 0; - } else if (ax._minDtick === undefined) { - // undefined means there's nothing there yet - - ax._minDtick = newDiff; - ax._forceTick0 = newFirst; - } else if (ax._minDtick) { - if ( - (ax._minDtick / newDiff + 1e-6) % 1 < 2e-6 && - // existing minDtick is an integer multiple of newDiff - // (within rounding err) - // and forceTick0 can be shifted to newFirst - - ((((newFirst - ax._forceTick0) / newDiff) % 1) + 1.000001) % 1 < 2e-6 - ) { - ax._minDtick = newDiff; - ax._forceTick0 = newFirst; - } else if ( - (newDiff / ax._minDtick + 1e-6) % 1 > 2e-6 || - // if the converse is true (newDiff is a multiple of minDtick and - // newFirst can be shifted to forceTick0) then do nothing - same - // forcing stands. Otherwise, cancel forced minimum - - ((((newFirst - ax._forceTick0) / ax._minDtick) % 1) + 1.000001) % 1 > 2e-6 - ) { - ax._minDtick = 0; +axes.minDtick = function(ax, newDiff, newFirst, allow) { + // doesn't make sense to do forced min dTick on log or category axes, + // and the plot itself may decide to cancel (ie non-grouped bars) + if(['log', 'category', 'multicategory'].indexOf(ax.type) !== -1 || !allow) { + ax._minDtick = 0; + } else if(ax._minDtick === undefined) { + // undefined means there's nothing there yet + + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } else if(ax._minDtick) { + if((ax._minDtick / newDiff + 1e-6) % 1 < 2e-6 && + // existing minDtick is an integer multiple of newDiff + // (within rounding err) + // and forceTick0 can be shifted to newFirst + + (((newFirst - ax._forceTick0) / newDiff % 1) + + 1.000001) % 1 < 2e-6) { + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } else if((newDiff / ax._minDtick + 1e-6) % 1 > 2e-6 || + // if the converse is true (newDiff is a multiple of minDtick and + // newFirst can be shifted to forceTick0) then do nothing - same + // forcing stands. Otherwise, cancel forced minimum + + (((newFirst - ax._forceTick0) / ax._minDtick % 1) + + 1.000001) % 1 > 2e-6) { + ax._minDtick = 0; + } } - } }; // save a copy of the initial axis ranges in fullLayout // use them in mode bar and dblclick events -axes.saveRangeInitial = function (gd, overwrite) { - var axList = axes.list(gd, "", true); - var hasOneAxisChanged = false; - - for (var i = 0; i < axList.length; i++) { - var ax = axList[i]; - var isNew = - ax._rangeInitial0 === undefined && ax._rangeInitial1 === undefined; - - var hasChanged = - isNew || - ax.range[0] !== ax._rangeInitial0 || - ax.range[1] !== ax._rangeInitial1; - - var autorange = ax.autorange; - if ((isNew && autorange !== true) || (overwrite && hasChanged)) { - ax._rangeInitial0 = - autorange === "min" || autorange === "max reversed" - ? undefined - : ax.range[0]; - ax._rangeInitial1 = - autorange === "max" || autorange === "min reversed" - ? undefined - : ax.range[1]; - ax._autorangeInitial = autorange; - hasOneAxisChanged = true; - } - } - - return hasOneAxisChanged; +axes.saveRangeInitial = function(gd, overwrite) { + var axList = axes.list(gd, '', true); + var hasOneAxisChanged = false; + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + var isNew = + ax._rangeInitial0 === undefined && + ax._rangeInitial1 === undefined; + + var hasChanged = isNew || ( + ax.range[0] !== ax._rangeInitial0 || + ax.range[1] !== ax._rangeInitial1 + ); + + var autorange = ax.autorange; + if((isNew && autorange !== true) || (overwrite && hasChanged)) { + ax._rangeInitial0 = (autorange === 'min' || autorange === 'max reversed') ? undefined : ax.range[0]; + ax._rangeInitial1 = (autorange === 'max' || autorange === 'min reversed') ? undefined : ax.range[1]; + ax._autorangeInitial = autorange; + hasOneAxisChanged = true; + } + } + + return hasOneAxisChanged; }; // save a copy of the initial spike visibility -axes.saveShowSpikeInitial = function (gd, overwrite) { - var axList = axes.list(gd, "", true); - var hasOneAxisChanged = false; - var allSpikesEnabled = "on"; +axes.saveShowSpikeInitial = function(gd, overwrite) { + var axList = axes.list(gd, '', true); + var hasOneAxisChanged = false; + var allSpikesEnabled = 'on'; + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + var isNew = (ax._showSpikeInitial === undefined); + var hasChanged = isNew || !(ax.showspikes === ax._showspikes); + + if(isNew || (overwrite && hasChanged)) { + ax._showSpikeInitial = ax.showspikes; + hasOneAxisChanged = true; + } + + if(allSpikesEnabled === 'on' && !ax.showspikes) { + allSpikesEnabled = 'off'; + } + } + gd._fullLayout._cartesianSpikesEnabled = allSpikesEnabled; + return hasOneAxisChanged; +}; - for (var i = 0; i < axList.length; i++) { - var ax = axList[i]; - var isNew = ax._showSpikeInitial === undefined; - var hasChanged = isNew || !(ax.showspikes === ax._showspikes); +axes.autoBin = function(data, ax, nbins, is2d, calendar, size) { + var dataMin = Lib.aggNums(Math.min, null, data); + var dataMax = Lib.aggNums(Math.max, null, data); - if (isNew || (overwrite && hasChanged)) { - ax._showSpikeInitial = ax.showspikes; - hasOneAxisChanged = true; + if(ax.type === 'category' || ax.type === 'multicategory') { + return { + start: dataMin - 0.5, + end: dataMax + 0.5, + size: Math.max(1, Math.round(size) || 1), + _dataSpan: dataMax - dataMin, + }; } - if (allSpikesEnabled === "on" && !ax.showspikes) { - allSpikesEnabled = "off"; + if(!calendar) calendar = ax.calendar; + + // piggyback off tick code to make "nice" bin sizes and edges + var dummyAx; + if(ax.type === 'log') { + dummyAx = { + type: 'linear', + range: [dataMin, dataMax] + }; + } else { + dummyAx = { + type: ax.type, + range: Lib.simpleMap([dataMin, dataMax], ax.c2r, 0, calendar), + calendar: calendar + }; } - } - gd._fullLayout._cartesianSpikesEnabled = allSpikesEnabled; - return hasOneAxisChanged; -}; + axes.setConvert(dummyAx); -axes.autoBin = function (data, ax, nbins, is2d, calendar, size) { - var dataMin = Lib.aggNums(Math.min, null, data); - var dataMax = Lib.aggNums(Math.max, null, data); + size = size && cleanTicks.dtick(size, dummyAx.type); - if (ax.type === "category" || ax.type === "multicategory") { - return { - start: dataMin - 0.5, - end: dataMax + 0.5, - size: Math.max(1, Math.round(size) || 1), - _dataSpan: dataMax - dataMin, - }; - } + if(size) { + dummyAx.dtick = size; + dummyAx.tick0 = cleanTicks.tick0(undefined, dummyAx.type, calendar); + } else { + var size0; + if(nbins) size0 = ((dataMax - dataMin) / nbins); + else { + // totally auto: scale off std deviation so the highest bin is + // somewhat taller than the total number of bins, but don't let + // the size get smaller than the 'nice' rounded down minimum + // difference between values + var distinctData = Lib.distinctVals(data); + var msexp = Math.pow(10, Math.floor( + Math.log(distinctData.minDiff) / Math.LN10)); + var minSize = msexp * Lib.roundUp( + distinctData.minDiff / msexp, [0.9, 1.9, 4.9, 9.9], true); + size0 = Math.max(minSize, 2 * Lib.stdev(data) / + Math.pow(data.length, is2d ? 0.25 : 0.4)); + + // fallback if ax.d2c output BADNUMs + // e.g. when user try to plot categorical bins + // on a layout.xaxis.type: 'linear' + if(!isNumeric(size0)) size0 = 1; + } - if (!calendar) calendar = ax.calendar; + axes.autoTicks(dummyAx, size0); + } - // piggyback off tick code to make "nice" bin sizes and edges - var dummyAx; - if (ax.type === "log") { - dummyAx = { - type: "linear", - range: [dataMin, dataMax], - }; - } else { - dummyAx = { - type: ax.type, - range: Lib.simpleMap([dataMin, dataMax], ax.c2r, 0, calendar), - calendar: calendar, + var finalSize = dummyAx.dtick; + var binStart = axes.tickIncrement( + axes.tickFirst(dummyAx), finalSize, 'reverse', calendar); + var binEnd, bincount; + + // check for too many data points right at the edges of bins + // (>50% within 1% of bin edges) or all data points integral + // and offset the bins accordingly + if(typeof finalSize === 'number') { + binStart = autoShiftNumericBins(binStart, data, dummyAx, dataMin, dataMax); + + bincount = 1 + Math.floor((dataMax - binStart) / finalSize); + binEnd = binStart + bincount * finalSize; + } else { + // month ticks - should be the only nonlinear kind we have at this point. + // dtick (as supplied by axes.autoTick) only has nonlinear values on + // date and log axes, but even if you display a histogram on a log axis + // we bin it on a linear axis (which one could argue against, but that's + // a separate issue) + if(dummyAx.dtick.charAt(0) === 'M') { + binStart = autoShiftMonthBins(binStart, data, finalSize, dataMin, calendar); + } + + // calculate the endpoint for nonlinear ticks - you have to + // just increment until you're done + binEnd = binStart; + bincount = 0; + while(binEnd <= dataMax) { + binEnd = axes.tickIncrement(binEnd, finalSize, false, calendar); + bincount++; + } + } + + return { + start: ax.c2r(binStart, 0, calendar), + end: ax.c2r(binEnd, 0, calendar), + size: finalSize, + _dataSpan: dataMax - dataMin }; - } - axes.setConvert(dummyAx); - - size = size && cleanTicks.dtick(size, dummyAx.type); - - if (size) { - dummyAx.dtick = size; - dummyAx.tick0 = cleanTicks.tick0(undefined, dummyAx.type, calendar); - } else { - var size0; - if (nbins) size0 = (dataMax - dataMin) / nbins; - else { - // totally auto: scale off std deviation so the highest bin is - // somewhat taller than the total number of bins, but don't let - // the size get smaller than the 'nice' rounded down minimum - // difference between values - var distinctData = Lib.distinctVals(data); - var msexp = Math.pow( - 10, - Math.floor(Math.log(distinctData.minDiff) / Math.LN10) - ); - var minSize = - msexp * - Lib.roundUp(distinctData.minDiff / msexp, [0.9, 1.9, 4.9, 9.9], true); - size0 = Math.max( - minSize, - (2 * Lib.stdev(data)) / Math.pow(data.length, is2d ? 0.25 : 0.4) - ); - - // fallback if ax.d2c output BADNUMs - // e.g. when user try to plot categorical bins - // on a layout.xaxis.type: 'linear' - if (!isNumeric(size0)) size0 = 1; - } - - axes.autoTicks(dummyAx, size0); - } - - var finalSize = dummyAx.dtick; - var binStart = axes.tickIncrement( - axes.tickFirst(dummyAx), - finalSize, - "reverse", - calendar - ); - var binEnd, bincount; - - // check for too many data points right at the edges of bins - // (>50% within 1% of bin edges) or all data points integral - // and offset the bins accordingly - if (typeof finalSize === "number") { - binStart = autoShiftNumericBins(binStart, data, dummyAx, dataMin, dataMax); - - bincount = 1 + Math.floor((dataMax - binStart) / finalSize); - binEnd = binStart + bincount * finalSize; - } else { - // month ticks - should be the only nonlinear kind we have at this point. - // dtick (as supplied by axes.autoTick) only has nonlinear values on - // date and log axes, but even if you display a histogram on a log axis - // we bin it on a linear axis (which one could argue against, but that's - // a separate issue) - if (dummyAx.dtick.charAt(0) === "M") { - binStart = autoShiftMonthBins( - binStart, - data, - finalSize, - dataMin, - calendar - ); - } - - // calculate the endpoint for nonlinear ticks - you have to - // just increment until you're done - binEnd = binStart; - bincount = 0; - while (binEnd <= dataMax) { - binEnd = axes.tickIncrement(binEnd, finalSize, false, calendar); - bincount++; - } - } - - return { - start: ax.c2r(binStart, 0, calendar), - end: ax.c2r(binEnd, 0, calendar), - size: finalSize, - _dataSpan: dataMax - dataMin, - }; }; + function autoShiftNumericBins(binStart, data, ax, dataMin, dataMax) { - var edgecount = 0; - var midcount = 0; - var intcount = 0; - var blankCount = 0; - - function nearEdge(v) { - // is a value within 1% of a bin edge? - return (1 + ((v - binStart) * 100) / ax.dtick) % 100 < 2; - } - - for (var i = 0; i < data.length; i++) { - if (data[i] % 1 === 0) intcount++; - else if (!isNumeric(data[i])) blankCount++; - - if (nearEdge(data[i])) edgecount++; - if (nearEdge(data[i] + ax.dtick / 2)) midcount++; - } - var dataCount = data.length - blankCount; - - if (intcount === dataCount && ax.type !== "date") { - if (ax.dtick < 1) { - // all integers: if bin size is <1, it's because - // that was specifically requested (large nbins) - // so respect that... but center the bins containing - // integers on those integers - - binStart = dataMin - 0.5 * ax.dtick; - } else { - // otherwise start half an integer down regardless of - // the bin size, just enough to clear up endpoint - // ambiguity about which integers are in which bins. - - binStart -= 0.5; - if (binStart + ax.dtick < dataMin) binStart += ax.dtick; - } - } else if (midcount < dataCount * 0.1) { - if (edgecount > dataCount * 0.3 || nearEdge(dataMin) || nearEdge(dataMax)) { - // lots of points at the edge, not many in the middle - // shift half a bin - var binshift = ax.dtick / 2; - binStart += binStart + binshift < dataMin ? binshift : -binshift; - } - } - return binStart; + var edgecount = 0; + var midcount = 0; + var intcount = 0; + var blankCount = 0; + + function nearEdge(v) { + // is a value within 1% of a bin edge? + return (1 + (v - binStart) * 100 / ax.dtick) % 100 < 2; + } + + for(var i = 0; i < data.length; i++) { + if(data[i] % 1 === 0) intcount++; + else if(!isNumeric(data[i])) blankCount++; + + if(nearEdge(data[i])) edgecount++; + if(nearEdge(data[i] + ax.dtick / 2)) midcount++; + } + var dataCount = data.length - blankCount; + + if(intcount === dataCount && ax.type !== 'date') { + if(ax.dtick < 1) { + // all integers: if bin size is <1, it's because + // that was specifically requested (large nbins) + // so respect that... but center the bins containing + // integers on those integers + + binStart = dataMin - 0.5 * ax.dtick; + } else { + // otherwise start half an integer down regardless of + // the bin size, just enough to clear up endpoint + // ambiguity about which integers are in which bins. + + binStart -= 0.5; + if(binStart + ax.dtick < dataMin) binStart += ax.dtick; + } + } else if(midcount < dataCount * 0.1) { + if(edgecount > dataCount * 0.3 || + nearEdge(dataMin) || nearEdge(dataMax)) { + // lots of points at the edge, not many in the middle + // shift half a bin + var binshift = ax.dtick / 2; + binStart += (binStart + binshift < dataMin) ? binshift : -binshift; + } + } + return binStart; } + function autoShiftMonthBins(binStart, data, dtick, dataMin, calendar) { - var stats = Lib.findExactDates(data, calendar); - // number of data points that needs to be an exact value - // to shift that increment to (near) the bin center - var threshold = 0.8; - - if (stats.exactDays > threshold) { - var numMonths = Number(dtick.substr(1)); - - if (stats.exactYears > threshold && numMonths % 12 === 0) { - // The exact middle of a non-leap-year is 1.5 days into July - // so if we start the bins here, all but leap years will - // get hover-labeled as exact years. - binStart = axes.tickIncrement(binStart, "M6", "reverse") + ONEDAY * 1.5; - } else if (stats.exactMonths > threshold) { - // Months are not as clean, but if we shift half the *longest* - // month (31/2 days) then 31-day months will get labeled exactly - // and shorter months will get labeled with the correct month - // but shifted 12-36 hours into it. - binStart = axes.tickIncrement(binStart, "M1", "reverse") + ONEDAY * 15.5; - } else { - // Shifting half a day is exact, but since these are month bins it - // will always give a somewhat odd-looking label, until we do something - // smarter like showing the bin boundaries (or the bounds of the actual - // data in each bin) - binStart -= HALFDAY; - } - var nextBinStart = axes.tickIncrement(binStart, dtick); + var stats = Lib.findExactDates(data, calendar); + // number of data points that needs to be an exact value + // to shift that increment to (near) the bin center + var threshold = 0.8; + + if(stats.exactDays > threshold) { + var numMonths = Number(dtick.substr(1)); + + if((stats.exactYears > threshold) && (numMonths % 12 === 0)) { + // The exact middle of a non-leap-year is 1.5 days into July + // so if we start the bins here, all but leap years will + // get hover-labeled as exact years. + binStart = axes.tickIncrement(binStart, 'M6', 'reverse') + ONEDAY * 1.5; + } else if(stats.exactMonths > threshold) { + // Months are not as clean, but if we shift half the *longest* + // month (31/2 days) then 31-day months will get labeled exactly + // and shorter months will get labeled with the correct month + // but shifted 12-36 hours into it. + binStart = axes.tickIncrement(binStart, 'M1', 'reverse') + ONEDAY * 15.5; + } else { + // Shifting half a day is exact, but since these are month bins it + // will always give a somewhat odd-looking label, until we do something + // smarter like showing the bin boundaries (or the bounds of the actual + // data in each bin) + binStart -= HALFDAY; + } + var nextBinStart = axes.tickIncrement(binStart, dtick); - if (nextBinStart <= dataMin) return nextBinStart; - } - return binStart; + if(nextBinStart <= dataMin) return nextBinStart; + } + return binStart; } // ---------------------------------------------------- @@ -611,352 +558,346 @@ function autoShiftMonthBins(binStart, data, dtick, dataMin, calendar) { // ---------------------------------------------------- // ensure we have minor tick0 and dtick calculated -axes.prepMinorTicks = function (mockAx, ax, opts) { - if (!ax.minor.dtick) { - delete mockAx.dtick; - var hasMajor = ax.dtick && isNumeric(ax._tmin); - var mockMinorRange; - if (hasMajor) { - var tick2 = axes.tickIncrement(ax._tmin, ax.dtick, true); - // mock range a tiny bit smaller than one major tick interval - mockMinorRange = [ax._tmin, tick2 * 0.99 + ax._tmin * 0.01]; - } else { - var rl = Lib.simpleMap(ax.range, ax.r2l); - // If we don't have a major dtick, the concept of minor ticks is a little - // ambiguous - just take a stab and say minor.nticks should span 1/5 the axis - mockMinorRange = [rl[0], 0.8 * rl[0] + 0.2 * rl[1]]; - } - mockAx.range = Lib.simpleMap(mockMinorRange, ax.l2r); - mockAx._isMinor = true; - - axes.prepTicks(mockAx, opts); - - if (hasMajor) { - var numericMajor = isNumeric(ax.dtick); - var numericMinor = isNumeric(mockAx.dtick); - var majorNum = numericMajor ? ax.dtick : +ax.dtick.substring(1); - var minorNum = numericMinor ? mockAx.dtick : +mockAx.dtick.substring(1); - if (numericMajor && numericMinor) { - if (!isMultiple(majorNum, minorNum)) { - // give up on minor ticks - outside the below exceptions, - // this can only happen if minor.nticks is smaller than two jumps - // in the auto-tick scale and the first jump is not an even multiple - // (5 -> 2 or for dates 3 ->2, 15 -> 10 etc) or if you provided - // an explicit dtick, in which case it's fine to give up, - // you can provide an explicit minor.dtick. - if (majorNum === 2 * ONEWEEK && minorNum === 3 * ONEDAY) { - mockAx.dtick = ONEWEEK; - } else if (majorNum === ONEWEEK && !(ax._input.minor || {}).nticks) { - // minor.nticks defaults to 5, but in this one case we want 7, - // so the minor ticks show on all days of the week - mockAx.dtick = ONEDAY; - } else if (isClose(majorNum / minorNum, 2.5)) { - // 5*10^n -> 2*10^n and you've set nticks < 5 - // quarters are pretty common, we don't do this by default as it - // would add an extra digit to display, but minor has no labels - mockAx.dtick = majorNum / 2; - } else { - mockAx.dtick = majorNum; - } - } else if (majorNum === 2 * ONEWEEK && minorNum === 2 * ONEDAY) { - // this is a weird one: we don't want to automatically choose - // 2-day minor ticks for 2-week major, even though it IS an even multiple, - // because people would expect to see the weeks clearly - mockAx.dtick = ONEWEEK; - } - } else if (String(ax.dtick).charAt(0) === "M") { - if (numericMinor) { - mockAx.dtick = "M1"; +axes.prepMinorTicks = function(mockAx, ax, opts) { + if(!ax.minor.dtick) { + delete mockAx.dtick; + var hasMajor = ax.dtick && isNumeric(ax._tmin); + var mockMinorRange; + if(hasMajor) { + var tick2 = axes.tickIncrement(ax._tmin, ax.dtick, true); + // mock range a tiny bit smaller than one major tick interval + mockMinorRange = [ax._tmin, tick2 * 0.99 + ax._tmin * 0.01]; } else { - if (!isMultiple(majorNum, minorNum)) { - // unless you provided an explicit ax.dtick (in which case - // it's OK for us to give up, you can provide an explicit - // minor.dtick too), this can only happen with: - // minor.nticks < 3 and dtick === M3, or - // minor.nticks < 5 and dtick === 5 * 10^n years - // so in all cases we just give up. - mockAx.dtick = ax.dtick; - } else if (majorNum >= 12 && minorNum === 2) { - // another special carve-out: for year major ticks, don't show - // 2-month minor ticks, bump to quarters - mockAx.dtick = "M3"; - } + var rl = Lib.simpleMap(ax.range, ax.r2l); + // If we don't have a major dtick, the concept of minor ticks is a little + // ambiguous - just take a stab and say minor.nticks should span 1/5 the axis + mockMinorRange = [rl[0], 0.8 * rl[0] + 0.2 * rl[1]]; } - } else if (String(mockAx.dtick).charAt(0) === "L") { - if (String(ax.dtick).charAt(0) === "L") { - if (!isMultiple(majorNum, minorNum)) { - mockAx.dtick = isClose(majorNum / minorNum, 2.5) - ? ax.dtick / 2 - : ax.dtick; - } - } else { - mockAx.dtick = "D1"; + mockAx.range = Lib.simpleMap(mockMinorRange, ax.l2r); + mockAx._isMinor = true; + + axes.prepTicks(mockAx, opts); + + if(hasMajor) { + var numericMajor = isNumeric(ax.dtick); + var numericMinor = isNumeric(mockAx.dtick); + var majorNum = numericMajor ? ax.dtick : +ax.dtick.substring(1); + var minorNum = numericMinor ? mockAx.dtick : +mockAx.dtick.substring(1); + if(numericMajor && numericMinor) { + if(!isMultiple(majorNum, minorNum)) { + // give up on minor ticks - outside the below exceptions, + // this can only happen if minor.nticks is smaller than two jumps + // in the auto-tick scale and the first jump is not an even multiple + // (5 -> 2 or for dates 3 ->2, 15 -> 10 etc) or if you provided + // an explicit dtick, in which case it's fine to give up, + // you can provide an explicit minor.dtick. + if((majorNum === 2 * ONEWEEK) && (minorNum === 3 * ONEDAY)) { + mockAx.dtick = ONEWEEK; + } else if(majorNum === ONEWEEK && !(ax._input.minor || {}).nticks) { + // minor.nticks defaults to 5, but in this one case we want 7, + // so the minor ticks show on all days of the week + mockAx.dtick = ONEDAY; + } else if(isClose(majorNum / minorNum, 2.5)) { + // 5*10^n -> 2*10^n and you've set nticks < 5 + // quarters are pretty common, we don't do this by default as it + // would add an extra digit to display, but minor has no labels + mockAx.dtick = majorNum / 2; + } else { + mockAx.dtick = majorNum; + } + } else if(majorNum === 2 * ONEWEEK && minorNum === 2 * ONEDAY) { + // this is a weird one: we don't want to automatically choose + // 2-day minor ticks for 2-week major, even though it IS an even multiple, + // because people would expect to see the weeks clearly + mockAx.dtick = ONEWEEK; + } + } else if(String(ax.dtick).charAt(0) === 'M') { + if(numericMinor) { + mockAx.dtick = 'M1'; + } else { + if(!isMultiple(majorNum, minorNum)) { + // unless you provided an explicit ax.dtick (in which case + // it's OK for us to give up, you can provide an explicit + // minor.dtick too), this can only happen with: + // minor.nticks < 3 and dtick === M3, or + // minor.nticks < 5 and dtick === 5 * 10^n years + // so in all cases we just give up. + mockAx.dtick = ax.dtick; + } else if((majorNum >= 12) && (minorNum === 2)) { + // another special carve-out: for year major ticks, don't show + // 2-month minor ticks, bump to quarters + mockAx.dtick = 'M3'; + } + } + } else if(String(mockAx.dtick).charAt(0) === 'L') { + if(String(ax.dtick).charAt(0) === 'L') { + if(!isMultiple(majorNum, minorNum)) { + mockAx.dtick = isClose(majorNum / minorNum, 2.5) ? (ax.dtick / 2) : ax.dtick; + } + } else { + mockAx.dtick = 'D1'; + } + } else if(mockAx.dtick === 'D2' && +ax.dtick > 1) { + // the D2 log axis tick spacing is confusing for unlabeled minor ticks if + // the major dtick is more than one order of magnitude. + mockAx.dtick = 1; + } } - } else if (mockAx.dtick === "D2" && +ax.dtick > 1) { - // the D2 log axis tick spacing is confusing for unlabeled minor ticks if - // the major dtick is more than one order of magnitude. - mockAx.dtick = 1; - } - } - // put back the original range, to use to find the full set of minor ticks - mockAx.range = ax.range; - } - if (ax.minor._tick0Init === undefined) { - // ensure identical tick0 - mockAx.tick0 = ax.tick0; - } + // put back the original range, to use to find the full set of minor ticks + mockAx.range = ax.range; + } + if(ax.minor._tick0Init === undefined) { + // ensure identical tick0 + mockAx.tick0 = ax.tick0; + } }; function isMultiple(bigger, smaller) { - return Math.abs(((bigger / smaller + 0.5) % 1) - 0.5) < 0.001; + return Math.abs((bigger / smaller + 0.5) % 1 - 0.5) < 0.001; } function isClose(a, b) { - return Math.abs(a / b - 1) < 0.001; + return Math.abs((a / b) - 1) < 0.001; } // ensure we have tick0, dtick, and tick rounding calculated -axes.prepTicks = function (ax, opts) { - var rng = Lib.simpleMap(ax.range, ax.r2l, undefined, undefined, opts); +axes.prepTicks = function(ax, opts) { + var rng = Lib.simpleMap(ax.range, ax.r2l, undefined, undefined, opts); + + // calculate max number of (auto) ticks to display based on plot size + if(ax.tickmode === 'auto' || !ax.dtick) { + var nt = ax.nticks; + var minPx; + + if(!nt) { + if(ax.type === 'category' || ax.type === 'multicategory') { + minPx = ax.tickfont ? Lib.bigFont(ax.tickfont.size || 12) : 15; + nt = ax._length / minPx; + } else { + minPx = ax._id.charAt(0) === 'y' ? 40 : 80; + nt = Lib.constrain(ax._length / minPx, 4, 9) + 1; + } + + // radial axes span half their domain, + // multiply nticks value by two to get correct number of auto ticks. + if(ax._name === 'radialaxis') nt *= 2; + } - // calculate max number of (auto) ticks to display based on plot size - if (ax.tickmode === "auto" || !ax.dtick) { - var nt = ax.nticks; - var minPx; + if(!(ax.minor && ax.minor.tickmode !== 'array')) { + // add a couple of extra digits for filling in ticks when we + // have explicit tickvals without tick text + if(ax.tickmode === 'array') nt *= 100; + } - if (!nt) { - if (ax.type === "category" || ax.type === "multicategory") { - minPx = ax.tickfont ? Lib.bigFont(ax.tickfont.size || 12) : 15; - nt = ax._length / minPx; - } else { - minPx = ax._id.charAt(0) === "y" ? 40 : 80; - nt = Lib.constrain(ax._length / minPx, 4, 9) + 1; - } + ax._roughDTick = Math.abs(rng[1] - rng[0]) / nt; + axes.autoTicks(ax, ax._roughDTick); - // radial axes span half their domain, - // multiply nticks value by two to get correct number of auto ticks. - if (ax._name === "radialaxis") nt *= 2; + // check for a forced minimum dtick + if(ax._minDtick > 0 && ax.dtick < ax._minDtick * 2) { + ax.dtick = ax._minDtick; + ax.tick0 = ax.l2r(ax._forceTick0); + } } - if (!(ax.minor && ax.minor.tickmode !== "array")) { - // add a couple of extra digits for filling in ticks when we - // have explicit tickvals without tick text - if (ax.tickmode === "array") nt *= 100; + if(ax.ticklabelmode === 'period') { + adjustPeriodDelta(ax); } - ax._roughDTick = Math.abs(rng[1] - rng[0]) / nt; - axes.autoTicks(ax, ax._roughDTick); - - // check for a forced minimum dtick - if (ax._minDtick > 0 && ax.dtick < ax._minDtick * 2) { - ax.dtick = ax._minDtick; - ax.tick0 = ax.l2r(ax._forceTick0); + // check for missing tick0 + if(!ax.tick0) { + ax.tick0 = (ax.type === 'date') ? '2000-01-01' : 0; } - } - - if (ax.ticklabelmode === "period") { - adjustPeriodDelta(ax); - } - - // check for missing tick0 - if (!ax.tick0) { - ax.tick0 = ax.type === "date" ? "2000-01-01" : 0; - } - // ensure we don't try to make ticks below our minimum precision - // see https://github.com/plotly/plotly.js/issues/2892 - if (ax.type === "date" && ax.dtick < 0.1) ax.dtick = 0.1; + // ensure we don't try to make ticks below our minimum precision + // see https://github.com/plotly/plotly.js/issues/2892 + if(ax.type === 'date' && ax.dtick < 0.1) ax.dtick = 0.1; - // now figure out rounding of tick values - autoTickRound(ax); + // now figure out rounding of tick values + autoTickRound(ax); }; function nMonths(dtick) { - return +dtick.substring(1); + return +(dtick.substring(1)); } -function adjustPeriodDelta(ax) { - // adjusts ax.dtick and sets ax._definedDelta - var definedDelta; - - function mDate() { - return !(isNumeric(ax.dtick) || ax.dtick.charAt(0) !== "M"); - } - var isMDate = mDate(); - var tickformat = axes.getTickFormat(ax); - if (tickformat) { - var noDtick = ax._dtickInit !== ax.dtick; - if ( - !/%[fLQsSMX]/.test(tickformat) - // %f: microseconds as a decimal number [000000, 999999] - // %L: milliseconds as a decimal number [000, 999] - // %Q: milliseconds since UNIX epoch - // %s: seconds since UNIX epoch - // %S: second as a decimal number [00,61] - // %M: minute as a decimal number [00,59] - // %X: the locale’s time, such as %-I:%M:%S %p - ) { - if ( - /%[HI]/.test(tickformat) - // %H: hour (24-hour clock) as a decimal number [00,23] - // %I: hour (12-hour clock) as a decimal number [01,12] - ) { - definedDelta = ONEHOUR; - if (noDtick && !isMDate && ax.dtick < ONEHOUR) ax.dtick = ONEHOUR; - } else if ( - /%p/.test(tickformat) // %p: either AM or PM - ) { - definedDelta = HALFDAY; - if (noDtick && !isMDate && ax.dtick < HALFDAY) ax.dtick = HALFDAY; - } else if ( - /%[Aadejuwx]/.test(tickformat) - // %A: full weekday name - // %a: abbreviated weekday name - // %d: zero-padded day of the month as a decimal number [01,31] - // %e: space-padded day of the month as a decimal number [ 1,31] - // %j: day of the year as a decimal number [001,366] - // %u: Monday-based (ISO 8601) weekday as a decimal number [1,7] - // %w: Sunday-based weekday as a decimal number [0,6] - // %x: the locale’s date, such as %-m/%-d/%Y - ) { - definedDelta = ONEDAY; - if (noDtick && !isMDate && ax.dtick < ONEDAY) ax.dtick = ONEDAY; - } else if ( - /%[UVW]/.test(tickformat) - // %U: Sunday-based week of the year as a decimal number [00,53] - // %V: ISO 8601 week of the year as a decimal number [01, 53] - // %W: Monday-based week of the year as a decimal number [00,53] - ) { - definedDelta = ONEWEEK; - if (noDtick && !isMDate && ax.dtick < ONEWEEK) ax.dtick = ONEWEEK; - } else if ( - /%[Bbm]/.test(tickformat) - // %B: full month name - // %b: abbreviated month name - // %m: month as a decimal number [01,12] - ) { - definedDelta = ONEAVGMONTH; - if ( - noDtick && - (isMDate ? nMonths(ax.dtick) < 1 : ax.dtick < ONEMINMONTH) - ) - ax.dtick = "M1"; - } else if ( - /%[q]/.test(tickformat) - // %q: quarter of the year as a decimal number [1,4] - ) { - definedDelta = ONEAVGQUARTER; - if ( - noDtick && - (isMDate ? nMonths(ax.dtick) < 3 : ax.dtick < ONEMINQUARTER) - ) - ax.dtick = "M3"; - } else if ( - /%[Yy]/.test(tickformat) - // %Y: year with century as a decimal number, such as 1999 - // %y: year without century as a decimal number [00,99] - ) { - definedDelta = ONEAVGYEAR; - if ( - noDtick && - (isMDate ? nMonths(ax.dtick) < 12 : ax.dtick < ONEMINYEAR) - ) - ax.dtick = "M12"; - } +function adjustPeriodDelta(ax) { // adjusts ax.dtick and sets ax._definedDelta + var definedDelta; + + function mDate() { + return !( + isNumeric(ax.dtick) || + ax.dtick.charAt(0) !== 'M' + ); + } + var isMDate = mDate(); + var tickformat = axes.getTickFormat(ax); + if(tickformat) { + var noDtick = ax._dtickInit !== ax.dtick; + if( + !(/%[fLQsSMX]/.test(tickformat)) + // %f: microseconds as a decimal number [000000, 999999] + // %L: milliseconds as a decimal number [000, 999] + // %Q: milliseconds since UNIX epoch + // %s: seconds since UNIX epoch + // %S: second as a decimal number [00,61] + // %M: minute as a decimal number [00,59] + // %X: the locale’s time, such as %-I:%M:%S %p + ) { + if( + /%[HI]/.test(tickformat) + // %H: hour (24-hour clock) as a decimal number [00,23] + // %I: hour (12-hour clock) as a decimal number [01,12] + ) { + definedDelta = ONEHOUR; + if(noDtick && !isMDate && ax.dtick < ONEHOUR) ax.dtick = ONEHOUR; + } else if( + /%p/.test(tickformat) // %p: either AM or PM + ) { + definedDelta = HALFDAY; + if(noDtick && !isMDate && ax.dtick < HALFDAY) ax.dtick = HALFDAY; + } else if( + /%[Aadejuwx]/.test(tickformat) + // %A: full weekday name + // %a: abbreviated weekday name + // %d: zero-padded day of the month as a decimal number [01,31] + // %e: space-padded day of the month as a decimal number [ 1,31] + // %j: day of the year as a decimal number [001,366] + // %u: Monday-based (ISO 8601) weekday as a decimal number [1,7] + // %w: Sunday-based weekday as a decimal number [0,6] + // %x: the locale’s date, such as %-m/%-d/%Y + ) { + definedDelta = ONEDAY; + if(noDtick && !isMDate && ax.dtick < ONEDAY) ax.dtick = ONEDAY; + } else if( + /%[UVW]/.test(tickformat) + // %U: Sunday-based week of the year as a decimal number [00,53] + // %V: ISO 8601 week of the year as a decimal number [01, 53] + // %W: Monday-based week of the year as a decimal number [00,53] + ) { + definedDelta = ONEWEEK; + if(noDtick && !isMDate && ax.dtick < ONEWEEK) ax.dtick = ONEWEEK; + } else if( + /%[Bbm]/.test(tickformat) + // %B: full month name + // %b: abbreviated month name + // %m: month as a decimal number [01,12] + ) { + definedDelta = ONEAVGMONTH; + if(noDtick && ( + isMDate ? nMonths(ax.dtick) < 1 : ax.dtick < ONEMINMONTH) + ) ax.dtick = 'M1'; + } else if( + /%[q]/.test(tickformat) + // %q: quarter of the year as a decimal number [1,4] + ) { + definedDelta = ONEAVGQUARTER; + if(noDtick && ( + isMDate ? nMonths(ax.dtick) < 3 : ax.dtick < ONEMINQUARTER) + ) ax.dtick = 'M3'; + } else if( + /%[Yy]/.test(tickformat) + // %Y: year with century as a decimal number, such as 1999 + // %y: year without century as a decimal number [00,99] + ) { + definedDelta = ONEAVGYEAR; + if(noDtick && ( + isMDate ? nMonths(ax.dtick) < 12 : ax.dtick < ONEMINYEAR) + ) ax.dtick = 'M12'; + } + } } - } - isMDate = mDate(); - if (isMDate && ax.tick0 === ax._dowTick0) { - // discard Sunday/Monday tweaks - ax.tick0 = ax._rawTick0; - } + isMDate = mDate(); + if(isMDate && ax.tick0 === ax._dowTick0) { + // discard Sunday/Monday tweaks + ax.tick0 = ax._rawTick0; + } - ax._definedDelta = definedDelta; + ax._definedDelta = definedDelta; } function positionPeriodTicks(tickVals, ax, definedDelta) { - for (var i = 0; i < tickVals.length; i++) { - var v = tickVals[i].value; - - var a = i; - var b = i + 1; - if (i < tickVals.length - 1) { - a = i; - b = i + 1; - } else if (i > 0) { - a = i - 1; - b = i; - } else { - a = i; - b = i; - } - - var A = tickVals[a].value; - var B = tickVals[b].value; - var actualDelta = Math.abs(B - A); - var delta = definedDelta || actualDelta; - var periodLength = 0; - - if (delta >= ONEMINYEAR) { - if (actualDelta >= ONEMINYEAR && actualDelta <= ONEMAXYEAR) { - periodLength = actualDelta; - } else { - periodLength = ONEAVGYEAR; - } - } else if (definedDelta === ONEAVGQUARTER && delta >= ONEMINQUARTER) { - if (actualDelta >= ONEMINQUARTER && actualDelta <= ONEMAXQUARTER) { - periodLength = actualDelta; - } else { - periodLength = ONEAVGQUARTER; - } - } else if (delta >= ONEMINMONTH) { - if (actualDelta >= ONEMINMONTH && actualDelta <= ONEMAXMONTH) { - periodLength = actualDelta; - } else { - periodLength = ONEAVGMONTH; - } - } else if (definedDelta === ONEWEEK && delta >= ONEWEEK) { - periodLength = ONEWEEK; - } else if (delta >= ONEDAY) { - periodLength = ONEDAY; - } else if (definedDelta === HALFDAY && delta >= HALFDAY) { - periodLength = HALFDAY; - } else if (definedDelta === ONEHOUR && delta >= ONEHOUR) { - periodLength = ONEHOUR; - } - - var inBetween; - if (periodLength >= actualDelta) { - // ensure new label positions remain between ticks - periodLength = actualDelta; - inBetween = true; - } - - var endPeriod = v + periodLength; - if (ax.rangebreaks && periodLength > 0) { - var nAll = 84; // highly divisible 7 * 12 - var n = 0; - for (var c = 0; c < nAll; c++) { - var r = (c + 0.5) / nAll; - if (ax.maskBreaks(v * (1 - r) + r * endPeriod) !== BADNUM) n++; - } - periodLength *= n / nAll; - - if (!periodLength) { - tickVals[i].drop = true; - } - - if (inBetween && actualDelta > ONEWEEK) periodLength = actualDelta; // center monthly & longer periods - } - - if ( - periodLength > 0 || // not instant - i === 0 // taking care first tick added - ) { - tickVals[i].periodX = v + periodLength / 2; + for(var i = 0; i < tickVals.length; i++) { + var v = tickVals[i].value; + + var a = i; + var b = i + 1; + if(i < tickVals.length - 1) { + a = i; + b = i + 1; + } else if(i > 0) { + a = i - 1; + b = i; + } else { + a = i; + b = i; + } + + var A = tickVals[a].value; + var B = tickVals[b].value; + var actualDelta = Math.abs(B - A); + var delta = definedDelta || actualDelta; + var periodLength = 0; + + if(delta >= ONEMINYEAR) { + if(actualDelta >= ONEMINYEAR && actualDelta <= ONEMAXYEAR) { + periodLength = actualDelta; + } else { + periodLength = ONEAVGYEAR; + } + } else if(definedDelta === ONEAVGQUARTER && delta >= ONEMINQUARTER) { + if(actualDelta >= ONEMINQUARTER && actualDelta <= ONEMAXQUARTER) { + periodLength = actualDelta; + } else { + periodLength = ONEAVGQUARTER; + } + } else if(delta >= ONEMINMONTH) { + if(actualDelta >= ONEMINMONTH && actualDelta <= ONEMAXMONTH) { + periodLength = actualDelta; + } else { + periodLength = ONEAVGMONTH; + } + } else if(definedDelta === ONEWEEK && delta >= ONEWEEK) { + periodLength = ONEWEEK; + } else if(delta >= ONEDAY) { + periodLength = ONEDAY; + } else if(definedDelta === HALFDAY && delta >= HALFDAY) { + periodLength = HALFDAY; + } else if(definedDelta === ONEHOUR && delta >= ONEHOUR) { + periodLength = ONEHOUR; + } + + var inBetween; + if(periodLength >= actualDelta) { + // ensure new label positions remain between ticks + periodLength = actualDelta; + inBetween = true; + } + + var endPeriod = v + periodLength; + if(ax.rangebreaks && periodLength > 0) { + var nAll = 84; // highly divisible 7 * 12 + var n = 0; + for(var c = 0; c < nAll; c++) { + var r = (c + 0.5) / nAll; + if(ax.maskBreaks(v * (1 - r) + r * endPeriod) !== BADNUM) n++; + } + periodLength *= n / nAll; + + if(!periodLength) { + tickVals[i].drop = true; + } + + if(inBetween && actualDelta > ONEWEEK) periodLength = actualDelta; // center monthly & longer periods + } + + if( + periodLength > 0 || // not instant + i === 0 // taking care first tick added + ) { + tickVals[i].periodX = v + periodLength / 2; + } } - } } // calculate the ticks: text, values, positioning @@ -964,475 +905,466 @@ function positionPeriodTicks(tickVals, ax, definedDelta) { // in any case, set tickround to # of digits to round tick labels to, // or codes to this effect for log and date scales axes.calcTicks = function calcTicks(ax, opts) { - var type = ax.type; - var calendar = ax.calendar; - var ticklabelstep = ax.ticklabelstep; - var isPeriod = ax.ticklabelmode === "period"; - var isReversed = ax.range[0] > ax.range[1]; - var ticklabelIndex = - !ax.ticklabelindex || Lib.isArrayOrTypedArray(ax.ticklabelindex) - ? ax.ticklabelindex - : [ax.ticklabelindex]; - var rng = Lib.simpleMap(ax.range, ax.r2l, undefined, undefined, opts); - var axrev = rng[1] < rng[0]; - var minRange = Math.min(rng[0], rng[1]); - var maxRange = Math.max(rng[0], rng[1]); - - var maxTicks = Math.max(1000, ax._length || 0); - - var ticksOut = []; - var minorTicks = []; - - var tickVals = []; - var minorTickVals = []; - // all ticks for which labels are drawn which is not necessarily the major ticks when - // `ticklabelindex` is set. - var allTicklabelVals = []; - - var hasMinor = ax.minor && (ax.minor.ticks || ax.minor.showgrid); - - // calc major first - for (var major = 1; major >= (hasMinor ? 0 : 1); major--) { - var isMinor = !major; - - if (major) { - ax._dtickInit = ax.dtick; - ax._tick0Init = ax.tick0; - } else { - ax.minor._dtickInit = ax.minor.dtick; - ax.minor._tick0Init = ax.minor.tick0; - } + var type = ax.type; + var calendar = ax.calendar; + var ticklabelstep = ax.ticklabelstep; + var isPeriod = ax.ticklabelmode === 'period'; + var isReversed = ax.range[0] > ax.range[1]; + var ticklabelIndex = (!ax.ticklabelindex || Lib.isArrayOrTypedArray(ax.ticklabelindex)) ? + ax.ticklabelindex : [ax.ticklabelindex]; + var rng = Lib.simpleMap(ax.range, ax.r2l, undefined, undefined, opts); + var axrev = (rng[1] < rng[0]); + var minRange = Math.min(rng[0], rng[1]); + var maxRange = Math.max(rng[0], rng[1]); + + var maxTicks = Math.max(1000, ax._length || 0); + + var ticksOut = []; + var minorTicks = []; + + var tickVals = []; + var minorTickVals = []; + // all ticks for which labels are drawn which is not necessarily the major ticks when + // `ticklabelindex` is set. + var allTicklabelVals = []; + + var hasMinor = ax.minor && (ax.minor.ticks || ax.minor.showgrid); + + // calc major first + for(var major = 1; major >= (hasMinor ? 0 : 1); major--) { + var isMinor = !major; + + if(major) { + ax._dtickInit = ax.dtick; + ax._tick0Init = ax.tick0; + } else { + ax.minor._dtickInit = ax.minor.dtick; + ax.minor._tick0Init = ax.minor.tick0; + } - var mockAx = major ? ax : Lib.extendFlat({}, ax, ax.minor); + var mockAx = major ? ax : Lib.extendFlat({}, ax, ax.minor); - if (isMinor) { - axes.prepMinorTicks(mockAx, ax, opts); - } else { - axes.prepTicks(mockAx, opts); - } + if(isMinor) { + axes.prepMinorTicks(mockAx, ax, opts); + } else { + axes.prepTicks(mockAx, opts); + } - // now that we've figured out the auto values for formatting - // in case we're missing some ticktext, we can break out for array ticks - if (mockAx.tickmode === "array") { - if (major) { - tickVals = []; - ticksOut = arrayTicks(ax, !isMinor); - } else { - minorTickVals = []; - minorTicks = arrayTicks(ax, !isMinor); - } - continue; - } + // now that we've figured out the auto values for formatting + // in case we're missing some ticktext, we can break out for array ticks + if(mockAx.tickmode === 'array') { + if(major) { + tickVals = []; + ticksOut = arrayTicks(ax, !isMinor); + } else { + minorTickVals = []; + minorTicks = arrayTicks(ax, !isMinor); + } + continue; + } - // fill tickVals based on overlaying axis - if (mockAx.tickmode === "sync") { - tickVals = []; - ticksOut = syncTicks(ax); - continue; - } + // fill tickVals based on overlaying axis + if(mockAx.tickmode === 'sync') { + tickVals = []; + ticksOut = syncTicks(ax); + continue; + } - // add a tiny bit so we get ticks which may have rounded out - var exRng = expandRange(rng); - var startTick = exRng[0]; - var endTick = exRng[1]; - - var numDtick = isNumeric(mockAx.dtick); - var isDLog = - type === "log" && !(numDtick || mockAx.dtick.charAt(0) === "L"); - - // find the first tick - var x0 = axes.tickFirst(mockAx, opts); - - if (major) { - ax._tmin = x0; - - // No visible ticks? Quit. - // I've only seen this on category axes with all categories off the edge. - if (x0 < startTick !== axrev) break; - - // return the full set of tick vals - if (type === "category" || type === "multicategory") { - endTick = axrev - ? Math.max(-0.5, endTick) - : Math.min(ax._categories.length - 0.5, endTick); - } - } - - var prevX = null; - var x = x0; - var majorId; - - if (major) { - // ids for ticklabelstep - var _dTick; - if (numDtick) { - _dTick = ax.dtick; - } else { - if (type === "date") { - if (typeof ax.dtick === "string" && ax.dtick.charAt(0) === "M") { - _dTick = ONEAVGMONTH * ax.dtick.substring(1); - } - } else { - _dTick = ax._roughDTick; + // add a tiny bit so we get ticks which may have rounded out + var exRng = expandRange(rng); + var startTick = exRng[0]; + var endTick = exRng[1]; + + var numDtick = isNumeric(mockAx.dtick); + var isDLog = (type === 'log') && !(numDtick || mockAx.dtick.charAt(0) === 'L'); + + // find the first tick + var x0 = axes.tickFirst(mockAx, opts); + + if(major) { + ax._tmin = x0; + + // No visible ticks? Quit. + // I've only seen this on category axes with all categories off the edge. + if((x0 < startTick) !== axrev) break; + + // return the full set of tick vals + if(type === 'category' || type === 'multicategory') { + endTick = (axrev) ? Math.max(-0.5, endTick) : + Math.min(ax._categories.length - 0.5, endTick); + } } - } - majorId = Math.round((ax.r2l(x) - ax.r2l(ax.tick0)) / _dTick) - 1; - } + var prevX = null; + var x = x0; + var majorId; + + if(major) { + // ids for ticklabelstep + var _dTick; + if(numDtick) { + _dTick = ax.dtick; + } else { + if(type === 'date') { + if(typeof ax.dtick === 'string' && ax.dtick.charAt(0) === 'M') { + _dTick = ONEAVGMONTH * ax.dtick.substring(1); + } + } else { + _dTick = ax._roughDTick; + } + } + + majorId = Math.round(( + ax.r2l(x) - + ax.r2l(ax.tick0) + ) / _dTick) - 1; + } - var dtick = mockAx.dtick; + var dtick = mockAx.dtick; - if (mockAx.rangebreaks && mockAx._tick0Init !== mockAx.tick0) { - // adjust tick0 - x = moveOutsideBreak(x, ax); - if (!axrev) { - x = axes.tickIncrement(x, dtick, !axrev, calendar); - } + if(mockAx.rangebreaks && mockAx._tick0Init !== mockAx.tick0) { + // adjust tick0 + x = moveOutsideBreak(x, ax); + if(!axrev) { + x = axes.tickIncrement(x, dtick, !axrev, calendar); + } + } + + if(major && isPeriod) { + // add one item to label period before tick0 + x = axes.tickIncrement(x, dtick, !axrev, calendar); + majorId--; + } + + for(; + axrev ? + (x >= endTick) : + (x <= endTick); + x = axes.tickIncrement( + x, + dtick, + axrev, + calendar + ) + ) { + if(major) majorId++; + + if(mockAx.rangebreaks) { + if(!axrev) { + if(x < startTick) continue; + if(mockAx.maskBreaks(x) === BADNUM && moveOutsideBreak(x, mockAx) >= maxRange) break; + } + } + + // prevent infinite loops - no more than one tick per pixel, + // and make sure each value is different from the previous + if(tickVals.length > maxTicks || x === prevX) break; + prevX = x; + + var obj = { value: x }; + + if(major) { + if(isDLog && (x !== (x | 0))) { + obj.simpleLabel = true; + } + + if(ticklabelstep > 1 && majorId % ticklabelstep) { + obj.skipLabel = true; + } + + tickVals.push(obj); + } else { + obj.minor = true; + + minorTickVals.push(obj); + } + } } - if (major && isPeriod) { - // add one item to label period before tick0 - x = axes.tickIncrement(x, dtick, !axrev, calendar); - majorId--; + // check if ticklabelIndex makes sense, otherwise ignore it + if(!minorTickVals || minorTickVals.length < 2) { + ticklabelIndex = false; + } else { + var diff = (minorTickVals[1].value - minorTickVals[0].value) * (isReversed ? -1 : 1); + if(!periodCompatibleWithTickformat(diff, ax.tickformat)) { + ticklabelIndex = false; + } } + // Determine for which ticks to draw labels + if(!ticklabelIndex) { + allTicklabelVals = tickVals; + } else { + // Collect and sort all major and minor ticks, to find the minor ticks `ticklabelIndex` + // steps away from each major tick. For those minor ticks we want to draw the label. - for ( - ; - axrev ? x >= endTick : x <= endTick; - x = axes.tickIncrement(x, dtick, axrev, calendar) - ) { - if (major) majorId++; - - if (mockAx.rangebreaks) { - if (!axrev) { - if (x < startTick) continue; - if ( - mockAx.maskBreaks(x) === BADNUM && - moveOutsideBreak(x, mockAx) >= maxRange - ) - break; + var allTickVals = tickVals.concat(minorTickVals); + if(isPeriod && tickVals.length) { + // first major tick was just added for period handling + allTickVals = allTickVals.slice(1); } - } - // prevent infinite loops - no more than one tick per pixel, - // and make sure each value is different from the previous - if (tickVals.length > maxTicks || x === prevX) break; - prevX = x; + allTickVals = + allTickVals + .sort(function(a, b) { return a.value - b.value; }) + .filter(function(tick, index, self) { + return index === 0 || tick.value !== self[index - 1].value; + }); - var obj = { value: x }; + var majorTickIndices = + allTickVals + .map(function(item, index) { + return item.minor === undefined && !item.skipLabel ? index : null; + }) + .filter(function(index) { return index !== null; }); + + majorTickIndices.forEach(function(majorIdx) { + ticklabelIndex.map(function(nextLabelIdx) { + var minorIdx = majorIdx + nextLabelIdx; + if(minorIdx >= 0 && minorIdx < allTickVals.length) { + Lib.pushUnique(allTicklabelVals, allTickVals[minorIdx]); + } + }); + }); + } - if (major) { - if (isDLog && x !== (x | 0)) { - obj.simpleLabel = true; + if(hasMinor) { + var canOverlap = + (ax.minor.ticks === 'inside' && ax.ticks === 'outside') || + (ax.minor.ticks === 'outside' && ax.ticks === 'inside'); + + if(!canOverlap) { + // remove duplicate minors + + var majorValues = tickVals.map(function(d) { return d.value; }); + + var list = []; + for(var k = 0; k < minorTickVals.length; k++) { + var T = minorTickVals[k]; + var v = T.value; + if(majorValues.indexOf(v) !== -1) { + continue; + } + var found = false; + for(var q = 0; !found && (q < tickVals.length); q++) { + if( + // add 10e6 to eliminate problematic digits + 10e6 + tickVals[q].value === + 10e6 + v + ) { + found = true; + } + } + if(!found) list.push(T); + } + minorTickVals = list; } + } - if (ticklabelstep > 1 && majorId % ticklabelstep) { - obj.skipLabel = true; - } + if(isPeriod) positionPeriodTicks(allTicklabelVals, ax, ax._definedDelta); + + var i; + if(ax.rangebreaks) { + var flip = ax._id.charAt(0) === 'y'; - tickVals.push(obj); - } else { - obj.minor = true; - - minorTickVals.push(obj); - } - } - } - - // check if ticklabelIndex makes sense, otherwise ignore it - if (!minorTickVals || minorTickVals.length < 2) { - ticklabelIndex = false; - } else { - var diff = - (minorTickVals[1].value - minorTickVals[0].value) * (isReversed ? -1 : 1); - if (!periodCompatibleWithTickformat(diff, ax.tickformat)) { - ticklabelIndex = false; - } - } - // Determine for which ticks to draw labels - if (!ticklabelIndex) { - allTicklabelVals = tickVals; - } else { - // Collect and sort all major and minor ticks, to find the minor ticks `ticklabelIndex` - // steps away from each major tick. For those minor ticks we want to draw the label. - - var allTickVals = tickVals.concat(minorTickVals); - if (isPeriod && tickVals.length) { - // first major tick was just added for period handling - allTickVals = allTickVals.slice(1); - } - - allTickVals = allTickVals - .sort(function (a, b) { - return a.value - b.value; - }) - .filter(function (tick, index, self) { - return index === 0 || tick.value !== self[index - 1].value; - }); - - var majorTickIndices = allTickVals - .map(function (item, index) { - return item.minor === undefined && !item.skipLabel ? index : null; - }) - .filter(function (index) { - return index !== null; - }); - - majorTickIndices.forEach(function (majorIdx) { - ticklabelIndex.map(function (nextLabelIdx) { - var minorIdx = majorIdx + nextLabelIdx; - if (minorIdx >= 0 && minorIdx < allTickVals.length) { - Lib.pushUnique(allTicklabelVals, allTickVals[minorIdx]); + var fontSize = 1; // one pixel minimum + if(ax.tickmode === 'auto') { + fontSize = ax.tickfont ? ax.tickfont.size : 12; } - }); - }); - } - - if (hasMinor) { - var canOverlap = - (ax.minor.ticks === "inside" && ax.ticks === "outside") || - (ax.minor.ticks === "outside" && ax.ticks === "inside"); - - if (!canOverlap) { - // remove duplicate minors - - var majorValues = tickVals.map(function (d) { - return d.value; - }); - - var list = []; - for (var k = 0; k < minorTickVals.length; k++) { - var T = minorTickVals[k]; - var v = T.value; - if (majorValues.indexOf(v) !== -1) { - continue; + + var prevL = NaN; + for(i = tickVals.length - 1; i > -1; i--) { + if(tickVals[i].drop) { + tickVals.splice(i, 1); + continue; + } + + tickVals[i].value = moveOutsideBreak(tickVals[i].value, ax); + + // avoid overlaps + var l = ax.c2p(tickVals[i].value); + if(flip ? + (prevL > l - fontSize) : + (prevL < l + fontSize) + ) { // ensure one pixel minimum + tickVals.splice(axrev ? i + 1 : i, 1); + } else { + prevL = l; + } } - var found = false; - for (var q = 0; !found && q < tickVals.length; q++) { - if ( - // add 10e6 to eliminate problematic digits - 10e6 + tickVals[q].value === - 10e6 + v - ) { - found = true; - } + } + + // If same angle over a full circle, the last tick vals is a duplicate. + // TODO must do something similar for angular date axes. + if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) { + tickVals.pop(); + } + + // save the last tick as well as first, so we can + // show the exponent only on the last one + ax._tmax = (tickVals[tickVals.length - 1] || {}).value; + + // for showing the rest of a date when the main tick label is only the + // latter part: ax._prevDateHead holds what we showed most recently. + // Start with it cleared and mark that we're in calcTicks (ie calculating a + // whole string of these so we should care what the previous date head was!) + ax._prevDateHead = ''; + ax._inCalcTicks = true; + + var lastVisibleHead; + var hideLabel = function(tick) { + tick.text = ''; + ax._prevDateHead = lastVisibleHead; + }; + + tickVals = tickVals.concat(minorTickVals); + + function setTickLabel(ax, tickVal) { + var text = axes.tickText( + ax, + tickVal.value, + false, // hover + tickVal.simpleLabel // noSuffixPrefix + ); + var p = tickVal.periodX; + if(p !== undefined) { + text.periodX = p; + if(p > maxRange || p < minRange) { // hide label if outside the range + if(p > maxRange) text.periodX = maxRange; + if(p < minRange) text.periodX = minRange; + + hideLabel(text); + } } - if (!found) list.push(T); - } - minorTickVals = list; - } - } - - if (isPeriod) positionPeriodTicks(allTicklabelVals, ax, ax._definedDelta); - - var i; - if (ax.rangebreaks) { - var flip = ax._id.charAt(0) === "y"; - - var fontSize = 1; // one pixel minimum - if (ax.tickmode === "auto") { - fontSize = ax.tickfont ? ax.tickfont.size : 12; - } - - var prevL = NaN; - for (i = tickVals.length - 1; i > -1; i--) { - if (tickVals[i].drop) { - tickVals.splice(i, 1); - continue; - } - - tickVals[i].value = moveOutsideBreak(tickVals[i].value, ax); - - // avoid overlaps - var l = ax.c2p(tickVals[i].value); - if (flip ? prevL > l - fontSize : prevL < l + fontSize) { - // ensure one pixel minimum - tickVals.splice(axrev ? i + 1 : i, 1); - } else { - prevL = l; - } - } - } - - // If same angle over a full circle, the last tick vals is a duplicate. - // TODO must do something similar for angular date axes. - if (isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) { - tickVals.pop(); - } - - // save the last tick as well as first, so we can - // show the exponent only on the last one - ax._tmax = (tickVals[tickVals.length - 1] || {}).value; - - // for showing the rest of a date when the main tick label is only the - // latter part: ax._prevDateHead holds what we showed most recently. - // Start with it cleared and mark that we're in calcTicks (ie calculating a - // whole string of these so we should care what the previous date head was!) - ax._prevDateHead = ""; - ax._inCalcTicks = true; - - var lastVisibleHead; - var hideLabel = function (tick) { - tick.text = ""; - ax._prevDateHead = lastVisibleHead; - }; - - tickVals = tickVals.concat(minorTickVals); - - function setTickLabel(ax, tickVal) { - var text = axes.tickText( - ax, - tickVal.value, - false, // hover - tickVal.simpleLabel // noSuffixPrefix - ); - var p = tickVal.periodX; - if (p !== undefined) { - text.periodX = p; - if (p > maxRange || p < minRange) { - // hide label if outside the range - if (p > maxRange) text.periodX = maxRange; - if (p < minRange) text.periodX = minRange; - - hideLabel(text); - } - } - return text; - } - - var t; - for (i = 0; i < tickVals.length; i++) { - var _minor = tickVals[i].minor; - var _value = tickVals[i].value; - - if (_minor) { - if (ticklabelIndex && allTicklabelVals.indexOf(tickVals[i]) !== -1) { - t = setTickLabel(ax, tickVals[i]); - } else { - t = { x: _value }; - } - t.minor = true; - minorTicks.push(t); - } else { - lastVisibleHead = ax._prevDateHead; - t = setTickLabel(ax, tickVals[i]); - if ( - tickVals[i].skipLabel || - (ticklabelIndex && allTicklabelVals.indexOf(tickVals[i]) === -1) - ) { - hideLabel(t); - } + return text; + } - ticksOut.push(t); + var t; + for(i = 0; i < tickVals.length; i++) { + var _minor = tickVals[i].minor; + var _value = tickVals[i].value; + + if(_minor) { + if(ticklabelIndex && allTicklabelVals.indexOf(tickVals[i]) !== -1) { + t = setTickLabel(ax, tickVals[i]); + } else { + t = { x: _value }; + } + t.minor = true; + minorTicks.push(t); + } else { + lastVisibleHead = ax._prevDateHead; + t = setTickLabel(ax, tickVals[i]); + if(tickVals[i].skipLabel || + ticklabelIndex && allTicklabelVals.indexOf(tickVals[i]) === -1) { + hideLabel(t); + } + + ticksOut.push(t); + } } - } - ticksOut = ticksOut.concat(minorTicks); + ticksOut = ticksOut.concat(minorTicks); - ax._inCalcTicks = false; + ax._inCalcTicks = false; - if (isPeriod && ticksOut.length) { - // drop very first tick that we added to handle period - ticksOut[0].noTick = true; - } + if(isPeriod && ticksOut.length) { + // drop very first tick that we added to handle period + ticksOut[0].noTick = true; + } - return ticksOut; + return ticksOut; }; function filterRangeBreaks(ax, ticksOut) { - if (ax.rangebreaks) { - // remove ticks falling inside rangebreaks - ticksOut = ticksOut.filter(function (d) { - return ax.maskBreaks(d.x) !== BADNUM; - }); - } + if(ax.rangebreaks) { + // remove ticks falling inside rangebreaks + ticksOut = ticksOut.filter(function(d) { + return ax.maskBreaks(d.x) !== BADNUM; + }); + } - return ticksOut; + return ticksOut; } function syncTicks(ax) { - // get the overlaying axis - var baseAxis = ax._mainAxis; + // get the overlaying axis + var baseAxis = ax._mainAxis; + + var ticksOut = []; + if(baseAxis._vals) { + for(var i = 0; i < baseAxis._vals.length; i++) { + // filter vals with noTick flag + if(baseAxis._vals[i].noTick) { + continue; + } + + // get the position of the every tick + var pos = baseAxis.l2p(baseAxis._vals[i].x); + + // get the tick for the current axis based on position + var vali = ax.p2l(pos); + var obj = axes.tickText(ax, vali); + + // assign minor ticks + if(baseAxis._vals[i].minor) { + obj.minor = true; + obj.text = ''; + } + + ticksOut.push(obj); + } + } - var ticksOut = []; - if (baseAxis._vals) { - for (var i = 0; i < baseAxis._vals.length; i++) { - // filter vals with noTick flag - if (baseAxis._vals[i].noTick) { - continue; - } + ticksOut = filterRangeBreaks(ax, ticksOut); - // get the position of the every tick - var pos = baseAxis.l2p(baseAxis._vals[i].x); + return ticksOut; +} - // get the tick for the current axis based on position - var vali = ax.p2l(pos); - var obj = axes.tickText(ax, vali); +function arrayTicks(ax, majorOnly) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + var exRng = expandRange(rng); + var tickMin = Math.min(exRng[0], exRng[1]); + var tickMax = Math.max(exRng[0], exRng[1]); - // assign minor ticks - if (baseAxis._vals[i].minor) { - obj.minor = true; - obj.text = ""; - } + // make sure showing ticks doesn't accidentally add new categories + // TODO multicategory, if we allow ticktext / tickvals + var tickVal2l = ax.type === 'category' ? ax.d2l_noadd : ax.d2l; - ticksOut.push(obj); + // array ticks on log axes always show the full number + // (if no explicit ticktext overrides it) + if(ax.type === 'log' && String(ax.dtick).charAt(0) !== 'L') { + ax.dtick = 'L' + Math.pow(10, Math.floor(Math.min(ax.range[0], ax.range[1])) - 1); } - } - - ticksOut = filterRangeBreaks(ax, ticksOut); - - return ticksOut; -} -function arrayTicks(ax, majorOnly) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - var exRng = expandRange(rng); - var tickMin = Math.min(exRng[0], exRng[1]); - var tickMax = Math.max(exRng[0], exRng[1]); - - // make sure showing ticks doesn't accidentally add new categories - // TODO multicategory, if we allow ticktext / tickvals - var tickVal2l = ax.type === "category" ? ax.d2l_noadd : ax.d2l; - - // array ticks on log axes always show the full number - // (if no explicit ticktext overrides it) - if (ax.type === "log" && String(ax.dtick).charAt(0) !== "L") { - ax.dtick = - "L" + Math.pow(10, Math.floor(Math.min(ax.range[0], ax.range[1])) - 1); - } - - var ticksOut = []; - for (var isMinor = 0; isMinor <= 1; isMinor++) { - if ( - majorOnly !== undefined && - ((majorOnly && isMinor) || (majorOnly === false && !isMinor)) - ) - continue; - if (isMinor && !ax.minor) continue; - var vals = !isMinor ? ax.tickvals : ax.minor.tickvals; - var text = !isMinor ? ax.ticktext : []; - if (!vals) continue; - - // without a text array, just format the given values as any other ticks - // except with more precision to the numbers - if (!Lib.isArrayOrTypedArray(text)) text = []; - - for (var i = 0; i < vals.length; i++) { - var vali = tickVal2l(vals[i]); - if (vali > tickMin && vali < tickMax) { - var obj = axes.tickText(ax, vali, false, String(text[i])); - if (isMinor) { - obj.minor = true; - obj.text = ""; + var ticksOut = []; + for(var isMinor = 0; isMinor <= 1; isMinor++) { + if((majorOnly !== undefined) && ((majorOnly && isMinor) || (majorOnly === false && !isMinor))) continue; + if(isMinor && !ax.minor) continue; + var vals = !isMinor ? ax.tickvals : ax.minor.tickvals; + var text = !isMinor ? ax.ticktext : []; + if(!vals) continue; + + + // without a text array, just format the given values as any other ticks + // except with more precision to the numbers + if(!Lib.isArrayOrTypedArray(text)) text = []; + + for(var i = 0; i < vals.length; i++) { + var vali = tickVal2l(vals[i]); + if(vali > tickMin && vali < tickMax) { + var obj = axes.tickText(ax, vali, false, String(text[i])); + if(isMinor) { + obj.minor = true; + obj.text = ''; + } + + ticksOut.push(obj); + } } - - ticksOut.push(obj); - } } - } - ticksOut = filterRangeBreaks(ax, ticksOut); + ticksOut = filterRangeBreaks(ax, ticksOut); - return ticksOut; + return ticksOut; } var roundBase10 = [2, 5, 10]; @@ -1442,15 +1374,13 @@ var roundBase60 = [1, 2, 5, 10, 15, 30]; var roundDays = [1, 2, 3, 7, 14]; // approx. tick positions for log axes, showing all (1) and just 1, 2, 5 (2) // these don't have to be exact, just close enough to round to the right value -var roundLog1 = [ - -0.046, 0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1, -]; +var roundLog1 = [-0.046, 0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1]; var roundLog2 = [-0.301, 0, 0.301, 0.699, 1]; // N.B. `thetaunit; 'radians' angular axes must be converted to degrees var roundAngles = [15, 30, 45, 90, 180]; function roundDTick(roughDTick, base, roundingSet) { - return base * Lib.roundUp(roughDTick / base, roundingSet); + return base * Lib.roundUp(roughDTick / base, roundingSet); } // autoTicks: calculate best guess at pleasant ticks for this axis @@ -1469,109 +1399,106 @@ function roundDTick(roughDTick, base, roundingSet) { // log with linear ticks: L# where # is the linear tick spacing // log showing powers plus some intermediates: // D1 shows all digits, D2 shows 2 and 5 -axes.autoTicks = function (ax, roughDTick, isMinor) { - var base; - - function getBase(v) { - return Math.pow(v, Math.floor(Math.log(roughDTick) / Math.LN10)); - } - - if (ax.type === "date") { - ax.tick0 = Lib.dateTick0(ax.calendar, 0); - - // the criteria below are all based on the rough spacing we calculate - // being > half of the final unit - so precalculate twice the rough val - var roughX2 = 2 * roughDTick; - - if (roughX2 > ONEAVGYEAR) { - roughDTick /= ONEAVGYEAR; - base = getBase(10); - ax.dtick = "M" + 12 * roundDTick(roughDTick, base, roundBase10); - } else if (roughX2 > ONEAVGMONTH) { - roughDTick /= ONEAVGMONTH; - ax.dtick = "M" + roundDTick(roughDTick, 1, roundBase24); - } else if (roughX2 > ONEDAY) { - ax.dtick = roundDTick( - roughDTick, - ONEDAY, - ax._hasDayOfWeekBreaks ? [1, 2, 7, 14] : roundDays - ); - if (!isMinor) { - // get week ticks on sunday - // this will also move the base tick off 2000-01-01 if dtick is - // 2 or 3 days... but that's a weird enough case that we'll ignore it. - var tickformat = axes.getTickFormat(ax); - var isPeriod = ax.ticklabelmode === "period"; - if (isPeriod) ax._rawTick0 = ax.tick0; - - if (/%[uVW]/.test(tickformat)) { - ax.tick0 = Lib.dateTick0(ax.calendar, 2); // Monday +axes.autoTicks = function(ax, roughDTick, isMinor) { + var base; + + function getBase(v) { + return Math.pow(v, Math.floor(Math.log(roughDTick) / Math.LN10)); + } + + if(ax.type === 'date') { + ax.tick0 = Lib.dateTick0(ax.calendar, 0); + + // the criteria below are all based on the rough spacing we calculate + // being > half of the final unit - so precalculate twice the rough val + var roughX2 = 2 * roughDTick; + + if(roughX2 > ONEAVGYEAR) { + roughDTick /= ONEAVGYEAR; + base = getBase(10); + ax.dtick = 'M' + (12 * roundDTick(roughDTick, base, roundBase10)); + } else if(roughX2 > ONEAVGMONTH) { + roughDTick /= ONEAVGMONTH; + ax.dtick = 'M' + roundDTick(roughDTick, 1, roundBase24); + } else if(roughX2 > ONEDAY) { + ax.dtick = roundDTick(roughDTick, ONEDAY, ax._hasDayOfWeekBreaks ? [1, 2, 7, 14] : roundDays); + if(!isMinor) { + // get week ticks on sunday + // this will also move the base tick off 2000-01-01 if dtick is + // 2 or 3 days... but that's a weird enough case that we'll ignore it. + var tickformat = axes.getTickFormat(ax); + var isPeriod = ax.ticklabelmode === 'period'; + if(isPeriod) ax._rawTick0 = ax.tick0; + + if(/%[uVW]/.test(tickformat)) { + ax.tick0 = Lib.dateTick0(ax.calendar, 2); // Monday + } else { + ax.tick0 = Lib.dateTick0(ax.calendar, 1); // Sunday + } + + if(isPeriod) ax._dowTick0 = ax.tick0; + } + } else if(roughX2 > ONEHOUR) { + ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24); + } else if(roughX2 > ONEMIN) { + ax.dtick = roundDTick(roughDTick, ONEMIN, roundBase60); + } else if(roughX2 > ONESEC) { + ax.dtick = roundDTick(roughDTick, ONESEC, roundBase60); } else { - ax.tick0 = Lib.dateTick0(ax.calendar, 1); // Sunday + // milliseconds + base = getBase(10); + ax.dtick = roundDTick(roughDTick, base, roundBase10); } - - if (isPeriod) ax._dowTick0 = ax.tick0; - } - } else if (roughX2 > ONEHOUR) { - ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24); - } else if (roughX2 > ONEMIN) { - ax.dtick = roundDTick(roughDTick, ONEMIN, roundBase60); - } else if (roughX2 > ONESEC) { - ax.dtick = roundDTick(roughDTick, ONESEC, roundBase60); + } else if(ax.type === 'log') { + ax.tick0 = 0; + var rng = Lib.simpleMap(ax.range, ax.r2l); + if(ax._isMinor) { + // Log axes by default get MORE than nTicks based on the metrics below + // But for minor ticks we don't want this increase, we already have + // the major ticks. + roughDTick *= 1.5; + } + if(roughDTick > 0.7) { + // only show powers of 10 + ax.dtick = Math.ceil(roughDTick); + } else if(Math.abs(rng[1] - rng[0]) < 1) { + // span is less than one power of 10 + var nt = 1.5 * Math.abs((rng[1] - rng[0]) / roughDTick); + + // ticks on a linear scale, labeled fully + roughDTick = Math.abs(Math.pow(10, rng[1]) - + Math.pow(10, rng[0])) / nt; + base = getBase(10); + ax.dtick = 'L' + roundDTick(roughDTick, base, roundBase10); + } else { + // include intermediates between powers of 10, + // labeled with small digits + // ax.dtick = "D2" (show 2 and 5) or "D1" (show all digits) + ax.dtick = (roughDTick > 0.3) ? 'D2' : 'D1'; + } + } else if(ax.type === 'category' || ax.type === 'multicategory') { + ax.tick0 = 0; + ax.dtick = Math.ceil(Math.max(roughDTick, 1)); + } else if(isAngular(ax)) { + ax.tick0 = 0; + base = 1; + ax.dtick = roundDTick(roughDTick, base, roundAngles); } else { - // milliseconds - base = getBase(10); - ax.dtick = roundDTick(roughDTick, base, roundBase10); + // auto ticks always start at 0 + ax.tick0 = 0; + base = getBase(10); + ax.dtick = roundDTick(roughDTick, base, roundBase10); + } + + // prevent infinite loops + if(ax.dtick === 0) ax.dtick = 1; + + // TODO: this is from log axis histograms with autorange off + if(!isNumeric(ax.dtick) && typeof ax.dtick !== 'string') { + var olddtick = ax.dtick; + ax.dtick = 1; + throw 'ax.dtick error: ' + String(olddtick); } - } else if (ax.type === "log") { - ax.tick0 = 0; - var rng = Lib.simpleMap(ax.range, ax.r2l); - if (ax._isMinor) { - // Log axes by default get MORE than nTicks based on the metrics below - // But for minor ticks we don't want this increase, we already have - // the major ticks. - roughDTick *= 1.5; - } - if (roughDTick > 0.7) { - // only show powers of 10 - ax.dtick = Math.ceil(roughDTick); - } else if (Math.abs(rng[1] - rng[0]) < 1) { - // span is less than one power of 10 - var nt = 1.5 * Math.abs((rng[1] - rng[0]) / roughDTick); - - // ticks on a linear scale, labeled fully - roughDTick = Math.abs(Math.pow(10, rng[1]) - Math.pow(10, rng[0])) / nt; - base = getBase(10); - ax.dtick = "L" + roundDTick(roughDTick, base, roundBase10); - } else { - // include intermediates between powers of 10, - // labeled with small digits - // ax.dtick = "D2" (show 2 and 5) or "D1" (show all digits) - ax.dtick = roughDTick > 0.3 ? "D2" : "D1"; - } - } else if (ax.type === "category" || ax.type === "multicategory") { - ax.tick0 = 0; - ax.dtick = Math.ceil(Math.max(roughDTick, 1)); - } else if (isAngular(ax)) { - ax.tick0 = 0; - base = 1; - ax.dtick = roundDTick(roughDTick, base, roundAngles); - } else { - // auto ticks always start at 0 - ax.tick0 = 0; - base = getBase(10); - ax.dtick = roundDTick(roughDTick, base, roundBase10); - } - - // prevent infinite loops - if (ax.dtick === 0) ax.dtick = 1; - - // TODO: this is from log axis histograms with autorange off - if (!isNumeric(ax.dtick) && typeof ax.dtick !== "string") { - var olddtick = ax.dtick; - ax.dtick = 1; - throw "ax.dtick error: " + String(olddtick); - } }; // after dtick is already known, find tickround = precision @@ -1580,74 +1507,65 @@ axes.autoTicks = function (ax, roughDTick, isMinor) { // for date ticks, the last date part to show (y,m,d,H,M,S) // or an integer # digits past seconds function autoTickRound(ax) { - var dtick = ax.dtick; - - ax._tickexponent = 0; - if (!isNumeric(dtick) && typeof dtick !== "string") { - dtick = 1; - } - - if (ax.type === "category" || ax.type === "multicategory") { - ax._tickround = null; - } - if (ax.type === "date") { - // If tick0 is unusual, give tickround a bit more information - // not necessarily *all* the information in tick0 though, if it's really odd - // minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19 - // take off a leading minus (year < 0) and i (intercalary month) so length is consistent - var tick0ms = ax.r2l(ax.tick0); - var tick0str = ax.l2r(tick0ms).replace(/(^-|i)/g, ""); - var tick0len = tick0str.length; - - if (String(dtick).charAt(0) === "M") { - // any tick0 more specific than a year: alway show the full date - if (tick0len > 10 || tick0str.substr(5) !== "01-01") ax._tickround = "d"; - // show the month unless ticks are full multiples of a year - else ax._tickround = +dtick.substr(1) % 12 === 0 ? "y" : "m"; - } else if ((dtick >= ONEDAY && tick0len <= 10) || dtick >= ONEDAY * 15) - ax._tickround = "d"; - else if ((dtick >= ONEMIN && tick0len <= 16) || dtick >= ONEHOUR) - ax._tickround = "M"; - else if ((dtick >= ONESEC && tick0len <= 19) || dtick >= ONEMIN) - ax._tickround = "S"; - else { - // tickround is a number of digits of fractional seconds - // of any two adjacent ticks, at least one will have the maximum fractional digits - // of all possible ticks - so take the max. length of tick0 and the next one - var tick1len = ax.l2r(tick0ms + dtick).replace(/^-/, "").length; - ax._tickround = Math.max(tick0len, tick1len) - 20; - - // We shouldn't get here... but in case there's a situation I'm - // not thinking of where tick0str and tick1str are identical or - // something, fall back on maximum precision - if (ax._tickround < 0) ax._tickround = 4; - } - } else if (isNumeric(dtick) || dtick.charAt(0) === "L") { - // linear or log (except D1, D2) - var rng = ax.range.map(ax.r2d || Number); - if (!isNumeric(dtick)) dtick = Number(dtick.substr(1)); - // 2 digits past largest digit of dtick - ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); - - var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); - var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); - var minexponent = ax.minexponent === undefined ? 3 : ax.minexponent; - if (Math.abs(rangeexp) > minexponent) { - if ( - (isSIFormat(ax.exponentformat) && - ax.exponentformat !== "SI extended" && - !beyondSI(rangeexp)) || - (isSIFormat(ax.exponentformat) && - ax.exponentformat === "SI extended" && - !beyondSIExtended(rangeexp)) - ) { - ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); - } else ax._tickexponent = rangeexp; - } - } else { - // D1 or D2 (log) - ax._tickround = null; - } + var dtick = ax.dtick; + + ax._tickexponent = 0; + if(!isNumeric(dtick) && typeof dtick !== 'string') { + dtick = 1; + } + + if(ax.type === 'category' || ax.type === 'multicategory') { + ax._tickround = null; + } + if(ax.type === 'date') { + // If tick0 is unusual, give tickround a bit more information + // not necessarily *all* the information in tick0 though, if it's really odd + // minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19 + // take off a leading minus (year < 0) and i (intercalary month) so length is consistent + var tick0ms = ax.r2l(ax.tick0); + var tick0str = ax.l2r(tick0ms).replace(/(^-|i)/g, ''); + var tick0len = tick0str.length; + + if(String(dtick).charAt(0) === 'M') { + // any tick0 more specific than a year: alway show the full date + if(tick0len > 10 || tick0str.substr(5) !== '01-01') ax._tickround = 'd'; + // show the month unless ticks are full multiples of a year + else ax._tickround = (+(dtick.substr(1)) % 12 === 0) ? 'y' : 'm'; + } else if((dtick >= ONEDAY && tick0len <= 10) || (dtick >= ONEDAY * 15)) ax._tickround = 'd'; + else if((dtick >= ONEMIN && tick0len <= 16) || (dtick >= ONEHOUR)) ax._tickround = 'M'; + else if((dtick >= ONESEC && tick0len <= 19) || (dtick >= ONEMIN)) ax._tickround = 'S'; + else { + // tickround is a number of digits of fractional seconds + // of any two adjacent ticks, at least one will have the maximum fractional digits + // of all possible ticks - so take the max. length of tick0 and the next one + var tick1len = ax.l2r(tick0ms + dtick).replace(/^-/, '').length; + ax._tickround = Math.max(tick0len, tick1len) - 20; + + // We shouldn't get here... but in case there's a situation I'm + // not thinking of where tick0str and tick1str are identical or + // something, fall back on maximum precision + if(ax._tickround < 0) ax._tickround = 4; + } + } else if(isNumeric(dtick) || dtick.charAt(0) === 'L') { + // linear or log (except D1, D2) + var rng = ax.range.map(ax.r2d || Number); + if(!isNumeric(dtick)) dtick = Number(dtick.substr(1)); + // 2 digits past largest digit of dtick + ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); + + var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); + var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); + var minexponent = ax.minexponent === undefined ? 3 : ax.minexponent; + if(Math.abs(rangeexp) > minexponent) { + if((isSIFormat(ax.exponentformat) && ax.exponentformat !== 'SI extended' && !beyondSI(rangeexp)) || + (isSIFormat(ax.exponentformat) && ax.exponentformat === 'SI extended' && !beyondSIExtended(rangeexp))) { + ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); + } else ax._tickexponent = rangeexp; + } + } else { + // D1 or D2 (log) + ax._tickround = null; + } } // months and years don't have constant millisecond values @@ -1656,104 +1574,95 @@ function autoTickRound(ax) { // for pure powers of 10 // numeric ticks always have constant differences, other datetime ticks // can all be calculated as constant number of milliseconds -axes.tickIncrement = function (x, dtick, axrev, calendar) { - var axSign = axrev ? -1 : 1; +axes.tickIncrement = function(x, dtick, axrev, calendar) { + var axSign = axrev ? -1 : 1; - // includes linear, all dates smaller than month, and pure 10^n in log - if (isNumeric(dtick)) return Lib.increment(x, axSign * dtick); + // includes linear, all dates smaller than month, and pure 10^n in log + if(isNumeric(dtick)) return Lib.increment(x, axSign * dtick); - // everything else is a string, one character plus a number - var tType = dtick.charAt(0); - var dtSigned = axSign * Number(dtick.substr(1)); + // everything else is a string, one character plus a number + var tType = dtick.charAt(0); + var dtSigned = axSign * Number(dtick.substr(1)); - // Dates: months (or years - see Lib.incrementMonth) - if (tType === "M") return Lib.incrementMonth(x, dtSigned, calendar); + // Dates: months (or years - see Lib.incrementMonth) + if(tType === 'M') return Lib.incrementMonth(x, dtSigned, calendar); - // Log scales: Linear, Digits - if (tType === "L") return Math.log(Math.pow(10, x) + dtSigned) / Math.LN10; + // Log scales: Linear, Digits + if(tType === 'L') return Math.log(Math.pow(10, x) + dtSigned) / Math.LN10; - // log10 of 2,5,10, or all digits (logs just have to be - // close enough to round) - if (tType === "D") { - var tickset = dtick === "D2" ? roundLog2 : roundLog1; - var x2 = x + axSign * 0.01; - var frac = Lib.roundUp(Lib.mod(x2, 1), tickset, axrev); + // log10 of 2,5,10, or all digits (logs just have to be + // close enough to round) + if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1; + var x2 = x + axSign * 0.01; + var frac = Lib.roundUp(Lib.mod(x2, 1), tickset, axrev); - return ( - Math.floor(x2) + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10 - ); - } + return Math.floor(x2) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } - throw "unrecognized dtick " + String(dtick); + throw 'unrecognized dtick ' + String(dtick); }; // calculate the first tick on an axis -axes.tickFirst = function (ax, opts) { - var r2l = ax.r2l || Number; - var rng = Lib.simpleMap(ax.range, r2l, undefined, undefined, opts); - var axrev = rng[1] < rng[0]; - var sRound = axrev ? Math.floor : Math.ceil; - // add a tiny extra bit to make sure we get ticks - // that may have been rounded out - var r0 = expandRange(rng)[0]; - var dtick = ax.dtick; - var tick0 = r2l(ax.tick0); - - if (isNumeric(dtick)) { - var tmin = sRound((r0 - tick0) / dtick) * dtick + tick0; - - // make sure no ticks outside the category list - if (ax.type === "category" || ax.type === "multicategory") { - tmin = Lib.constrain(tmin, 0, ax._categories.length - 1); - } - return tmin; - } - - var tType = dtick.charAt(0); - var dtNum = Number(dtick.substr(1)); - - // Dates: months (or years) - if (tType === "M") { - var cnt = 0; - var t0 = tick0; - var t1, mult, newDTick; - - // This algorithm should work for *any* nonlinear (but close to linear!) - // tick spacing. Limit to 10 iterations, for gregorian months it's normally <=3. - while (cnt < 10) { - t1 = axes.tickIncrement(t0, dtick, axrev, ax.calendar); - if ((t1 - r0) * (t0 - r0) <= 0) { - // t1 and t0 are on opposite sides of r0! we've succeeded! - if (axrev) return Math.min(t0, t1); - return Math.max(t0, t1); - } - mult = (r0 - (t0 + t1) / 2) / (t1 - t0); - newDTick = tType + (Math.abs(Math.round(mult)) || 1) * dtNum; - t0 = axes.tickIncrement( - t0, - newDTick, - mult < 0 ? !axrev : axrev, - ax.calendar - ); - cnt++; - } - Lib.error("tickFirst did not converge", ax); - return t0; - } else if (tType === "L") { - // Log scales: Linear, Digits - - return ( - Math.log(sRound((Math.pow(10, r0) - tick0) / dtNum) * dtNum + tick0) / - Math.LN10 - ); - } else if (tType === "D") { - var tickset = dtick === "D2" ? roundLog2 : roundLog1; - var frac = Lib.roundUp(Lib.mod(r0, 1), tickset, axrev); +axes.tickFirst = function(ax, opts) { + var r2l = ax.r2l || Number; + var rng = Lib.simpleMap(ax.range, r2l, undefined, undefined, opts); + var axrev = rng[1] < rng[0]; + var sRound = axrev ? Math.floor : Math.ceil; + // add a tiny extra bit to make sure we get ticks + // that may have been rounded out + var r0 = expandRange(rng)[0]; + var dtick = ax.dtick; + var tick0 = r2l(ax.tick0); + + if(isNumeric(dtick)) { + var tmin = sRound((r0 - tick0) / dtick) * dtick + tick0; + + // make sure no ticks outside the category list + if(ax.type === 'category' || ax.type === 'multicategory') { + tmin = Lib.constrain(tmin, 0, ax._categories.length - 1); + } + return tmin; + } - return ( - Math.floor(r0) + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10 - ); - } else throw "unrecognized dtick " + String(dtick); + var tType = dtick.charAt(0); + var dtNum = Number(dtick.substr(1)); + + // Dates: months (or years) + if(tType === 'M') { + var cnt = 0; + var t0 = tick0; + var t1, mult, newDTick; + + // This algorithm should work for *any* nonlinear (but close to linear!) + // tick spacing. Limit to 10 iterations, for gregorian months it's normally <=3. + while(cnt < 10) { + t1 = axes.tickIncrement(t0, dtick, axrev, ax.calendar); + if((t1 - r0) * (t0 - r0) <= 0) { + // t1 and t0 are on opposite sides of r0! we've succeeded! + if(axrev) return Math.min(t0, t1); + return Math.max(t0, t1); + } + mult = (r0 - ((t0 + t1) / 2)) / (t1 - t0); + newDTick = tType + ((Math.abs(Math.round(mult)) || 1) * dtNum); + t0 = axes.tickIncrement(t0, newDTick, mult < 0 ? !axrev : axrev, ax.calendar); + cnt++; + } + Lib.error('tickFirst did not converge', ax); + return t0; + } else if(tType === 'L') { + // Log scales: Linear, Digits + + return Math.log(sRound( + (Math.pow(10, r0) - tick0) / dtNum) * dtNum + tick0) / Math.LN10; + } else if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1; + var frac = Lib.roundUp(Lib.mod(r0, 1), tickset, axrev); + + return Math.floor(r0) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } else throw 'unrecognized dtick ' + String(dtick); }; // draw the text for one tick. @@ -1762,79 +1671,81 @@ axes.tickFirst = function (ax, opts) { // ax is the axis layout, x is the tick value // hover is a (truthy) flag for whether to show numbers with a bit // more precision for hovertext -axes.tickText = function (ax, x, hover, noSuffixPrefix) { - var out = tickTextObj(ax, x); - var arrayMode = ax.tickmode === "array"; - var extraPrecision = hover || arrayMode; - var axType = ax.type; - // TODO multicategory, if we allow ticktext / tickvals - var tickVal2l = axType === "category" ? ax.d2l_noadd : ax.d2l; - var i; - - var inbounds = function (v) { - var p = ax.l2p(v); - return p >= 0 && p <= ax._length ? v : null; - }; - if (arrayMode && Lib.isArrayOrTypedArray(ax.ticktext)) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - var minDiff = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / 10000; - - for (i = 0; i < ax.ticktext.length; i++) { - if (Math.abs(x - tickVal2l(ax.tickvals[i])) < minDiff) break; - } - if (i < ax.ticktext.length) { - out.text = String(ax.ticktext[i]); - - out.xbnd = [inbounds(out.x - 0.5), inbounds(out.x + ax.dtick - 0.5)]; - return out; - } - } - - function isHidden(showAttr) { - if (showAttr === undefined) return true; - if (hover) return showAttr === "none"; - - var firstOrLast = { - first: ax._tmin, - last: ax._tmax, - }[showAttr]; - - return showAttr !== "all" && x !== firstOrLast; - } - - var hideexp = hover - ? "never" - : ax.exponentformat !== "none" && isHidden(ax.showexponent) - ? "hide" - : ""; - - if (axType === "date") formatDate(ax, out, hover, extraPrecision); - else if (axType === "log") formatLog(ax, out, hover, extraPrecision, hideexp); - else if (axType === "category") formatCategory(ax, out); - else if (axType === "multicategory") formatMultiCategory(ax, out, hover); - else if (isAngular(ax)) formatAngle(ax, out, hover, extraPrecision, hideexp); - else formatLinear(ax, out, hover, extraPrecision, hideexp); - - // add prefix and suffix - if (!noSuffixPrefix) { - if (ax.tickprefix && !isHidden(ax.showtickprefix)) - out.text = ax.tickprefix + out.text; - if (ax.ticksuffix && !isHidden(ax.showticksuffix)) - out.text += ax.ticksuffix; - } - - if (ax.labelalias && ax.labelalias.hasOwnProperty(out.text)) { - var t = ax.labelalias[out.text]; - if (typeof t === "string") out.text = t; - } - - // Setup ticks and grid lines boundaries - // at 1/2 a 'category' to the left/bottom - if (ax.tickson === "boundaries" || ax.showdividers) { - out.xbnd = [inbounds(out.x - 0.5), inbounds(out.x + ax.dtick - 0.5)]; - } - - return out; +axes.tickText = function(ax, x, hover, noSuffixPrefix) { + var out = tickTextObj(ax, x); + var arrayMode = ax.tickmode === 'array'; + var extraPrecision = hover || arrayMode; + var axType = ax.type; + // TODO multicategory, if we allow ticktext / tickvals + var tickVal2l = axType === 'category' ? ax.d2l_noadd : ax.d2l; + var i; + + var inbounds = function(v) { + var p = ax.l2p(v); + return p >= 0 && p <= ax._length ? v : null; + }; + if(arrayMode && Lib.isArrayOrTypedArray(ax.ticktext)) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + var minDiff = (Math.abs(rng[1] - rng[0]) - (ax._lBreaks || 0)) / 10000; + + for(i = 0; i < ax.ticktext.length; i++) { + if(Math.abs(x - tickVal2l(ax.tickvals[i])) < minDiff) break; + } + if(i < ax.ticktext.length) { + out.text = String(ax.ticktext[i]); + + out.xbnd = [ + inbounds(out.x - 0.5), + inbounds(out.x + ax.dtick - 0.5) + ]; + return out; + } + } + + function isHidden(showAttr) { + if(showAttr === undefined) return true; + if(hover) return showAttr === 'none'; + + var firstOrLast = { + first: ax._tmin, + last: ax._tmax + }[showAttr]; + + return showAttr !== 'all' && x !== firstOrLast; + } + + var hideexp = hover ? + 'never' : + ax.exponentformat !== 'none' && isHidden(ax.showexponent) ? 'hide' : ''; + + if(axType === 'date') formatDate(ax, out, hover, extraPrecision); + else if(axType === 'log') formatLog(ax, out, hover, extraPrecision, hideexp); + else if(axType === 'category') formatCategory(ax, out); + else if(axType === 'multicategory') formatMultiCategory(ax, out, hover); + else if(isAngular(ax)) formatAngle(ax, out, hover, extraPrecision, hideexp); + else formatLinear(ax, out, hover, extraPrecision, hideexp); + + // add prefix and suffix + if(!noSuffixPrefix) { + if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; + if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; + } + + if(ax.labelalias && ax.labelalias.hasOwnProperty(out.text)) { + var t = ax.labelalias[out.text]; + if(typeof t === 'string') out.text = t; + } + + // Setup ticks and grid lines boundaries + // at 1/2 a 'category' to the left/bottom + if(ax.tickson === 'boundaries' || ax.showdividers) { + out.xbnd = [ + inbounds(out.x - 0.5), + inbounds(out.x + ax.dtick - 0.5) + ]; + } + + return out; }; /** @@ -1849,366 +1760,316 @@ axes.tickText = function (ax, x, hover, noSuffixPrefix) { * first value and second value as a range (ie ' - ') if the second value is provided and * it's different from the first value. */ -axes.hoverLabelText = function (ax, values, hoverformat) { - if (hoverformat) ax = Lib.extendFlat({}, ax, { hoverformat: hoverformat }); - - var val = Lib.isArrayOrTypedArray(values) ? values[0] : values; - var val2 = Lib.isArrayOrTypedArray(values) ? values[1] : undefined; - if (val2 !== undefined && val2 !== val) { - return ( - axes.hoverLabelText(ax, val, hoverformat) + - " - " + - axes.hoverLabelText(ax, val2, hoverformat) - ); - } +axes.hoverLabelText = function(ax, values, hoverformat) { + if(hoverformat) ax = Lib.extendFlat({}, ax, {hoverformat: hoverformat}); + + var val = Lib.isArrayOrTypedArray(values) ? values[0] : values; + var val2 = Lib.isArrayOrTypedArray(values) ? values[1] : undefined; + if(val2 !== undefined && val2 !== val) { + return ( + axes.hoverLabelText(ax, val, hoverformat) + ' - ' + + axes.hoverLabelText(ax, val2, hoverformat) + ); + } - var logOffScale = ax.type === "log" && val <= 0; - var tx = axes.tickText(ax, ax.c2l(logOffScale ? -val : val), "hover").text; + var logOffScale = (ax.type === 'log' && val <= 0); + var tx = axes.tickText(ax, ax.c2l(logOffScale ? -val : val), 'hover').text; - if (logOffScale) { - return val === 0 ? "0" : MINUS_SIGN + tx; - } + if(logOffScale) { + return val === 0 ? '0' : MINUS_SIGN + tx; + } - // TODO: should we do something special if the axis calendar and - // the data calendar are different? Somehow display both dates with - // their system names? Right now it will just display in the axis calendar - // but users could add the other one as text. - return tx; + // TODO: should we do something special if the axis calendar and + // the data calendar are different? Somehow display both dates with + // their system names? Right now it will just display in the axis calendar + // but users could add the other one as text. + return tx; }; function tickTextObj(ax, x, text) { - var tf = ax.tickfont || {}; - - return { - x: x, - dx: 0, - dy: 0, - text: text || "", - fontSize: tf.size, - font: tf.family, - fontWeight: tf.weight, - fontStyle: tf.style, - fontVariant: tf.variant, - fontTextcase: tf.textcase, - fontLineposition: tf.lineposition, - fontShadow: tf.shadow, - fontColor: tf.color, - }; + var tf = ax.tickfont || {}; + + return { + x: x, + dx: 0, + dy: 0, + text: text || '', + fontSize: tf.size, + font: tf.family, + fontWeight: tf.weight, + fontStyle: tf.style, + fontVariant: tf.variant, + fontTextcase: tf.textcase, + fontLineposition: tf.lineposition, + fontShadow: tf.shadow, + fontColor: tf.color + }; } function formatDate(ax, out, hover, extraPrecision) { - var tr = ax._tickround; - var fmt = (hover && ax.hoverformat) || axes.getTickFormat(ax); - - // Only apply extra precision if no explicit format was provided. - extraPrecision = !fmt && extraPrecision; - - if (extraPrecision) { - // second or sub-second precision: extra always shows max digits. - // for other fields, extra precision just adds one field. - if (isNumeric(tr)) tr = 4; - else tr = { y: "m", m: "d", d: "M", M: "S", S: 4 }[tr]; - } - - var dateStr = Lib.formatDate( - out.x, - fmt, - tr, - ax._dateFormat, - ax.calendar, - ax._extraFormat - ); - var headStr; - - var splitIndex = dateStr.indexOf("\n"); - if (splitIndex !== -1) { - headStr = dateStr.substr(splitIndex + 1); - dateStr = dateStr.substr(0, splitIndex); - } - - if (extraPrecision) { - // if extraPrecision led to trailing zeros, strip them off - // actually, this can lead to removing even more zeros than - // in the original rounding, but that's fine because in these - // contexts uniformity is not so important (if there's even - // anything to be uniform with!) - - // can we remove the whole time part? - if ( - headStr !== undefined && - (dateStr === "00:00:00" || dateStr === "00:00") - ) { - dateStr = headStr; - headStr = ""; - } else if (dateStr.length === 8) { - // strip off seconds if they're zero (zero fractional seconds - // are already omitted) - // but we never remove minutes and leave just hours - dateStr = dateStr.replace(/:00$/, ""); - } - } - - if (headStr) { - if (hover) { - // hover puts it all on one line, so headPart works best up front - // except for year headPart: turn this into "Jan 1, 2000" etc. - if (tr === "d") dateStr += ", " + headStr; - else dateStr = headStr + (dateStr ? ", " + dateStr : ""); - } else { - if (!ax._inCalcTicks || ax._prevDateHead !== headStr) { - ax._prevDateHead = headStr; - dateStr += "
" + headStr; - } else { - var isInside = insideTicklabelposition(ax); - var side = ax._trueSide || ax.side; // polar mocks the side of the radial axis - if ((!isInside && side === "top") || (isInside && side === "bottom")) { - dateStr += "
"; + var tr = ax._tickround; + var fmt = (hover && ax.hoverformat) || axes.getTickFormat(ax); + + // Only apply extra precision if no explicit format was provided. + extraPrecision = !fmt && extraPrecision; + + if(extraPrecision) { + // second or sub-second precision: extra always shows max digits. + // for other fields, extra precision just adds one field. + if(isNumeric(tr)) tr = 4; + else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 4}[tr]; + } + + var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar, ax._extraFormat); + var headStr; + + var splitIndex = dateStr.indexOf('\n'); + if(splitIndex !== -1) { + headStr = dateStr.substr(splitIndex + 1); + dateStr = dateStr.substr(0, splitIndex); + } + + if(extraPrecision) { + // if extraPrecision led to trailing zeros, strip them off + // actually, this can lead to removing even more zeros than + // in the original rounding, but that's fine because in these + // contexts uniformity is not so important (if there's even + // anything to be uniform with!) + + // can we remove the whole time part? + if(headStr !== undefined && (dateStr === '00:00:00' || dateStr === '00:00')) { + dateStr = headStr; + headStr = ''; + } else if(dateStr.length === 8) { + // strip off seconds if they're zero (zero fractional seconds + // are already omitted) + // but we never remove minutes and leave just hours + dateStr = dateStr.replace(/:00$/, ''); + } + } + + if(headStr) { + if(hover) { + // hover puts it all on one line, so headPart works best up front + // except for year headPart: turn this into "Jan 1, 2000" etc. + if(tr === 'd') dateStr += ', ' + headStr; + else dateStr = headStr + (dateStr ? ', ' + dateStr : ''); + } else { + if( + !ax._inCalcTicks || + ax._prevDateHead !== headStr + ) { + ax._prevDateHead = headStr; + dateStr += '
' + headStr; + } else { + var isInside = insideTicklabelposition(ax); + var side = ax._trueSide || ax.side; // polar mocks the side of the radial axis + if( + (!isInside && side === 'top') || + (isInside && side === 'bottom') + ) { + dateStr += '
'; + } + } } - } } - } - out.text = dateStr; + out.text = dateStr; } function formatLog(ax, out, hover, extraPrecision, hideexp) { - var dtick = ax.dtick; - var x = out.x; - var tickformat = ax.tickformat; - var dtChar0 = typeof dtick === "string" && dtick.charAt(0); - - if (hideexp === "never") { - // If this is a hover label, then we must *never* hide the exponent - // for the sake of display, which could give the wrong value by - // potentially many orders of magnitude. If hideexp was 'never', then - // it's now succeeded by preventing the other condition from automating - // this choice. Thus we can unset it so that the axis formatting takes - // precedence. - hideexp = ""; - } - - if (extraPrecision && dtChar0 !== "L") { - dtick = "L3"; - dtChar0 = "L"; - } - - if (tickformat || dtChar0 === "L") { - out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision); - } else if ( - isNumeric(dtick) || - (dtChar0 === "D" && - (ax.minorloglabels === "complete" || Lib.mod(x + 0.01, 1) < 0.1)) - ) { - var isMinor; - if (ax.minorloglabels === "complete" && !(Lib.mod(x + 0.01, 1) < 0.1)) { - isMinor = true; - out.fontSize *= 0.75; - } - - var exponentialString = Math.pow(10, x).toExponential(0); - var parts = exponentialString.split("e"); - - var p = +parts[1]; - var absP = Math.abs(p); - var exponentFormat = ax.exponentformat; - if ( - exponentFormat === "power" || - (isSIFormat(exponentFormat) && - exponentFormat !== "SI extended" && - beyondSI(p)) || - (isSIFormat(exponentFormat) && - exponentFormat === "SI extended" && - beyondSIExtended(p)) - ) { - out.text = parts[0]; - if (absP > 0) out.text += "x10"; - if (out.text === "1x10") out.text = "10"; - if (p !== 0 && p !== 1) - out.text += "" + (p > 0 ? "" : MINUS_SIGN) + absP + ""; - - out.fontSize *= 1.25; - } else if ((exponentFormat === "e" || exponentFormat === "E") && absP > 2) { - out.text = parts[0] + exponentFormat + (p > 0 ? "+" : MINUS_SIGN) + absP; - } else { - out.text = numFormat(Math.pow(10, x), ax, "", "fakehover"); - if (dtick === "D1" && ax._id.charAt(0) === "y") { - out.dy -= out.fontSize / 6; - } - } - } else if (dtChar0 === "D") { - out.text = - ax.minorloglabels === "none" - ? "" - : /* ax.minorloglabels === 'small digits' */ String( - Math.round(Math.pow(10, Lib.mod(x, 1))) - ); - - out.fontSize *= 0.75; - } else throw "unrecognized dtick " + String(dtick); - - // if 9's are printed on log scale, move the 10's away a bit - if (ax.dtick === "D1") { - var firstChar = String(out.text).charAt(0); - if (firstChar === "0" || firstChar === "1") { - if (ax._id.charAt(0) === "y") { - out.dx -= out.fontSize / 4; - } else { - out.dy += out.fontSize / 2; - out.dx += - (ax.range[1] > ax.range[0] ? 1 : -1) * - out.fontSize * - (x < 0 ? 0.5 : 0.25); - } - } - } + var dtick = ax.dtick; + var x = out.x; + var tickformat = ax.tickformat; + var dtChar0 = typeof dtick === 'string' && dtick.charAt(0); + + if(hideexp === 'never') { + // If this is a hover label, then we must *never* hide the exponent + // for the sake of display, which could give the wrong value by + // potentially many orders of magnitude. If hideexp was 'never', then + // it's now succeeded by preventing the other condition from automating + // this choice. Thus we can unset it so that the axis formatting takes + // precedence. + hideexp = ''; + } + + if(extraPrecision && (dtChar0 !== 'L')) { + dtick = 'L3'; + dtChar0 = 'L'; + } + + if(tickformat || (dtChar0 === 'L')) { + out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision); + } else if(isNumeric(dtick) || ((dtChar0 === 'D') && + (ax.minorloglabels === 'complete' || Lib.mod(x + 0.01, 1) < 0.1))) { + + var isMinor; + if(ax.minorloglabels === 'complete' && !(Lib.mod(x + 0.01, 1) < 0.1)) { + isMinor = true; + out.fontSize *= 0.75; + } + + var exponentialString = Math.pow(10, x).toExponential(0); + var parts = exponentialString.split('e'); + + var p = +parts[1]; + var absP = Math.abs(p); + var exponentFormat = ax.exponentformat; + if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(p)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(p))) { + out.text = parts[0]; + if(absP > 0) out.text += 'x10'; + if(out.text === '1x10') out.text = '10'; + if(p !== 0 && p !== 1) out.text += '' + (p > 0 ? '' : MINUS_SIGN) + absP + ''; + + out.fontSize *= 1.25; + } else if((exponentFormat === 'e' || exponentFormat === 'E') && absP > 2) { + out.text = parts[0] + exponentFormat + (p > 0 ? '+' : MINUS_SIGN) + absP; + } else { + out.text = numFormat(Math.pow(10, x), ax, '', 'fakehover'); + if(dtick === 'D1' && ax._id.charAt(0) === 'y') { + out.dy -= out.fontSize / 6; + } + } + } else if(dtChar0 === 'D') { + out.text = + ax.minorloglabels === 'none' ? '' : + /* ax.minorloglabels === 'small digits' */ String(Math.round(Math.pow(10, Lib.mod(x, 1)))); + + out.fontSize *= 0.75; + } else throw 'unrecognized dtick ' + String(dtick); + + // if 9's are printed on log scale, move the 10's away a bit + if(ax.dtick === 'D1') { + var firstChar = String(out.text).charAt(0); + if(firstChar === '0' || firstChar === '1') { + if(ax._id.charAt(0) === 'y') { + out.dx -= out.fontSize / 4; + } else { + out.dy += out.fontSize / 2; + out.dx += (ax.range[1] > ax.range[0] ? 1 : -1) * + out.fontSize * (x < 0 ? 0.5 : 0.25); + } + } + } } function formatCategory(ax, out) { - var tt = ax._categories[Math.round(out.x)]; - if (tt === undefined) tt = ""; - out.text = String(tt); + var tt = ax._categories[Math.round(out.x)]; + if(tt === undefined) tt = ''; + out.text = String(tt); } function formatMultiCategory(ax, out, hover) { - var v = Math.round(out.x); - var cats = ax._categories[v] || []; - var tt = cats[1] === undefined ? "" : String(cats[1]); - var tt2 = cats[0] === undefined ? "" : String(cats[0]); - - if (hover) { - // TODO is this what we want? - out.text = tt2 + " - " + tt; - } else { - // setup for secondary labels - out.text = tt; - out.text2 = tt2; - } + var v = Math.round(out.x); + var cats = ax._categories[v] || []; + var tt = cats[1] === undefined ? '' : String(cats[1]); + var tt2 = cats[0] === undefined ? '' : String(cats[0]); + + if(hover) { + // TODO is this what we want? + out.text = tt2 + ' - ' + tt; + } else { + // setup for secondary labels + out.text = tt; + out.text2 = tt2; + } } function formatLinear(ax, out, hover, extraPrecision, hideexp) { - if (hideexp === "never") { - // If this is a hover label, then we must *never* hide the exponent - // for the sake of display, which could give the wrong value by - // potentially many orders of magnitude. If hideexp was 'never', then - // it's now succeeded by preventing the other condition from automating - // this choice. Thus we can unset it so that the axis formatting takes - // precedence. - hideexp = ""; - } else if (ax.showexponent === "all" && Math.abs(out.x / ax.dtick) < 1e-6) { - // don't add an exponent to zero if we're showing all exponents - // so the only reason you'd show an exponent on zero is if it's the - // ONLY tick to get an exponent (first or last) - hideexp = "hide"; - } - out.text = numFormat(out.x, ax, hideexp, extraPrecision); + if(hideexp === 'never') { + // If this is a hover label, then we must *never* hide the exponent + // for the sake of display, which could give the wrong value by + // potentially many orders of magnitude. If hideexp was 'never', then + // it's now succeeded by preventing the other condition from automating + // this choice. Thus we can unset it so that the axis formatting takes + // precedence. + hideexp = ''; + } else if(ax.showexponent === 'all' && Math.abs(out.x / ax.dtick) < 1e-6) { + // don't add an exponent to zero if we're showing all exponents + // so the only reason you'd show an exponent on zero is if it's the + // ONLY tick to get an exponent (first or last) + hideexp = 'hide'; + } + out.text = numFormat(out.x, ax, hideexp, extraPrecision); } function formatAngle(ax, out, hover, extraPrecision, hideexp) { - if (ax.thetaunit === "radians" && !hover) { - var num = out.x / 180; - - if (num === 0) { - out.text = "0"; - } else { - var frac = num2frac(num); + if(ax.thetaunit === 'radians' && !hover) { + var num = out.x / 180; - if (frac[1] >= 100) { - out.text = numFormat(Lib.deg2rad(out.x), ax, hideexp, extraPrecision); - } else { - var isNeg = out.x < 0; - - if (frac[1] === 1) { - if (frac[0] === 1) out.text = "π"; - else out.text = frac[0] + "π"; + if(num === 0) { + out.text = '0'; } else { - out.text = [ - "", - frac[0], - "", - "⁄", - "", - frac[1], - "", - "π", - ].join(""); + var frac = num2frac(num); + + if(frac[1] >= 100) { + out.text = numFormat(Lib.deg2rad(out.x), ax, hideexp, extraPrecision); + } else { + var isNeg = out.x < 0; + + if(frac[1] === 1) { + if(frac[0] === 1) out.text = 'π'; + else out.text = frac[0] + 'π'; + } else { + out.text = [ + '', frac[0], '', + '⁄', + '', frac[1], '', + 'π' + ].join(''); + } + + if(isNeg) out.text = MINUS_SIGN + out.text; + } } - - if (isNeg) out.text = MINUS_SIGN + out.text; - } + } else { + out.text = numFormat(out.x, ax, hideexp, extraPrecision); } - } else { - out.text = numFormat(out.x, ax, hideexp, extraPrecision); - } } // inspired by // https://github.com/yisibl/num2fraction/blob/master/index.js function num2frac(num) { - function almostEq(a, b) { - return Math.abs(a - b) <= 1e-6; - } - - function findGCD(a, b) { - return almostEq(b, 0) ? a : findGCD(b, a % b); - } - - function findPrecision(n) { - var e = 1; - while (!almostEq(Math.round(n * e) / e, n)) { - e *= 10; - } - return e; - } - - var precision = findPrecision(num); - var number = num * precision; - var gcd = Math.abs(findGCD(number, precision)); - - return [ - // numerator - Math.round(number / gcd), - // denominator - Math.round(precision / gcd), - ]; + function almostEq(a, b) { + return Math.abs(a - b) <= 1e-6; + } + + function findGCD(a, b) { + return almostEq(b, 0) ? a : findGCD(b, a % b); + } + + function findPrecision(n) { + var e = 1; + while(!almostEq(Math.round(n * e) / e, n)) { + e *= 10; + } + return e; + } + + var precision = findPrecision(num); + var number = num * precision; + var gcd = Math.abs(findGCD(number, precision)); + + return [ + // numerator + Math.round(number / gcd), + // denominator + Math.round(precision / gcd) + ]; } // format a number (tick value) according to the axis settings // new, more reliable procedure than d3.round or similar: // add half the rounding increment, then stringify and truncate // also automatically switch to sci. notation -var SIPREFIXES = ["f", "p", "n", "μ", "m", "", "k", "M", "G", "T"]; +var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; // extending SI prefixes -var SIPREFIXES_EXTENDED = [ - "q", - "r", - "y", - "z", - "a", - "f", - "p", - "n", - "μ", - "m", - "", - "k", - "M", - "G", - "T", - "P", - "E", - "Z", - "Y", - "R", - "Q", -]; +var SIPREFIXES_EXTENDED = ['q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q']; function isSIFormat(exponentFormat) { - return ( - exponentFormat === "SI" || - exponentFormat === "SI extended" || - exponentFormat === "B" - ); + return exponentFormat === 'SI' || exponentFormat === 'SI extended' || exponentFormat === 'B'; } // are we beyond the range of common SI prefixes? @@ -2219,218 +2080,188 @@ function isSIFormat(exponentFormat) { // 10^15 -> 1x10^15 // 10^16 -> 1x10^16 function beyondSI(exponent) { - return exponent > 14 || exponent < -15; + return exponent > 14 || exponent < -15; } function beyondSIExtended(exponent) { - return exponent > 32 || exponent < -30; + return exponent > 32 || exponent < -30; } function numFormat(v, ax, fmtoverride, hover) { - var isNeg = v < 0; - // max number of digits past decimal point to show - var tickRound = ax._tickround; - var exponentFormat = fmtoverride || ax.exponentformat || "B"; - var exponent = ax._tickexponent; - var tickformat = axes.getTickFormat(ax); - var separatethousands = ax.separatethousands; - - // special case for hover: set exponent just for this value, and - // add a couple more digits of precision over tick labels - if (hover) { - // make a dummy axis obj to get the auto rounding and exponent - var ah = { - exponentformat: exponentFormat, - minexponent: ax.minexponent, - dtick: - ax.showexponent === "none" - ? ax.dtick - : isNumeric(v) - ? Math.abs(v) || 1 - : 1, - // if not showing any exponents, don't change the exponent - // from what we calculate - range: ax.showexponent === "none" ? ax.range.map(ax.r2d) : [0, v || 1], - }; - autoTickRound(ah); - tickRound = (Number(ah._tickround) || 0) + 4; - exponent = ah._tickexponent; - if (ax.hoverformat) tickformat = ax.hoverformat; - } - - if (tickformat) return ax._numFormat(tickformat)(v).replace(/-/g, MINUS_SIGN); - - // 'epsilon' - rounding increment - var e = Math.pow(10, -tickRound) / 2; - - // exponentFormat codes: - // 'e' (1.2e+6, default) - // 'E' (1.2E+6) - // 'SI' (1.2M) - // 'B' (same as SI except 10^9=B not G) - // 'none' (1200000) - // 'power' (1.2x10^6) - // 'hide' (1.2, use 3rd argument=='hide' to eg - // only show exponent on last tick) - if (exponentFormat === "none") exponent = 0; - - // take the sign out, put it back manually at the end - // - makes cases easier - v = Math.abs(v); - if (v < e) { - // 0 is just 0, but may get exponent if it's the last tick - v = "0"; - isNeg = false; - } else { - v += e; - // take out a common exponent, if any - if (exponent) { - v *= Math.pow(10, -exponent); - tickRound += exponent; - } - // round the mantissa - if (tickRound === 0) v = String(Math.floor(v)); - else if (tickRound < 0) { - v = String(Math.round(v)); - v = v.substr(0, v.length + tickRound); - for (var i = tickRound; i < 0; i++) v += "0"; + var isNeg = v < 0; + // max number of digits past decimal point to show + var tickRound = ax._tickround; + var exponentFormat = fmtoverride || ax.exponentformat || 'B'; + var exponent = ax._tickexponent; + var tickformat = axes.getTickFormat(ax); + var separatethousands = ax.separatethousands; + + // special case for hover: set exponent just for this value, and + // add a couple more digits of precision over tick labels + if(hover) { + // make a dummy axis obj to get the auto rounding and exponent + var ah = { + exponentformat: exponentFormat, + minexponent: ax.minexponent, + dtick: ax.showexponent === 'none' ? ax.dtick : + (isNumeric(v) ? Math.abs(v) || 1 : 1), + // if not showing any exponents, don't change the exponent + // from what we calculate + range: ax.showexponent === 'none' ? ax.range.map(ax.r2d) : [0, v || 1] + }; + autoTickRound(ah); + tickRound = (Number(ah._tickround) || 0) + 4; + exponent = ah._tickexponent; + if(ax.hoverformat) tickformat = ax.hoverformat; + } + + if(tickformat) return ax._numFormat(tickformat)(v).replace(/-/g, MINUS_SIGN); + + // 'epsilon' - rounding increment + var e = Math.pow(10, -tickRound) / 2; + + // exponentFormat codes: + // 'e' (1.2e+6, default) + // 'E' (1.2E+6) + // 'SI' (1.2M) + // 'B' (same as SI except 10^9=B not G) + // 'none' (1200000) + // 'power' (1.2x10^6) + // 'hide' (1.2, use 3rd argument=='hide' to eg + // only show exponent on last tick) + if(exponentFormat === 'none') exponent = 0; + + // take the sign out, put it back manually at the end + // - makes cases easier + v = Math.abs(v); + if(v < e) { + // 0 is just 0, but may get exponent if it's the last tick + v = '0'; + isNeg = false; } else { - v = String(v); - var dp = v.indexOf(".") + 1; - if (dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ""); - } - // insert appropriate decimal point and thousands separator - v = Lib.numSeparate(v, ax._separators, separatethousands); - } - - // add exponent - if (exponent && exponentFormat !== "hide") { - if ( - (isSIFormat(exponentFormat) && - exponentFormat !== "SI extended" && - beyondSI(exponent)) || - (isSIFormat(exponentFormat) && - exponentFormat === "SI extended" && - beyondSIExtended(exponent)) - ) - exponentFormat = "power"; - - var signedExponent; - if (exponent < 0) signedExponent = MINUS_SIGN + -exponent; - else if (exponentFormat !== "power") signedExponent = "+" + exponent; - else signedExponent = String(exponent); - - if (exponentFormat === "e" || exponentFormat === "E") { - v += exponentFormat + signedExponent; - } else if (exponentFormat === "power") { - v += "×10" + signedExponent + ""; - } else if (exponentFormat === "B" && exponent === 9) { - v += "B"; - } else if (isSIFormat(exponentFormat)) { - if (exponentFormat !== "SI extended") { - v += SIPREFIXES[exponent / 3 + 5]; - } else if (exponentFormat === "SI extended") { - v += SIPREFIXES_EXTENDED[exponent / 3 + 10]; - } - } - } - - // put sign back in and return - // replace standard minus character (which is technically a hyphen) - // with a true minus sign - if (isNeg) return MINUS_SIGN + v; - return v; + v += e; + // take out a common exponent, if any + if(exponent) { + v *= Math.pow(10, -exponent); + tickRound += exponent; + } + // round the mantissa + if(tickRound === 0) v = String(Math.floor(v)); + else if(tickRound < 0) { + v = String(Math.round(v)); + v = v.substr(0, v.length + tickRound); + for(var i = tickRound; i < 0; i++) v += '0'; + } else { + v = String(v); + var dp = v.indexOf('.') + 1; + if(dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ''); + } + // insert appropriate decimal point and thousands separator + v = Lib.numSeparate(v, ax._separators, separatethousands); + } + + // add exponent + if(exponent && exponentFormat !== 'hide') { + if((isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(exponent)) || + (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(exponent))) exponentFormat = 'power'; + + var signedExponent; + if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; + else if(exponentFormat !== 'power') signedExponent = '+' + exponent; + else signedExponent = String(exponent); + + if(exponentFormat === 'e' || exponentFormat === 'E') { + v += exponentFormat + signedExponent; + } else if(exponentFormat === 'power') { + v += '×10' + signedExponent + ''; + } else if(exponentFormat === 'B' && exponent === 9) { + v += 'B'; + } else if(isSIFormat(exponentFormat)) { + if(exponentFormat !== 'SI extended') { + v += SIPREFIXES[exponent / 3 + 5]; + } else if(exponentFormat === 'SI extended') { + v += SIPREFIXES_EXTENDED[exponent / 3 + 10]; + } + } + } + + // put sign back in and return + // replace standard minus character (which is technically a hyphen) + // with a true minus sign + if(isNeg) return MINUS_SIGN + v; + return v; } -axes.getTickFormat = function (ax) { - var i; - - function convertToMs(dtick) { - return typeof dtick !== "string" - ? dtick - : Number(dtick.replace("M", "")) * ONEAVGMONTH; - } - - function compareLogTicks(left, right) { - var priority = ["L", "D"]; - if (typeof left === typeof right) { - if (typeof left === "number") { - return left - right; - } else { - var leftPriority = priority.indexOf(left.charAt(0)); - var rightPriority = priority.indexOf(right.charAt(0)); - if (leftPriority === rightPriority) { - return ( - Number(left.replace(/(L|D)/g, "")) - - Number(right.replace(/(L|D)/g, "")) - ); +axes.getTickFormat = function(ax) { + var i; + + function convertToMs(dtick) { + return typeof dtick !== 'string' ? dtick : Number(dtick.replace('M', '')) * ONEAVGMONTH; + } + + function compareLogTicks(left, right) { + var priority = ['L', 'D']; + if(typeof left === typeof right) { + if(typeof left === 'number') { + return left - right; + } else { + var leftPriority = priority.indexOf(left.charAt(0)); + var rightPriority = priority.indexOf(right.charAt(0)); + if(leftPriority === rightPriority) { + return Number(left.replace(/(L|D)/g, '')) - Number(right.replace(/(L|D)/g, '')); + } else { + return leftPriority - rightPriority; + } + } } else { - return leftPriority - rightPriority; + return typeof left === 'number' ? 1 : -1; } - } - } else { - return typeof left === "number" ? 1 : -1; - } - } - - function isProperStop(dtick, range, convert) { - var convertFn = - convert || - function (x) { - return x; - }; - var leftDtick = range[0]; - var rightDtick = range[1]; - return ( - ((!leftDtick && typeof leftDtick !== "number") || - convertFn(leftDtick) <= convertFn(dtick)) && - ((!rightDtick && typeof rightDtick !== "number") || - convertFn(rightDtick) >= convertFn(dtick)) - ); - } + } - function isProperLogStop(dtick, range) { - var isLeftDtickNull = range[0] === null; - var isRightDtickNull = range[1] === null; - var isDtickInRangeLeft = compareLogTicks(dtick, range[0]) >= 0; - var isDtickInRangeRight = compareLogTicks(dtick, range[1]) <= 0; - return ( - (isLeftDtickNull || isDtickInRangeLeft) && - (isRightDtickNull || isDtickInRangeRight) - ); - } - - var tickstop, stopi; - if (ax.tickformatstops && ax.tickformatstops.length > 0) { - switch (ax.type) { - case "date": - case "linear": { - for (i = 0; i < ax.tickformatstops.length; i++) { - stopi = ax.tickformatstops[i]; - if ( - stopi.enabled && - isProperStop(ax.dtick, stopi.dtickrange, convertToMs) - ) { - tickstop = stopi; - break; - } - } - break; - } - case "log": { - for (i = 0; i < ax.tickformatstops.length; i++) { - stopi = ax.tickformatstops[i]; - if (stopi.enabled && isProperLogStop(ax.dtick, stopi.dtickrange)) { - tickstop = stopi; - break; - } + function isProperStop(dtick, range, convert) { + var convertFn = convert || function(x) { return x;}; + var leftDtick = range[0]; + var rightDtick = range[1]; + return ((!leftDtick && typeof leftDtick !== 'number') || convertFn(leftDtick) <= convertFn(dtick)) && + ((!rightDtick && typeof rightDtick !== 'number') || convertFn(rightDtick) >= convertFn(dtick)); + } + + function isProperLogStop(dtick, range) { + var isLeftDtickNull = range[0] === null; + var isRightDtickNull = range[1] === null; + var isDtickInRangeLeft = compareLogTicks(dtick, range[0]) >= 0; + var isDtickInRangeRight = compareLogTicks(dtick, range[1]) <= 0; + return (isLeftDtickNull || isDtickInRangeLeft) && (isRightDtickNull || isDtickInRangeRight); + } + + var tickstop, stopi; + if(ax.tickformatstops && ax.tickformatstops.length > 0) { + switch(ax.type) { + case 'date': + case 'linear': { + for(i = 0; i < ax.tickformatstops.length; i++) { + stopi = ax.tickformatstops[i]; + if(stopi.enabled && isProperStop(ax.dtick, stopi.dtickrange, convertToMs)) { + tickstop = stopi; + break; + } + } + break; + } + case 'log': { + for(i = 0; i < ax.tickformatstops.length; i++) { + stopi = ax.tickformatstops[i]; + if(stopi.enabled && isProperLogStop(ax.dtick, stopi.dtickrange)) { + tickstop = stopi; + break; + } + } + break; + } + default: } - break; - } - default: } - } - return tickstop ? tickstop.value : ax.tickformat; + return tickstop ? tickstop.value : ax.tickformat; }; // getSubplots - extract all subplot IDs we need @@ -2440,92 +2271,83 @@ axes.getTickFormat = function (ax) { // // NOTE: this is currently only used OUTSIDE plotly.js (toolpanel, webapp) // ideally we get rid of it there (or just copy this there) and remove it here -axes.getSubplots = function (gd, ax) { - var subplotObj = gd._fullLayout._subplots; - var allSubplots = subplotObj.cartesian.concat(subplotObj.gl2d || []); +axes.getSubplots = function(gd, ax) { + var subplotObj = gd._fullLayout._subplots; + var allSubplots = subplotObj.cartesian.concat(subplotObj.gl2d || []); - var out = ax ? axes.findSubplotsWithAxis(allSubplots, ax) : allSubplots; + var out = ax ? axes.findSubplotsWithAxis(allSubplots, ax) : allSubplots; - out.sort(function (a, b) { - var aParts = a.substr(1).split("y"); - var bParts = b.substr(1).split("y"); + out.sort(function(a, b) { + var aParts = a.substr(1).split('y'); + var bParts = b.substr(1).split('y'); - if (aParts[0] === bParts[0]) return +aParts[1] - +bParts[1]; - return +aParts[0] - +bParts[0]; - }); + if(aParts[0] === bParts[0]) return +aParts[1] - +bParts[1]; + return +aParts[0] - +bParts[0]; + }); - return out; + return out; }; // find all subplots with axis 'ax' // NOTE: this is only used in axes.getSubplots (only used outside plotly.js) and // gl2d/convert (where it restricts axis subplots to only those with gl2d) -axes.findSubplotsWithAxis = function (subplots, ax) { - var axMatch = new RegExp( - ax._id.charAt(0) === "x" ? "^" + ax._id + "y" : ax._id + "$" - ); - var subplotsWithAx = []; - - for (var i = 0; i < subplots.length; i++) { - var sp = subplots[i]; - if (axMatch.test(sp)) subplotsWithAx.push(sp); - } - - return subplotsWithAx; +axes.findSubplotsWithAxis = function(subplots, ax) { + var axMatch = new RegExp( + (ax._id.charAt(0) === 'x') ? ('^' + ax._id + 'y') : (ax._id + '$') + ); + var subplotsWithAx = []; + + for(var i = 0; i < subplots.length; i++) { + var sp = subplots[i]; + if(axMatch.test(sp)) subplotsWithAx.push(sp); + } + + return subplotsWithAx; }; // makeClipPaths: prepare clipPaths for all single axes and all possible xy pairings -axes.makeClipPaths = function (gd) { - var fullLayout = gd._fullLayout; - - // for more info: https://github.com/plotly/plotly.js/issues/2595 - if (fullLayout._hasOnlyLargeSploms) return; - - var fullWidth = { _offset: 0, _length: fullLayout.width, _id: "" }; - var fullHeight = { _offset: 0, _length: fullLayout.height, _id: "" }; - var xaList = axes.list(gd, "x", true); - var yaList = axes.list(gd, "y", true); - var clipList = []; - var i, j; - - for (i = 0; i < xaList.length; i++) { - clipList.push({ x: xaList[i], y: fullHeight }); - for (j = 0; j < yaList.length; j++) { - if (i === 0) clipList.push({ x: fullWidth, y: yaList[j] }); - clipList.push({ x: xaList[i], y: yaList[j] }); - } - } - - // selectors don't work right with camelCase tags, - // have to use class instead - // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I - var axClips = fullLayout._clips - .selectAll(".axesclip") - .data(clipList, function (d) { - return d.x._id + d.y._id; - }); +axes.makeClipPaths = function(gd) { + var fullLayout = gd._fullLayout; + + // for more info: https://github.com/plotly/plotly.js/issues/2595 + if(fullLayout._hasOnlyLargeSploms) return; + + var fullWidth = {_offset: 0, _length: fullLayout.width, _id: ''}; + var fullHeight = {_offset: 0, _length: fullLayout.height, _id: ''}; + var xaList = axes.list(gd, 'x', true); + var yaList = axes.list(gd, 'y', true); + var clipList = []; + var i, j; + + for(i = 0; i < xaList.length; i++) { + clipList.push({x: xaList[i], y: fullHeight}); + for(j = 0; j < yaList.length; j++) { + if(i === 0) clipList.push({x: fullWidth, y: yaList[j]}); + clipList.push({x: xaList[i], y: yaList[j]}); + } + } - axClips - .enter() - .append("clipPath") - .classed("axesclip", true) - .attr("id", function (d) { - return "clip" + fullLayout._uid + d.x._id + d.y._id; - }) - .append("rect"); - - axClips.exit().remove(); - - axClips.each(function (d) { - d3.select(this) - .select("rect") - .attr({ - x: d.x._offset || 0, - y: d.y._offset || 0, - width: d.x._length || 1, - height: d.y._length || 1, - }); - }); + // selectors don't work right with camelCase tags, + // have to use class instead + // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I + var axClips = fullLayout._clips.selectAll('.axesclip') + .data(clipList, function(d) { return d.x._id + d.y._id; }); + + axClips.enter().append('clipPath') + .classed('axesclip', true) + .attr('id', function(d) { return 'clip' + fullLayout._uid + d.x._id + d.y._id; }) + .append('rect'); + + axClips.exit().remove(); + + axClips.each(function(d) { + d3.select(this).select('rect').attr({ + x: d.x._offset || 0, + y: d.y._offset || 0, + width: d.x._length || 1, + height: d.y._length || 1 + }); + }); }; /** @@ -2551,90 +2373,81 @@ axes.makeClipPaths = function (gd) { * - ax._r (stored range for use by zoom/pan) * - ax._rl (stored linearized range for use by zoom/pan) */ -axes.draw = function (gd, arg, opts) { - var fullLayout = gd._fullLayout; - - if (arg === "redraw") { - fullLayout._paper.selectAll("g.subplot").each(function (d) { - var id = d[0]; - var plotinfo = fullLayout._plots[id]; - if (plotinfo) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - plotinfo.xaxislayer.selectAll("." + xa._id + "tick").remove(); - plotinfo.yaxislayer.selectAll("." + ya._id + "tick").remove(); - plotinfo.xaxislayer.selectAll("." + xa._id + "tick2").remove(); - plotinfo.yaxislayer.selectAll("." + ya._id + "tick2").remove(); - plotinfo.xaxislayer.selectAll("." + xa._id + "divider").remove(); - plotinfo.yaxislayer.selectAll("." + ya._id + "divider").remove(); - - if (plotinfo.minorGridlayer) - plotinfo.minorGridlayer.selectAll("path").remove(); - if (plotinfo.gridlayer) plotinfo.gridlayer.selectAll("path").remove(); - if (plotinfo.zerolinelayer) - plotinfo.zerolinelayer.selectAll("path").remove(); - if (plotinfo.zerolinelayerAbove) - plotinfo.zerolinelayerAbove.selectAll("path").remove(); - - fullLayout._infolayer.select(".g-" + xa._id + "title").remove(); - fullLayout._infolayer.select(".g-" + ya._id + "title").remove(); - } - }); - } - - var axList = !arg || arg === "redraw" ? axes.listIds(gd) : arg; - - var fullAxList = axes.list(gd); - // Get the list of the overlaying axis for all 'shift' axes - var overlayingShiftedAx = fullAxList - .filter(function (ax) { - return ax.autoshift; - }) - .map(function (ax) { - return ax.overlaying; +axes.draw = function(gd, arg, opts) { + var fullLayout = gd._fullLayout; + + if(arg === 'redraw') { + fullLayout._paper.selectAll('g.subplot').each(function(d) { + var id = d[0]; + var plotinfo = fullLayout._plots[id]; + if(plotinfo) { + var xa = plotinfo.xaxis; + var ya = plotinfo.yaxis; + + plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick').remove(); + plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick').remove(); + plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick2').remove(); + plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick2').remove(); + plotinfo.xaxislayer.selectAll('.' + xa._id + 'divider').remove(); + plotinfo.yaxislayer.selectAll('.' + ya._id + 'divider').remove(); + + if(plotinfo.minorGridlayer) plotinfo.minorGridlayer.selectAll('path').remove(); + if(plotinfo.gridlayer) plotinfo.gridlayer.selectAll('path').remove(); + if(plotinfo.zerolinelayer) plotinfo.zerolinelayer.selectAll('path').remove(); + if(plotinfo.zerolinelayerAbove) plotinfo.zerolinelayerAbove.selectAll('path').remove(); + + fullLayout._infolayer.select('.g-' + xa._id + 'title').remove(); + fullLayout._infolayer.select('.g-' + ya._id + 'title').remove(); + } + }); + } + + var axList = (!arg || arg === 'redraw') ? axes.listIds(gd) : arg; + + var fullAxList = axes.list(gd); + // Get the list of the overlaying axis for all 'shift' axes + var overlayingShiftedAx = fullAxList.filter(function(ax) { + return ax.autoshift; + }).map(function(ax) { + return ax.overlaying; }); - // order axes that have dependency to other axes - axList.map(function (axId) { - var ax = axes.getFromId(gd, axId); + // order axes that have dependency to other axes + axList.map(function(axId) { + var ax = axes.getFromId(gd, axId); - if (ax.tickmode === "sync" && ax.overlaying) { - var overlayingIndex = axList.findIndex(function (axis) { - return axis === ax.overlaying; - }); + if(ax.tickmode === 'sync' && ax.overlaying) { + var overlayingIndex = axList.findIndex(function(axis) {return axis === ax.overlaying;}); - if (overlayingIndex >= 0) { - axList.unshift(axList.splice(overlayingIndex, 1).shift()); - } - } - }); + if(overlayingIndex >= 0) { + axList.unshift(axList.splice(overlayingIndex, 1).shift()); + } + } + }); - var axShifts = { false: { left: 0, right: 0 } }; + var axShifts = {false: {left: 0, right: 0}}; - return Lib.syncOrAsync( - axList.map(function (axId) { - return function () { - if (!axId) return; + return Lib.syncOrAsync(axList.map(function(axId) { + return function() { + if(!axId) return; - var ax = axes.getFromId(gd, axId); + var ax = axes.getFromId(gd, axId); - if (!opts) opts = {}; - opts.axShifts = axShifts; - opts.overlayingShiftedAx = overlayingShiftedAx; + if(!opts) opts = {}; + opts.axShifts = axShifts; + opts.overlayingShiftedAx = overlayingShiftedAx; - var axDone = axes.drawOne(gd, ax, opts); + var axDone = axes.drawOne(gd, ax, opts); - if (ax._shiftPusher) { - incrementShift(ax, ax._fullDepth || 0, axShifts, true); - } - ax._r = ax.range.slice(); - ax._rl = Lib.simpleMap(ax._r, ax.r2l); + if(ax._shiftPusher) { + incrementShift(ax, ax._fullDepth || 0, axShifts, true); + } + ax._r = ax.range.slice(); + ax._rl = Lib.simpleMap(ax._r, ax.r2l); - return axDone; - }; - }) - ); + return axDone; + }; + })); }; /** @@ -2664,606 +2477,537 @@ axes.draw = function (gd, arg, opts) { * - ax._depth (when required only): * - and calls ax.setScale */ -axes.drawOne = function (gd, ax, opts) { - opts = opts || {}; - - var axShifts = opts.axShifts || {}; - var overlayingShiftedAx = opts.overlayingShiftedAx || []; - - var i, sp, plotinfo; - - ax.setScale(); - - var fullLayout = gd._fullLayout; - var axId = ax._id; - var axLetter = axId.charAt(0); - var counterLetter = axes.counterLetter(axId); - var mainPlotinfo = fullLayout._plots[ax._mainSubplot]; - var zerolineIsAbove = ax.zerolinelayer === "above traces"; - - // this happens when updating matched group with 'missing' axes - if (!mainPlotinfo) return; - - ax._shiftPusher = - ax.autoshift || - overlayingShiftedAx.indexOf(ax._id) !== -1 || - overlayingShiftedAx.indexOf(ax.overlaying) !== -1; - // An axis is also shifted by 1/2 of its own linewidth and inside tick length if applicable - // as well as its manually specified `shift` val if we're in the context of `autoshift` - if (ax._shiftPusher & (ax.anchor === "free")) { - var selfPush = ax.linewidth / 2 || 0; - if (ax.ticks === "inside") { - selfPush += ax.ticklen; - } - incrementShift(ax, selfPush, axShifts, true); - incrementShift(ax, ax.shift || 0, axShifts, false); - } - - // Somewhat inelegant way of making sure that the shift value is only updated when the - // Axes.DrawOne() function is called from the right context. An issue when redrawing the - // axis as result of using the dragbox, for example. - if (opts.skipTitle !== true || ax._shift === undefined) - ax._shift = setShiftVal(ax, axShifts); - - var mainAxLayer = mainPlotinfo[axLetter + "axislayer"]; - var mainLinePosition = ax._mainLinePosition; - var mainLinePositionShift = (mainLinePosition += ax._shift); - var mainMirrorPosition = ax._mainMirrorPosition; - - var vals = (ax._vals = axes.calcTicks(ax)); - - // Add a couple of axis properties that should cause us to recreate - // elements. Used in d3 data function. - var axInfo = [ax.mirror, mainLinePositionShift, mainMirrorPosition].join("_"); - for (i = 0; i < vals.length; i++) { - vals[i].axInfo = axInfo; - } - - // stash selections to avoid DOM queries e.g. - // - stash tickLabels selection, so that drawTitle can use it to scoot title - ax._selections = {}; - // stash tick angle (including the computed 'auto' values) per tick-label class - // linkup 'previous' tick angles on redraws - if (ax._tickAngles) ax._prevTickAngles = ax._tickAngles; - ax._tickAngles = {}; - // measure [in px] between axis position and outward-most part of bounding box - // (touching either the tick label or ticks) - // depth can be expansive to compute, so we only do so when required - ax._depth = null; - - // calcLabelLevelBbox can be expensive, - // so make sure to not call it twice during the same Axes.drawOne call - // by stashing label-level bounding boxes per tick-label class - var llbboxes = {}; - function getLabelLevelBbox(suffix) { - var cls = axId + (suffix || "tick"); - if (!llbboxes[cls]) - llbboxes[cls] = calcLabelLevelBbox(ax, cls, mainLinePositionShift); - return llbboxes[cls]; - } - - if (!ax.visible) return; - - var transTickFn = axes.makeTransTickFn(ax); - var transTickLabelFn = axes.makeTransTickLabelFn(ax); - - var tickVals; - // We remove zero lines, grid lines, and inside ticks if they're within 1px of the end - // The key case here is removing zero lines when the axis bound is zero - var valsClipped; - - var insideTicks = ax.ticks === "inside"; - var outsideTicks = ax.ticks === "outside"; - - if (ax.tickson === "boundaries") { - var boundaryVals = getBoundaryVals(ax, vals); - valsClipped = axes.clipEnds(ax, boundaryVals); - tickVals = insideTicks ? valsClipped : boundaryVals; - } else { - valsClipped = axes.clipEnds(ax, vals); - tickVals = - insideTicks && ax.ticklabelmode !== "period" ? valsClipped : vals; - } - - var gridVals = (ax._gridVals = valsClipped); - var dividerVals = getDividerVals(ax, vals); - - if (!fullLayout._hasOnlyLargeSploms) { - var subplotsWithAx = ax._subplotsWith; - - // keep track of which subplots (by main counter axis) we've already - // drawn grids for, so we don't overdraw overlaying subplots - var finishedGrids = {}; - - for (i = 0; i < subplotsWithAx.length; i++) { - sp = subplotsWithAx[i]; - plotinfo = fullLayout._plots[sp]; - - var counterAxis = plotinfo[counterLetter + "axis"]; - var mainCounterID = counterAxis._mainAxis._id; - if (finishedGrids[mainCounterID]) continue; - finishedGrids[mainCounterID] = 1; - - var gridPath = - axLetter === "x" - ? "M0," + counterAxis._offset + "v" + counterAxis._length - : "M" + counterAxis._offset + ",0h" + counterAxis._length; - - axes.drawGrid(gd, ax, { - vals: gridVals, - counterAxis: counterAxis, - layer: plotinfo.gridlayer.select("." + axId), - minorLayer: plotinfo.minorGridlayer.select("." + axId), - path: gridPath, - transFn: transTickFn, - }); - axes.drawZeroLine(gd, ax, { - counterAxis: counterAxis, - layer: zerolineIsAbove - ? plotinfo.zerolinelayerAbove - : plotinfo.zerolinelayer, - path: gridPath, - transFn: transTickFn, - }); - } - } - - var tickPath; - - var majorTickSigns = axes.getTickSigns(ax); - var minorTickSigns = axes.getTickSigns(ax, "minor"); - - if (ax.ticks || (ax.minor && ax.minor.ticks)) { - var majorTickPath = axes.makeTickPath( - ax, - mainLinePositionShift, - majorTickSigns[2] - ); - var minorTickPath = axes.makeTickPath( - ax, - mainLinePositionShift, - minorTickSigns[2], - { minor: true } - ); +axes.drawOne = function(gd, ax, opts) { + opts = opts || {}; + + var axShifts = opts.axShifts || {}; + var overlayingShiftedAx = opts.overlayingShiftedAx || []; + + var i, sp, plotinfo; + + ax.setScale(); + + var fullLayout = gd._fullLayout; + var axId = ax._id; + var axLetter = axId.charAt(0); + var counterLetter = axes.counterLetter(axId); + var mainPlotinfo = fullLayout._plots[ax._mainSubplot]; + var zerolineIsAbove = ax.zerolinelayer === 'above traces'; + + // this happens when updating matched group with 'missing' axes + if(!mainPlotinfo) return; + + ax._shiftPusher = ax.autoshift || + overlayingShiftedAx.indexOf(ax._id) !== -1 || + overlayingShiftedAx.indexOf(ax.overlaying) !== -1; + // An axis is also shifted by 1/2 of its own linewidth and inside tick length if applicable + // as well as its manually specified `shift` val if we're in the context of `autoshift` + if(ax._shiftPusher & ax.anchor === 'free') { + var selfPush = (ax.linewidth / 2 || 0); + if(ax.ticks === 'inside') { + selfPush += ax.ticklen; + } + incrementShift(ax, selfPush, axShifts, true); + incrementShift(ax, (ax.shift || 0), axShifts, false); + } - var mirrorMajorTickPath; - var mirrorMinorTickPath; - - var fullMajorTickPath; - var fullMinorTickPath; - - if (ax._anchorAxis && ax.mirror && ax.mirror !== true) { - mirrorMajorTickPath = axes.makeTickPath( - ax, - mainMirrorPosition, - majorTickSigns[3] - ); - mirrorMinorTickPath = axes.makeTickPath( - ax, - mainMirrorPosition, - minorTickSigns[3], - { minor: true } - ); - - fullMajorTickPath = majorTickPath + mirrorMajorTickPath; - fullMinorTickPath = minorTickPath + mirrorMinorTickPath; - } else { - mirrorMajorTickPath = ""; - mirrorMinorTickPath = ""; - fullMajorTickPath = majorTickPath; - fullMinorTickPath = minorTickPath; - } - - if (ax.showdividers && outsideTicks && ax.tickson === "boundaries") { - var dividerLookup = {}; - for (i = 0; i < dividerVals.length; i++) { - dividerLookup[dividerVals[i].x] = 1; - } - tickPath = function (d) { - return dividerLookup[d.x] ? mirrorMajorTickPath : fullMajorTickPath; - }; + // Somewhat inelegant way of making sure that the shift value is only updated when the + // Axes.DrawOne() function is called from the right context. An issue when redrawing the + // axis as result of using the dragbox, for example. + if(opts.skipTitle !== true || ax._shift === undefined) ax._shift = setShiftVal(ax, axShifts); + + var mainAxLayer = mainPlotinfo[axLetter + 'axislayer']; + var mainLinePosition = ax._mainLinePosition; + var mainLinePositionShift = mainLinePosition += ax._shift; + var mainMirrorPosition = ax._mainMirrorPosition; + + var vals = ax._vals = axes.calcTicks(ax); + + // Add a couple of axis properties that should cause us to recreate + // elements. Used in d3 data function. + var axInfo = [ax.mirror, mainLinePositionShift, mainMirrorPosition].join('_'); + for(i = 0; i < vals.length; i++) { + vals[i].axInfo = axInfo; + } + + // stash selections to avoid DOM queries e.g. + // - stash tickLabels selection, so that drawTitle can use it to scoot title + ax._selections = {}; + // stash tick angle (including the computed 'auto' values) per tick-label class + // linkup 'previous' tick angles on redraws + if(ax._tickAngles) ax._prevTickAngles = ax._tickAngles; + ax._tickAngles = {}; + // measure [in px] between axis position and outward-most part of bounding box + // (touching either the tick label or ticks) + // depth can be expansive to compute, so we only do so when required + ax._depth = null; + + // calcLabelLevelBbox can be expensive, + // so make sure to not call it twice during the same Axes.drawOne call + // by stashing label-level bounding boxes per tick-label class + var llbboxes = {}; + function getLabelLevelBbox(suffix) { + var cls = axId + (suffix || 'tick'); + if(!llbboxes[cls]) llbboxes[cls] = calcLabelLevelBbox(ax, cls, mainLinePositionShift); + return llbboxes[cls]; + } + + if(!ax.visible) return; + + var transTickFn = axes.makeTransTickFn(ax); + var transTickLabelFn = axes.makeTransTickLabelFn(ax); + + var tickVals; + // We remove zero lines, grid lines, and inside ticks if they're within 1px of the end + // The key case here is removing zero lines when the axis bound is zero + var valsClipped; + + var insideTicks = ax.ticks === 'inside'; + var outsideTicks = ax.ticks === 'outside'; + + if(ax.tickson === 'boundaries') { + var boundaryVals = getBoundaryVals(ax, vals); + valsClipped = axes.clipEnds(ax, boundaryVals); + tickVals = insideTicks ? valsClipped : boundaryVals; } else { - tickPath = function (d) { - return d.minor ? fullMinorTickPath : fullMajorTickPath; - }; - } - } - - axes.drawTicks(gd, ax, { - vals: tickVals, - layer: mainAxLayer, - path: tickPath, - transFn: transTickFn, - }); - - if (ax.mirror === "allticks") { - var tickSubplots = Object.keys(ax._linepositions || {}); - - for (i = 0; i < tickSubplots.length; i++) { - sp = tickSubplots[i]; - plotinfo = fullLayout._plots[sp]; - // [bottom or left, top or right], free and main are handled above - var linepositions = ax._linepositions[sp] || []; - - var p0 = linepositions[0]; - var p1 = linepositions[1]; - var isMinor = linepositions[2]; - - var spTickPath = - axes.makeTickPath( - ax, - p0, - isMinor ? majorTickSigns[0] : minorTickSigns[0], - { minor: isMinor } - ) + - axes.makeTickPath( - ax, - p1, - isMinor ? majorTickSigns[1] : minorTickSigns[1], - { minor: isMinor } - ); + valsClipped = axes.clipEnds(ax, vals); + tickVals = (insideTicks && ax.ticklabelmode !== 'period') ? valsClipped : vals; + } - axes.drawTicks(gd, ax, { - vals: tickVals, - layer: plotinfo[axLetter + "axislayer"], - path: spTickPath, - transFn: transTickFn, - }); + var gridVals = ax._gridVals = valsClipped; + var dividerVals = getDividerVals(ax, vals); + + if(!fullLayout._hasOnlyLargeSploms) { + var subplotsWithAx = ax._subplotsWith; + + // keep track of which subplots (by main counter axis) we've already + // drawn grids for, so we don't overdraw overlaying subplots + var finishedGrids = {}; + + for(i = 0; i < subplotsWithAx.length; i++) { + sp = subplotsWithAx[i]; + plotinfo = fullLayout._plots[sp]; + + var counterAxis = plotinfo[counterLetter + 'axis']; + var mainCounterID = counterAxis._mainAxis._id; + if(finishedGrids[mainCounterID]) continue; + finishedGrids[mainCounterID] = 1; + + var gridPath = axLetter === 'x' ? + 'M0,' + counterAxis._offset + 'v' + counterAxis._length : + 'M' + counterAxis._offset + ',0h' + counterAxis._length; + + axes.drawGrid(gd, ax, { + vals: gridVals, + counterAxis: counterAxis, + layer: plotinfo.gridlayer.select('.' + axId), + minorLayer: plotinfo.minorGridlayer.select('.' + axId), + path: gridPath, + transFn: transTickFn + }); + axes.drawZeroLine(gd, ax, { + counterAxis: counterAxis, + layer: zerolineIsAbove ? plotinfo.zerolinelayerAbove : plotinfo.zerolinelayer, + path: gridPath, + transFn: transTickFn + }); + } } - } - var seq = []; + var tickPath; - // tick labels - for now just the main labels. - // TODO: mirror labels, esp for subplots + var majorTickSigns = axes.getTickSigns(ax); + var minorTickSigns = axes.getTickSigns(ax, 'minor'); - seq.push(function () { - return axes.drawLabels(gd, ax, { - vals: vals, - layer: mainAxLayer, - plotinfo: plotinfo, - transFn: transTickLabelFn, - labelFns: axes.makeLabelFns(ax, mainLinePositionShift), - }); - }); + if(ax.ticks || (ax.minor && ax.minor.ticks)) { + var majorTickPath = axes.makeTickPath(ax, mainLinePositionShift, majorTickSigns[2]); + var minorTickPath = axes.makeTickPath(ax, mainLinePositionShift, minorTickSigns[2], { minor: true }); - if (ax.type === "multicategory") { - var pad = { x: 2, y: 10 }[axLetter]; + var mirrorMajorTickPath; + var mirrorMinorTickPath; - seq.push(function () { - var bboxKey = { x: "height", y: "width" }[axLetter]; - var standoff = - getLabelLevelBbox()[bboxKey] + - pad + - (ax._tickAngles[axId + "tick"] ? ax.tickfont.size * LINE_SPACING : 0); + var fullMajorTickPath; + var fullMinorTickPath; - return axes.drawLabels(gd, ax, { - vals: getSecondaryLabelVals(ax, vals), - layer: mainAxLayer, - cls: axId + "tick2", - repositionOnUpdate: true, - secondary: true, - transFn: transTickFn, - labelFns: axes.makeLabelFns( - ax, - mainLinePositionShift + standoff * majorTickSigns[4] - ), - }); - }); + if(ax._anchorAxis && ax.mirror && ax.mirror !== true) { + mirrorMajorTickPath = axes.makeTickPath(ax, mainMirrorPosition, majorTickSigns[3]); + mirrorMinorTickPath = axes.makeTickPath(ax, mainMirrorPosition, minorTickSigns[3], { minor: true }); - seq.push(function () { - ax._depth = - majorTickSigns[4] * - (getLabelLevelBbox("tick2")[ax.side] - mainLinePositionShift); + fullMajorTickPath = majorTickPath + mirrorMajorTickPath; + fullMinorTickPath = minorTickPath + mirrorMinorTickPath; + } else { + mirrorMajorTickPath = ''; + mirrorMinorTickPath = ''; + fullMajorTickPath = majorTickPath; + fullMinorTickPath = minorTickPath; + } + + if(ax.showdividers && outsideTicks && ax.tickson === 'boundaries') { + var dividerLookup = {}; + for(i = 0; i < dividerVals.length; i++) { + dividerLookup[dividerVals[i].x] = 1; + } + tickPath = function(d) { + return dividerLookup[d.x] ? mirrorMajorTickPath : fullMajorTickPath; + }; + } else { + tickPath = function(d) { + return d.minor ? fullMinorTickPath : fullMajorTickPath; + }; + } + } - return drawDividers(gd, ax, { - vals: dividerVals, + axes.drawTicks(gd, ax, { + vals: tickVals, layer: mainAxLayer, - path: axes.makeTickPath(ax, mainLinePositionShift, majorTickSigns[4], { - len: ax._depth, - }), - transFn: transTickFn, - }); + path: tickPath, + transFn: transTickFn }); - } else if (ax.title.hasOwnProperty("standoff")) { - seq.push(function () { - ax._depth = - majorTickSigns[4] * - (getLabelLevelBbox()[ax.side] - mainLinePositionShift); - }); - } - var hasRangeSlider = Registry.getComponentMethod( - "rangeslider", - "isVisible" - )(ax); + if(ax.mirror === 'allticks') { + var tickSubplots = Object.keys(ax._linepositions || {}); + + for(i = 0; i < tickSubplots.length; i++) { + sp = tickSubplots[i]; + plotinfo = fullLayout._plots[sp]; + // [bottom or left, top or right], free and main are handled above + var linepositions = ax._linepositions[sp] || []; + + var p0 = linepositions[0]; + var p1 = linepositions[1]; + var isMinor = linepositions[2]; + + var spTickPath = + axes.makeTickPath(ax, p0, + isMinor ? majorTickSigns[0] : minorTickSigns[0], + { minor: isMinor } + ) + + axes.makeTickPath(ax, p1, + isMinor ? majorTickSigns[1] : minorTickSigns[1], + { minor: isMinor } + ); + + axes.drawTicks(gd, ax, { + vals: tickVals, + layer: plotinfo[axLetter + 'axislayer'], + path: spTickPath, + transFn: transTickFn + }); + } + } + + var seq = []; + + // tick labels - for now just the main labels. + // TODO: mirror labels, esp for subplots - if (!opts.skipTitle && !(hasRangeSlider && ax.side === "bottom")) { - seq.push(function () { - return drawTitle(gd, ax); + seq.push(function() { + return axes.drawLabels(gd, ax, { + vals: vals, + layer: mainAxLayer, + plotinfo: plotinfo, + transFn: transTickLabelFn, + labelFns: axes.makeLabelFns(ax, mainLinePositionShift) + }); }); - } - seq.push(function () { - var s = ax.side.charAt(0); - var sMirror = OPPOSITE_SIDE[ax.side].charAt(0); - var pos = axes.getPxPosition(gd, ax); - var outsideTickLen = outsideTicks ? ax.ticklen : 0; - var llbbox; - - var push; - var mirrorPush; - var rangeSliderPush; - - if (ax.automargin || hasRangeSlider || ax._shiftPusher) { - if (ax.type === "multicategory") { - llbbox = getLabelLevelBbox("tick2"); - } else { - llbbox = getLabelLevelBbox(); - if (axLetter === "x" && s === "b") { - ax._depth = Math.max( - llbbox.width > 0 ? llbbox.bottom - pos : 0, - outsideTickLen - ); - } - } - } - - var axDepth = 0; - var titleDepth = 0; - if (ax._shiftPusher) { - axDepth = Math.max( - outsideTickLen, - llbbox.height > 0 - ? s === "l" - ? pos - llbbox.left - : llbbox.right - pos - : 0 - ); - if (ax.title.text !== fullLayout._dfltTitle[axLetter]) { - titleDepth = (ax._titleStandoff || 0) + (ax._titleScoot || 0); - if (s === "l") { - titleDepth += approxTitleDepth(ax); - } - } + if(ax.type === 'multicategory') { + var pad = {x: 2, y: 10}[axLetter]; + + seq.push(function() { + var bboxKey = {x: 'height', y: 'width'}[axLetter]; + var standoff = getLabelLevelBbox()[bboxKey] + pad + + (ax._tickAngles[axId + 'tick'] ? ax.tickfont.size * LINE_SPACING : 0); + + return axes.drawLabels(gd, ax, { + vals: getSecondaryLabelVals(ax, vals), + layer: mainAxLayer, + cls: axId + 'tick2', + repositionOnUpdate: true, + secondary: true, + transFn: transTickFn, + labelFns: axes.makeLabelFns(ax, mainLinePositionShift + standoff * majorTickSigns[4]) + }); + }); + + seq.push(function() { + ax._depth = majorTickSigns[4] * (getLabelLevelBbox('tick2')[ax.side] - mainLinePositionShift); + + return drawDividers(gd, ax, { + vals: dividerVals, + layer: mainAxLayer, + path: axes.makeTickPath(ax, mainLinePositionShift, majorTickSigns[4], { len: ax._depth }), + transFn: transTickFn + }); + }); + } else if(ax.title.hasOwnProperty('standoff')) { + seq.push(function() { + ax._depth = majorTickSigns[4] * (getLabelLevelBbox()[ax.side] - mainLinePositionShift); + }); + } + + var hasRangeSlider = Registry.getComponentMethod('rangeslider', 'isVisible')(ax); - ax._fullDepth = Math.max(axDepth, titleDepth); + if(!opts.skipTitle && + !(hasRangeSlider && ax.side === 'bottom') + ) { + seq.push(function() { return drawTitle(gd, ax); }); } - if (ax.automargin) { - push = { x: 0, y: 0, r: 0, l: 0, t: 0, b: 0 }; - var domainIndices = [0, 1]; - var shift = typeof ax._shift === "number" ? ax._shift : 0; - if (axLetter === "x") { - if (s === "b") { - push[s] = ax._depth; - } else { - push[s] = ax._depth = Math.max( - llbbox.width > 0 ? pos - llbbox.top : 0, - outsideTickLen - ); - domainIndices.reverse(); + seq.push(function() { + var s = ax.side.charAt(0); + var sMirror = OPPOSITE_SIDE[ax.side].charAt(0); + var pos = axes.getPxPosition(gd, ax); + var outsideTickLen = outsideTicks ? ax.ticklen : 0; + var llbbox; + + var push; + var mirrorPush; + var rangeSliderPush; + + if(ax.automargin || hasRangeSlider || ax._shiftPusher) { + if(ax.type === 'multicategory') { + llbbox = getLabelLevelBbox('tick2'); + } else { + llbbox = getLabelLevelBbox(); + if(axLetter === 'x' && s === 'b') { + ax._depth = Math.max(llbbox.width > 0 ? llbbox.bottom - pos : 0, outsideTickLen); + } + } } - if (llbbox.width > 0) { - var rExtra = llbbox.right - (ax._offset + ax._length); - if (rExtra > 0) { - push.xr = 1; - push.r = rExtra; - } - var lExtra = ax._offset - llbbox.left; - if (lExtra > 0) { - push.xl = 0; - push.l = lExtra; - } - } - } else { - if (s === "l") { - ax._depth = Math.max( - llbbox.height > 0 ? pos - llbbox.left : 0, - outsideTickLen - ); - push[s] = ax._depth - shift; - } else { - ax._depth = Math.max( - llbbox.height > 0 ? llbbox.right - pos : 0, - outsideTickLen - ); - push[s] = ax._depth + shift; - domainIndices.reverse(); + var axDepth = 0; + var titleDepth = 0; + if(ax._shiftPusher) { + axDepth = Math.max( + outsideTickLen, + llbbox.height > 0 ? (s === 'l' ? pos - llbbox.left : llbbox.right - pos) : 0 + ); + if(ax.title.text !== fullLayout._dfltTitle[axLetter]) { + titleDepth = (ax._titleStandoff || 0) + (ax._titleScoot || 0); + if(s === 'l') { + titleDepth += approxTitleDepth(ax); + } + } + + ax._fullDepth = Math.max(axDepth, titleDepth); } - if (llbbox.height > 0) { - var bExtra = llbbox.bottom - (ax._offset + ax._length); - if (bExtra > 0) { - push.yb = 0; - push.b = bExtra; - } - var tExtra = ax._offset - llbbox.top; - if (tExtra > 0) { - push.yt = 1; - push.t = tExtra; - } + if(ax.automargin) { + push = {x: 0, y: 0, r: 0, l: 0, t: 0, b: 0}; + var domainIndices = [0, 1]; + var shift = typeof ax._shift === 'number' ? ax._shift : 0; + if(axLetter === 'x') { + if(s === 'b') { + push[s] = ax._depth; + } else { + push[s] = ax._depth = Math.max(llbbox.width > 0 ? pos - llbbox.top : 0, outsideTickLen); + domainIndices.reverse(); + } + + if(llbbox.width > 0) { + var rExtra = llbbox.right - (ax._offset + ax._length); + if(rExtra > 0) { + push.xr = 1; + push.r = rExtra; + } + var lExtra = ax._offset - llbbox.left; + if(lExtra > 0) { + push.xl = 0; + push.l = lExtra; + } + } + } else { + if(s === 'l') { + ax._depth = Math.max(llbbox.height > 0 ? pos - llbbox.left : 0, outsideTickLen); + push[s] = ax._depth - shift; + } else { + ax._depth = Math.max(llbbox.height > 0 ? llbbox.right - pos : 0, outsideTickLen); + push[s] = ax._depth + shift; + domainIndices.reverse(); + } + + if(llbbox.height > 0) { + var bExtra = llbbox.bottom - (ax._offset + ax._length); + if(bExtra > 0) { + push.yb = 0; + push.b = bExtra; + } + var tExtra = ax._offset - llbbox.top; + if(tExtra > 0) { + push.yt = 1; + push.t = tExtra; + } + } + } + + push[counterLetter] = ax.anchor === 'free' ? + ax.position : + ax._anchorAxis.domain[domainIndices[0]]; + + if(ax.title.text !== fullLayout._dfltTitle[axLetter]) { + push[s] += approxTitleDepth(ax) + (ax.title.standoff || 0); + } + + if(ax.mirror && ax.anchor !== 'free') { + mirrorPush = {x: 0, y: 0, r: 0, l: 0, t: 0, b: 0}; + + mirrorPush[sMirror] = ax.linewidth; + if(ax.mirror && ax.mirror !== true) mirrorPush[sMirror] += outsideTickLen; + + if(ax.mirror === true || ax.mirror === 'ticks') { + mirrorPush[counterLetter] = ax._anchorAxis.domain[domainIndices[1]]; + } else if(ax.mirror === 'all' || ax.mirror === 'allticks') { + mirrorPush[counterLetter] = [ax._counterDomainMin, ax._counterDomainMax][domainIndices[1]]; + } + } } - } - - push[counterLetter] = - ax.anchor === "free" - ? ax.position - : ax._anchorAxis.domain[domainIndices[0]]; - - if (ax.title.text !== fullLayout._dfltTitle[axLetter]) { - push[s] += approxTitleDepth(ax) + (ax.title.standoff || 0); - } - - if (ax.mirror && ax.anchor !== "free") { - mirrorPush = { x: 0, y: 0, r: 0, l: 0, t: 0, b: 0 }; - - mirrorPush[sMirror] = ax.linewidth; - if (ax.mirror && ax.mirror !== true) - mirrorPush[sMirror] += outsideTickLen; - - if (ax.mirror === true || ax.mirror === "ticks") { - mirrorPush[counterLetter] = ax._anchorAxis.domain[domainIndices[1]]; - } else if (ax.mirror === "all" || ax.mirror === "allticks") { - mirrorPush[counterLetter] = [ - ax._counterDomainMin, - ax._counterDomainMax, - ][domainIndices[1]]; + if(hasRangeSlider) { + rangeSliderPush = Registry.getComponentMethod('rangeslider', 'autoMarginOpts')(gd, ax); } - } - } - if (hasRangeSlider) { - rangeSliderPush = Registry.getComponentMethod( - "rangeslider", - "autoMarginOpts" - )(gd, ax); - } - if (typeof ax.automargin === "string") { - filterPush(push, ax.automargin); - filterPush(mirrorPush, ax.automargin); - } + if(typeof ax.automargin === 'string') { + filterPush(push, ax.automargin); + filterPush(mirrorPush, ax.automargin); + } - Plots.autoMargin(gd, axAutoMarginID(ax), push); - Plots.autoMargin(gd, axMirrorAutoMarginID(ax), mirrorPush); - Plots.autoMargin(gd, rangeSliderAutoMarginID(ax), rangeSliderPush); - }); + Plots.autoMargin(gd, axAutoMarginID(ax), push); + Plots.autoMargin(gd, axMirrorAutoMarginID(ax), mirrorPush); + Plots.autoMargin(gd, rangeSliderAutoMarginID(ax), rangeSliderPush); + }); - return Lib.syncOrAsync(seq); + return Lib.syncOrAsync(seq); }; function filterPush(push, automargin) { - if (!push) return; - - var keepMargin = Object.keys(MARGIN_MAPPING).reduce(function (data, nextKey) { - if (automargin.indexOf(nextKey) !== -1) { - MARGIN_MAPPING[nextKey].forEach(function (key) { - data[key] = 1; - }); - } - return data; - }, {}); - Object.keys(push).forEach(function (key) { - if (!keepMargin[key]) { - if (key.length === 1) push[key] = 0; - else delete push[key]; - } - }); + if(!push) return; + + var keepMargin = Object.keys(MARGIN_MAPPING).reduce(function(data, nextKey) { + if(automargin.indexOf(nextKey) !== -1) { + MARGIN_MAPPING[nextKey].forEach(function(key) { data[key] = 1;}); + } + return data; + }, {}); + Object.keys(push).forEach(function(key) { + if(!keepMargin[key]) { + if(key.length === 1) push[key] = 0; + else delete push[key]; + } + }); } function getBoundaryVals(ax, vals) { - var out = []; - var i; - - // boundaryVals are never used for labels; - // no need to worry about the other tickTextObj keys - var _push = function (d, bndIndex) { - var xb = d.xbnd[bndIndex]; - if (xb !== null) { - out.push(Lib.extendFlat({}, d, { x: xb })); - } - }; + var out = []; + var i; + + // boundaryVals are never used for labels; + // no need to worry about the other tickTextObj keys + var _push = function(d, bndIndex) { + var xb = d.xbnd[bndIndex]; + if(xb !== null) { + out.push(Lib.extendFlat({}, d, {x: xb})); + } + }; - if (vals.length) { - for (i = 0; i < vals.length; i++) { - _push(vals[i], 0); + if(vals.length) { + for(i = 0; i < vals.length; i++) { + _push(vals[i], 0); + } + _push(vals[i - 1], 1); } - _push(vals[i - 1], 1); - } - return out; + return out; } function getSecondaryLabelVals(ax, vals) { - var out = []; - var lookup = {}; + var out = []; + var lookup = {}; - for (var i = 0; i < vals.length; i++) { - var d = vals[i]; - if (lookup[d.text2]) { - lookup[d.text2].push(d.x); - } else { - lookup[d.text2] = [d.x]; + for(var i = 0; i < vals.length; i++) { + var d = vals[i]; + if(lookup[d.text2]) { + lookup[d.text2].push(d.x); + } else { + lookup[d.text2] = [d.x]; + } } - } - for (var k in lookup) { - out.push(tickTextObj(ax, Lib.interp(lookup[k], 0.5), k)); - } + for(var k in lookup) { + out.push(tickTextObj(ax, Lib.interp(lookup[k], 0.5), k)); + } - return out; + return out; } function getDividerVals(ax, vals) { - var out = []; - var i, current; + var out = []; + var i, current; - var reversed = vals.length && vals[vals.length - 1].x < vals[0].x; + var reversed = (vals.length && vals[vals.length - 1].x < vals[0].x); - // never used for labels; - // no need to worry about the other tickTextObj keys - var _push = function (d, bndIndex) { - var xb = d.xbnd[bndIndex]; - if (xb !== null) { - out.push(Lib.extendFlat({}, d, { x: xb })); - } - }; + // never used for labels; + // no need to worry about the other tickTextObj keys + var _push = function(d, bndIndex) { + var xb = d.xbnd[bndIndex]; + if(xb !== null) { + out.push(Lib.extendFlat({}, d, {x: xb})); + } + }; - if (ax.showdividers && vals.length) { - for (i = 0; i < vals.length; i++) { - var d = vals[i]; - if (d.text2 !== current) { - _push(d, reversed ? 1 : 0); - } - current = d.text2; + if(ax.showdividers && vals.length) { + for(i = 0; i < vals.length; i++) { + var d = vals[i]; + if(d.text2 !== current) { + _push(d, reversed ? 1 : 0); + } + current = d.text2; + } + _push(vals[i - 1], reversed ? 0 : 1); } - _push(vals[i - 1], reversed ? 0 : 1); - } - return out; + return out; } function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { - var top, bottom; - var left, right; - - if (ax._selections[cls].size()) { - top = Infinity; - bottom = -Infinity; - left = Infinity; - right = -Infinity; - ax._selections[cls].each(function () { - var thisLabel = selectTickLabel(this); - // Use parent node , to make Drawing.bBox - // retrieve a bbox computed with transform info - // - // To improve perf, it would be nice to use `thisLabel.node()` - // (like in fixLabelOverlaps) instead and use Axes.getPxPosition - // together with the makeLabelFns outputs and `tickangle` - // to compute one bbox per (tick value x tick style) - if (thisLabel.node().style.display !== "none") { - var bb = Drawing.bBox(thisLabel.node().parentNode); - top = Math.min(top, bb.top); - bottom = Math.max(bottom, bb.bottom); - left = Math.min(left, bb.left); - right = Math.max(right, bb.right); - } - }); - } else { - var dummyCalc = axes.makeLabelFns(ax, mainLinePositionShift); - top = bottom = dummyCalc.yFn({ dx: 0, dy: 0, fontSize: 0 }); - left = right = dummyCalc.xFn({ dx: 0, dy: 0, fontSize: 0 }); - } - - return { - top: top, - bottom: bottom, - left: left, - right: right, - height: bottom - top, - width: right - left, - }; + var top, bottom; + var left, right; + + if(ax._selections[cls].size()) { + top = Infinity; + bottom = -Infinity; + left = Infinity; + right = -Infinity; + ax._selections[cls].each(function() { + var thisLabel = selectTickLabel(this); + // Use parent node , to make Drawing.bBox + // retrieve a bbox computed with transform info + // + // To improve perf, it would be nice to use `thisLabel.node()` + // (like in fixLabelOverlaps) instead and use Axes.getPxPosition + // together with the makeLabelFns outputs and `tickangle` + // to compute one bbox per (tick value x tick style) + if (thisLabel.node().style.display !== 'none') { + var bb = Drawing.bBox(thisLabel.node().parentNode); + top = Math.min(top, bb.top); + bottom = Math.max(bottom, bb.bottom); + left = Math.min(left, bb.left); + right = Math.max(right, bb.right); + } + }); + } else { + var dummyCalc = axes.makeLabelFns(ax, mainLinePositionShift); + top = bottom = dummyCalc.yFn({dx: 0, dy: 0, fontSize: 0}); + left = right = dummyCalc.xFn({dx: 0, dy: 0, fontSize: 0}); + } + + return { + top: top, + bottom: bottom, + left: left, + right: right, + height: bottom - top, + width: right - left + }; } /** @@ -3280,24 +3024,22 @@ function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { * - [3]: sign for ticks mirroring 'ax.side' * - [4]: sign of arrow starting at axis pointing towards margin */ -axes.getTickSigns = function (ax, minor) { - var axLetter = ax._id.charAt(0); - var sideOpposite = { x: "top", y: "right" }[axLetter]; - var main = ax.side === sideOpposite ? 1 : -1; - var out = [-1, 1, main, -main]; - // then we flip if outside XOR y axis - - var ticks = minor ? (ax.minor || {}).ticks : ax.ticks; - if ((ticks !== "inside") === (axLetter === "x")) { - out = out.map(function (v) { - return -v; - }); - } - // independent of `ticks`; do not flip this one - if (ax.side) { - out.push({ l: -1, t: -1, r: 1, b: 1 }[ax.side.charAt(0)]); - } - return out; +axes.getTickSigns = function(ax, minor) { + var axLetter = ax._id.charAt(0); + var sideOpposite = {x: 'top', y: 'right'}[axLetter]; + var main = ax.side === sideOpposite ? 1 : -1; + var out = [-1, 1, main, -main]; + // then we flip if outside XOR y axis + + var ticks = minor ? (ax.minor || {}).ticks : ax.ticks; + if((ticks !== 'inside') === (axLetter === 'x')) { + out = out.map(function(v) { return -v; }); + } + // independent of `ticks`; do not flip this one + if(ax.side) { + out.push({l: -1, t: -1, r: 1, b: 1}[ax.side.charAt(0)]); + } + return out; }; /** @@ -3309,104 +3051,100 @@ axes.getTickSigns = function (ax, minor) { * - {fn} l2p * @return {fn} function of calcTicks items */ -axes.makeTransTickFn = function (ax) { - return ax._id.charAt(0) === "x" - ? function (d) { - return strTranslate(ax._offset + ax.l2p(d.x), 0); - } - : function (d) { - return strTranslate(0, ax._offset + ax.l2p(d.x)); - }; +axes.makeTransTickFn = function(ax) { + return ax._id.charAt(0) === 'x' ? + function(d) { return strTranslate(ax._offset + ax.l2p(d.x), 0); } : + function(d) { return strTranslate(0, ax._offset + ax.l2p(d.x)); }; }; -axes.makeTransTickLabelFn = function (ax) { - var uv = getTickLabelUV(ax); - var shift = ax.ticklabelshift || 0; - var standoff = ax.ticklabelstandoff || 0; +axes.makeTransTickLabelFn = function(ax) { + var uv = getTickLabelUV(ax); + var shift = ax.ticklabelshift || 0; + var standoff = ax.ticklabelstandoff || 0; - var u = uv[0]; - var v = uv[1]; + var u = uv[0]; + var v = uv[1]; - var isReversed = ax.range[0] > ax.range[1]; - var labelsInside = - ax.ticklabelposition && ax.ticklabelposition.indexOf("inside") !== -1; - var labelsOutside = !labelsInside; + var isReversed = ax.range[0] > ax.range[1]; + var labelsInside = ax.ticklabelposition && ax.ticklabelposition.indexOf('inside') !== -1; + var labelsOutside = !labelsInside; - if (shift) { - var shiftSign = isReversed ? -1 : 1; - shift = shift * shiftSign; - } - if (standoff) { - var side = ax.side; - var standoffSign = - (labelsInside && (side === "top" || side === "left")) || - (labelsOutside && (side === "bottom" || side === "right")) - ? 1 - : -1; - standoff = standoff * standoffSign; - } - return ax._id.charAt(0) === "x" - ? function (d) { - return strTranslate( - u + ax._offset + ax.l2p(getPosX(d)) + shift, - v + standoff - ); - } - : function (d) { - return strTranslate( - v + standoff, - u + ax._offset + ax.l2p(getPosX(d)) + shift - ); - }; + if(shift) { + var shiftSign = isReversed ? -1 : 1; + shift = shift * shiftSign; + } + if(standoff) { + var side = ax.side; + var standoffSign = ( + (labelsInside && (side === 'top' || side === 'left')) || + (labelsOutside && (side === 'bottom' || side === 'right')) + ) ? 1 : -1; + standoff = standoff * standoffSign; + } + return ax._id.charAt(0) === 'x' ? + function(d) { + return strTranslate( + u + ax._offset + ax.l2p(getPosX(d)) + shift, + v + standoff + ); + } : + function(d) { + return strTranslate( + v + standoff, + u + ax._offset + ax.l2p(getPosX(d)) + shift + ); + }; }; function getPosX(d) { - return d.periodX !== undefined ? d.periodX : d.x; + return d.periodX !== undefined ? d.periodX : d.x; } // u is a shift along the axis, // v is a shift perpendicular to the axis function getTickLabelUV(ax) { - var ticklabelposition = ax.ticklabelposition || ""; - var tickson = ax.tickson || ""; - var has = function (str) { - return ticklabelposition.indexOf(str) !== -1; - }; - - var isTop = has("top"); - var isLeft = has("left"); - var isRight = has("right"); - var isBottom = has("bottom"); - var isInside = has("inside"); - - var isAligned = - tickson !== "boundaries" && (isBottom || isLeft || isTop || isRight); - - // early return - if (!isAligned && !isInside) return [0, 0]; - - var side = ax.side; - - var u = isAligned ? (ax.tickwidth || 0) / 2 : 0; - var v = TEXTPAD; - - var fontSize = ax.tickfont ? ax.tickfont.size : 12; - if (isBottom || isTop) { - u += fontSize * CAP_SHIFT; - v += (ax.linewidth || 0) / 2; - } - if (isLeft || isRight) { - u += (ax.linewidth || 0) / 2; - v += TEXTPAD; - } - if (isInside && side === "top") { - v -= fontSize * (1 - CAP_SHIFT); - } - - if (isLeft || isTop) u = -u; - if (side === "bottom" || side === "right") v = -v; - - return [isAligned ? u : 0, isInside ? v : 0]; + var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson || ''; + var has = function(str) { + return ticklabelposition.indexOf(str) !== -1; + }; + + var isTop = has('top'); + var isLeft = has('left'); + var isRight = has('right'); + var isBottom = has('bottom'); + var isInside = has('inside'); + + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); + + // early return + if(!isAligned && !isInside) return [0, 0]; + + var side = ax.side; + + var u = isAligned ? (ax.tickwidth || 0) / 2 : 0; + var v = TEXTPAD; + + var fontSize = ax.tickfont ? ax.tickfont.size : 12; + if(isBottom || isTop) { + u += fontSize * CAP_SHIFT; + v += (ax.linewidth || 0) / 2; + } + if(isLeft || isRight) { + u += (ax.linewidth || 0) / 2; + v += TEXTPAD; + } + if(isInside && side === 'top') { + v -= fontSize * (1 - CAP_SHIFT); + } + + if(isLeft || isTop) u = -u; + if(side === 'bottom' || side === 'right') v = -v; + + return [ + isAligned ? u : 0, + isInside ? v : 0 + ]; } /** @@ -3422,20 +3160,20 @@ function getTickLabelUV(ax) { * - {number (optional)} len tick length * @return {string} */ -axes.makeTickPath = function (ax, shift, sgn, opts) { - if (!opts) opts = {}; - var minor = opts.minor; - if (minor && !ax.minor) return ""; +axes.makeTickPath = function(ax, shift, sgn, opts) { + if(!opts) opts = {}; + var minor = opts.minor; + if(minor && !ax.minor) return ''; - var len = - opts.len !== undefined ? opts.len : minor ? ax.minor.ticklen : ax.ticklen; + var len = opts.len !== undefined ? opts.len : + minor ? ax.minor.ticklen : ax.ticklen; - var axLetter = ax._id.charAt(0); - var pad = (ax.linewidth || 1) / 2; + var axLetter = ax._id.charAt(0); + var pad = (ax.linewidth || 1) / 2; - return axLetter === "x" - ? "M0," + (shift + pad * sgn) + "v" + len * sgn - : "M" + (shift + pad * sgn) + ",0h" + len * sgn; + return axLetter === 'x' ? + 'M0,' + (shift + pad * sgn) + 'v' + (len * sgn) : + 'M' + (shift + pad * sgn) + ',0h' + (len * sgn); }; /** @@ -3459,170 +3197,161 @@ axes.makeTickPath = function (ax, shift, sgn, opts) { * - {number} labelStandoff (gap parallel to ticks) * - {number} labelShift (gap perpendicular to ticks) */ -axes.makeLabelFns = function (ax, shift, angle) { - var ticklabelposition = ax.ticklabelposition || ""; - var tickson = ax.tickson || ""; - - var has = function (str) { - return ticklabelposition.indexOf(str) !== -1; - }; - - var isTop = has("top"); - var isLeft = has("left"); - var isRight = has("right"); - var isBottom = has("bottom"); - var isAligned = - tickson !== "boundaries" && (isBottom || isLeft || isTop || isRight); - - var insideTickLabels = has("inside"); - var labelsOverTicks = - (ticklabelposition === "inside" && ax.ticks === "inside") || - (!insideTickLabels && ax.ticks === "outside" && tickson !== "boundaries"); - - var labelStandoff = 0; - var labelShift = 0; - - var tickLen = labelsOverTicks ? ax.ticklen : 0; - if (insideTickLabels) { - tickLen *= -1; - } else if (isAligned) { - tickLen = 0; - } - - if (labelsOverTicks) { - labelStandoff += tickLen; - if (angle) { - var rad = Lib.deg2rad(angle); - labelStandoff = tickLen * Math.cos(rad) + 1; - labelShift = tickLen * Math.sin(rad); - } - } - - if (ax.showticklabels && (labelsOverTicks || ax.showline)) { - labelStandoff += 0.2 * ax.tickfont.size; - } - labelStandoff += ((ax.linewidth || 1) / 2) * (insideTickLabels ? -1 : 1); - - var out = { - labelStandoff: labelStandoff, - labelShift: labelShift, - }; - - var x0, y0, ff, flipIt; - var xQ = 0; - - var side = ax.side; - var axLetter = ax._id.charAt(0); - var tickangle = ax.tickangle; - var endSide; - if (axLetter === "x") { - endSide = - (!insideTickLabels && side === "bottom") || - (insideTickLabels && side === "top"); - - flipIt = endSide ? 1 : -1; - if (insideTickLabels) flipIt *= -1; - - x0 = labelShift * flipIt; - y0 = shift + labelStandoff * flipIt; - ff = endSide ? 1 : -0.2; - if (Math.abs(tickangle) === 90) { - if (insideTickLabels) { - ff += MID_SHIFT; - } else { - if (tickangle === -90 && side === "bottom") { - ff = CAP_SHIFT; - } else if (tickangle === 90 && side === "top") { - ff = MID_SHIFT; - } else { - ff = 0.5; +axes.makeLabelFns = function(ax, shift, angle) { + var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson || ''; + + var has = function(str) { + return ticklabelposition.indexOf(str) !== -1; + }; + + var isTop = has('top'); + var isLeft = has('left'); + var isRight = has('right'); + var isBottom = has('bottom'); + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); + + var insideTickLabels = has('inside'); + var labelsOverTicks = + (ticklabelposition === 'inside' && ax.ticks === 'inside') || + (!insideTickLabels && ax.ticks === 'outside' && tickson !== 'boundaries'); + + var labelStandoff = 0; + var labelShift = 0; + + var tickLen = labelsOverTicks ? ax.ticklen : 0; + if(insideTickLabels) { + tickLen *= -1; + } else if(isAligned) { + tickLen = 0; + } + + if(labelsOverTicks) { + labelStandoff += tickLen; + if(angle) { + var rad = Lib.deg2rad(angle); + labelStandoff = tickLen * Math.cos(rad) + 1; + labelShift = tickLen * Math.sin(rad); } - } + } - xQ = (MID_SHIFT / 2) * (tickangle / 90); + if(ax.showticklabels && (labelsOverTicks || ax.showline)) { + labelStandoff += 0.2 * ax.tickfont.size; } + labelStandoff += (ax.linewidth || 1) / 2 * (insideTickLabels ? -1 : 1); - out.xFn = function (d) { - return d.dx + x0 + xQ * d.fontSize; - }; - out.yFn = function (d) { - return d.dy + y0 + d.fontSize * ff; + var out = { + labelStandoff: labelStandoff, + labelShift: labelShift }; - out.anchorFn = function (d, a) { - if (isAligned) { - if (isLeft) return "end"; - if (isRight) return "start"; - } - if (!isNumeric(a) || a === 0 || a === 180) { - return "middle"; - } + var x0, y0, ff, flipIt; + var xQ = 0; - return a * flipIt < 0 !== insideTickLabels ? "end" : "start"; - }; - out.heightFn = function (d, a, h) { - return a < -60 || a > 60 - ? -0.5 * h - : (ax.side === "top") !== insideTickLabels - ? -h - : 0; - }; - } else if (axLetter === "y") { - endSide = - (!insideTickLabels && side === "left") || - (insideTickLabels && side === "right"); - - flipIt = endSide ? 1 : -1; - if (insideTickLabels) flipIt *= -1; - - x0 = labelStandoff; - y0 = labelShift * flipIt; - ff = 0; - if (!insideTickLabels && Math.abs(tickangle) === 90) { - if ( - (tickangle === -90 && side === "left") || - (tickangle === 90 && side === "right") - ) { - ff = CAP_SHIFT; - } else { - ff = 0.5; - } - } - - if (insideTickLabels) { - var ang = isNumeric(tickangle) ? +tickangle : 0; - if (ang !== 0) { - var rA = Lib.deg2rad(ang); - xQ = Math.abs(Math.sin(rA)) * CAP_SHIFT * flipIt; + var side = ax.side; + var axLetter = ax._id.charAt(0); + var tickangle = ax.tickangle; + var endSide; + if(axLetter === 'x') { + endSide = + (!insideTickLabels && side === 'bottom') || + (insideTickLabels && side === 'top'); + + flipIt = endSide ? 1 : -1; + if(insideTickLabels) flipIt *= -1; + + x0 = labelShift * flipIt; + y0 = shift + labelStandoff * flipIt; + ff = endSide ? 1 : -0.2; + if(Math.abs(tickangle) === 90) { + if(insideTickLabels) { + ff += MID_SHIFT; + } else { + if(tickangle === -90 && side === 'bottom') { + ff = CAP_SHIFT; + } else if(tickangle === 90 && side === 'top') { + ff = MID_SHIFT; + } else { + ff = 0.5; + } + } + + xQ = (MID_SHIFT / 2) * (tickangle / 90); + } + + out.xFn = function(d) { return d.dx + x0 + xQ * d.fontSize; }; + out.yFn = function(d) { return d.dy + y0 + d.fontSize * ff; }; + out.anchorFn = function(d, a) { + if(isAligned) { + if(isLeft) return 'end'; + if(isRight) return 'start'; + } + + if(!isNumeric(a) || a === 0 || a === 180) { + return 'middle'; + } + + return ((a * flipIt < 0) !== insideTickLabels) ? 'end' : 'start'; + }; + out.heightFn = function(d, a, h) { + return (a < -60 || a > 60) ? -0.5 * h : + ((ax.side === 'top') !== insideTickLabels) ? -h : + 0; + }; + } else if(axLetter === 'y') { + endSide = + (!insideTickLabels && side === 'left') || + (insideTickLabels && side === 'right'); + + flipIt = endSide ? 1 : -1; + if(insideTickLabels) flipIt *= -1; + + x0 = labelStandoff; + y0 = labelShift * flipIt; ff = 0; - } - } + if(!insideTickLabels && Math.abs(tickangle) === 90) { + if( + (tickangle === -90 && side === 'left') || + (tickangle === 90 && side === 'right') + ) { + ff = CAP_SHIFT; + } else { + ff = 0.5; + } + } - out.xFn = function (d) { - return d.dx + shift - (x0 + d.fontSize * ff) * flipIt + xQ * d.fontSize; - }; - out.yFn = function (d) { - return d.dy + y0 + d.fontSize * MID_SHIFT; - }; - out.anchorFn = function (d, a) { - if (isNumeric(a) && Math.abs(a) === 90) { - return "middle"; - } + if(insideTickLabels) { + var ang = isNumeric(tickangle) ? +tickangle : 0; + if(ang !== 0) { + var rA = Lib.deg2rad(ang); + xQ = Math.abs(Math.sin(rA)) * CAP_SHIFT * flipIt; + ff = 0; + } + } - return endSide ? "end" : "start"; - }; - out.heightFn = function (d, a, h) { - if (ax.side === "right") a *= -1; + out.xFn = function(d) { return d.dx + shift - (x0 + d.fontSize * ff) * flipIt + xQ * d.fontSize; }; + out.yFn = function(d) { return d.dy + y0 + d.fontSize * MID_SHIFT; }; + out.anchorFn = function(d, a) { + if(isNumeric(a) && Math.abs(a) === 90) { + return 'middle'; + } - return a < -30 ? -h : a < 30 ? -0.5 * h : 0; - }; - } + return endSide ? 'end' : 'start'; + }; + out.heightFn = function(d, a, h) { + if(ax.side === 'right') a *= -1; + + return a < -30 ? -h : + a < 30 ? -0.5 * h : + 0; + }; + } - return out; + return out; }; function tickDataFn(d) { - return [d.text, d.x, d.axInfo, d.font, d.fontSize, d.fontColor].join("_"); + return [d.text, d.x, d.axInfo, d.font, d.fontSize, d.fontColor].join('_'); } /** @@ -3641,57 +3370,48 @@ function tickDataFn(d) { * - {fn} transFn * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) */ -axes.drawTicks = function (gd, ax, opts) { - opts = opts || {}; - - var cls = ax._id + "tick"; - - var vals = [] - .concat( - ax.minor && ax.minor.ticks - ? // minor vals - opts.vals.filter(function (d) { - return d.minor && !d.noTick; - }) - : [] - ) - .concat( - ax.ticks - ? // major vals - opts.vals.filter(function (d) { - return !d.minor && !d.noTick; - }) - : [] - ); +axes.drawTicks = function(gd, ax, opts) { + opts = opts || {}; + + var cls = ax._id + 'tick'; + + var vals = [] + .concat(ax.minor && ax.minor.ticks ? + // minor vals + opts.vals.filter(function(d) { return d.minor && !d.noTick; }) : + [] + ) + .concat(ax.ticks ? + // major vals + opts.vals.filter(function(d) { return !d.minor && !d.noTick; }) : + [] + ); + + var ticks = opts.layer.selectAll('path.' + cls) + .data(vals, tickDataFn); - var ticks = opts.layer.selectAll("path." + cls).data(vals, tickDataFn); - - ticks.exit().remove(); - - ticks - .enter() - .append("path") - .classed(cls, 1) - .classed("ticks", 1) - .classed("crisp", opts.crisp !== false) - .each(function (d) { - return Color.stroke( - d3.select(this), - d.minor ? ax.minor.tickcolor : ax.tickcolor - ); - }) - .style("stroke-width", function (d) { - return ( - Drawing.crispRound(gd, d.minor ? ax.minor.tickwidth : ax.tickwidth, 1) + - "px" - ); - }) - .attr("d", opts.path) - .style("display", null); // visible - - hideCounterAxisInsideTickLabels(ax, [TICK_PATH]); - - ticks.attr("transform", opts.transFn); + ticks.exit().remove(); + + ticks.enter().append('path') + .classed(cls, 1) + .classed('ticks', 1) + .classed('crisp', opts.crisp !== false) + .each(function(d) { + return Color.stroke(d3.select(this), d.minor ? ax.minor.tickcolor : ax.tickcolor); + }) + .style('stroke-width', function(d) { + return Drawing.crispRound( + gd, + d.minor ? ax.minor.tickwidth : ax.tickwidth, + 1 + ) + 'px'; + }) + .attr('d', opts.path) + .style('display', null); // visible + + hideCounterAxisInsideTickLabels(ax, [TICK_PATH]); + + ticks.attr('transform', opts.transFn); }; /** @@ -3716,90 +3436,80 @@ axes.drawTicks = function (gd, ax, opts) { * - {fn} transFn * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) */ -axes.drawGrid = function (gd, ax, opts) { - opts = opts || {}; - - if (ax.tickmode === "sync") { - // for tickmode sync we use the overlaying axis grid - return; - } - - var cls = ax._id + "grid"; - - var hasMinor = ax.minor && ax.minor.showgrid; - var minorVals = hasMinor - ? opts.vals.filter(function (d) { - return d.minor; - }) - : []; - var majorVals = ax.showgrid - ? opts.vals.filter(function (d) { - return !d.minor; - }) - : []; - - var counterAx = opts.counterAxis; - if (counterAx && axes.shouldShowZeroLine(gd, ax, counterAx)) { - var isArrayMode = ax.tickmode === "array"; - for (var i = 0; i < majorVals.length; i++) { - var xi = majorVals[i].x; - if (isArrayMode ? !xi : Math.abs(xi) < ax.dtick / 100) { - majorVals = majorVals.slice(0, i).concat(majorVals.slice(i + 1)); - // In array mode you can in principle have multiple - // ticks at 0, so test them all. Otherwise once we found - // one we can stop. - if (isArrayMode) i--; - else break; - } - } - } - - ax._gw = Drawing.crispRound(gd, ax.gridwidth, 1); - - var wMinor = !hasMinor ? 0 : Drawing.crispRound(gd, ax.minor.gridwidth, 1); - - var majorLayer = opts.layer; - var minorLayer = opts.minorLayer; - for (var major = 1; major >= 0; major--) { - var layer = major ? majorLayer : minorLayer; - if (!layer) continue; - - var grid = layer - .selectAll("path." + cls) - .data(major ? majorVals : minorVals, tickDataFn); - - grid.exit().remove(); - - grid - .enter() - .append("path") - .classed(cls, 1) - .classed("crisp", opts.crisp !== false); - - grid - .attr("transform", opts.transFn) - .attr("d", opts.path) - .each(function (d) { - return Color.stroke( - d3.select(this), - d.minor ? ax.minor.gridcolor : ax.gridcolor || "#ddd" - ); - }) - .style("stroke-dasharray", function (d) { - return Drawing.dashStyle( - d.minor ? ax.minor.griddash : ax.griddash, - d.minor ? ax.minor.gridwidth : ax.gridwidth - ); - }) - .style("stroke-width", function (d) { - return (d.minor ? wMinor : ax._gw) + "px"; - }) - .style("display", null); // visible +axes.drawGrid = function(gd, ax, opts) { + opts = opts || {}; + + if(ax.tickmode === 'sync') { + // for tickmode sync we use the overlaying axis grid + return; + } + + var cls = ax._id + 'grid'; + + var hasMinor = ax.minor && ax.minor.showgrid; + var minorVals = hasMinor ? opts.vals.filter(function(d) { return d.minor; }) : []; + var majorVals = ax.showgrid ? opts.vals.filter(function(d) { return !d.minor; }) : []; + + var counterAx = opts.counterAxis; + if(counterAx && axes.shouldShowZeroLine(gd, ax, counterAx)) { + var isArrayMode = ax.tickmode === 'array'; + for(var i = 0; i < majorVals.length; i++) { + var xi = majorVals[i].x; + if(isArrayMode ? !xi : (Math.abs(xi) < ax.dtick / 100)) { + majorVals = majorVals.slice(0, i).concat(majorVals.slice(i + 1)); + // In array mode you can in principle have multiple + // ticks at 0, so test them all. Otherwise once we found + // one we can stop. + if(isArrayMode) i--; + else break; + } + } + } - if (typeof opts.path === "function") grid.attr("d", opts.path); - } + ax._gw = + Drawing.crispRound(gd, ax.gridwidth, 1); + + var wMinor = !hasMinor ? 0 : + Drawing.crispRound(gd, ax.minor.gridwidth, 1); + + var majorLayer = opts.layer; + var minorLayer = opts.minorLayer; + for(var major = 1; major >= 0; major--) { + var layer = major ? majorLayer : minorLayer; + if(!layer) continue; + + var grid = layer.selectAll('path.' + cls) + .data(major ? majorVals : minorVals, tickDataFn); + + grid.exit().remove(); + + grid.enter().append('path') + .classed(cls, 1) + .classed('crisp', opts.crisp !== false); + + grid.attr('transform', opts.transFn) + .attr('d', opts.path) + .each(function(d) { + return Color.stroke(d3.select(this), d.minor ? + ax.minor.gridcolor : + (ax.gridcolor || '#ddd') + ); + }) + .style('stroke-dasharray', function(d) { + return Drawing.dashStyle( + d.minor ? ax.minor.griddash : ax.griddash, + d.minor ? ax.minor.gridwidth : ax.gridwidth + ); + }) + .style('stroke-width', function(d) { + return (d.minor ? wMinor : ax._gw) + 'px'; + }) + .style('display', null); // visible + + if(typeof opts.path === 'function') grid.attr('d', opts.path); + } - hideCounterAxisInsideTickLabels(ax, [GRID_PATH, MINORGRID_PATH]); + hideCounterAxisInsideTickLabels(ax, [GRID_PATH, MINORGRID_PATH]); }; /** @@ -3819,42 +3529,37 @@ axes.drawGrid = function (gd, ax, opts) { * - {fn} transFn * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) */ -axes.drawZeroLine = function (gd, ax, opts) { - opts = opts || opts; - - var cls = ax._id + "zl"; - var show = axes.shouldShowZeroLine(gd, ax, opts.counterAxis); - - var zl = opts.layer - .selectAll("path." + cls) - .data(show ? [{ x: 0, id: ax._id }] : []); - - zl.exit().remove(); - - zl.enter() - .append("path") - .classed(cls, 1) - .classed("zl", 1) - .classed("crisp", opts.crisp !== false) - .each(function () { - // use the fact that only one element can enter to trigger a sort. - // If several zerolines enter at the same time we will sort once per, - // but generally this should be a minimal overhead. - opts.layer.selectAll("path").sort(function (da, db) { - return idSort(da.id, db.id); - }); - }); +axes.drawZeroLine = function(gd, ax, opts) { + opts = opts || opts; + + var cls = ax._id + 'zl'; + var show = axes.shouldShowZeroLine(gd, ax, opts.counterAxis); + + var zl = opts.layer.selectAll('path.' + cls) + .data(show ? [{x: 0, id: ax._id}] : []); + + zl.exit().remove(); + + zl.enter().append('path') + .classed(cls, 1) + .classed('zl', 1) + .classed('crisp', opts.crisp !== false) + .each(function() { + // use the fact that only one element can enter to trigger a sort. + // If several zerolines enter at the same time we will sort once per, + // but generally this should be a minimal overhead. + opts.layer.selectAll('path').sort(function(da, db) { + return idSort(da.id, db.id); + }); + }); - zl.attr("transform", opts.transFn) - .attr("d", opts.path) - .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) - .style( - "stroke-width", - Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + "px" - ) - .style("display", null); // visible + zl.attr('transform', opts.transFn) + .attr('d', opts.path) + .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) + .style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px') + .style('display', null); // visible - hideCounterAxisInsideTickLabels(ax, [ZERO_PATH]); + hideCounterAxisInsideTickLabels(ax, [ZERO_PATH]); }; /** @@ -3881,571 +3586,528 @@ axes.drawZeroLine = function (gd, ax, opts) { * + {fn} anchorFn * + {fn} heightFn */ -axes.drawLabels = function (gd, ax, opts) { - opts = opts || {}; - - var fullLayout = gd._fullLayout; - var axId = ax._id; - var zerolineIsAbove = ax.zerolinelayer === "above traces"; - var cls = opts.cls || axId + "tick"; - - var vals = opts.vals.filter(function (d) { - return d.text; - }); - - var labelFns = opts.labelFns; - var tickAngle = opts.secondary ? 0 : ax.tickangle; - - var prevAngle = (ax._prevTickAngles || {})[cls]; - - var tickLabels = opts.layer - .selectAll("g." + cls) - .data(ax.showticklabels ? vals : [], tickDataFn); - - var labelsReady = []; - - tickLabels - .enter() - .append("g") - .classed(cls, 1) - .append("text") - // only so tex has predictable alignment that we can - // alter later - .attr("text-anchor", "middle") - .each(function (d) { - var thisLabel = d3.select(this); - var newPromise = gd._promises.length; - - thisLabel - .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)) - .call(Drawing.font, { - family: d.font, - size: d.fontSize, - color: d.fontColor, - weight: d.fontWeight, - style: d.fontStyle, - variant: d.fontVariant, - textcase: d.fontTextcase, - lineposition: d.fontLineposition, - shadow: d.fontShadow, - }) - .text(d.text) - .call(svgTextUtils.convertToTspans, gd); - - if (gd._promises[newPromise]) { - // if we have an async label, we'll deal with that - // all here so take it out of gd._promises and - // instead position the label and promise this in - // labelsReady - labelsReady.push( - gd._promises.pop().then(function () { - positionLabels(thisLabel, tickAngle); - }) - ); - } else { - // sync label: just position it now. - positionLabels(thisLabel, tickAngle); - } - }); +axes.drawLabels = function(gd, ax, opts) { + opts = opts || {}; + + var fullLayout = gd._fullLayout; + var axId = ax._id; + var zerolineIsAbove = ax.zerolinelayer === 'above traces'; + var cls = opts.cls || axId + 'tick'; + + var vals = opts.vals.filter(function(d) { return d.text; }); + + var labelFns = opts.labelFns; + var tickAngle = opts.secondary ? 0 : ax.tickangle; + + var prevAngle = (ax._prevTickAngles || {})[cls]; + + var tickLabels = opts.layer.selectAll('g.' + cls) + .data(ax.showticklabels ? vals : [], tickDataFn); + + var labelsReady = []; + + tickLabels.enter().append('g') + .classed(cls, 1) + .append('text') + // only so tex has predictable alignment that we can + // alter later + .attr('text-anchor', 'middle') + .each(function(d) { + var thisLabel = d3.select(this); + var newPromise = gd._promises.length; + + thisLabel + .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)) + .call(Drawing.font, { + family: d.font, + size: d.fontSize, + color: d.fontColor, + weight: d.fontWeight, + style: d.fontStyle, + variant: d.fontVariant, + textcase: d.fontTextcase, + lineposition: d.fontLineposition, + shadow: d.fontShadow, + }) + .text(d.text) + .call(svgTextUtils.convertToTspans, gd); + + if(gd._promises[newPromise]) { + // if we have an async label, we'll deal with that + // all here so take it out of gd._promises and + // instead position the label and promise this in + // labelsReady + labelsReady.push(gd._promises.pop().then(function() { + positionLabels(thisLabel, tickAngle); + })); + } else { + // sync label: just position it now. + positionLabels(thisLabel, tickAngle); + } + }); - hideCounterAxisInsideTickLabels(ax, [TICK_TEXT]); + hideCounterAxisInsideTickLabels(ax, [TICK_TEXT]); - tickLabels.exit().remove(); + tickLabels.exit().remove(); - if (opts.repositionOnUpdate) { - tickLabels.each(function (d) { - d3.select(this) - .select("text") - .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)); - }); - } - - function positionLabels(s, angle) { - s.each(function (d) { - var thisLabel = d3.select(this); - var mathjaxGroup = thisLabel.select(".text-math-group"); - var anchor = labelFns.anchorFn(d, angle); - - var transform = - opts.transFn.call(thisLabel.node(), d) + - (isNumeric(angle) && +angle !== 0 - ? " rotate(" + - angle + - "," + - labelFns.xFn(d) + - "," + - (labelFns.yFn(d) - d.fontSize / 2) + - ")" - : ""); - - // how much to shift a multi-line label to center it vertically. - var nLines = svgTextUtils.lineCount(thisLabel); - var lineHeight = LINE_SPACING * d.fontSize; - var anchorHeight = labelFns.heightFn( - d, - isNumeric(angle) ? +angle : 0, - (nLines - 1) * lineHeight - ); - - if (anchorHeight) { - transform += strTranslate(0, anchorHeight); - } - - if (mathjaxGroup.empty()) { - var thisText = thisLabel.select("text"); - thisText.attr({ - transform: transform, - "text-anchor": anchor, + if(opts.repositionOnUpdate) { + tickLabels.each(function(d) { + d3.select(this).select('text') + .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)); + }); + } + + function positionLabels(s, angle) { + s.each(function(d) { + var thisLabel = d3.select(this); + var mathjaxGroup = thisLabel.select('.text-math-group'); + var anchor = labelFns.anchorFn(d, angle); + + var transform = opts.transFn.call(thisLabel.node(), d) + + ((isNumeric(angle) && +angle !== 0) ? + (' rotate(' + angle + ',' + labelFns.xFn(d) + ',' + + (labelFns.yFn(d) - d.fontSize / 2) + ')') : + ''); + + // how much to shift a multi-line label to center it vertically. + var nLines = svgTextUtils.lineCount(thisLabel); + var lineHeight = LINE_SPACING * d.fontSize; + var anchorHeight = labelFns.heightFn(d, isNumeric(angle) ? +angle : 0, (nLines - 1) * lineHeight); + + if(anchorHeight) { + transform += strTranslate(0, anchorHeight); + } + + if(mathjaxGroup.empty()) { + var thisText = thisLabel.select('text'); + thisText.attr({ + transform: transform, + 'text-anchor': anchor + }); + + thisText.style('display', null); // visible + + if(ax._adjustTickLabelsOverflow) { + ax._adjustTickLabelsOverflow(); + } + } else { + var mjWidth = Drawing.bBox(mathjaxGroup.node()).width; + var mjShift = mjWidth * {end: -0.5, start: 0.5}[anchor]; + mathjaxGroup.attr('transform', transform + strTranslate(mjShift, 0)); + } }); + } + + ax._adjustTickLabelsOverflow = function() { + var ticklabeloverflow = ax.ticklabeloverflow; + if(!ticklabeloverflow || ticklabeloverflow === 'allow') return; - thisText.style("display", null); // visible + var hideOverflow = ticklabeloverflow.indexOf('hide') !== -1; - if (ax._adjustTickLabelsOverflow) { - ax._adjustTickLabelsOverflow(); + var isX = ax._id.charAt(0) === 'x'; + // div positions + var p0 = 0; + var p1 = isX ? + gd._fullLayout.width : + gd._fullLayout.height; + + if(ticklabeloverflow.indexOf('domain') !== -1) { + // domain positions + var rl = Lib.simpleMap(ax.range, ax.r2l); + p0 = ax.l2p(rl[0]) + ax._offset; + p1 = ax.l2p(rl[1]) + ax._offset; } - } else { - var mjWidth = Drawing.bBox(mathjaxGroup.node()).width; - var mjShift = mjWidth * { end: -0.5, start: 0.5 }[anchor]; - mathjaxGroup.attr("transform", transform + strTranslate(mjShift, 0)); - } - }); - } - ax._adjustTickLabelsOverflow = function () { - var ticklabeloverflow = ax.ticklabeloverflow; - if (!ticklabeloverflow || ticklabeloverflow === "allow") return; + var min = Math.min(p0, p1); + var max = Math.max(p0, p1); + + var side = ax.side; + + var visibleLabelMin = Infinity; + var visibleLabelMax = -Infinity; + + tickLabels.each(function(d) { + var thisLabel = d3.select(this); + var mathjaxGroup = thisLabel.select('.text-math-group'); + + if(mathjaxGroup.empty()) { + var bb = Drawing.bBox(thisLabel.node()); + var adjust = 0; + if(isX) { + if(bb.right > max) adjust = 1; + else if(bb.left < min) adjust = 1; + } else { + if(bb.bottom > max) adjust = 1; + else if(bb.top + (ax.tickangle ? 0 : d.fontSize / 4) < min) adjust = 1; + } + + var t = thisLabel.select('text'); + if(adjust) { + if(hideOverflow) t.style('display', 'none'); // hidden + } else if(t.node().style.display !== 'none'){ + t.style('display', null); + + if(side === 'bottom' || side === 'right') { + visibleLabelMin = Math.min(visibleLabelMin, isX ? bb.top : bb.left); + } else { + visibleLabelMin = -Infinity; + } + + if(side === 'top' || side === 'left') { + visibleLabelMax = Math.max(visibleLabelMax, isX ? bb.bottom : bb.right); + } else { + visibleLabelMax = Infinity; + } + } + } // TODO: hide mathjax? + }); + + for(var subplot in fullLayout._plots) { + var plotinfo = fullLayout._plots[subplot]; + if(ax._id !== plotinfo.xaxis._id && ax._id !== plotinfo.yaxis._id) continue; + var anchorAx = isX ? plotinfo.yaxis : plotinfo.xaxis; + if(anchorAx) { + anchorAx['_visibleLabelMin_' + ax._id] = visibleLabelMin; + anchorAx['_visibleLabelMax_' + ax._id] = visibleLabelMax; + } + } + }; + + ax._hideCounterAxisInsideTickLabels = function(partialOpts) { + var isX = ax._id.charAt(0) === 'x'; + + var anchoredAxes = []; + for(var subplot in fullLayout._plots) { + var plotinfo = fullLayout._plots[subplot]; + if(ax._id !== plotinfo.xaxis._id && ax._id !== plotinfo.yaxis._id) continue; + anchoredAxes.push(isX ? plotinfo.yaxis : plotinfo.xaxis); + } - var hideOverflow = ticklabeloverflow.indexOf("hide") !== -1; + anchoredAxes.forEach(function(anchorAx, idx) { + if(anchorAx && insideTicklabelposition(anchorAx)) { + (partialOpts || [ + ZERO_PATH, + MINORGRID_PATH, + GRID_PATH, + TICK_PATH, + TICK_TEXT + ]).forEach(function(e) { + var isPeriodLabel = + e.K === 'tick' && + e.L === 'text' && + ax.ticklabelmode === 'period'; + + var mainPlotinfo = fullLayout._plots[ax._mainSubplot]; + + var sel; + if(e.K === ZERO_PATH.K) { + var zerolineLayer = zerolineIsAbove ? mainPlotinfo.zerolinelayerAbove : mainPlotinfo.zerolinelayer; + sel = zerolineLayer.selectAll('.' + ax._id + 'zl'); + } else if(e.K === MINORGRID_PATH.K) sel = mainPlotinfo.minorGridlayer.selectAll('.' + ax._id); + else if(e.K === GRID_PATH.K) sel = mainPlotinfo.gridlayer.selectAll('.' + ax._id); + else sel = mainPlotinfo[ax._id.charAt(0) + 'axislayer']; + + sel.each(function() { + var w = d3.select(this); + if(e.L) w = w.selectAll(e.L); + + w.each(function(d) { + var q = ax.l2p( + isPeriodLabel ? getPosX(d) : d.x + ) + ax._offset; + + var t = d3.select(this); + if( + q < ax['_visibleLabelMax_' + anchorAx._id] && + q > ax['_visibleLabelMin_' + anchorAx._id] + ) { + t.style('display', 'none'); // hidden + } else if(e.K === 'tick' && !idx && t.node().style.display !== 'none') { + t.style('display', null); // visible + } + }); + }); + }); + } + }); + }; - var isX = ax._id.charAt(0) === "x"; - // div positions - var p0 = 0; - var p1 = isX ? gd._fullLayout.width : gd._fullLayout.height; + // make sure all labels are correctly positioned at their base angle + // the positionLabels call above is only for newly drawn labels. + // do this without waiting, using the last calculated angle to + // minimize flicker, then do it again when we know all labels are + // there, putting back the prescribed angle to check for overlaps. + positionLabels(tickLabels, (prevAngle + 1) ? prevAngle : tickAngle); - if (ticklabeloverflow.indexOf("domain") !== -1) { - // domain positions - var rl = Lib.simpleMap(ax.range, ax.r2l); - p0 = ax.l2p(rl[0]) + ax._offset; - p1 = ax.l2p(rl[1]) + ax._offset; + function allLabelsReady() { + return labelsReady.length && Promise.all(labelsReady); } - var min = Math.min(p0, p1); - var max = Math.max(p0, p1); + var autoangle = null; - var side = ax.side; + function fixLabelOverlaps() { + positionLabels(tickLabels, tickAngle); + + // check for auto-angling if x labels overlap + // don't auto-angle at all for log axes with + // base and digit format + if(vals.length && ax.autotickangles && + (ax.type !== 'log' || String(ax.dtick).charAt(0) !== 'D') + ) { + autoangle = ax.autotickangles[0]; + + var maxFontSize = 0; + var lbbArray = []; + var i; + var maxLines = 1; + tickLabels.each(function(d) { + maxFontSize = Math.max(maxFontSize, d.fontSize); + + var x = ax.l2p(d.x); + var thisLabel = selectTickLabel(this); + var bb = Drawing.bBox(thisLabel.node()); + maxLines = Math.max(maxLines, svgTextUtils.lineCount(thisLabel)); + + lbbArray.push({ + // ignore about y, just deal with x overlaps + top: 0, + bottom: 10, + height: 10, + left: x - bb.width / 2, + // impose a 2px gap + right: x + bb.width / 2 + 2, + width: bb.width + 2 + }); + }); - var visibleLabelMin = Infinity; - var visibleLabelMax = -Infinity; + // autotickangles + // if there are dividers or ticks on boundaries, the labels will be in between and + // we need to prevent overlap with the next divider/tick. Else the labels will be on + // the ticks and we need to prevent overlap with the next label. - tickLabels.each(function (d) { - var thisLabel = d3.select(this); - var mathjaxGroup = thisLabel.select(".text-math-group"); + // TODO should secondary labels also fall into this fix-overlap regime? + var preventOverlapWithTick = (ax.tickson === 'boundaries' || ax.showdividers) && !opts.secondary; - if (mathjaxGroup.empty()) { - var bb = Drawing.bBox(thisLabel.node()); - var adjust = 0; - if (isX) { - if (bb.right > max) adjust = 1; - else if (bb.left < min) adjust = 1; - } else { - if (bb.bottom > max) adjust = 1; - else if (bb.top + (ax.tickangle ? 0 : d.fontSize / 4) < min) - adjust = 1; - } + var vLen = vals.length; + var tickSpacing = Math.abs((vals[vLen - 1].x - vals[0].x) * ax._m) / (vLen - 1); - var t = thisLabel.select("text"); - if (adjust) { - if (hideOverflow) t.style("display", "none"); // hidden - } else if (t.node().style.display !== "none") { - t.style("display", null); - - if (side === "bottom" || side === "right") { - visibleLabelMin = Math.min(visibleLabelMin, isX ? bb.top : bb.left); - } else { - visibleLabelMin = -Infinity; - } - - if (side === "top" || side === "left") { - visibleLabelMax = Math.max( - visibleLabelMax, - isX ? bb.bottom : bb.right + var adjacent = preventOverlapWithTick ? tickSpacing / 2 : tickSpacing; + var opposite = preventOverlapWithTick ? ax.ticklen : maxFontSize * 1.25 * maxLines; + var hypotenuse = Math.sqrt(Math.pow(adjacent, 2) + Math.pow(opposite, 2)); + var maxCos = adjacent / hypotenuse; + var autoTickAnglesRadians = ax.autotickangles.map( + function(degrees) { return degrees * Math.PI / 180; } + ); + var angleRadians = autoTickAnglesRadians.find( + function(angle) { return Math.abs(Math.cos(angle)) <= maxCos; } ); - } else { - visibleLabelMax = Infinity; - } + if(angleRadians === undefined) { + // no angle with smaller cosine than maxCos, just pick the angle with smallest cosine + angleRadians = autoTickAnglesRadians.reduce( + function(currentMax, nextAngle) { + return Math.abs(Math.cos(currentMax)) < Math.abs(Math.cos(nextAngle)) ? currentMax : nextAngle; + } + , autoTickAnglesRadians[0] + ); + } + var newAngle = angleRadians * (180 / Math.PI /* to degrees */); + + if(preventOverlapWithTick) { + var gap = 2; + if(ax.ticks) gap += ax.tickwidth / 2; + + for(i = 0; i < lbbArray.length; i++) { + var xbnd = vals[i].xbnd; + var lbb = lbbArray[i]; + if( + (xbnd[0] !== null && (lbb.left - ax.l2p(xbnd[0])) < gap) || + (xbnd[1] !== null && (ax.l2p(xbnd[1]) - lbb.right) < gap) + ) { + autoangle = newAngle; + break; + } + } + } else { + var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson ||''; + + var has = function(str) { + return ticklabelposition.indexOf(str) !== -1; + }; + var isTop = has('top'); + var isLeft = has('left'); + var isRight = has('right'); + var isBottom = has('bottom'); + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); + var pad = !isAligned ? 0 : + (ax.tickwidth || 0) + 2 * TEXTPAD; + + for(i = 0; i < lbbArray.length - 1; i++) { + if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1], pad)) { + autoangle = newAngle; + break; + } + } + } + + if(autoangle) { + positionLabels(tickLabels, autoangle); + } } - } // TODO: hide mathjax? - }); + } - for (var subplot in fullLayout._plots) { - var plotinfo = fullLayout._plots[subplot]; - if (ax._id !== plotinfo.xaxis._id && ax._id !== plotinfo.yaxis._id) - continue; - var anchorAx = isX ? plotinfo.yaxis : plotinfo.xaxis; - if (anchorAx) { - anchorAx["_visibleLabelMin_" + ax._id] = visibleLabelMin; - anchorAx["_visibleLabelMax_" + ax._id] = visibleLabelMax; - } + if(ax._selections) { + ax._selections[cls] = tickLabels; } - }; - ax._hideCounterAxisInsideTickLabels = function (partialOpts) { - var isX = ax._id.charAt(0) === "x"; + var seq = [allLabelsReady]; - var anchoredAxes = []; - for (var subplot in fullLayout._plots) { - var plotinfo = fullLayout._plots[subplot]; - if (ax._id !== plotinfo.xaxis._id && ax._id !== plotinfo.yaxis._id) - continue; - anchoredAxes.push(isX ? plotinfo.yaxis : plotinfo.xaxis); + // N.B. during auto-margin redraws, if the axis fixed its label overlaps + // by rotating 90 degrees, do not attempt to re-fix its label overlaps + // as this can lead to infinite redraw loops! + if(ax.automargin && fullLayout._redrawFromAutoMarginCount && prevAngle === 90) { + autoangle = prevAngle; + seq.push(function() { + positionLabels(tickLabels, prevAngle); + }); + } else { + seq.push(fixLabelOverlaps); } - anchoredAxes.forEach(function (anchorAx, idx) { - if (anchorAx && insideTicklabelposition(anchorAx)) { - ( - partialOpts || [ - ZERO_PATH, - MINORGRID_PATH, - GRID_PATH, - TICK_PATH, - TICK_TEXT, - ] - ).forEach(function (e) { - var isPeriodLabel = - e.K === "tick" && e.L === "text" && ax.ticklabelmode === "period"; - - var mainPlotinfo = fullLayout._plots[ax._mainSubplot]; - - var sel; - if (e.K === ZERO_PATH.K) { - var zerolineLayer = zerolineIsAbove - ? mainPlotinfo.zerolinelayerAbove - : mainPlotinfo.zerolinelayer; - sel = zerolineLayer.selectAll("." + ax._id + "zl"); - } else if (e.K === MINORGRID_PATH.K) - sel = mainPlotinfo.minorGridlayer.selectAll("." + ax._id); - else if (e.K === GRID_PATH.K) - sel = mainPlotinfo.gridlayer.selectAll("." + ax._id); - else sel = mainPlotinfo[ax._id.charAt(0) + "axislayer"]; - - sel.each(function () { - var w = d3.select(this); - if (e.L) w = w.selectAll(e.L); - - w.each(function (d) { - var q = ax.l2p(isPeriodLabel ? getPosX(d) : d.x) + ax._offset; - - var t = d3.select(this); - if ( - q < ax["_visibleLabelMax_" + anchorAx._id] && - q > ax["_visibleLabelMin_" + anchorAx._id] - ) { - t.style("display", "none"); // hidden - } else if ( - e.K === "tick" && - !idx && - t.node().style.display !== "none" - ) { - t.style("display", null); // visible - } - }); - }); + // save current tick angle for future redraws + if(ax._tickAngles) { + seq.push(function() { + ax._tickAngles[cls] = autoangle === null ? + (isNumeric(tickAngle) ? tickAngle : 0) : + autoangle; }); - } - }); - }; - - // make sure all labels are correctly positioned at their base angle - // the positionLabels call above is only for newly drawn labels. - // do this without waiting, using the last calculated angle to - // minimize flicker, then do it again when we know all labels are - // there, putting back the prescribed angle to check for overlaps. - positionLabels(tickLabels, prevAngle + 1 ? prevAngle : tickAngle); - - function allLabelsReady() { - return labelsReady.length && Promise.all(labelsReady); - } - - var autoangle = null; - - function fixLabelOverlaps() { - positionLabels(tickLabels, tickAngle); - - // check for auto-angling if x labels overlap - // don't auto-angle at all for log axes with - // base and digit format - if ( - vals.length && - ax.autotickangles && - (ax.type !== "log" || String(ax.dtick).charAt(0) !== "D") - ) { - autoangle = ax.autotickangles[0]; - - var maxFontSize = 0; - var lbbArray = []; - var i; - var maxLines = 1; - tickLabels.each(function (d) { - maxFontSize = Math.max(maxFontSize, d.fontSize); - - var x = ax.l2p(d.x); - var thisLabel = selectTickLabel(this); - var bb = Drawing.bBox(thisLabel.node()); - maxLines = Math.max(maxLines, svgTextUtils.lineCount(thisLabel)); - - lbbArray.push({ - // ignore about y, just deal with x overlaps - top: 0, - bottom: 10, - height: 10, - left: x - bb.width / 2, - // impose a 2px gap - right: x + bb.width / 2 + 2, - width: bb.width + 2, + } + + var computeTickLabelBoundingBoxes = function() { + var labelsMaxW = 0; + var labelsMaxH = 0; + tickLabels.each(function(d, i) { + var thisLabel = selectTickLabel(this); + var mathjaxGroup = thisLabel.select('.text-math-group'); + + if(mathjaxGroup.empty()) { + var bb; + + if(ax._vals[i]) { + bb = ax._vals[i].bb || Drawing.bBox(thisLabel.node()); + ax._vals[i].bb = bb; + } + + labelsMaxW = Math.max(labelsMaxW, bb.width); + labelsMaxH = Math.max(labelsMaxH, bb.height); + } }); - }); - - // autotickangles - // if there are dividers or ticks on boundaries, the labels will be in between and - // we need to prevent overlap with the next divider/tick. Else the labels will be on - // the ticks and we need to prevent overlap with the next label. - - // TODO should secondary labels also fall into this fix-overlap regime? - var preventOverlapWithTick = - (ax.tickson === "boundaries" || ax.showdividers) && !opts.secondary; - - var vLen = vals.length; - var tickSpacing = - Math.abs((vals[vLen - 1].x - vals[0].x) * ax._m) / (vLen - 1); - - var adjacent = preventOverlapWithTick ? tickSpacing / 2 : tickSpacing; - var opposite = preventOverlapWithTick - ? ax.ticklen - : maxFontSize * 1.25 * maxLines; - var hypotenuse = Math.sqrt(Math.pow(adjacent, 2) + Math.pow(opposite, 2)); - var maxCos = adjacent / hypotenuse; - var autoTickAnglesRadians = ax.autotickangles.map(function (degrees) { - return (degrees * Math.PI) / 180; - }); - var angleRadians = autoTickAnglesRadians.find(function (angle) { - return Math.abs(Math.cos(angle)) <= maxCos; - }); - if (angleRadians === undefined) { - // no angle with smaller cosine than maxCos, just pick the angle with smallest cosine - angleRadians = autoTickAnglesRadians.reduce(function ( - currentMax, - nextAngle - ) { - return Math.abs(Math.cos(currentMax)) < Math.abs(Math.cos(nextAngle)) - ? currentMax - : nextAngle; - }, - autoTickAnglesRadians[0]); - } - var newAngle = angleRadians * (180 / Math.PI) /* to degrees */; - - if (preventOverlapWithTick) { - var gap = 2; - if (ax.ticks) gap += ax.tickwidth / 2; - - for (i = 0; i < lbbArray.length; i++) { - var xbnd = vals[i].xbnd; - var lbb = lbbArray[i]; - if ( - (xbnd[0] !== null && lbb.left - ax.l2p(xbnd[0]) < gap) || - (xbnd[1] !== null && ax.l2p(xbnd[1]) - lbb.right < gap) - ) { - autoangle = newAngle; - break; - } - } - } else { - var ticklabelposition = ax.ticklabelposition || ""; - var tickson = ax.tickson || ""; - var has = function (str) { - return ticklabelposition.indexOf(str) !== -1; + return { + labelsMaxW: labelsMaxW, + labelsMaxH: labelsMaxH }; - var isTop = has("top"); - var isLeft = has("left"); - var isRight = has("right"); - var isBottom = has("bottom"); - var isAligned = - tickson !== "boundaries" && (isBottom || isLeft || isTop || isRight); - var pad = !isAligned ? 0 : (ax.tickwidth || 0) + 2 * TEXTPAD; - - for (i = 0; i < lbbArray.length - 1; i++) { - if (Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1], pad)) { - autoangle = newAngle; - break; - } - } - } - - if (autoangle) { - positionLabels(tickLabels, autoangle); - } - } - } - - if (ax._selections) { - ax._selections[cls] = tickLabels; - } - - var seq = [allLabelsReady]; - - // N.B. during auto-margin redraws, if the axis fixed its label overlaps - // by rotating 90 degrees, do not attempt to re-fix its label overlaps - // as this can lead to infinite redraw loops! - if ( - ax.automargin && - fullLayout._redrawFromAutoMarginCount && - prevAngle === 90 - ) { - autoangle = prevAngle; - seq.push(function () { - positionLabels(tickLabels, prevAngle); - }); - } else { - seq.push(fixLabelOverlaps); - } - - // save current tick angle for future redraws - if (ax._tickAngles) { - seq.push(function () { - ax._tickAngles[cls] = - autoangle === null ? (isNumeric(tickAngle) ? tickAngle : 0) : autoangle; - }); - } + }; - var computeTickLabelBoundingBoxes = function () { - var labelsMaxW = 0; - var labelsMaxH = 0; - tickLabels.each(function (d, i) { - var thisLabel = selectTickLabel(this); - var mathjaxGroup = thisLabel.select(".text-math-group"); + var anchorAx = ax._anchorAxis; + if( + anchorAx && (anchorAx.autorange || anchorAx.insiderange) && + insideTicklabelposition(ax) && + !isLinked(fullLayout, ax._id) + ) { + if(!fullLayout._insideTickLabelsUpdaterange) { + fullLayout._insideTickLabelsUpdaterange = {}; + } - if (mathjaxGroup.empty()) { - var bb; + if(anchorAx.autorange) { + fullLayout._insideTickLabelsUpdaterange[anchorAx._name + '.autorange'] = anchorAx.autorange; - if (ax._vals[i]) { - bb = ax._vals[i].bb || Drawing.bBox(thisLabel.node()); - ax._vals[i].bb = bb; + seq.push(computeTickLabelBoundingBoxes); } - labelsMaxW = Math.max(labelsMaxW, bb.width); - labelsMaxH = Math.max(labelsMaxH, bb.height); - } - }); + if(anchorAx.insiderange) { + var BBs = computeTickLabelBoundingBoxes(); + var move = ax._id.charAt(0) === 'y' ? + BBs.labelsMaxW : + BBs.labelsMaxH; - return { - labelsMaxW: labelsMaxW, - labelsMaxH: labelsMaxH, - }; - }; + move += 2 * TEXTPAD; - var anchorAx = ax._anchorAxis; - if ( - anchorAx && - (anchorAx.autorange || anchorAx.insiderange) && - insideTicklabelposition(ax) && - !isLinked(fullLayout, ax._id) - ) { - if (!fullLayout._insideTickLabelsUpdaterange) { - fullLayout._insideTickLabelsUpdaterange = {}; - } + if(ax.ticklabelposition === 'inside') { + move += ax.ticklen || 0; + } - if (anchorAx.autorange) { - fullLayout._insideTickLabelsUpdaterange[anchorAx._name + ".autorange"] = - anchorAx.autorange; + var sgn = (ax.side === 'right' || ax.side === 'top') ? 1 : -1; + var index = sgn === 1 ? 1 : 0; + var otherIndex = sgn === 1 ? 0 : 1; - seq.push(computeTickLabelBoundingBoxes); - } + var newRange = []; + newRange[otherIndex] = anchorAx.range[otherIndex]; - if (anchorAx.insiderange) { - var BBs = computeTickLabelBoundingBoxes(); - var move = ax._id.charAt(0) === "y" ? BBs.labelsMaxW : BBs.labelsMaxH; + var anchorAxRange = anchorAx.range; - move += 2 * TEXTPAD; + var p0 = anchorAx.r2p(anchorAxRange[index]); + var p1 = anchorAx.r2p(anchorAxRange[otherIndex]); - if (ax.ticklabelposition === "inside") { - move += ax.ticklen || 0; - } + var _tempNewRange = fullLayout._insideTickLabelsUpdaterange[anchorAx._name + '.range']; + if(_tempNewRange) { // case of having multiple anchored axes having insideticklabel + var q0 = anchorAx.r2p(_tempNewRange[index]); + var q1 = anchorAx.r2p(_tempNewRange[otherIndex]); - var sgn = ax.side === "right" || ax.side === "top" ? 1 : -1; - var index = sgn === 1 ? 1 : 0; - var otherIndex = sgn === 1 ? 0 : 1; + var dir = sgn * (ax._id.charAt(0) === 'y' ? 1 : -1); - var newRange = []; - newRange[otherIndex] = anchorAx.range[otherIndex]; + if(dir * p0 < dir * q0) { + p0 = q0; + newRange[index] = anchorAxRange[index] = _tempNewRange[index]; + } - var anchorAxRange = anchorAx.range; + if(dir * p1 > dir * q1) { + p1 = q1; + newRange[otherIndex] = anchorAxRange[otherIndex] = _tempNewRange[otherIndex]; + } + } - var p0 = anchorAx.r2p(anchorAxRange[index]); - var p1 = anchorAx.r2p(anchorAxRange[otherIndex]); + var dist = Math.abs(p1 - p0); + if(dist - move > 0) { + dist -= move; + move *= 1 + move / dist; + } else { + move = 0; + } - var _tempNewRange = - fullLayout._insideTickLabelsUpdaterange[anchorAx._name + ".range"]; - if (_tempNewRange) { - // case of having multiple anchored axes having insideticklabel - var q0 = anchorAx.r2p(_tempNewRange[index]); - var q1 = anchorAx.r2p(_tempNewRange[otherIndex]); + if(ax._id.charAt(0) !== 'y') move = -move; - var dir = sgn * (ax._id.charAt(0) === "y" ? 1 : -1); + newRange[index] = anchorAx.p2r( + anchorAx.r2p(anchorAxRange[index]) + + sgn * move + ); - if (dir * p0 < dir * q0) { - p0 = q0; - newRange[index] = anchorAxRange[index] = _tempNewRange[index]; + // handle partial ranges in insiderange + if( + anchorAx.autorange === 'min' || + anchorAx.autorange === 'max reversed' + ) { + newRange[0] = null; + + anchorAx._rangeInitial0 = undefined; + anchorAx._rangeInitial1 = undefined; + } else if( + anchorAx.autorange === 'max' || + anchorAx.autorange === 'min reversed' + ) { + newRange[1] = null; + + anchorAx._rangeInitial0 = undefined; + anchorAx._rangeInitial1 = undefined; + } + + fullLayout._insideTickLabelsUpdaterange[anchorAx._name + '.range'] = newRange; } + } - if (dir * p1 > dir * q1) { - p1 = q1; - newRange[otherIndex] = anchorAxRange[otherIndex] = - _tempNewRange[otherIndex]; - } - } - - var dist = Math.abs(p1 - p0); - if (dist - move > 0) { - dist -= move; - move *= 1 + move / dist; - } else { - move = 0; - } - - if (ax._id.charAt(0) !== "y") move = -move; - - newRange[index] = anchorAx.p2r( - anchorAx.r2p(anchorAxRange[index]) + sgn * move - ); - - // handle partial ranges in insiderange - if ( - anchorAx.autorange === "min" || - anchorAx.autorange === "max reversed" - ) { - newRange[0] = null; - - anchorAx._rangeInitial0 = undefined; - anchorAx._rangeInitial1 = undefined; - } else if ( - anchorAx.autorange === "max" || - anchorAx.autorange === "min reversed" - ) { - newRange[1] = null; - - anchorAx._rangeInitial0 = undefined; - anchorAx._rangeInitial1 = undefined; - } - - fullLayout._insideTickLabelsUpdaterange[anchorAx._name + ".range"] = - newRange; - } - } - - var done = Lib.syncOrAsync(seq); - if (done && done.then) gd._promises.push(done); - return done; + var done = Lib.syncOrAsync(seq); + if(done && done.then) gd._promises.push(done); + return done; }; /** @@ -4464,22 +4126,23 @@ axes.drawLabels = function (gd, ax, opts) { * - {fn} transFn */ function drawDividers(gd, ax, opts) { - var cls = ax._id + "divider"; - var vals = opts.vals; + var cls = ax._id + 'divider'; + var vals = opts.vals; - var dividers = opts.layer.selectAll("path." + cls).data(vals, tickDataFn); + var dividers = opts.layer.selectAll('path.' + cls) + .data(vals, tickDataFn); - dividers.exit().remove(); + dividers.exit().remove(); - dividers - .enter() - .insert("path", ":first-child") - .classed(cls, 1) - .classed("crisp", 1) - .call(Color.stroke, ax.dividercolor) - .style("stroke-width", Drawing.crispRound(gd, ax.dividerwidth, 1) + "px"); + dividers.enter().insert('path', ':first-child') + .classed(cls, 1) + .classed('crisp', 1) + .call(Color.stroke, ax.dividercolor) + .style('stroke-width', Drawing.crispRound(gd, ax.dividerwidth, 1) + 'px'); - dividers.attr("transform", opts.transFn).attr("d", opts.path); + dividers + .attr('transform', opts.transFn) + .attr('d', opts.path); } /** @@ -4496,31 +4159,31 @@ function drawDividers(gd, ax, opts) { * - {number} position * @return {number} */ -axes.getPxPosition = function (gd, ax) { - var gs = gd._fullLayout._size; - var axLetter = ax._id.charAt(0); - var side = ax.side; - var anchorAxis; - - if (ax.anchor !== "free") { - anchorAxis = ax._anchorAxis; - } else if (axLetter === "x") { - anchorAxis = { - _offset: gs.t + (1 - (ax.position || 0)) * gs.h, - _length: 0, - }; - } else if (axLetter === "y") { - anchorAxis = { - _offset: gs.l + (ax.position || 0) * gs.w + ax._shift, - _length: 0, - }; - } +axes.getPxPosition = function(gd, ax) { + var gs = gd._fullLayout._size; + var axLetter = ax._id.charAt(0); + var side = ax.side; + var anchorAxis; + + if(ax.anchor !== 'free') { + anchorAxis = ax._anchorAxis; + } else if(axLetter === 'x') { + anchorAxis = { + _offset: gs.t + (1 - (ax.position || 0)) * gs.h, + _length: 0 + }; + } else if(axLetter === 'y') { + anchorAxis = { + _offset: gs.l + (ax.position || 0) * gs.w + ax._shift, + _length: 0 + }; + } - if (side === "top" || side === "left") { - return anchorAxis._offset; - } else if (side === "bottom" || side === "right") { - return anchorAxis._offset + anchorAxis._length; - } + if(side === 'top' || side === 'left') { + return anchorAxis._offset; + } else if(side === 'bottom' || side === 'right') { + return anchorAxis._offset + anchorAxis._length; + } }; /** @@ -4533,13 +4196,15 @@ axes.getPxPosition = function (gd, ax) { * @return {number} (in px) */ function approxTitleDepth(ax) { - var fontSize = ax.title.font.size; - var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; - if (ax.title.hasOwnProperty("standoff")) { - return fontSize * (CAP_SHIFT + extraLines * LINE_SPACING); - } else { - return extraLines ? fontSize * (extraLines + 1) * LINE_SPACING : fontSize; - } + var fontSize = ax.title.font.size; + var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; + if(ax.title.hasOwnProperty('standoff')) { + return fontSize * (CAP_SHIFT + (extraLines * LINE_SPACING)); + } else { + return extraLines ? + fontSize * (extraLines + 1) * LINE_SPACING : + fontSize; + } } /** @@ -4560,212 +4225,199 @@ function approxTitleDepth(ax) { * - {boolean} showticklabels */ function drawTitle(gd, ax) { - var fullLayout = gd._fullLayout; - var axId = ax._id; - var axLetter = axId.charAt(0); - var fontSize = ax.title.font.size; - var titleStandoff; - var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; - - if (ax.title.hasOwnProperty("standoff")) { - // With ax._depth the initial drawing baseline is at the outer axis border (where the - // ticklabels are drawn). Since the title text will be drawn above the baseline, - // bottom/right axes must be shifted by 1 text line to draw below ticklabels instead of on - // top of them, whereas for top/left axes, the first line would be drawn - // before the ticklabels, but we need an offset for the descender portion of the first line - // and all subsequent lines. - if (ax.side === "bottom" || ax.side === "right") { - titleStandoff = ax._depth + ax.title.standoff + fontSize * CAP_SHIFT; - } else if (ax.side === "top" || ax.side === "left") { - titleStandoff = - ax._depth + - ax.title.standoff + - fontSize * (MID_SHIFT + extraLines * LINE_SPACING); - } - } else { - var isInside = insideTicklabelposition(ax); - - if (ax.type === "multicategory") { - titleStandoff = ax._depth; + var fullLayout = gd._fullLayout; + var axId = ax._id; + var axLetter = axId.charAt(0); + var fontSize = ax.title.font.size; + var titleStandoff; + var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; + + if(ax.title.hasOwnProperty('standoff')) { + // With ax._depth the initial drawing baseline is at the outer axis border (where the + // ticklabels are drawn). Since the title text will be drawn above the baseline, + // bottom/right axes must be shifted by 1 text line to draw below ticklabels instead of on + // top of them, whereas for top/left axes, the first line would be drawn + // before the ticklabels, but we need an offset for the descender portion of the first line + // and all subsequent lines. + if(ax.side === 'bottom' || ax.side === 'right') { + titleStandoff = ax._depth + ax.title.standoff + fontSize * CAP_SHIFT; + } else if(ax.side === 'top' || ax.side === 'left') { + titleStandoff = ax._depth + ax.title.standoff + fontSize * (MID_SHIFT + (extraLines * LINE_SPACING)); + } } else { - var offsetBase = 1.5 * fontSize; - if (isInside) { - offsetBase = 0.5 * fontSize; - if (ax.ticks === "outside") { - offsetBase += ax.ticklen; + var isInside = insideTicklabelposition(ax); + + if(ax.type === 'multicategory') { + titleStandoff = ax._depth; + } else { + var offsetBase = 1.5 * fontSize; + if(isInside) { + offsetBase = 0.5 * fontSize; + if(ax.ticks === 'outside') { + offsetBase += ax.ticklen; + } + } + titleStandoff = 10 + offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0); } - } - titleStandoff = 10 + offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0); - } - - if (!isInside) { - if (axLetter === "x") { - titleStandoff += - ax.side === "top" - ? fontSize * (ax.showticklabels ? 1 : 0) - : fontSize * (ax.showticklabels ? 1.5 : 0.5); - } else { - titleStandoff += - ax.side === "right" - ? fontSize * (ax.showticklabels ? 1 : 0.5) - : fontSize * (ax.showticklabels ? 0.5 : 0); - } - } - } - - var pos = axes.getPxPosition(gd, ax); - var transform, x, y; - - if (axLetter === "x") { - x = ax._offset + ax._length / 2; - y = ax.side === "top" ? pos - titleStandoff : pos + titleStandoff; - } else { - y = ax._offset + ax._length / 2; - x = ax.side === "right" ? pos + titleStandoff : pos - titleStandoff; - transform = { rotate: "-90", offset: 0 }; - } - - var avoid; - - if (ax.type !== "multicategory") { - var tickLabels = ax._selections[ax._id + "tick"]; - - avoid = { - selection: tickLabels, - side: ax.side, - }; - if (tickLabels && tickLabels.node() && tickLabels.node().parentNode) { - var translation = Drawing.getTranslate(tickLabels.node().parentNode); - avoid.offsetLeft = translation.x; - avoid.offsetTop = translation.y; + if(!isInside) { + if(axLetter === 'x') { + titleStandoff += ax.side === 'top' ? + fontSize * (ax.showticklabels ? 1 : 0) : + fontSize * (ax.showticklabels ? 1.5 : 0.5); + } else { + titleStandoff += ax.side === 'right' ? + fontSize * (ax.showticklabels ? 1 : 0.5) : + fontSize * (ax.showticklabels ? 0.5 : 0); + } + } + } + + var pos = axes.getPxPosition(gd, ax); + var transform, x, y; + + if(axLetter === 'x') { + x = ax._offset + ax._length / 2; + y = (ax.side === 'top') ? pos - titleStandoff : pos + titleStandoff; + } else { + y = ax._offset + ax._length / 2; + x = (ax.side === 'right') ? pos + titleStandoff : pos - titleStandoff; + transform = {rotate: '-90', offset: 0}; } - if (ax.title.hasOwnProperty("standoff")) { - avoid.pad = 0; + var avoid; + + if(ax.type !== 'multicategory') { + var tickLabels = ax._selections[ax._id + 'tick']; + + avoid = { + selection: tickLabels, + side: ax.side + }; + + if(tickLabels && tickLabels.node() && tickLabels.node().parentNode) { + var translation = Drawing.getTranslate(tickLabels.node().parentNode); + avoid.offsetLeft = translation.x; + avoid.offsetTop = translation.y; + } + + if(ax.title.hasOwnProperty('standoff')) { + avoid.pad = 0; + } } - } - ax._titleStandoff = titleStandoff; + ax._titleStandoff = titleStandoff; - return Titles.draw(gd, axId + "title", { - propContainer: ax, - propName: ax._name + ".title.text", - placeholder: fullLayout._dfltTitle[axLetter], - avoid: avoid, - transform: transform, - attributes: { x: x, y: y, "text-anchor": "middle" }, - }); + return Titles.draw(gd, axId + 'title', { + propContainer: ax, + propName: ax._name + '.title.text', + placeholder: fullLayout._dfltTitle[axLetter], + avoid: avoid, + transform: transform, + attributes: {x: x, y: y, 'text-anchor': 'middle'} + }); } -axes.shouldShowZeroLine = function (gd, ax, counterAxis) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - return ( - rng[0] * rng[1] <= 0 && - ax.zeroline && - (ax.type === "linear" || ax.type === "-") && - !(ax.rangebreaks && ax.maskBreaks(0) === BADNUM) && - (clipEnds(ax, 0) || - !anyCounterAxLineAtZero(gd, ax, counterAxis, rng) || - hasBarsOrFill(gd, ax)) - ); +axes.shouldShowZeroLine = function(gd, ax, counterAxis) { + var rng = Lib.simpleMap(ax.range, ax.r2l); + return ( + (rng[0] * rng[1] <= 0) && + ax.zeroline && + (ax.type === 'linear' || ax.type === '-') && + !(ax.rangebreaks && ax.maskBreaks(0) === BADNUM) && + ( + clipEnds(ax, 0) || + !anyCounterAxLineAtZero(gd, ax, counterAxis, rng) || + hasBarsOrFill(gd, ax) + ) + ); }; -axes.clipEnds = function (ax, vals) { - return vals.filter(function (d) { - return clipEnds(ax, d.x); - }); +axes.clipEnds = function(ax, vals) { + return vals.filter(function(d) { return clipEnds(ax, d.x); }); }; function clipEnds(ax, l) { - var p = ax.l2p(l); - return p > 1 && p < ax._length - 1; + var p = ax.l2p(l); + return (p > 1 && p < ax._length - 1); } function anyCounterAxLineAtZero(gd, ax, counterAxis, rng) { - var mainCounterAxis = counterAxis._mainAxis; - if (!mainCounterAxis) return; + var mainCounterAxis = counterAxis._mainAxis; + if(!mainCounterAxis) return; - var fullLayout = gd._fullLayout; - var axLetter = ax._id.charAt(0); - var counterLetter = axes.counterLetter(ax._id); + var fullLayout = gd._fullLayout; + var axLetter = ax._id.charAt(0); + var counterLetter = axes.counterLetter(ax._id); + + var zeroPosition = ax._offset + ( + ((Math.abs(rng[0]) < Math.abs(rng[1])) === (axLetter === 'x')) ? + 0 : ax._length + ); - var zeroPosition = - ax._offset + - (Math.abs(rng[0]) < Math.abs(rng[1]) === (axLetter === "x") - ? 0 - : ax._length); + function lineNearZero(ax2) { + if(!ax2.showline || !ax2.linewidth) return false; + var tolerance = Math.max((ax2.linewidth + ax.zerolinewidth) / 2, 1); - function lineNearZero(ax2) { - if (!ax2.showline || !ax2.linewidth) return false; - var tolerance = Math.max((ax2.linewidth + ax.zerolinewidth) / 2, 1); + function closeEnough(pos2) { + return typeof pos2 === 'number' && Math.abs(pos2 - zeroPosition) < tolerance; + } - function closeEnough(pos2) { - return ( - typeof pos2 === "number" && Math.abs(pos2 - zeroPosition) < tolerance - ); + if(closeEnough(ax2._mainLinePosition) || closeEnough(ax2._mainMirrorPosition)) { + return true; + } + var linePositions = ax2._linepositions || {}; + for(var k in linePositions) { + if(closeEnough(linePositions[k][0]) || closeEnough(linePositions[k][1])) { + return true; + } + } } - if ( - closeEnough(ax2._mainLinePosition) || - closeEnough(ax2._mainMirrorPosition) - ) { - return true; - } - var linePositions = ax2._linepositions || {}; - for (var k in linePositions) { - if ( - closeEnough(linePositions[k][0]) || - closeEnough(linePositions[k][1]) - ) { - return true; - } - } - } - - var plotinfo = fullLayout._plots[counterAxis._mainSubplot]; - if (!(plotinfo.mainplotinfo || plotinfo).overlays.length) { - return lineNearZero(counterAxis, zeroPosition); - } - - var counterLetterAxes = axes.list(gd, counterLetter); - for (var i = 0; i < counterLetterAxes.length; i++) { - var counterAxis2 = counterLetterAxes[i]; - if ( - counterAxis2._mainAxis === mainCounterAxis && - lineNearZero(counterAxis2, zeroPosition) - ) { - return true; + var plotinfo = fullLayout._plots[counterAxis._mainSubplot]; + if(!(plotinfo.mainplotinfo || plotinfo).overlays.length) { + return lineNearZero(counterAxis, zeroPosition); + } + + var counterLetterAxes = axes.list(gd, counterLetter); + for(var i = 0; i < counterLetterAxes.length; i++) { + var counterAxis2 = counterLetterAxes[i]; + if( + counterAxis2._mainAxis === mainCounterAxis && + lineNearZero(counterAxis2, zeroPosition) + ) { + return true; + } } - } } function hasBarsOrFill(gd, ax) { - var fullData = gd._fullData; - var subplot = ax._mainSubplot; - var axLetter = ax._id.charAt(0); - - for (var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if (trace.visible === true && trace.xaxis + trace.yaxis === subplot) { - if ( - Registry.traceIs(trace, "bar-like") && - trace.orientation === { x: "h", y: "v" }[axLetter] - ) - return true; - - if (trace.fill && trace.fill.charAt(trace.fill.length - 1) === axLetter) - return true; + var fullData = gd._fullData; + var subplot = ax._mainSubplot; + var axLetter = ax._id.charAt(0); + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(trace.visible === true && (trace.xaxis + trace.yaxis) === subplot) { + if( + Registry.traceIs(trace, 'bar-like') && + trace.orientation === {x: 'h', y: 'v'}[axLetter] + ) return true; + + if( + trace.fill && + trace.fill.charAt(trace.fill.length - 1) === axLetter + ) return true; + } } - } - return false; + return false; } function selectTickLabel(gTick) { - var s = d3.select(gTick); - var mj = s.select(".text-math-group"); - return mj.empty() ? s.select("text") : mj; + var s = d3.select(gTick); + var mj = s.select('.text-math-group'); + return mj.empty() ? s.select('text') : mj; } /** @@ -4777,247 +4429,217 @@ function selectTickLabel(gTick) { * We're probably also doing multiple redraws in this case, would be faster * if we can just do the whole calculation ahead of time and draw once. */ -axes.allowAutoMargin = function (gd) { - var axList = axes.list(gd, "", true); - for (var i = 0; i < axList.length; i++) { - var ax = axList[i]; - if (ax.automargin) { - Plots.allowAutoMargin(gd, axAutoMarginID(ax)); - if (ax.mirror) { - Plots.allowAutoMargin(gd, axMirrorAutoMarginID(ax)); - } - } - if (Registry.getComponentMethod("rangeslider", "isVisible")(ax)) { - Plots.allowAutoMargin(gd, rangeSliderAutoMarginID(ax)); - } - } +axes.allowAutoMargin = function(gd) { + var axList = axes.list(gd, '', true); + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + if(ax.automargin) { + Plots.allowAutoMargin(gd, axAutoMarginID(ax)); + if(ax.mirror) { + Plots.allowAutoMargin(gd, axMirrorAutoMarginID(ax)); + } + } + if(Registry.getComponentMethod('rangeslider', 'isVisible')(ax)) { + Plots.allowAutoMargin(gd, rangeSliderAutoMarginID(ax)); + } + } }; -function axAutoMarginID(ax) { - return ax._id + ".automargin"; -} -function axMirrorAutoMarginID(ax) { - return axAutoMarginID(ax) + ".mirror"; -} -function rangeSliderAutoMarginID(ax) { - return ax._id + ".rangeslider"; -} +function axAutoMarginID(ax) { return ax._id + '.automargin'; } +function axMirrorAutoMarginID(ax) { return axAutoMarginID(ax) + '.mirror'; } +function rangeSliderAutoMarginID(ax) { return ax._id + '.rangeslider'; } // swap all the presentation attributes of the axes showing these traces -axes.swap = function (gd, traces) { - var axGroups = makeAxisGroups(gd, traces); +axes.swap = function(gd, traces) { + var axGroups = makeAxisGroups(gd, traces); - for (var i = 0; i < axGroups.length; i++) { - swapAxisGroup(gd, axGroups[i].x, axGroups[i].y); - } + for(var i = 0; i < axGroups.length; i++) { + swapAxisGroup(gd, axGroups[i].x, axGroups[i].y); + } }; function makeAxisGroups(gd, traces) { - var groups = []; - var i, j; - - for (i = 0; i < traces.length; i++) { - var groupsi = []; - var xi = gd._fullData[traces[i]].xaxis; - var yi = gd._fullData[traces[i]].yaxis; - if (!xi || !yi) continue; // not a 2D cartesian trace? - - for (j = 0; j < groups.length; j++) { - if (groups[j].x.indexOf(xi) !== -1 || groups[j].y.indexOf(yi) !== -1) { - groupsi.push(j); - } - } + var groups = []; + var i, j; + + for(i = 0; i < traces.length; i++) { + var groupsi = []; + var xi = gd._fullData[traces[i]].xaxis; + var yi = gd._fullData[traces[i]].yaxis; + if(!xi || !yi) continue; // not a 2D cartesian trace? + + for(j = 0; j < groups.length; j++) { + if(groups[j].x.indexOf(xi) !== -1 || groups[j].y.indexOf(yi) !== -1) { + groupsi.push(j); + } + } - if (!groupsi.length) { - groups.push({ x: [xi], y: [yi] }); - continue; - } + if(!groupsi.length) { + groups.push({x: [xi], y: [yi]}); + continue; + } - var group0 = groups[groupsi[0]]; - var groupj; + var group0 = groups[groupsi[0]]; + var groupj; - if (groupsi.length > 1) { - for (j = 1; j < groupsi.length; j++) { - groupj = groups[groupsi[j]]; - mergeAxisGroups(group0.x, groupj.x); - mergeAxisGroups(group0.y, groupj.y); - } + if(groupsi.length > 1) { + for(j = 1; j < groupsi.length; j++) { + groupj = groups[groupsi[j]]; + mergeAxisGroups(group0.x, groupj.x); + mergeAxisGroups(group0.y, groupj.y); + } + } + mergeAxisGroups(group0.x, [xi]); + mergeAxisGroups(group0.y, [yi]); } - mergeAxisGroups(group0.x, [xi]); - mergeAxisGroups(group0.y, [yi]); - } - return groups; + return groups; } function mergeAxisGroups(intoSet, fromSet) { - for (var i = 0; i < fromSet.length; i++) { - if (intoSet.indexOf(fromSet[i]) === -1) intoSet.push(fromSet[i]); - } + for(var i = 0; i < fromSet.length; i++) { + if(intoSet.indexOf(fromSet[i]) === -1) intoSet.push(fromSet[i]); + } } function swapAxisGroup(gd, xIds, yIds) { - var xFullAxes = []; - var yFullAxes = []; - var layout = gd.layout; - var i, j; - - for (i = 0; i < xIds.length; i++) xFullAxes.push(axes.getFromId(gd, xIds[i])); - for (i = 0; i < yIds.length; i++) yFullAxes.push(axes.getFromId(gd, yIds[i])); - - var allAxKeys = Object.keys(axAttrs); - - var noSwapAttrs = [ - "anchor", - "domain", - "overlaying", - "position", - "side", - "tickangle", - "editType", - ]; - var numericTypes = ["linear", "log"]; - - for (i = 0; i < allAxKeys.length; i++) { - var keyi = allAxKeys[i]; - var xVal = xFullAxes[0][keyi]; - var yVal = yFullAxes[0][keyi]; - var allEqual = true; - var coerceLinearX = false; - var coerceLinearY = false; - if ( - keyi.charAt(0) === "_" || - typeof xVal === "function" || - noSwapAttrs.indexOf(keyi) !== -1 - ) { - continue; - } - for (j = 1; j < xFullAxes.length && allEqual; j++) { - var xVali = xFullAxes[j][keyi]; - if ( - keyi === "type" && - numericTypes.indexOf(xVal) !== -1 && - numericTypes.indexOf(xVali) !== -1 && - xVal !== xVali - ) { - // type is special - if we find a mixture of linear and log, - // coerce them all to linear on flipping - coerceLinearX = true; - } else if (xVali !== xVal) allEqual = false; - } - for (j = 1; j < yFullAxes.length && allEqual; j++) { - var yVali = yFullAxes[j][keyi]; - if ( - keyi === "type" && - numericTypes.indexOf(yVal) !== -1 && - numericTypes.indexOf(yVali) !== -1 && - yVal !== yVali - ) { - // type is special - if we find a mixture of linear and log, - // coerce them all to linear on flipping - coerceLinearY = true; - } else if (yFullAxes[j][keyi] !== yVal) allEqual = false; - } - if (allEqual) { - if (coerceLinearX) layout[xFullAxes[0]._name].type = "linear"; - if (coerceLinearY) layout[yFullAxes[0]._name].type = "linear"; - swapAxisAttrs( - layout, - keyi, - xFullAxes, - yFullAxes, - gd._fullLayout._dfltTitle - ); - } - } - - // now swap x&y for any annotations anchored to these x & y - for (i = 0; i < gd._fullLayout.annotations.length; i++) { - var ann = gd._fullLayout.annotations[i]; - if (xIds.indexOf(ann.xref) !== -1 && yIds.indexOf(ann.yref) !== -1) { - Lib.swapAttrs(layout.annotations[i], ["?"]); - } - } + var xFullAxes = []; + var yFullAxes = []; + var layout = gd.layout; + var i, j; + + for(i = 0; i < xIds.length; i++) xFullAxes.push(axes.getFromId(gd, xIds[i])); + for(i = 0; i < yIds.length; i++) yFullAxes.push(axes.getFromId(gd, yIds[i])); + + var allAxKeys = Object.keys(axAttrs); + + var noSwapAttrs = [ + 'anchor', 'domain', 'overlaying', 'position', 'side', 'tickangle', 'editType' + ]; + var numericTypes = ['linear', 'log']; + + for(i = 0; i < allAxKeys.length; i++) { + var keyi = allAxKeys[i]; + var xVal = xFullAxes[0][keyi]; + var yVal = yFullAxes[0][keyi]; + var allEqual = true; + var coerceLinearX = false; + var coerceLinearY = false; + if(keyi.charAt(0) === '_' || typeof xVal === 'function' || + noSwapAttrs.indexOf(keyi) !== -1) { + continue; + } + for(j = 1; j < xFullAxes.length && allEqual; j++) { + var xVali = xFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(xVal) !== -1 && + numericTypes.indexOf(xVali) !== -1 && xVal !== xVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearX = true; + } else if(xVali !== xVal) allEqual = false; + } + for(j = 1; j < yFullAxes.length && allEqual; j++) { + var yVali = yFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(yVal) !== -1 && + numericTypes.indexOf(yVali) !== -1 && yVal !== yVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearY = true; + } else if(yFullAxes[j][keyi] !== yVal) allEqual = false; + } + if(allEqual) { + if(coerceLinearX) layout[xFullAxes[0]._name].type = 'linear'; + if(coerceLinearY) layout[yFullAxes[0]._name].type = 'linear'; + swapAxisAttrs(layout, keyi, xFullAxes, yFullAxes, gd._fullLayout._dfltTitle); + } + } + + // now swap x&y for any annotations anchored to these x & y + for(i = 0; i < gd._fullLayout.annotations.length; i++) { + var ann = gd._fullLayout.annotations[i]; + if(xIds.indexOf(ann.xref) !== -1 && + yIds.indexOf(ann.yref) !== -1) { + Lib.swapAttrs(layout.annotations[i], ['?']); + } + } } function swapAxisAttrs(layout, key, xFullAxes, yFullAxes, dfltTitle) { - // in case the value is the default for either axis, - // look at the first axis in each list and see if - // this key's value is undefined - var np = Lib.nestedProperty; - var xVal = np(layout[xFullAxes[0]._name], key).get(); - var yVal = np(layout[yFullAxes[0]._name], key).get(); - var i; - - if (key === "title") { - // special handling of placeholder titles - if (xVal && xVal.text === dfltTitle.x) { - xVal.text = dfltTitle.y; - } - if (yVal && yVal.text === dfltTitle.y) { - yVal.text = dfltTitle.x; - } - } - - for (i = 0; i < xFullAxes.length; i++) { - np(layout, xFullAxes[i]._name + "." + key).set(yVal); - } - for (i = 0; i < yFullAxes.length; i++) { - np(layout, yFullAxes[i]._name + "." + key).set(xVal); - } + // in case the value is the default for either axis, + // look at the first axis in each list and see if + // this key's value is undefined + var np = Lib.nestedProperty; + var xVal = np(layout[xFullAxes[0]._name], key).get(); + var yVal = np(layout[yFullAxes[0]._name], key).get(); + var i; + + if(key === 'title') { + // special handling of placeholder titles + if(xVal && xVal.text === dfltTitle.x) { + xVal.text = dfltTitle.y; + } + if(yVal && yVal.text === dfltTitle.y) { + yVal.text = dfltTitle.x; + } + } + + for(i = 0; i < xFullAxes.length; i++) { + np(layout, xFullAxes[i]._name + '.' + key).set(yVal); + } + for(i = 0; i < yFullAxes.length; i++) { + np(layout, yFullAxes[i]._name + '.' + key).set(xVal); + } } function isAngular(ax) { - return ax._id === "angularaxis"; + return ax._id === 'angularaxis'; } function moveOutsideBreak(v, ax) { - var len = ax._rangebreaks.length; - for (var k = 0; k < len; k++) { - var brk = ax._rangebreaks[k]; - if (v >= brk.min && v < brk.max) { - return brk.max; - } - } - return v; + var len = ax._rangebreaks.length; + for(var k = 0; k < len; k++) { + var brk = ax._rangebreaks[k]; + if(v >= brk.min && v < brk.max) { + return brk.max; + } + } + return v; } function insideTicklabelposition(ax) { - return (ax.ticklabelposition || "").indexOf("inside") !== -1; + return ((ax.ticklabelposition || '').indexOf('inside') !== -1); } function hideCounterAxisInsideTickLabels(ax, opts) { - if (insideTicklabelposition(ax._anchorAxis || {})) { - if (ax._hideCounterAxisInsideTickLabels) { - ax._hideCounterAxisInsideTickLabels(opts); + if(insideTicklabelposition(ax._anchorAxis || {})) { + if(ax._hideCounterAxisInsideTickLabels) { + ax._hideCounterAxisInsideTickLabels(opts); + } } - } } function incrementShift(ax, shiftVal, axShifts, normalize) { - // Need to set 'overlay' for anchored axis - var overlay = - ax.anchor !== "free" && - (ax.overlaying === undefined || ax.overlaying === false) - ? ax._id - : ax.overlaying; - var shiftValAdj; - if (normalize) { - shiftValAdj = ax.side === "right" ? shiftVal : -shiftVal; - } else { - shiftValAdj = shiftVal; - } - if (!(overlay in axShifts)) { - axShifts[overlay] = {}; - } - if (!(ax.side in axShifts[overlay])) { - axShifts[overlay][ax.side] = 0; - } - axShifts[overlay][ax.side] += shiftValAdj; + // Need to set 'overlay' for anchored axis + var overlay = ((ax.anchor !== 'free') && ((ax.overlaying === undefined) || (ax.overlaying === false))) ? ax._id : ax.overlaying; + var shiftValAdj; + if(normalize) { + shiftValAdj = ax.side === 'right' ? shiftVal : -shiftVal; + } else { + shiftValAdj = shiftVal; + } + if(!(overlay in axShifts)) { + axShifts[overlay] = {}; + } + if(!(ax.side in axShifts[overlay])) { + axShifts[overlay][ax.side] = 0; + } + axShifts[overlay][ax.side] += shiftValAdj; } function setShiftVal(ax, axShifts) { - return ax.autoshift ? axShifts[ax.overlaying][ax.side] : ax.shift || 0; + return ax.autoshift ? + axShifts[ax.overlaying][ax.side] : + (ax.shift || 0); } /** @@ -5029,27 +4651,18 @@ function setShiftVal(ax, axShifts) { * @returns {boolean} */ function periodCompatibleWithTickformat(period, tickformat) { - return /%f/.test(tickformat) - ? period >= ONEMICROSEC - : /%L/.test(tickformat) - ? period >= ONEMILLI - : /%[SX]/.test(tickformat) - ? period >= ONESEC - : /%M/.test(tickformat) - ? period >= ONEMIN - : /%[HI]/.test(tickformat) - ? period >= ONEHOUR - : /%p/.test(tickformat) - ? period >= HALFDAY - : /%[Aadejuwx]/.test(tickformat) - ? period >= ONEDAY - : /%[UVW]/.test(tickformat) - ? period >= ONEWEEK - : /%[Bbm]/.test(tickformat) - ? period >= ONEMINMONTH - : /%[q]/.test(tickformat) - ? period >= ONEMINQUARTER - : /%[Yy]/.test(tickformat) - ? period >= ONEMINYEAR - : true; + return ( + /%f/.test(tickformat) ? period >= ONEMICROSEC : + /%L/.test(tickformat) ? period >= ONEMILLI : + /%[SX]/.test(tickformat) ? period >= ONESEC : + /%M/.test(tickformat) ? period >= ONEMIN : + /%[HI]/.test(tickformat) ? period >= ONEHOUR : + /%p/.test(tickformat) ? period >= HALFDAY : + /%[Aadejuwx]/.test(tickformat) ? period >= ONEDAY : + /%[UVW]/.test(tickformat) ? period >= ONEWEEK : + /%[Bbm]/.test(tickformat) ? period >= ONEMINMONTH : + /%[q]/.test(tickformat) ? period >= ONEMINQUARTER : + /%[Yy]/.test(tickformat) ? period >= ONEMINYEAR : + true + ); } diff --git a/test/image/mocks/20.json b/test/image/mocks/20.json index 078f4d66429..d26ef4d9a50 100644 --- a/test/image/mocks/20.json +++ b/test/image/mocks/20.json @@ -36,7 +36,10 @@ }, { "x": [6, 7, 8], - "y": [400000000000000000000000000000000, 500000000000000000000000000000000, 600000000000000000000000000000000], + "y": [ + 400000000000000000000000000000000, 500000000000000000000000000000000, + 600000000000000000000000000000000 + ], "name": "yaxis6 data", "yaxis": "y6", "type": "scatter" From 13921b306357c56e9443ed730c28544126c37cd1 Mon Sep 17 00:00:00 2001 From: Alex Hsu Date: Wed, 15 Oct 2025 15:17:21 -0400 Subject: [PATCH 5/8] update plot-schema diff --- test/plot-schema.json | 256 +++++++++++++++++++++++++----------------- 1 file changed, 154 insertions(+), 102 deletions(-) diff --git a/test/plot-schema.json b/test/plot-schema.json index dbc320a4631..618423414bf 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -1248,7 +1248,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -1258,7 +1258,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -5121,7 +5122,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -5131,7 +5132,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -5813,7 +5815,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -5823,7 +5825,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -7241,7 +7244,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -7251,7 +7254,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -7980,7 +7984,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -7990,7 +7994,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -8719,7 +8724,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -8729,7 +8734,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -11132,7 +11138,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -11142,7 +11148,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -11645,7 +11652,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -11655,7 +11662,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -12164,7 +12172,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -12174,7 +12182,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "gridcolor": { @@ -13700,7 +13709,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "ticks", "valType": "enumerated", @@ -13710,7 +13719,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "fixedrange": { @@ -15295,7 +15305,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "ticks", "valType": "enumerated", @@ -15305,7 +15315,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "fixedrange": { @@ -17196,7 +17207,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -17206,7 +17217,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -19246,7 +19258,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -19256,7 +19268,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -22689,7 +22702,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "fixedrange": { @@ -23360,7 +23374,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "fixedrange": { @@ -24339,7 +24354,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -24349,7 +24364,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -25632,7 +25648,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -25642,7 +25658,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -26915,7 +26932,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -26925,7 +26942,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -28237,7 +28255,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -28247,7 +28265,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -29588,7 +29607,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -29598,7 +29617,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -31411,7 +31431,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -31421,7 +31441,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -32637,7 +32658,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -32647,7 +32668,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -33858,7 +33880,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -33868,7 +33890,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -35747,7 +35770,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -35757,7 +35780,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -38377,7 +38401,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -38387,7 +38411,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -40731,7 +40756,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -40741,7 +40766,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -42188,7 +42214,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -42198,7 +42224,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -43692,7 +43719,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -43702,7 +43729,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -46065,7 +46093,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -46075,7 +46103,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -48359,7 +48388,7 @@ }, "editType": "plot", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "plot", "valType": "enumerated", @@ -48369,7 +48398,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -49436,7 +49466,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -49446,7 +49476,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -50962,7 +50993,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -50972,7 +51003,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -53570,7 +53602,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -53580,7 +53612,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -54853,7 +54886,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -54863,7 +54896,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -59608,7 +59642,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -59618,7 +59652,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -62244,7 +62279,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -62254,7 +62289,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -62953,7 +62989,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -62963,7 +62999,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -64786,7 +64823,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -64796,7 +64833,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -67079,7 +67117,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -67089,7 +67127,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -69487,7 +69526,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -69497,7 +69536,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -71815,7 +71855,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -71825,7 +71865,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -73358,7 +73399,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -73368,7 +73409,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -74884,7 +74926,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -74894,7 +74936,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -77150,7 +77193,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -77160,7 +77203,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -79360,7 +79404,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -79370,7 +79414,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -81665,7 +81710,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -81675,7 +81720,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -83901,7 +83947,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -83911,7 +83957,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -85422,7 +85469,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -85432,7 +85479,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -87479,7 +87527,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -87489,7 +87537,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -88760,7 +88809,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -88770,7 +88819,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -92104,7 +92154,7 @@ }, "editType": "colorbars", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "colorbars", "valType": "enumerated", @@ -92114,7 +92164,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { @@ -95149,7 +95200,7 @@ }, "editType": "calc", "exponentformat": { - "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B.", + "description": "Determines a formatting rule for the tick exponents. For example, consider the number 1,000,000,000. If *none*, it appears as 1,000,000,000. If *e*, 1e+9. If *E*, 1E+9. If *power*, 1x10^9 (with 9 in a super script). If *SI*, 1G. If *B*, 1B. *SI* uses prefixes from \"femto\" f (10^-15) to \"tera\" T (10^12). *SI extended* covers instead the full SI range from \"quecto\" q (10^-30) to \"quetta\" Q (10^30). If *SI* or *SI extended* is used and the exponent is beyond the above ranges, the formatting rule will automatically be switched to the power notation.", "dflt": "B", "editType": "calc", "valType": "enumerated", @@ -95159,7 +95210,8 @@ "E", "power", "SI", - "B" + "B", + "SI extended" ] }, "labelalias": { From 6806e558e97da106e3999380ca0dc27c49d3aab6 Mon Sep 17 00:00:00 2001 From: Alex Hsu Date: Wed, 15 Oct 2025 15:57:12 -0400 Subject: [PATCH 6/8] Fix baseline mock image --- test/image/baselines/20.png | Bin 76587 -> 94220 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/image/baselines/20.png b/test/image/baselines/20.png index 05cc733bd2520de8c790299ff9650c2430b571dd..99c40ea0507a88c0ceae570f5c990ff00265d908 100644 GIT binary patch literal 94220 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
i`QJ0A~YZpST%#is^j-7*XI< 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 literal 76587 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%0DW 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 Date: Thu, 16 Oct 2025 11:20:18 -0400 Subject: [PATCH 7/8] Simplify logic in `numFormat` --- src/plots/cartesian/axes.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 662bb39791f..bb0cead5689 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -2066,11 +2066,9 @@ function num2frac(num) { var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; // extending SI prefixes -var SIPREFIXES_EXTENDED = ['q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q']; +var SIPREFIXES_EXTENDED = ['q', 'r', 'y', 'z', 'a', ...SIPREFIXES, 'P', 'E', 'Z', 'Y', 'R', 'Q']; -function isSIFormat(exponentFormat) { - return exponentFormat === 'SI' || exponentFormat === 'SI extended' || exponentFormat === 'B'; -} +const isSIFormat = (exponentFormat) => ['SI', 'SI extended','B'].includes(exponentFormat); // are we beyond the range of common SI prefixes? // 10^-16 -> 1x10^-16 @@ -2083,10 +2081,26 @@ function beyondSI(exponent) { return exponent > 14 || exponent < -15; } + +// are we beyond the range of all SI prefixes? +// 10^-31 -> 1x10^-31 +// 10^-30 -> 1q +// 10^-29 -> 10q +// ... +// 10^31 -> 10Q +// 10^32 -> 100Q +// 10^33 -> 1x10^33 function beyondSIExtended(exponent) { return exponent > 32 || exponent < -30; } +function shouldSwitchSIToPowerFormat(exponent, exponentFormat) { + if (!isSIFormat(exponentFormat)) return false; + if (exponentFormat === 'SI extended' && beyondSIExtended(exponent)) return true; + if (exponentFormat !== 'SI extended' && beyondSI(exponent)) return true; + return false; +} + function numFormat(v, ax, fmtoverride, hover) { var isNeg = v < 0; // max number of digits past decimal point to show @@ -2162,8 +2176,7 @@ function numFormat(v, ax, fmtoverride, hover) { // add exponent if(exponent && exponentFormat !== 'hide') { - if((isSIFormat(exponentFormat) && exponentFormat !== 'SI extended' && beyondSI(exponent)) || - (isSIFormat(exponentFormat) && exponentFormat === 'SI extended' && beyondSIExtended(exponent))) exponentFormat = 'power'; + if (shouldSwitchSIToPowerFormat(exponent, exponentFormat)) exponentFormat = 'power'; var signedExponent; if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; @@ -2177,11 +2190,9 @@ function numFormat(v, ax, fmtoverride, hover) { } else if(exponentFormat === 'B' && exponent === 9) { v += 'B'; } else if(isSIFormat(exponentFormat)) { - if(exponentFormat !== 'SI extended') { - v += SIPREFIXES[exponent / 3 + 5]; - } else if(exponentFormat === 'SI extended') { - v += SIPREFIXES_EXTENDED[exponent / 3 + 10]; - } + v += exponentFormat === 'SI extended' + ? SIPREFIXES_EXTENDED[exponent / 3 + 10] + : SIPREFIXES[exponent / 3 + 5]; } } From beab33e59cfadb191e040fe6aa9ff67fba648b0c Mon Sep 17 00:00:00 2001 From: Alex Hsu Date: Thu, 16 Oct 2025 12:20:08 -0400 Subject: [PATCH 8/8] Add entry to draftlogs --- draftlogs/7249_add.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 draftlogs/7249_add.md diff --git a/draftlogs/7249_add.md b/draftlogs/7249_add.md new file mode 100644 index 00000000000..2f289e3c8f5 --- /dev/null +++ b/draftlogs/7249_add.md @@ -0,0 +1 @@ +- Add "SI extended" formatting rule for tick exponents on axis labels, allowing values to be displayed with extended SI prefixes (e.g., femto, pico, atto) [[#7249](https://github.com/plotly/plotly.js/pull/7249)] \ No newline at end of file