diff --git a/src/components/colorbar/connect.js b/src/components/colorbar/connect.js index f551b32b511..e90d03009c3 100644 --- a/src/components/colorbar/connect.js +++ b/src/components/colorbar/connect.js @@ -6,10 +6,10 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var drawColorbar = require('./draw'); +var flipScale = require('../colorscale/helpers').flipScale; /** * connectColorbar: create a colorbar from a trace, using its module to @@ -49,7 +49,11 @@ module.exports = function connectColorbar(gd, cd, moduleOpts) { var cb = cd[0].t.cb = drawColorbar(gd, cbId); - cb.fillgradient(container.colorscale) + var scl = container.reversescale ? + flipScale(container.colorscale) : + container.colorscale; + + cb.fillgradient(scl) .zrange([container[moduleOpts.min], container[moduleOpts.max]]) .options(container.colorbar)(); }; diff --git a/src/components/colorscale/attributes.js b/src/components/colorscale/attributes.js index a0df770a15b..0e95fd06ed3 100644 --- a/src/components/colorscale/attributes.js +++ b/src/components/colorscale/attributes.js @@ -8,7 +8,7 @@ 'use strict'; -var palettes = require('./scales.js'); +var palettes = require('./scales.js').scales; var paletteStr = Object.keys(palettes); function code(s) { @@ -197,7 +197,7 @@ module.exports = function colorScaleAttrs(context, opts) { valType: 'boolean', role: 'style', dflt: false, - editType: 'calc', + editType: 'plot', description: [ 'Reverses the color mapping if true.', effectDesc, diff --git a/src/components/colorscale/calc.js b/src/components/colorscale/calc.js index e887b6820cd..a17f4717524 100644 --- a/src/components/colorscale/calc.js +++ b/src/components/colorscale/calc.js @@ -6,52 +6,19 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Lib = require('../../lib'); -var flipScale = require('./flip_scale'); - - module.exports = function calc(gd, trace, opts) { var fullLayout = gd._fullLayout; var vals = opts.vals; var containerStr = opts.containerStr; var cLetter = opts.cLetter; - var container = trace; - var inputContainer = trace._input; - var fullInputContainer = trace._fullInput; - // set by traces with groupby transforms - var updateStyle = trace.updateStyle; - - function doUpdate(attr, inputVal, fullVal) { - if(fullVal === undefined) fullVal = inputVal; - - if(updateStyle) { - updateStyle(trace._input, containerStr ? (containerStr + '.' + attr) : attr, inputVal); - } - else { - inputContainer[attr] = inputVal; - } - - container[attr] = fullVal; - if(fullInputContainer && (trace !== trace._fullInput)) { - if(updateStyle) { - updateStyle(trace._fullInput, containerStr ? (containerStr + '.' + attr) : attr, fullVal); - } - else { - fullInputContainer[attr] = fullVal; - } - } - } - - if(containerStr) { - container = Lib.nestedProperty(container, containerStr).get(); - inputContainer = Lib.nestedProperty(inputContainer, containerStr).get(); - fullInputContainer = Lib.nestedProperty(fullInputContainer, containerStr).get() || {}; - } + var container = containerStr ? + Lib.nestedProperty(trace, containerStr).get() : + trace; var autoAttr = cLetter + 'auto'; var minAttr = cLetter + 'min'; @@ -74,32 +41,14 @@ module.exports = function calc(gd, trace, opts) { max += 0.5; } - doUpdate(minAttr, min); - doUpdate(maxAttr, max); - - /* - * If auto was explicitly false but min or max was missing, - * we filled in the missing piece here but later the trace does - * not look auto. - * Otherwise make sure the trace still looks auto as far as later - * changes are concerned. - */ - doUpdate(autoAttr, (auto !== false || (min === undefined && max === undefined))); + container['_' + minAttr] = container[minAttr] = min; + container['_' + maxAttr] = container[maxAttr] = max; if(container.autocolorscale) { if(min * max < 0) scl = fullLayout.colorscale.diverging; else if(min >= 0) scl = fullLayout.colorscale.sequential; - else scl = gd._fullLayout.colorscale.sequentialminus; - - // reversescale is handled at the containerOut level - doUpdate('colorscale', scl, container.reversescale ? flipScale(scl) : scl); + else scl = fullLayout.colorscale.sequentialminus; - // We pushed a colorscale back to input, which will change the default autocolorscale next time - // to avoid spurious redraws from Plotly.react, update resulting autocolorscale now - // This is a conscious decision so that changing the data later does not unexpectedly - // give you a new colorscale - if(!inputContainer.autocolorscale) { - doUpdate('autocolorscale', false); - } + container._colorscale = container.colorscale = scl; } }; diff --git a/src/components/colorscale/cross_trace_defaults.js b/src/components/colorscale/cross_trace_defaults.js new file mode 100644 index 00000000000..d3d9a2f388a --- /dev/null +++ b/src/components/colorscale/cross_trace_defaults.js @@ -0,0 +1,70 @@ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var hasColorscale = require('./helpers').hasColorscale; + +module.exports = function crossTraceDefaults(fullData) { + function replace(cont, k) { + var val = cont['_' + k]; + if(val !== undefined) { + cont[k] = val; + } + } + + function relinkColorAtts(trace, cAttrs) { + var cont = cAttrs.container ? + Lib.nestedProperty(trace, cAttrs.container).get() : + trace; + + if(cont) { + var isAuto = cont.zauto || cont.cauto; + var minAttr = cAttrs.min; + var maxAttr = cAttrs.max; + + if(isAuto || cont[minAttr] === undefined) { + replace(cont, minAttr); + } + if(isAuto || cont[maxAttr] === undefined) { + replace(cont, maxAttr); + } + if(cont.autocolorscale) { + replace(cont, 'colorscale'); + } + } + } + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + var _module = trace._module; + + if(_module.colorbar) { + relinkColorAtts(trace, _module.colorbar); + } + + // TODO could generalize _module.colorscale and use it here? + + if(hasColorscale(trace, 'marker.line')) { + relinkColorAtts(trace, { + container: 'marker.line', + min: 'cmin', + max: 'cmax' + }); + } + + if(hasColorscale(trace, 'line')) { + relinkColorAtts(trace, { + container: 'line', + min: 'cmin', + max: 'cmax' + }); + } + } +}; diff --git a/src/components/colorscale/default_scale.js b/src/components/colorscale/default_scale.js deleted file mode 100644 index 3cd063788c9..00000000000 --- a/src/components/colorscale/default_scale.js +++ /dev/null @@ -1,14 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scales = require('./scales'); - - -module.exports = scales.RdBu; diff --git a/src/components/colorscale/defaults.js b/src/components/colorscale/defaults.js index 459fe1bb4dc..a3ae8e97d80 100644 --- a/src/components/colorscale/defaults.js +++ b/src/components/colorscale/defaults.js @@ -6,33 +6,32 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var isNumeric = require('fast-isnumeric'); var Lib = require('../../lib'); - var hasColorbar = require('../colorbar/has_colorbar'); var colorbarDefaults = require('../colorbar/defaults'); -var isValidScale = require('./is_valid_scale'); -var flipScale = require('./flip_scale'); +var isValidScale = require('./scales').isValid; -module.exports = function colorScaleDefaults(traceIn, traceOut, layout, coerce, opts) { - var prefix = opts.prefix, - cLetter = opts.cLetter, - containerStr = prefix.slice(0, prefix.length - 1), - containerIn = prefix ? - Lib.nestedProperty(traceIn, containerStr).get() || {} : - traceIn, - containerOut = prefix ? - Lib.nestedProperty(traceOut, containerStr).get() || {} : - traceOut, - minIn = containerIn[cLetter + 'min'], - maxIn = containerIn[cLetter + 'max'], - sclIn = containerIn.colorscale; +function npMaybe(cont, prefix) { + var containerStr = prefix.slice(0, prefix.length - 1); + return prefix ? + Lib.nestedProperty(cont, containerStr).get() || {} : + cont; +} +module.exports = function colorScaleDefaults(traceIn, traceOut, layout, coerce, opts) { + var prefix = opts.prefix; + var cLetter = opts.cLetter; + var containerIn = npMaybe(traceIn, prefix); + var containerOut = npMaybe(traceOut, prefix); + var template = npMaybe(traceOut._template || {}, prefix) || {}; + + var minIn = containerIn[cLetter + 'min']; + var maxIn = containerIn[cLetter + 'max']; var validMinMax = isNumeric(minIn) && isNumeric(maxIn) && (minIn < maxIn); coerce(prefix + cLetter + 'auto', !validMinMax); coerce(prefix + cLetter + 'min'); @@ -40,19 +39,17 @@ module.exports = function colorScaleDefaults(traceIn, traceOut, layout, coerce, // handles both the trace case (autocolorscale is false by default) and // the marker and marker.line case (autocolorscale is true by default) + var sclIn = containerIn.colorscale; + var sclTemplate = template.colorscale; var autoColorscaleDflt; if(sclIn !== undefined) autoColorscaleDflt = !isValidScale(sclIn); + if(sclTemplate !== undefined) autoColorscaleDflt = !isValidScale(sclTemplate); coerce(prefix + 'autocolorscale', autoColorscaleDflt); - var sclOut = coerce(prefix + 'colorscale'); - - // reversescale is handled at the containerOut level - var reverseScale = coerce(prefix + 'reversescale'); - if(reverseScale) containerOut.colorscale = flipScale(sclOut); - // ... until Scatter.colorbar can handle marker line colorbars - if(prefix === 'marker.line.') return; + coerce(prefix + 'colorscale'); + coerce(prefix + 'reversescale'); - if(!opts.noScale) { + if(!opts.noScale && prefix !== 'marker.line.') { // handles both the trace case where the dflt is listed in attributes and // the marker case where the dflt is determined by hasColorbar var showScaleDflt; diff --git a/src/components/colorscale/extract_scale.js b/src/components/colorscale/extract_scale.js deleted file mode 100644 index 98e844bc82d..00000000000 --- a/src/components/colorscale/extract_scale.js +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -/** - * Extract colorscale into numeric domain and color range. - * - * @param {array} scl colorscale array of arrays - * @param {number} cmin minimum color value (used to clamp scale) - * @param {number} cmax maximum color value (used to clamp scale) - */ -module.exports = function extractScale(scl, cmin, cmax) { - var N = scl.length, - domain = new Array(N), - range = new Array(N); - - for(var i = 0; i < N; i++) { - var si = scl[i]; - - domain[i] = cmin + si[0] * (cmax - cmin); - range[i] = si[1]; - } - - return { - domain: domain, - range: range - }; -}; diff --git a/src/components/colorscale/flip_scale.js b/src/components/colorscale/flip_scale.js deleted file mode 100644 index e2d3585802c..00000000000 --- a/src/components/colorscale/flip_scale.js +++ /dev/null @@ -1,23 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = function flipScale(scl) { - var N = scl.length, - sclNew = new Array(N), - si; - - for(var i = N - 1, j = 0; i >= 0; i--, j++) { - si = scl[i]; - sclNew[j] = [1 - si[0], si[1]]; - } - - return sclNew; -}; diff --git a/src/components/colorscale/get_scale.js b/src/components/colorscale/get_scale.js deleted file mode 100644 index 5e8dd5d6474..00000000000 --- a/src/components/colorscale/get_scale.js +++ /dev/null @@ -1,38 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var scales = require('./scales'); -var defaultScale = require('./default_scale'); -var isValidScaleArray = require('./is_valid_scale_array'); - - -module.exports = function getScale(scl, dflt) { - if(!dflt) dflt = defaultScale; - if(!scl) return dflt; - - function parseScale() { - try { - scl = scales[scl] || JSON.parse(scl); - } - catch(e) { - scl = dflt; - } - } - - if(typeof scl === 'string') { - parseScale(); - // occasionally scl is double-JSON encoded... - if(typeof scl === 'string') parseScale(); - } - - if(!isValidScaleArray(scl)) return dflt; - return scl; -}; diff --git a/src/components/colorscale/has_colorscale.js b/src/components/colorscale/has_colorscale.js deleted file mode 100644 index 85f793a48aa..00000000000 --- a/src/components/colorscale/has_colorscale.js +++ /dev/null @@ -1,40 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = require('fast-isnumeric'); -var Lib = require('../../lib'); -var isValidScale = require('./is_valid_scale'); - -module.exports = function hasColorscale(trace, containerStr) { - var container = containerStr ? - Lib.nestedProperty(trace, containerStr).get() || {} : - trace; - var color = container.color; - - var isArrayWithOneNumber = false; - if(Lib.isArrayOrTypedArray(color)) { - for(var i = 0; i < color.length; i++) { - if(isNumeric(color[i])) { - isArrayWithOneNumber = true; - break; - } - } - } - - return ( - Lib.isPlainObject(container) && ( - isArrayWithOneNumber || - container.showscale === true || - (isNumeric(container.cmin) && isNumeric(container.cmax)) || - isValidScale(container.colorscale) || - Lib.isPlainObject(container.colorbar) - ) - ); -}; diff --git a/src/components/colorscale/helpers.js b/src/components/colorscale/helpers.js new file mode 100644 index 00000000000..676a3fb8699 --- /dev/null +++ b/src/components/colorscale/helpers.js @@ -0,0 +1,184 @@ +/** +* Copyright 2012-2018, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); +var tinycolor = require('tinycolor2'); +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Color = require('../color'); + +var isValidScale = require('./scales').isValid; + +function hasColorscale(trace, containerStr) { + var container = containerStr ? + Lib.nestedProperty(trace, containerStr).get() || {} : + trace; + var color = container.color; + + var isArrayWithOneNumber = false; + if(Lib.isArrayOrTypedArray(color)) { + for(var i = 0; i < color.length; i++) { + if(isNumeric(color[i])) { + isArrayWithOneNumber = true; + break; + } + } + } + + return ( + Lib.isPlainObject(container) && ( + isArrayWithOneNumber || + container.showscale === true || + (isNumeric(container.cmin) && isNumeric(container.cmax)) || + isValidScale(container.colorscale) || + Lib.isPlainObject(container.colorbar) + ) + ); +} + +/** + * Extract colorscale into numeric domain and color range. + * + * @param {object} cont colorscale container (e.g. trace, marker) + * - colorscale {array of arrays} + * - cmin/zmin {number} + * - cmax/zmax {number} + * - reversescale {boolean} + * @param {object} opts + * - cLetter {string} 'c' (for cmin/cmax) or 'z' (for zmin/zmax) + * + * @return {object} + * - domain {array} + * - range {array} + */ +function extractScale(cont, opts) { + var cLetter = opts.cLetter; + + var scl = cont.reversescale ? + flipScale(cont.colorscale) : + cont.colorscale; + + // minimum color value (used to clamp scale) + var cmin = cont[cLetter + 'min']; + // maximum color value (used to clamp scale) + var cmax = cont[cLetter + 'max']; + + var N = scl.length; + var domain = new Array(N); + var range = new Array(N); + + for(var i = 0; i < N; i++) { + var si = scl[i]; + domain[i] = cmin + si[0] * (cmax - cmin); + range[i] = si[1]; + } + + return { + domain: domain, + range: range + }; +} + +function flipScale(scl) { + var N = scl.length; + var sclNew = new Array(N); + + for(var i = N - 1, j = 0; i >= 0; i--, j++) { + var si = scl[i]; + sclNew[j] = [1 - si[0], si[1]]; + } + return sclNew; +} + +/** + * General colorscale function generator. + * + * @param {object} specs output of Colorscale.extractScale or precomputed domain, range. + * - domain {array} + * - range {array} + * + * @param {object} opts + * - noNumericCheck {boolean} if true, scale func bypasses numeric checks + * - returnArray {boolean} if true, scale func return 4-item array instead of color strings + * + * @return {function} + */ +function makeColorScaleFunc(specs, opts) { + opts = opts || {}; + + var domain = specs.domain, + range = specs.range, + N = range.length, + _range = new Array(N); + + for(var i = 0; i < N; i++) { + var rgba = tinycolor(range[i]).toRgb(); + _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a]; + } + + var _sclFunc = d3.scale.linear() + .domain(domain) + .range(_range) + .clamp(true); + + var noNumericCheck = opts.noNumericCheck, + returnArray = opts.returnArray, + sclFunc; + + if(noNumericCheck && returnArray) { + sclFunc = _sclFunc; + } + else if(noNumericCheck) { + sclFunc = function(v) { + return colorArray2rbga(_sclFunc(v)); + }; + } + else if(returnArray) { + sclFunc = function(v) { + if(isNumeric(v)) return _sclFunc(v); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + else { + sclFunc = function(v) { + if(isNumeric(v)) return colorArray2rbga(_sclFunc(v)); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + + // colorbar draw looks into the d3 scale closure for domain and range + + sclFunc.domain = _sclFunc.domain; + + sclFunc.range = function() { return range; }; + + return sclFunc; +} + +function colorArray2rbga(colorArray) { + var colorObj = { + r: colorArray[0], + g: colorArray[1], + b: colorArray[2], + a: colorArray[3] + }; + + return tinycolor(colorObj).toRgbString(); +} + +module.exports = { + hasColorscale: hasColorscale, + extractScale: extractScale, + flipScale: flipScale, + makeColorScaleFunc: makeColorScaleFunc +}; diff --git a/src/components/colorscale/index.js b/src/components/colorscale/index.js index d17e8f2305b..0e0b50fcd84 100644 --- a/src/components/colorscale/index.js +++ b/src/components/colorscale/index.js @@ -6,35 +6,33 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; -exports.moduleType = 'component'; - -exports.name = 'colorscale'; - -exports.scales = require('./scales'); - -exports.defaultScale = require('./default_scale'); - -exports.attributes = require('./attributes'); - -exports.layoutAttributes = require('./layout_attributes'); - -exports.supplyLayoutDefaults = require('./layout_defaults'); - -exports.handleDefaults = require('./defaults'); - -exports.calc = require('./calc'); +var scales = require('./scales'); +var helpers = require('./helpers'); -exports.hasColorscale = require('./has_colorscale'); +module.exports = { + moduleType: 'component', + name: 'colorscale', -exports.isValidScale = require('./is_valid_scale'); + attributes: require('./attributes'), + layoutAttributes: require('./layout_attributes'), -exports.getScale = require('./get_scale'); + supplyLayoutDefaults: require('./layout_defaults'), + handleDefaults: require('./defaults'), + crossTraceDefaults: require('./cross_trace_defaults'), -exports.flipScale = require('./flip_scale'); + calc: require('./calc'), -exports.extractScale = require('./extract_scale'); + // ./scales.js is required in lib/coerce.js ; + // it needs to be a seperate module to avoid circular a dependency + scales: scales.scales, + defaultScale: scales.defaultScale, + getScale: scales.get, + isValidScale: scales.isValid, -exports.makeColorScaleFunc = require('./make_color_scale_func'); + hasColorscale: helpers.hasColorscale, + flipScale: helpers.flipScale, + extractScale: helpers.extractScale, + makeColorScaleFunc: helpers.makeColorScaleFunc +}; diff --git a/src/components/colorscale/is_valid_scale.js b/src/components/colorscale/is_valid_scale.js deleted file mode 100644 index 8cc1a873f1d..00000000000 --- a/src/components/colorscale/is_valid_scale.js +++ /dev/null @@ -1,19 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var scales = require('./scales'); -var isValidScaleArray = require('./is_valid_scale_array'); - - -module.exports = function isValidScale(scl) { - if(scales[scl] !== undefined) return true; - else return isValidScaleArray(scl); -}; diff --git a/src/components/colorscale/is_valid_scale_array.js b/src/components/colorscale/is_valid_scale_array.js deleted file mode 100644 index 86e8669e6aa..00000000000 --- a/src/components/colorscale/is_valid_scale_array.js +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var tinycolor = require('tinycolor2'); - - -module.exports = function isValidScaleArray(scl) { - var highestVal = 0; - - if(!Array.isArray(scl) || scl.length < 2) return false; - - if(!scl[0] || !scl[scl.length - 1]) return false; - - if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; - - for(var i = 0; i < scl.length; i++) { - var si = scl[i]; - - if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) { - return false; - } - - highestVal = +si[0]; - } - - return true; -}; diff --git a/src/components/colorscale/layout_attributes.js b/src/components/colorscale/layout_attributes.js index 9285951850d..d59b2ba7a78 100644 --- a/src/components/colorscale/layout_attributes.js +++ b/src/components/colorscale/layout_attributes.js @@ -8,9 +8,10 @@ 'use strict'; -var scales = require('./scales'); +var scales = require('./scales').scales; var msg = 'Note that `autocolorscale` must be true for this attribute to work.'; + module.exports = { editType: 'calc', sequential: { diff --git a/src/components/colorscale/layout_defaults.js b/src/components/colorscale/layout_defaults.js index bbc12580614..caad6ceb5f9 100644 --- a/src/components/colorscale/layout_defaults.js +++ b/src/components/colorscale/layout_defaults.js @@ -6,7 +6,6 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Lib = require('../../lib'); diff --git a/src/components/colorscale/make_color_scale_func.js b/src/components/colorscale/make_color_scale_func.js deleted file mode 100644 index 50fc7758c8c..00000000000 --- a/src/components/colorscale/make_color_scale_func.js +++ /dev/null @@ -1,94 +0,0 @@ -/** -* Copyright 2012-2018, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = require('d3'); -var tinycolor = require('tinycolor2'); -var isNumeric = require('fast-isnumeric'); - -var Color = require('../color'); - -/** - * General colorscale function generator. - * - * @param {object} specs output of Colorscale.extractScale or precomputed domain, range. - * - domain {array} - * - range {array} - * - * @param {object} opts - * - noNumericCheck {boolean} if true, scale func bypasses numeric checks - * - returnArray {boolean} if true, scale func return 4-item array instead of color strings - * - * @return {function} - */ -module.exports = function makeColorScaleFunc(specs, opts) { - opts = opts || {}; - - var domain = specs.domain, - range = specs.range, - N = range.length, - _range = new Array(N); - - for(var i = 0; i < N; i++) { - var rgba = tinycolor(range[i]).toRgb(); - _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a]; - } - - var _sclFunc = d3.scale.linear() - .domain(domain) - .range(_range) - .clamp(true); - - var noNumericCheck = opts.noNumericCheck, - returnArray = opts.returnArray, - sclFunc; - - if(noNumericCheck && returnArray) { - sclFunc = _sclFunc; - } - else if(noNumericCheck) { - sclFunc = function(v) { - return colorArray2rbga(_sclFunc(v)); - }; - } - else if(returnArray) { - sclFunc = function(v) { - if(isNumeric(v)) return _sclFunc(v); - else if(tinycolor(v).isValid()) return v; - else return Color.defaultLine; - }; - } - else { - sclFunc = function(v) { - if(isNumeric(v)) return colorArray2rbga(_sclFunc(v)); - else if(tinycolor(v).isValid()) return v; - else return Color.defaultLine; - }; - } - - // colorbar draw looks into the d3 scale closure for domain and range - - sclFunc.domain = _sclFunc.domain; - - sclFunc.range = function() { return range; }; - - return sclFunc; -}; - -function colorArray2rbga(colorArray) { - var colorObj = { - r: colorArray[0], - g: colorArray[1], - b: colorArray[2], - a: colorArray[3] - }; - - return tinycolor(colorObj).toRgbString(); -} diff --git a/src/components/colorscale/scales.js b/src/components/colorscale/scales.js index ce9081c26a9..958b3c684aa 100644 --- a/src/components/colorscale/scales.js +++ b/src/components/colorscale/scales.js @@ -8,8 +8,9 @@ 'use strict'; +var tinycolor = require('tinycolor2'); -module.exports = { +var scales = { 'Greys': [ [0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)'] ], @@ -139,3 +140,63 @@ module.exports = { [0.941176, 'rgb(243,219,79)'], [1.000000, 'rgb(255,233,69)'] ] }; + +var defaultScale = scales.RdBu; + +function getScale(scl, dflt) { + if(!dflt) dflt = defaultScale; + if(!scl) return dflt; + + function parseScale() { + try { + scl = scales[scl] || JSON.parse(scl); + } catch(e) { + scl = dflt; + } + } + + if(typeof scl === 'string') { + parseScale(); + // occasionally scl is double-JSON encoded... + if(typeof scl === 'string') parseScale(); + } + + if(!isValidScaleArray(scl)) return dflt; + return scl; +} + + +function isValidScaleArray(scl) { + var highestVal = 0; + + if(!Array.isArray(scl) || scl.length < 2) return false; + + if(!scl[0] || !scl[scl.length - 1]) return false; + + if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; + + for(var i = 0; i < scl.length; i++) { + var si = scl[i]; + + if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) { + return false; + } + + highestVal = +si[0]; + } + + return true; +} + +function isValidScale(scl) { + if(scales[scl] !== undefined) return true; + else return isValidScaleArray(scl); +} + +module.exports = { + scales: scales, + defaultScale: defaultScale, + + get: getScale, + isValid: isValidScale +}; diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index fdc79a38a69..b014c3ffb87 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -643,7 +643,7 @@ drawing.tryColorscale = function(marker, prefix) { if(scl && Lib.isArrayOrTypedArray(colorArray)) { return Colorscale.makeColorScaleFunc( - Colorscale.extractScale(scl, cont.cmin, cont.cmax) + Colorscale.extractScale(cont, {cLetter: 'c'}) ); } } diff --git a/src/lib/coerce.js b/src/lib/coerce.js index 87cc1473446..0129ef40578 100644 --- a/src/lib/coerce.js +++ b/src/lib/coerce.js @@ -6,18 +6,17 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var isNumeric = require('fast-isnumeric'); var tinycolor = require('tinycolor2'); var baseTraceAttrs = require('../plots/attributes'); -var getColorscale = require('../components/colorscale/get_scale'); -var colorscaleNames = Object.keys(require('../components/colorscale/scales')); +var scales = require('../components/colorscale/scales'); +var DESELECTDIM = require('../constants/interactions').DESELECTDIM; + var nestedProperty = require('./nested_property'); var counterRegex = require('./regex').counter; -var DESELECTDIM = require('../constants/interactions').DESELECTDIM; var modHalf = require('./mod').modHalf; var isArrayOrTypedArray = require('./array').isArrayOrTypedArray; @@ -165,7 +164,7 @@ exports.valObjectMeta = { colorscale: { description: [ 'A Plotly colorscale either picked by a name:', - '(any of', colorscaleNames.join(', '), ')', + '(any of', Object.keys(scales.scales).join(', '), ')', 'customized as an {array} of 2-element {arrays} where', 'the first element is the normalized color level value', '(starting at *0* and ending at *1*),', @@ -174,7 +173,7 @@ exports.valObjectMeta = { requiredOpts: [], otherOpts: ['dflt'], coerceFunction: function(v, propOut, dflt) { - propOut.set(getColorscale(v, dflt)); + propOut.set(scales.get(v, dflt)); } }, angle: { diff --git a/src/lib/gl_format_color.js b/src/lib/gl_format_color.js index 1fe622c8443..be02153bd16 100644 --- a/src/lib/gl_format_color.js +++ b/src/lib/gl_format_color.js @@ -48,11 +48,7 @@ function formatColor(containerIn, opacityIn, len) { if(containerIn.colorscale !== undefined) { sclFunc = Colorscale.makeColorScaleFunc( - Colorscale.extractScale( - containerIn.colorscale, - containerIn.cmin, - containerIn.cmax - ) + Colorscale.extractScale(containerIn, {cLetter: 'c'}) ); } else { diff --git a/src/lib/index.js b/src/lib/index.js index 9c3d46c7841..e4652691f8b 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -644,7 +644,13 @@ lib.minExtend = function(obj1, obj2) { v = obj1[k]; if(k.charAt(0) === '_' || typeof v === 'function') continue; else if(k === 'module') objOut[k] = v; - else if(Array.isArray(v)) objOut[k] = v.slice(0, arrayLen); + else if(Array.isArray(v)) { + if(k === 'colorscale') { + objOut[k] = v.slice(); + } else { + objOut[k] = v.slice(0, arrayLen); + } + } else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); else objOut[k] = v; } diff --git a/src/plots/plots.js b/src/plots/plots.js index aa52e9e05ef..987ec881f1e 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -449,6 +449,7 @@ plots.supplyDefaults = function(gd, opts) { for(i = 0; i < crossTraceDefaultsFuncs.length; i++) { crossTraceDefaultsFuncs[i](newFullData, newFullLayout); } + Registry.getComponentMethod('colorscale', 'crossTraceDefaults')(newFullData, newFullLayout); // turn on flag to optimize large splom-only graphs // mostly by omitting SVG layers during Cartesian.drawFramework diff --git a/src/traces/bar/calc.js b/src/traces/bar/calc.js index 6c2ec1ecb19..99981267cbd 100644 --- a/src/traces/bar/calc.js +++ b/src/traces/bar/calc.js @@ -9,7 +9,7 @@ 'use strict'; var Axes = require('../../plots/cartesian/axes'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleCalc = require('../../components/colorscale/calc'); var arraysToCalcdata = require('./arrays_to_calcdata'); var calcSelection = require('../scatter/calc_selection'); diff --git a/src/traces/bar/style_defaults.js b/src/traces/bar/style_defaults.js index 84e272e26a5..2fdc2110a15 100644 --- a/src/traces/bar/style_defaults.js +++ b/src/traces/bar/style_defaults.js @@ -6,11 +6,10 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Color = require('../../components/color'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleDefaults = require('../../components/colorscale/defaults'); module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout) { diff --git a/src/traces/barpolar/calc.js b/src/traces/barpolar/calc.js index 7181fccca41..a27ef1b8062 100644 --- a/src/traces/barpolar/calc.js +++ b/src/traces/barpolar/calc.js @@ -8,7 +8,7 @@ 'use strict'; -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleCalc = require('../../components/colorscale/calc'); var arraysToCalcdata = require('../bar/arrays_to_calcdata'); var setGroupPositions = require('../bar/cross_trace_calc').setGroupPositions; diff --git a/src/traces/choropleth/style.js b/src/traces/choropleth/style.js index 6a07afa7b17..dd211817417 100644 --- a/src/traces/choropleth/style.js +++ b/src/traces/choropleth/style.js @@ -25,11 +25,7 @@ function styleTrace(gd, calcTrace) { var markerLine = marker.line || {}; var sclFunc = Colorscale.makeColorScaleFunc( - Colorscale.extractScale( - trace.colorscale, - trace.zmin, - trace.zmax - ) + Colorscale.extractScale(trace, {cLetter: 'z'}) ); locs.each(function(d) { diff --git a/src/traces/contour/make_color_map.js b/src/traces/contour/make_color_map.js index c7147f6cf94..825bf534caa 100644 --- a/src/traces/contour/make_color_map.js +++ b/src/traces/contour/make_color_map.js @@ -26,11 +26,13 @@ module.exports = function makeColorMap(trace) { nc = 1; } - var scl = trace.colorscale, - len = scl.length; + var scl = trace.reversescale ? + Colorscale.flipScale(trace.colorscale) : + trace.colorscale; - var domain = new Array(len), - range = new Array(len); + var len = scl.length; + var domain = new Array(len); + var range = new Array(len); var si, i; diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js index ef309be4f80..d282504d854 100644 --- a/src/traces/heatmap/plot.js +++ b/src/traces/heatmap/plot.js @@ -141,11 +141,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { var context = canvas.getContext('2d'); var sclFunc = Colorscale.makeColorScaleFunc( - Colorscale.extractScale( - trace.colorscale, - trace.zmin, - trace.zmax - ), + Colorscale.extractScale(trace, {cLetter: 'z'}), { noNumericCheck: true, returnArray: true } ); diff --git a/src/traces/parcats/calc.js b/src/traces/parcats/calc.js index 07ea14d3794..67d4b6c9217 100644 --- a/src/traces/parcats/calc.js +++ b/src/traces/parcats/calc.js @@ -11,7 +11,7 @@ // Requirements // ============ var wrap = require('../../lib/gup').wrap; -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleCalc = require('../../components/colorscale/calc'); var filterUnique = require('../../lib/filter_unique.js'); var Drawing = require('../../components/drawing'); diff --git a/src/traces/parcats/defaults.js b/src/traces/parcats/defaults.js index 47537f1519e..6eb290741de 100644 --- a/src/traces/parcats/defaults.js +++ b/src/traces/parcats/defaults.js @@ -9,7 +9,7 @@ 'use strict'; var Lib = require('../../lib'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleDefaults = require('../../components/colorscale/defaults'); var handleDomainDefaults = require('../../plots/domain').defaults; var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); diff --git a/src/traces/parcoords/calc.js b/src/traces/parcoords/calc.js index c9ce1f7c7a0..5411f92f892 100644 --- a/src/traces/parcoords/calc.js +++ b/src/traces/parcoords/calc.js @@ -8,7 +8,7 @@ 'use strict'; -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var calcColorscale = require('../../components/colorscale/calc'); var Lib = require('../../lib'); var wrap = require('../../lib/gup').wrap; diff --git a/src/traces/parcoords/defaults.js b/src/traces/parcoords/defaults.js index e88b9f0b188..9b05150260d 100644 --- a/src/traces/parcoords/defaults.js +++ b/src/traces/parcoords/defaults.js @@ -9,7 +9,7 @@ 'use strict'; var Lib = require('../../lib'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleDefaults = require('../../components/colorscale/defaults'); var handleDomainDefaults = require('../../plots/domain').defaults; var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); diff --git a/src/traces/parcoords/parcoords.js b/src/traces/parcoords/parcoords.js index 14874abaccf..26d2da693aa 100644 --- a/src/traces/parcoords/parcoords.js +++ b/src/traces/parcoords/parcoords.js @@ -8,16 +8,20 @@ 'use strict'; -var lineLayerMaker = require('./lines'); -var c = require('./constants'); -var Lib = require('../../lib'); var d3 = require('d3'); + +var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); +var Colorscale = require('../../components/colorscale'); + var gup = require('../../lib/gup'); var keyFun = gup.keyFun; var repeat = gup.repeat; var unwrap = gup.unwrap; + +var c = require('./constants'); var brush = require('./axisbrush'); +var lineLayerMaker = require('./lines'); function visible(dimension) { return !('visible' in dimension) || dimension.visible; } @@ -129,8 +133,8 @@ function model(layout, d, i) { var cd0 = unwrap(d), trace = cd0.trace, lineColor = cd0.lineColor, - cscale = cd0.cscale, line = trace.line, + cscale = line.reversescale ? Colorscale.flipScale(cd0.cscale) : cd0.cscale, domain = trace.domain, dimensions = trace.dimensions, width = layout.width, diff --git a/src/traces/scatter/colorscale_calc.js b/src/traces/scatter/colorscale_calc.js index 69d225eb7ae..95e1f6aa2b9 100644 --- a/src/traces/scatter/colorscale_calc.js +++ b/src/traces/scatter/colorscale_calc.js @@ -6,15 +6,13 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var calcColorscale = require('../../components/colorscale/calc'); var subTypes = require('./subtypes'); - module.exports = function calcMarkerColorscale(gd, trace) { if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) { calcColorscale(gd, trace, { diff --git a/src/traces/scatter/line_defaults.js b/src/traces/scatter/line_defaults.js index 96133ca2149..64ed677d1cd 100644 --- a/src/traces/scatter/line_defaults.js +++ b/src/traces/scatter/line_defaults.js @@ -9,7 +9,7 @@ 'use strict'; var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray; -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleDefaults = require('../../components/colorscale/defaults'); module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) { diff --git a/src/traces/scatter/marker_defaults.js b/src/traces/scatter/marker_defaults.js index e0b9cf4fd68..9af06648d25 100644 --- a/src/traces/scatter/marker_defaults.js +++ b/src/traces/scatter/marker_defaults.js @@ -6,11 +6,10 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Color = require('../../components/color'); -var hasColorscale = require('../../components/colorscale/has_colorscale'); +var hasColorscale = require('../../components/colorscale/helpers').hasColorscale; var colorscaleDefaults = require('../../components/colorscale/defaults'); var subTypes = require('./subtypes'); diff --git a/src/traces/scatter3d/calc.js b/src/traces/scatter3d/calc.js index 9f2fa358d49..af767d40fcd 100644 --- a/src/traces/scatter3d/calc.js +++ b/src/traces/scatter3d/calc.js @@ -9,8 +9,7 @@ 'use strict'; var arraysToCalcdata = require('../scatter/arrays_to_calcdata'); -var calcColorscales = require('../scatter/colorscale_calc'); - +var calcColorscale = require('../scatter/colorscale_calc'); /** * This is a kludge to put the array attributes into @@ -21,7 +20,7 @@ module.exports = function calc(gd, trace) { var cd = [{x: false, y: false, trace: trace, t: {}}]; arraysToCalcdata(cd, trace); - calcColorscales(gd, trace); + calcColorscale(gd, trace); return cd; }; diff --git a/src/traces/scattergl/index.js b/src/traces/scattergl/index.js index ae16aa7e7fb..3e5806fbcc7 100644 --- a/src/traces/scattergl/index.js +++ b/src/traces/scattergl/index.js @@ -27,7 +27,7 @@ var scatterCalc = require('../scatter/calc'); var calcMarkerSize = scatterCalc.calcMarkerSize; var calcAxisExpansion = scatterCalc.calcAxisExpansion; var setFirstScatter = scatterCalc.setFirstScatter; -var calcColorscales = require('../scatter/colorscale_calc'); +var calcColorscale = require('../scatter/colorscale_calc'); var linkTraces = require('../scatter/link_traces'); var getTraceColor = require('../scatter/get_trace_color'); var fillHoverText = require('../scatter/fill_hover_text'); @@ -84,7 +84,7 @@ function calc(gd, trace) { } // create scene options and scene - calcColorscales(gd, trace); + calcColorscale(gd, trace); var opts = sceneOptions(gd, subplot, trace, positions, x, y); var scene = sceneUpdate(gd, subplot); diff --git a/src/traces/scattermapbox/convert.js b/src/traces/scattermapbox/convert.js index 0372ecc874f..42f37e0cb9a 100644 --- a/src/traces/scattermapbox/convert.js +++ b/src/traces/scattermapbox/convert.js @@ -158,7 +158,7 @@ function makeCircleOpts(calcTrace) { if(arrayColor) { if(Colorscale.hasColorscale(trace, 'marker')) { colorFn = Colorscale.makeColorScaleFunc( - Colorscale.extractScale(marker.colorscale, marker.cmin, marker.cmax) + Colorscale.extractScale(marker, {cLetter: 'c'}) ); } else { colorFn = Lib.identity; diff --git a/src/traces/scatterpolargl/index.js b/src/traces/scatterpolargl/index.js index 630904b668c..26da774bf7d 100644 --- a/src/traces/scatterpolargl/index.js +++ b/src/traces/scatterpolargl/index.js @@ -12,7 +12,7 @@ var cluster = require('point-cluster'); var isNumeric = require('fast-isnumeric'); var ScatterGl = require('../scattergl'); -var calcColorscales = require('../scatter/colorscale_calc'); +var calcColorscale = require('../scatter/colorscale_calc'); var calcMarkerSize = require('../scatter/calc').calcMarkerSize; var convert = require('../scattergl/convert'); @@ -38,7 +38,7 @@ function calc(gd, trace) { stash.r = rArray; stash.theta = thetaArray; - calcColorscales(gd, trace); + calcColorscale(gd, trace); // only compute 'style' options in calc, as position options // depend on the radial range and must be set in plot diff --git a/src/traces/splom/index.js b/src/traces/splom/index.js index a8c8cfbeb8d..2b7d8f4679f 100644 --- a/src/traces/splom/index.js +++ b/src/traces/splom/index.js @@ -19,7 +19,7 @@ var AxisIDs = require('../../plots/cartesian/axis_ids'); var subTypes = require('../scatter/subtypes'); var calcMarkerSize = require('../scatter/calc').calcMarkerSize; var calcAxisExpansion = require('../scatter/calc').calcAxisExpansion; -var calcColorscales = require('../scatter/colorscale_calc'); +var calcColorscale = require('../scatter/colorscale_calc'); var convertMarkerSelection = require('../scattergl/convert').markerSelection; var convertMarkerStyle = require('../scattergl/convert').markerStyle; var calcHover = require('../scattergl').calcHover; @@ -80,7 +80,7 @@ function calc(gd, trace) { } } - calcColorscales(gd, trace); + calcColorscale(gd, trace); Lib.extendFlat(opts, convertMarkerStyle(trace)); var visibleLength = cdata.length; @@ -310,7 +310,7 @@ function editStyle(gd, cd0) { var scene = gd._fullLayout._splomScenes[trace.uid]; if(scene) { - calcColorscales(gd, trace); + calcColorscale(gd, trace); Lib.extendFlat(scene.matrixOptions, convertMarkerStyle(trace)); // TODO [un]selected styles? diff --git a/src/transforms/groupby.js b/src/transforms/groupby.js index 74ef3a12f8a..f10b26afd9d 100644 --- a/src/transforms/groupby.js +++ b/src/transforms/groupby.js @@ -204,9 +204,6 @@ function transformOne(trace, state) { // Start with a deep extend that just copies array references. newTrace = newData[i] = Lib.extendDeepNoArrays({}, trace); newTrace._group = groupName; - // helper function for when we need to push updates back to the input, - // outside of the normal restyle/relayout pathway, like filling in auto values - newTrace.updateStyle = styleUpdater(groupName, transformIndex); newTrace.transforms[transformIndex]._indexToPoints = {}; var suppliedName = null; @@ -283,14 +280,3 @@ function transformOne(trace, state) { return newData; } - -function styleUpdater(groupName, transformIndex) { - return function(trace, attr, value) { - Lib.keyedContainer( - trace, - 'transforms[' + transformIndex + '].styles', - 'target', - 'value.' + attr - ).set(String(groupName), value); - }; -} diff --git a/test/image/baselines/geo_bubbles-colorscales.png b/test/image/baselines/geo_bubbles-colorscales.png index ffe6a751441..6d033fc33be 100644 Binary files a/test/image/baselines/geo_bubbles-colorscales.png and b/test/image/baselines/geo_bubbles-colorscales.png differ diff --git a/test/image/baselines/gl2d_transforms.png b/test/image/baselines/gl2d_transforms.png index a73688cc03c..3b88081f8e6 100644 Binary files a/test/image/baselines/gl2d_transforms.png and b/test/image/baselines/gl2d_transforms.png differ diff --git a/test/image/baselines/gl3d_line-colorscale-with-markers.png b/test/image/baselines/gl3d_line-colorscale-with-markers.png new file mode 100644 index 00000000000..2a86c805a5e Binary files /dev/null and b/test/image/baselines/gl3d_line-colorscale-with-markers.png differ diff --git a/test/image/baselines/gl3d_scatter-colorscale-marker.png b/test/image/baselines/gl3d_scatter-colorscale-marker.png index 4a322d053ee..1447f230729 100644 Binary files a/test/image/baselines/gl3d_scatter-colorscale-marker.png and b/test/image/baselines/gl3d_scatter-colorscale-marker.png differ diff --git a/test/image/baselines/marker_colorscale_template.png b/test/image/baselines/marker_colorscale_template.png new file mode 100644 index 00000000000..a22df3b544a Binary files /dev/null and b/test/image/baselines/marker_colorscale_template.png differ diff --git a/test/image/baselines/polar_transforms.png b/test/image/baselines/polar_transforms.png index b120caaafdc..9decc6694bd 100644 Binary files a/test/image/baselines/polar_transforms.png and b/test/image/baselines/polar_transforms.png differ diff --git a/test/image/baselines/transforms.png b/test/image/baselines/transforms.png index cbeeee98609..0a536e93ea1 100644 Binary files a/test/image/baselines/transforms.png and b/test/image/baselines/transforms.png differ diff --git a/test/image/mocks/gl3d_line-colorscale-with-markers.json b/test/image/mocks/gl3d_line-colorscale-with-markers.json new file mode 100644 index 00000000000..6a164830e06 --- /dev/null +++ b/test/image/mocks/gl3d_line-colorscale-with-markers.json @@ -0,0 +1,90 @@ +{ + "data": [ + { + "type": "scatter3d", + "x": [0, 0, 0], + "y": [1, 1, 1], + "z": [1, 2, 3], + "mode": "lines+markers", + "line": { + "width": 3, + "color": [0, 1, 2] + } + }, + { + "type": "scatter3d", + "x": [0, 0, 0], + "y": [2, 2, 2], + "z": [1, 2, 3], + "mode": "lines+markers", + "line": { + "width": 3, + "color": [0, 1, 2] + }, + "marker": { + "color": [0, 1, 2] + } + }, + { + "type": "scatter3d", + "x": [0, 0, 0], + "y": [3, 3, 3], + "z": [1, 2, 3], + "mode": "lines+markers", + "marker": { + "color": [0, 1, 2] + }, + "line": { + "width": 3 + } + }, + { + "type": "scatter3d", + "x": [1, 1, 1], + "y": [0, 0, 0], + "z": [1, 2, 3], + "mode": "lines+markers", + "line": { + "width": 3, + "colorscale": "Blues", + "color": [0, 1, 2] + }, + "marker": { + "colorscale": "Blues", + "color": [0, 1, 2] + } + }, + { + "type": "scatter3d", + "x": [2, 2, 2], + "y": [0, 0, 0], + "z": [1, 2, 3], + "mode": "lines+markers", + "line": { + "width": 3, + "colorscale": "RdBu", + "color": [0, 1, 2] + }, + "marker": { + "colorscale": "RdBu", + "color": [0, 1, 2] + } + }, + { + "type": "scatter3d", + "x": [3, 3, 3], + "y": [0, 0, 0], + "z": [1, 2, 3], + "mode": "lines+markers", + "line": { + "width": 3, + "colorscale": "BuRd", + "color": [0, 1, 2] + }, + "marker": { + "colorscale": "BuRd", + "color": [0, 1, 2] + } + } + ] +} diff --git a/test/image/mocks/marker_colorscale_template.json b/test/image/mocks/marker_colorscale_template.json new file mode 100644 index 00000000000..4fa75b80c58 --- /dev/null +++ b/test/image/mocks/marker_colorscale_template.json @@ -0,0 +1,33 @@ +{ + "data": [ + { + "type": "scatter", + "y": [1, 2, 3], + "marker": { + "size": 20, + "color": [1, 2, 3], + "showscale": true + }, + "mode": "markers" + } + ], + "layout": { + "template": { + "data": { + "scatter": [ + { + "marker": { + "symbol": "square", + "colorscale": "Viridis", + "colorbar": { + "ticks": "inside", + "ticklen": 10, + "tickcolor": "white" + } + } + } + ] + } + } + } +} diff --git a/test/jasmine/tests/colorscale_test.js b/test/jasmine/tests/colorscale_test.js index 2721f5710bf..94ba6061dbd 100644 --- a/test/jasmine/tests/colorscale_test.js +++ b/test/jasmine/tests/colorscale_test.js @@ -1,9 +1,16 @@ +var Plotly = require('@lib'); + var Colorscale = require('@src/components/colorscale'); + var Lib = require('@src/lib'); var Plots = require('@src/plots/plots'); var Heatmap = require('@src/traces/heatmap'); var Scatter = require('@src/traces/scatter'); +var d3 = require('d3'); +var createGraphDiv = require('../assets/create_graph_div'); +var destroyGraphDiv = require('../assets/destroy_graph_div'); +var failTest = require('../assets/fail_test'); var supplyAllDefaults = require('../assets/supply_defaults'); function _supply(trace, layout) { @@ -406,21 +413,6 @@ describe('Test colorscale:', function() { expect(trace.colorscale).toEqual(colorscale); }); - it('should set autocolorscale to false if it wasn\'t explicitly set true in input', function() { - trace = { - type: 'heatmap', - z: [[0, -1.5], [-2, -10]], - zmin: -10, - zmax: 0, - autocolorscale: true, - _input: {} - }; - gd = _supply(trace); - calcColorscale(gd, trace, {vals: trace.z, containerStr: '', cLetter: 'z'}); - expect(trace.autocolorscale).toBe(false); - expect(trace.colorscale[5]).toEqual([1, 'rgb(220,220,220)']); - }); - it('should be Blues when the only numerical z <= -0.5', function() { trace = { type: 'heatmap', @@ -530,23 +522,6 @@ describe('Test colorscale:', function() { expect(trace.autocolorscale).toBe(true); expect(trace.colorscale).toEqual(colorscale); }); - - it('should be reverse the auto scale when reversescale is true', function() { - trace = { - type: 'heatmap', - z: [['a', 'b'], [0.5, 'd']], - autocolorscale: true, - reversescale: true, - _input: {autocolorscale: true} - }; - z = [[undefined, undefined], [0.5, undefined]]; - gd = _supply(trace); - calcColorscale(gd, trace, {vals: z, containerStr: '', cLetter: 'z'}); - expect(trace.autocolorscale).toBe(true); - expect(trace.colorscale[trace.colorscale.length - 1]) - .toEqual([1, 'rgb(220,220,220)']); - }); - }); describe('extractScale + makeColorScaleFunc', function() { @@ -559,19 +534,372 @@ describe('Test colorscale:', function() { [1, 'rgb(178,10,28)'] ]; - var specs = Colorscale.extractScale(scale, 2, 3); - var sclFunc = Colorscale.makeColorScaleFunc(specs); - it('should constrain color array values between cmin and cmax', function() { - var color1 = sclFunc(1), - color2 = sclFunc(2), - color3 = sclFunc(3), - color4 = sclFunc(4); + var trace = { + colorscale: scale, + pmin: 2, + pmax: 3 + }; + + var specs = Colorscale.extractScale(trace, {cLetter: 'p'}); + var sclFunc = Colorscale.makeColorScaleFunc(specs); + + var color1 = sclFunc(1); + var color2 = sclFunc(2); + var color3 = sclFunc(3); + var color4 = sclFunc(4); expect(color1).toEqual(color2); expect(color1).toEqual('rgb(5, 10, 172)'); expect(color3).toEqual(color4); expect(color4).toEqual('rgb(178, 10, 28)'); }); + + it('should flip color range when reversescale is true', function() { + var trace = { + colorscale: scale, + reversescale: true, + pmin: 2, + pmax: 3 + }; + + var specs = Colorscale.extractScale(trace, {cLetter: 'p'}); + var sclFunc = Colorscale.makeColorScaleFunc(specs); + + var color1 = sclFunc(1); + var color2 = sclFunc(2); + var color3 = sclFunc(3); + var color4 = sclFunc(4); + + expect(color1).toEqual(color2); + expect(color1).toEqual('rgb(178, 10, 28)'); + expect(color3).toEqual(color4); + expect(color4).toEqual('rgb(5, 10, 172)'); + }); + }); +}); + +describe('Test colorscale restyle calls:', function() { + var gd; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + function getFill(q) { + return d3.select(q).node().style.fill; + } + + it('should be able to toggle between autocolorscale true/false and set colorscales (contour case)', function(done) { + function _assert(msg, exp) { + var cc = []; + cc.push(getFill('.contourbg > path')); + d3.selectAll('.contourfill > path').each(function() { + cc.push(getFill(this)); + }); + expect(cc).toEqual(exp.contourColors); + + expect(gd._fullData[0].colorscale).toEqual(exp.colorscale); + expect(gd._fullData[0].autocolorscale).toBe(exp.autocolorscale, msg); + + expect(gd.data[0].colorscale).toEqual(exp.colorscaleIn); + expect(gd.data[0].autocolorscale).toBe(exp.autocolorscaleIn, msg); + } + + // update via, assert then assert again (and again ;) after non-calc edits + function _run(msg, restyleObj, exp) { + return Plotly.restyle(gd, restyleObj) + .then(function() { _assert(msg, exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.range', [-1, 5]); }) + .then(function() { _assert(msg + ' after axrange relayout', exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }) + .then(function() { _assert(msg + ' after autorange', exp); }) + .then(function() { return Plotly.restyle(gd, 'contours.showlines', true); }) + .then(function() { _assert(msg + ' after contours.showlines restyle', exp); }) + .then(function() { return Plotly.restyle(gd, 'contours.showlines', false); }) + .then(function() { _assert(msg + ' back to original contours.showlines', exp); }); + } + + var rdbu = ['rgb(5, 10, 172)', 'rgb(190, 190, 190)', 'rgb(178, 10, 28)']; + var reds = ['rgb(220, 220, 220)', 'rgb(234, 135, 92)', 'rgb(178, 10, 28)']; + var grns = ['rgb(0, 68, 27)', 'rgb(116, 196, 118)', 'rgb(247, 252, 245)']; + + Plotly.plot(gd, [{ + type: 'contour', + z: [ + [1, 20, 30], + [20, 1, 60], + [30, 60, 1] + ], + ncontours: 3 + }]) + .then(function() { + _assert('base (autocolorscale:false by dflt)', { + contourColors: rdbu, + autocolorscale: false, + autocolorscaleIn: undefined, + colorscale: Colorscale.scales.RdBu, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('restyle to autocolorscale:true', {autocolorscale: true}, { + contourColors: reds, + autocolorscale: true, + autocolorscaleIn: true, + colorscale: Colorscale.scales.Reds, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('restyle to reversescale:true with autocolorscale:true', {reversescale: true}, { + contourColors: reds.slice().reverse(), + autocolorscale: true, + autocolorscaleIn: true, + colorscale: Colorscale.scales.Reds, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('restyle back to autocolorscale:false with reversescale:true', {autocolorscale: false}, { + contourColors: rdbu.slice().reverse(), + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.RdBu, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('restyle to *Greens* colorscale', {colorscale: 'Greens', reversescale: false}, { + contourColors: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('restyle back again to autocolorscale:true', {autocolorscale: true}, { + contourColors: reds, + autocolorscale: true, + autocolorscaleIn: true, + colorscale: Colorscale.scales.Reds, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('restyle back to autocolorscale:false with colorscale:Greens', {autocolorscale: false}, { + contourColors: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .catch(failTest) + .then(done); + }); + + it('should be able to toggle between autocolorscale true/false and set colorscales (scatter marker case)', function(done) { + function _assert(msg, exp) { + var mcc = []; + d3.selectAll('path.point').each(function() { + mcc.push(getFill(this)); + }); + expect(mcc).toEqual(exp.mcc); + + expect(gd._fullData[0].marker.colorscale).toEqual(exp.colorscale); + expect(gd._fullData[0].marker.autocolorscale).toBe(exp.autocolorscale, msg); + + expect(gd.data[0].marker.colorscale).toEqual(exp.colorscaleIn); + expect(gd.data[0].marker.autocolorscale).toBe(exp.autocolorscaleIn, msg); + } + + // update via, assert then assert again (and again ;) after non-calc edits + function _run(msg, restyleObj, exp) { + return Plotly.restyle(gd, restyleObj) + .then(function() { _assert(msg, exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.range', [-1, 5]); }) + .then(function() { _assert(msg + ' after axrange relayout', exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }) + .then(function() { _assert(msg + ' after autorange', exp); }) + .then(function() { return Plotly.restyle(gd, 'marker.symbol', 'square'); }) + .then(function() { _assert(msg + ' after marker.symbol restyle', exp); }) + .then(function() { return Plotly.restyle(gd, 'marker.symbol', null); }) + .then(function() { _assert(msg + ' back to original marker.symbol', exp); }); + } + + var rdbu = ['rgb(5, 10, 172)', 'rgb(77, 101, 226)', 'rgb(178, 10, 28)']; + var grns = ['rgb(0, 68, 27)', 'rgb(35, 139, 69)', 'rgb(247, 252, 245)']; + + Plotly.plot(gd, [{ + mode: 'markers', + y: [1, 2, 3], + marker: {color: [-1, 0, 3]} + }]) + .then(function() { + _assert('base (autocolorscale:true by dflt)', { + mcc: rdbu, + autocolorscale: true, + autocolorscaleIn: undefined, + colorscale: Colorscale.scales.RdBu, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('set *Greens* colorscale', {'marker.colorscale': 'Greens'}, { + mcc: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('back to autocolorscale:true', {'marker.autocolorscale': true}, { + mcc: rdbu, + autocolorscale: true, + autocolorscaleIn: true, + colorscale: Colorscale.scales.RdBu, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('back to autocolorscale:false w/ colorscale set', {'marker.autocolorscale': false}, { + mcc: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .catch(failTest) + .then(done); + }); + + it('should be able to toggle between autocolorscale true/false and set colorscales (scatter marker line case)', function(done) { + var mlw0 = 5; + + function _assert(msg, exp) { + var mlcc = []; + d3.selectAll('path.point').each(function() { + mlcc.push(d3.select(this).node().style.stroke); + }); + expect(mlcc).toEqual(exp.mlcc); + + expect(gd._fullData[0].marker.line.colorscale).toEqual(exp.colorscale); + expect(gd._fullData[0].marker.line.autocolorscale).toBe(exp.autocolorscale, msg); + + expect(gd.data[0].marker.line.colorscale).toEqual(exp.colorscaleIn); + expect(gd.data[0].marker.line.autocolorscale).toBe(exp.autocolorscaleIn, msg); + } + + // update via, assert then assert again (and again ;) after non-calc edits + function _run(msg, restyleObj, exp) { + return Plotly.restyle(gd, restyleObj) + .then(function() { _assert(msg, exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.range', [-1, 5]); }) + .then(function() { _assert(msg + ' after axrange relayout', exp); }) + .then(function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }) + .then(function() { _assert(msg + ' after autorange', exp); }) + .then(function() { return Plotly.restyle(gd, 'marker.line.width', 10); }) + .then(function() { _assert(msg + ' after marker lw restyle', exp); }) + .then(function() { return Plotly.restyle(gd, 'marker.line.width', mlw0); }) + .then(function() { _assert(msg + ' back to original marker lw', exp); }); + } + + var blues = ['rgb(220, 220, 220)', 'rgb(70, 100, 245)', 'rgb(5, 10, 172)']; + var grns = ['rgb(247, 252, 245)', 'rgb(116, 196, 118)', 'rgb(0, 68, 27)']; + + Plotly.plot(gd, [{ + mode: 'markers', + y: [1, 2, 3], + marker: { + size: 20, + line: { + color: [-1, -2, -3], + width: mlw0 + } + } + }]) + .then(function() { + _assert('base (autocolorscale:true by dflt)', { + mlcc: blues, + autocolorscale: true, + autocolorscaleIn: undefined, + colorscale: Colorscale.scales.Blues, + colorscaleIn: undefined + }); + }) + .then(function() { + return _run('set *Greens* colorscale', {'marker.line.colorscale': 'Greens'}, { + mlcc: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('back to autocolorscale:true', {'marker.line.autocolorscale': true}, { + mlcc: blues, + autocolorscale: true, + autocolorscaleIn: true, + colorscale: Colorscale.scales.Blues, + colorscaleIn: 'Greens' + }); + }) + .then(function() { + return _run('back to autocolorscale:false w/ colorscale set', {'marker.line.autocolorscale': false}, { + mlcc: grns, + autocolorscale: false, + autocolorscaleIn: false, + colorscale: Colorscale.scales.Greens, + colorscaleIn: 'Greens' + }); + }) + .catch(failTest) + .then(done); + }); + + it('should work with templates', function(done) { + function _assert(msg, exp) { + var mcc = []; + d3.selectAll('path.point').each(function() { + mcc.push(getFill(this)); + }); + + expect(mcc).toEqual(exp.mcc); + } + + var template = { + data: { + scatter: [{ + marker: {colorscale: 'Viridis'} + }] + } + }; + + Plotly.plot(gd, [{ + y: [1, 2, 3], + marker: {color: [1, 2, 3]} + }]) + .then(function() { + _assert('base - no templates', { + mcc: ['rgb(220, 220, 220)', 'rgb(234, 135, 92)', 'rgb(178, 10, 28)'] + }); + }) + .then(function() { + return Plotly.relayout(gd, 'template', template); + }) + .then(function() { + _assert('after relayouting in template', { + mcc: ['rgb(68, 1, 84)', 'rgb(33, 145, 140)', 'rgb(253, 231, 37)'] + }); + }) + .catch(failTest) + .then(done); }); }); diff --git a/test/jasmine/tests/contour_test.js b/test/jasmine/tests/contour_test.js index af831c2cb83..51d2de7add3 100644 --- a/test/jasmine/tests/contour_test.js +++ b/test/jasmine/tests/contour_test.js @@ -6,7 +6,7 @@ var Lib = require('@src/lib'); var Contour = require('@src/traces/contour'); var makeColorMap = require('@src/traces/contour/make_color_map'); -var colorScales = require('@src/components/colorscale/scales'); +var colorScales = require('@src/components/colorscale/scales').scales; var failTest = require('../assets/fail_test'); var createGraphDiv = require('../assets/create_graph_div'); @@ -309,14 +309,7 @@ describe('contour calc', function() { ['start', 'end', 'size'].forEach(function(attr) { expect(out.contours[attr]).toBe(spec[attr], [contoursIn, spec.inputNcontours, attr]); - // all these get copied back to the input trace - expect(out._input.contours[attr]).toBe(spec[attr], [contoursIn, spec.inputNcontours, attr]); }); - - expect(out._input.autocontour).toBe(true); - expect(out._input.zauto).toBe(true); - expect(out._input.zmin).toBe(0); - expect(out._input.zmax).toBe(5); }); }); }); diff --git a/test/jasmine/tests/mesh3d_test.js b/test/jasmine/tests/mesh3d_test.js index 2375061f915..e268057caaf 100644 --- a/test/jasmine/tests/mesh3d_test.js +++ b/test/jasmine/tests/mesh3d_test.js @@ -14,11 +14,11 @@ describe('Test mesh3d restyle', function() { var fullTrace = gd._fullData[0]; expect(trace.cauto).toBe(user[0], 'user cauto'); - expect(trace.cmin).toEqual(user[1], 'user cmin'); - expect(trace.cmax).toEqual(user[2], 'user cmax'); + expect(trace.cmin).toBe(user[1], 'user cmin'); + expect(trace.cmax).toBe(user[2], 'user cmax'); expect(fullTrace.cauto).toBe(full[0], 'full cauto'); - expect(fullTrace.cmin).toEqual(full[1], 'full cmin'); - expect(fullTrace.cmax).toEqual(full[2], 'full cmax'); + expect(fullTrace.cmin).toBe(full[1], 'full cmin'); + expect(fullTrace.cmax).toBe(full[2], 'full cmax'); } Plotly.plot(gd, [{ @@ -32,12 +32,12 @@ describe('Test mesh3d restyle', function() { intensity: [0, 0.33, 0.66, 3] }]) .then(function() { - _assert([true, 0, 3], [true, 0, 3]); + _assert([undefined, undefined, undefined], [true, 0, 3]); return Plotly.restyle(gd, 'cmin', 0); }) .then(function() { - _assert([false, 0, 3], [false, 0, 3]); + _assert([false, 0, undefined], [false, 0, 3]); return Plotly.restyle(gd, 'cmax', 10); }) @@ -47,7 +47,7 @@ describe('Test mesh3d restyle', function() { return Plotly.restyle(gd, 'cauto', true); }) .then(function() { - _assert([true, 0, 3], [true, 0, 3]); + _assert([true, 0, 10], [true, 0, 3]); return Plotly.purge(gd); }) diff --git a/test/jasmine/tests/parcoords_test.js b/test/jasmine/tests/parcoords_test.js index 3a8313c1d65..d70ed46ab6a 100644 --- a/test/jasmine/tests/parcoords_test.js +++ b/test/jasmine/tests/parcoords_test.js @@ -284,6 +284,8 @@ describe('parcoords initialization tests', function() { cauto: true, cmin: 21, cmax: 63, + _cmin: 21, + _cmax: 63, autocolorscale: false, reversescale: false, showscale: false diff --git a/test/jasmine/tests/plot_api_test.js b/test/jasmine/tests/plot_api_test.js index 5d12e336e34..c42f9f62cf2 100644 --- a/test/jasmine/tests/plot_api_test.js +++ b/test/jasmine/tests/plot_api_test.js @@ -1052,18 +1052,17 @@ describe('Test plot api', function() { it('should redo auto z/contour when editing z array', function(done) { Plotly.plot(gd, [{type: 'contour', z: [[1, 2], [3, 4]]}]).then(function() { - expect(gd.data[0].zauto).toBe(true, gd.data[0]); - expect(gd.data[0].zmin).toBe(1); - expect(gd.data[0].zmax).toBe(4); - + expect(gd._fullData[0].zauto).toBe(true); + expect(gd._fullData[0].zmin).toBe(1); + expect(gd._fullData[0].zmax).toBe(4); expect(gd.data[0].autocontour).toBe(true); expect(gd.data[0].contours).toEqual({start: 1.5, end: 3.5, size: 0.5}); return Plotly.restyle(gd, {'z[0][0]': 10}); }).then(function() { - expect(gd.data[0].zmin).toBe(2); - expect(gd.data[0].zmax).toBe(10); - + expect(gd._fullData[0].zauto).toBe(true); + expect(gd._fullData[0].zmin).toBe(2); + expect(gd._fullData[0].zmax).toBe(10); expect(gd.data[0].contours).toEqual({start: 3, end: 9, size: 1}); }) .catch(failTest) @@ -1111,10 +1110,10 @@ describe('Test plot api', function() { var zmax1 = 10; function check(auto, msg) { - expect(gd.data[0].zmin).negateIf(auto).toBe(zmin0, msg); - expect(gd.data[0].zauto).toBe(auto, msg); - expect(gd.data[1].zmax).negateIf(auto).toBe(zmax1, msg); - expect(gd.data[1].zauto).toBe(auto, msg); + expect(gd._fullData[0].zmin).negateIf(auto).toBe(zmin0, msg); + expect(gd._fullData[0].zauto).toBe(auto, msg); + expect(gd._fullData[1].zmax).negateIf(auto).toBe(zmax1, msg); + expect(gd._fullData[1].zauto).toBe(auto, msg); } Plotly.plot(gd, [ @@ -1144,22 +1143,24 @@ describe('Test plot api', function() { }); it('turns off cauto (autocolorscale) when you edit cmin or cmax (colorscale)', function(done) { - var autocscale = require('@src/components/colorscale/scales').Reds; + var scales = require('@src/components/colorscale/scales').scales; + var autocscale = scales.Reds; + var mcscl0 = 'Rainbow'; + var mlcscl1 = 'Greens'; var mcmin0 = 3; - var mcscl0 = 'rainbow'; var mlcmax1 = 6; - var mlcscl1 = 'greens'; function check(auto, autocolorscale, msg) { - expect(gd.data[0].marker.cauto).toBe(auto, msg); - expect(gd.data[0].marker.cmin).negateIf(auto).toBe(mcmin0); + expect(gd._fullData[0].marker.cauto).toBe(auto, msg); + expect(gd._fullData[0].marker.cmin).negateIf(auto).toBe(mcmin0); expect(gd._fullData[0].marker.autocolorscale).toBe(autocolorscale, msg); - expect(gd.data[0].marker.colorscale).toEqual(auto ? autocscale : mcscl0); - expect(gd.data[1].marker.line.cauto).toBe(auto, msg); - expect(gd.data[1].marker.line.cmax).negateIf(auto).toBe(mlcmax1); + expect(gd._fullData[0].marker.colorscale).toEqual(auto ? autocscale : scales[mcscl0]); + + expect(gd._fullData[1].marker.line.cauto).toBe(auto, msg); + expect(gd._fullData[1].marker.line.cmax).negateIf(auto).toBe(mlcmax1); expect(gd._fullData[1].marker.line.autocolorscale).toBe(autocolorscale, msg); - expect(gd.data[1].marker.line.colorscale).toEqual(auto ? autocscale : mlcscl1); + expect(gd._fullData[1].marker.line.colorscale).toEqual(auto ? autocscale : scales[mlcscl1]); } Plotly.plot(gd, [ @@ -1167,9 +1168,7 @@ describe('Test plot api', function() { {y: [2, 1], mode: 'markers', marker: {line: {width: 2, color: [3, 4]}}} ]) .then(function() { - // autocolorscale is actually true after supplyDefaults, but during calc it's set - // to false when we push the resulting colorscale back to the input container - check(true, false, 'initial'); + check(true, true, 'initial'); return Plotly.restyle(gd, {'marker.cmin': mcmin0, 'marker.colorscale': mcscl0}, null, [0]); }) .then(function() {