diff --git a/src/plots/ternary/index.js b/src/plots/ternary/index.js index fa5a265cb01..fd119f5f336 100644 --- a/src/plots/ternary/index.js +++ b/src/plots/ternary/index.js @@ -17,17 +17,29 @@ var TERNARY = 'ternary'; exports.name = TERNARY; -exports.attr = 'subplot'; +var attr = exports.attr = 'subplot'; exports.idRoot = TERNARY; exports.idRegex = exports.attrRegex = counterRegex(TERNARY); -exports.attributes = require('./layout/attributes'); +var attributes = exports.attributes = {}; +attributes[attr] = { + valType: 'subplotid', + role: 'info', + dflt: 'ternary', + editType: 'calc', + description: [ + 'Sets a reference between this trace\'s data coordinates and', + 'a ternary subplot.', + 'If *ternary* (the default value), the data refer to `layout.ternary`.', + 'If *ternary2*, the data refer to `layout.ternary2`, and so on.' + ].join(' ') +}; -exports.layoutAttributes = require('./layout/layout_attributes'); +exports.layoutAttributes = require('./layout_attributes'); -exports.supplyLayoutDefaults = require('./layout/defaults'); +exports.supplyLayoutDefaults = require('./layout_defaults'); exports.plot = function plotTernary(gd) { var fullLayout = gd._fullLayout; diff --git a/src/plots/ternary/layout/attributes.js b/src/plots/ternary/layout/attributes.js deleted file mode 100644 index 585b109cb10..00000000000 --- a/src/plots/ternary/layout/attributes.js +++ /dev/null @@ -1,25 +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 = { - subplot: { - valType: 'subplotid', - role: 'info', - dflt: 'ternary', - editType: 'calc', - description: [ - 'Sets a reference between this trace\'s data coordinates and', - 'a ternary subplot.', - 'If *ternary* (the default value), the data refer to `layout.ternary`.', - 'If *ternary2*, the data refer to `layout.ternary2`, and so on.' - ].join(' ') - } -}; diff --git a/src/plots/ternary/layout/axis_defaults.js b/src/plots/ternary/layout/axis_defaults.js deleted file mode 100644 index aa4f984c22a..00000000000 --- a/src/plots/ternary/layout/axis_defaults.js +++ /dev/null @@ -1,76 +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 Lib = require('../../../lib'); -var layoutAttributes = require('./axis_attributes'); -var handleTickLabelDefaults = require('../../cartesian/tick_label_defaults'); -var handleTickMarkDefaults = require('../../cartesian/tick_mark_defaults'); -var handleTickValueDefaults = require('../../cartesian/tick_value_defaults'); -var handleLineGridDefaults = require('../../cartesian/line_grid_defaults'); - -module.exports = function supplyLayoutDefaults(containerIn, containerOut, options) { - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, layoutAttributes, attr, dflt); - } - - containerOut.type = 'linear'; // no other types allowed for ternary - - var dfltColor = coerce('color'); - // if axis.color was provided, use it for fonts too; otherwise, - // inherit from global font color in case that was provided. - var dfltFontColor = (dfltColor !== layoutAttributes.color.dflt) ? dfltColor : options.font.color; - - var axName = containerOut._name, - letterUpper = axName.charAt(0).toUpperCase(), - dfltTitle = 'Component ' + letterUpper; - - var title = coerce('title', dfltTitle); - containerOut._hovertitle = title === dfltTitle ? title : letterUpper; - - Lib.coerceFont(coerce, 'titlefont', { - family: options.font.family, - size: Math.round(options.font.size * 1.2), - color: dfltFontColor - }); - - // range is just set by 'min' - max is determined by the other axes mins - coerce('min'); - - handleTickValueDefaults(containerIn, containerOut, coerce, 'linear'); - handleTickLabelDefaults(containerIn, containerOut, coerce, 'linear', {}); - handleTickMarkDefaults(containerIn, containerOut, coerce, - { outerTicks: true }); - - var showTickLabels = coerce('showticklabels'); - if(showTickLabels) { - Lib.coerceFont(coerce, 'tickfont', { - family: options.font.family, - size: options.font.size, - color: dfltFontColor - }); - coerce('tickangle'); - coerce('tickformat'); - } - - handleLineGridDefaults(containerIn, containerOut, coerce, { - dfltColor: dfltColor, - bgColor: options.bgColor, - // default grid color is darker here (60%, vs cartesian default ~91%) - // because the grid is not square so the eye needs heavier cues to follow - blend: 60, - showLine: true, - showGrid: true, - noZeroLine: true, - attributes: layoutAttributes - }); - - coerce('hoverformat'); - coerce('layer'); -}; diff --git a/src/plots/ternary/layout/defaults.js b/src/plots/ternary/layout/defaults.js deleted file mode 100644 index 12bcdf22499..00000000000 --- a/src/plots/ternary/layout/defaults.js +++ /dev/null @@ -1,63 +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 Color = require('../../../components/color'); -var Template = require('../../../plot_api/plot_template'); - -var handleSubplotDefaults = require('../../subplot_defaults'); -var layoutAttributes = require('./layout_attributes'); -var handleAxisDefaults = require('./axis_defaults'); - -var axesNames = ['aaxis', 'baxis', 'caxis']; - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: 'ternary', - attributes: layoutAttributes, - handleDefaults: handleTernaryDefaults, - font: layoutOut.font, - paper_bgcolor: layoutOut.paper_bgcolor - }); -}; - -function handleTernaryDefaults(ternaryLayoutIn, ternaryLayoutOut, coerce, options) { - var bgColor = coerce('bgcolor'); - var sum = coerce('sum'); - options.bgColor = Color.combine(bgColor, options.paper_bgcolor); - var axName, containerIn, containerOut; - - // TODO: allow most (if not all) axis attributes to be set - // in the outer container and used as defaults in the individual axes? - - for(var j = 0; j < axesNames.length; j++) { - axName = axesNames[j]; - containerIn = ternaryLayoutIn[axName] || {}; - containerOut = Template.newContainer(ternaryLayoutOut, axName); - containerOut._name = axName; - - handleAxisDefaults(containerIn, containerOut, options); - } - - // if the min values contradict each other, set them all to default (0) - // and delete *all* the inputs so the user doesn't get confused later by - // changing one and having them all change. - var aaxis = ternaryLayoutOut.aaxis, - baxis = ternaryLayoutOut.baxis, - caxis = ternaryLayoutOut.caxis; - if(aaxis.min + baxis.min + caxis.min >= sum) { - aaxis.min = 0; - baxis.min = 0; - caxis.min = 0; - if(ternaryLayoutIn.aaxis) delete ternaryLayoutIn.aaxis.min; - if(ternaryLayoutIn.baxis) delete ternaryLayoutIn.baxis.min; - if(ternaryLayoutIn.caxis) delete ternaryLayoutIn.caxis.min; - } -} diff --git a/src/plots/ternary/layout/layout_attributes.js b/src/plots/ternary/layout/layout_attributes.js deleted file mode 100644 index 77c06326974..00000000000 --- a/src/plots/ternary/layout/layout_attributes.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 colorAttrs = require('../../../components/color/attributes'); -var domainAttrs = require('../../domain').attributes; -var ternaryAxesAttrs = require('./axis_attributes'); -var overrideAll = require('../../../plot_api/edit_types').overrideAll; - -module.exports = overrideAll({ - domain: domainAttrs({name: 'ternary'}), - - bgcolor: { - valType: 'color', - role: 'style', - dflt: colorAttrs.background, - description: 'Set the background color of the subplot' - }, - sum: { - valType: 'number', - role: 'info', - dflt: 1, - min: 0, - description: [ - 'The number each triplet should sum to,', - 'and the maximum range of each axis' - ].join(' ') - }, - aaxis: ternaryAxesAttrs, - baxis: ternaryAxesAttrs, - caxis: ternaryAxesAttrs -}, 'plot', 'from-root'); diff --git a/src/plots/ternary/layout/axis_attributes.js b/src/plots/ternary/layout_attributes.js similarity index 67% rename from src/plots/ternary/layout/axis_attributes.js rename to src/plots/ternary/layout_attributes.js index 2ed0bcc74e2..72397f0f876 100644 --- a/src/plots/ternary/layout/axis_attributes.js +++ b/src/plots/ternary/layout_attributes.js @@ -8,12 +8,14 @@ 'use strict'; +var colorAttrs = require('../../components/color/attributes'); +var domainAttrs = require('../domain').attributes; +var axesAttrs = require('../cartesian/layout_attributes'); -var axesAttrs = require('../../cartesian/layout_attributes'); -var extendFlat = require('../../../lib/extend').extendFlat; +var overrideAll = require('../../plot_api/edit_types').overrideAll; +var extendFlat = require('../../lib/extend').extendFlat; - -module.exports = { +var ternaryAxesAttrs = { title: axesAttrs.title, titlefont: axesAttrs.titlefont, color: axesAttrs.color, @@ -63,3 +65,27 @@ module.exports = { ].join(' ') } }; + +module.exports = overrideAll({ + domain: domainAttrs({name: 'ternary'}), + + bgcolor: { + valType: 'color', + role: 'style', + dflt: colorAttrs.background, + description: 'Set the background color of the subplot' + }, + sum: { + valType: 'number', + role: 'info', + dflt: 1, + min: 0, + description: [ + 'The number each triplet should sum to,', + 'and the maximum range of each axis' + ].join(' ') + }, + aaxis: ternaryAxesAttrs, + baxis: ternaryAxesAttrs, + caxis: ternaryAxesAttrs +}, 'plot', 'from-root'); diff --git a/src/plots/ternary/layout_defaults.js b/src/plots/ternary/layout_defaults.js new file mode 100644 index 00000000000..7952a4559a5 --- /dev/null +++ b/src/plots/ternary/layout_defaults.js @@ -0,0 +1,128 @@ +/** +* 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 Color = require('../../components/color'); +var Template = require('../../plot_api/plot_template'); +var Lib = require('../../lib'); + +var handleSubplotDefaults = require('../subplot_defaults'); +var handleTickLabelDefaults = require('../cartesian/tick_label_defaults'); +var handleTickMarkDefaults = require('../cartesian/tick_mark_defaults'); +var handleTickValueDefaults = require('../cartesian/tick_value_defaults'); +var handleLineGridDefaults = require('../cartesian/line_grid_defaults'); +var layoutAttributes = require('./layout_attributes'); + +var axesNames = ['aaxis', 'baxis', 'caxis']; + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'ternary', + attributes: layoutAttributes, + handleDefaults: handleTernaryDefaults, + font: layoutOut.font, + paper_bgcolor: layoutOut.paper_bgcolor + }); +}; + +function handleTernaryDefaults(ternaryLayoutIn, ternaryLayoutOut, coerce, options) { + var bgColor = coerce('bgcolor'); + var sum = coerce('sum'); + options.bgColor = Color.combine(bgColor, options.paper_bgcolor); + var axName, containerIn, containerOut; + + // TODO: allow most (if not all) axis attributes to be set + // in the outer container and used as defaults in the individual axes? + + for(var j = 0; j < axesNames.length; j++) { + axName = axesNames[j]; + containerIn = ternaryLayoutIn[axName] || {}; + containerOut = Template.newContainer(ternaryLayoutOut, axName); + containerOut._name = axName; + + handleAxisDefaults(containerIn, containerOut, options); + } + + // if the min values contradict each other, set them all to default (0) + // and delete *all* the inputs so the user doesn't get confused later by + // changing one and having them all change. + var aaxis = ternaryLayoutOut.aaxis, + baxis = ternaryLayoutOut.baxis, + caxis = ternaryLayoutOut.caxis; + if(aaxis.min + baxis.min + caxis.min >= sum) { + aaxis.min = 0; + baxis.min = 0; + caxis.min = 0; + if(ternaryLayoutIn.aaxis) delete ternaryLayoutIn.aaxis.min; + if(ternaryLayoutIn.baxis) delete ternaryLayoutIn.baxis.min; + if(ternaryLayoutIn.caxis) delete ternaryLayoutIn.caxis.min; + } +} + +function handleAxisDefaults(containerIn, containerOut, options) { + var axAttrs = layoutAttributes[containerOut._name]; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, axAttrs, attr, dflt); + } + + containerOut.type = 'linear'; // no other types allowed for ternary + + var dfltColor = coerce('color'); + // if axis.color was provided, use it for fonts too; otherwise, + // inherit from global font color in case that was provided. + var dfltFontColor = (dfltColor !== axAttrs.color.dflt) ? dfltColor : options.font.color; + + var axName = containerOut._name, + letterUpper = axName.charAt(0).toUpperCase(), + dfltTitle = 'Component ' + letterUpper; + + var title = coerce('title', dfltTitle); + containerOut._hovertitle = title === dfltTitle ? title : letterUpper; + + Lib.coerceFont(coerce, 'titlefont', { + family: options.font.family, + size: Math.round(options.font.size * 1.2), + color: dfltFontColor + }); + + // range is just set by 'min' - max is determined by the other axes mins + coerce('min'); + + handleTickValueDefaults(containerIn, containerOut, coerce, 'linear'); + handleTickLabelDefaults(containerIn, containerOut, coerce, 'linear', {}); + handleTickMarkDefaults(containerIn, containerOut, coerce, + { outerTicks: true }); + + var showTickLabels = coerce('showticklabels'); + if(showTickLabels) { + Lib.coerceFont(coerce, 'tickfont', { + family: options.font.family, + size: options.font.size, + color: dfltFontColor + }); + coerce('tickangle'); + coerce('tickformat'); + } + + handleLineGridDefaults(containerIn, containerOut, coerce, { + dfltColor: dfltColor, + bgColor: options.bgColor, + // default grid color is darker here (60%, vs cartesian default ~91%) + // because the grid is not square so the eye needs heavier cues to follow + blend: 60, + showLine: true, + showGrid: true, + noZeroLine: true, + attributes: axAttrs + }); + + coerce('hoverformat'); + coerce('layer'); +} diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js index 8d0cfd9cc41..a4ec4a7427c 100644 --- a/src/plots/ternary/ternary.js +++ b/src/plots/ternary/ternary.js @@ -34,6 +34,12 @@ function Ternary(options, fullLayout) { this.graphDiv = options.graphDiv; this.init(fullLayout); this.makeFramework(fullLayout); + + // unfortunately, we have to keep track of some axis tick settings + // as ternary subplots do not implement the 'ticks' editType + this.aTickLayout = null; + this.bTickLayout = null; + this.cTickLayout = null; } module.exports = Ternary; @@ -254,6 +260,8 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { domain: [yDomain0, yDomain0 + yDomainFinal * w_over_h], _axislayer: _this.layers.aaxis, _gridlayer: _this.layers.agrid, + anchor: 'free', + position: 0, _pos: 0, // _this.xaxis.domain[0] * graphSize.w, _id: 'y', _length: w, @@ -274,6 +282,8 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { _axislayer: _this.layers.baxis, _gridlayer: _this.layers.bgrid, _counteraxis: _this.aaxis, + anchor: 'free', + position: 0, _pos: 0, // (1 - yDomain0) * graphSize.h, _id: 'x', _length: w, @@ -296,6 +306,8 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { _axislayer: _this.layers.caxis, _gridlayer: _this.layers.cgrid, _counteraxis: _this.baxis, + anchor: 'free', + position: 0, _pos: 0, // _this.xaxis.domain[1] * graphSize.w, _id: 'y', _length: w, @@ -369,12 +381,33 @@ proto.adjustLayout = function(ternaryLayout, graphSize) { }; proto.drawAxes = function(doTitles) { - var _this = this, - gd = _this.graphDiv, - titlesuffix = _this.id.substr(7) + 'title', - aaxis = _this.aaxis, - baxis = _this.baxis, - caxis = _this.caxis; + var _this = this; + var gd = _this.graphDiv; + var titlesuffix = _this.id.substr(7) + 'title'; + var layers = _this.layers; + var aaxis = _this.aaxis; + var baxis = _this.baxis; + var caxis = _this.caxis; + var newTickLayout; + + newTickLayout = strTickLayout(aaxis); + if(_this.aTickLayout !== newTickLayout) { + layers.aaxis.selectAll('.ytick').remove(); + _this.aTickLayout = newTickLayout; + } + + newTickLayout = strTickLayout(baxis); + if(_this.bTickLayout !== newTickLayout) { + layers.baxis.selectAll('.xtick').remove(); + _this.bTickLayout = newTickLayout; + } + + newTickLayout = strTickLayout(caxis); + if(_this.cTickLayout !== newTickLayout) { + layers.caxis.selectAll('.ytick').remove(); + _this.cTickLayout = newTickLayout; + } + // 3rd arg true below skips titles, so we can configure them // correctly later on. Axes.doTicksSingle(gd, aaxis, true); @@ -424,6 +457,11 @@ proto.drawAxes = function(doTitles) { } }; +function strTickLayout(axLayout) { + return axLayout.ticks + String(axLayout.ticklen) + String(axLayout.showticklabels); +} + + // hard coded paths for zoom corners // uses the same sizing as cartesian, length is MINZOOM/2, width is 3px var CLEN = constants.MINZOOM / 2 + 0.87; diff --git a/test/image/baselines/ternary_noticks.png b/test/image/baselines/ternary_noticks.png new file mode 100644 index 00000000000..e643f587845 Binary files /dev/null and b/test/image/baselines/ternary_noticks.png differ diff --git a/test/image/mocks/ternary_noticks.json b/test/image/mocks/ternary_noticks.json new file mode 100644 index 00000000000..bb0f110a3ab --- /dev/null +++ b/test/image/mocks/ternary_noticks.json @@ -0,0 +1,31 @@ +{ + "data": [ + { + "a": [2, 1, 1], + "b": [1, 2, 1], + "c": [1, 1, 2.12345], + "type": "scatterternary" + } + ], + "layout": { + "ternary": { + "aaxis": { + "showticklabels": false, + "showline": false, + "title": "no labels / no line" + }, + "baxis": { + "ticks": "", + "showticklabels": false, + "title": "no ticks / no labels" + }, + "caxis": { + "showticklabels": false, + "showgrid": false, + "title": "no grid / no labels" + } + }, + "height": 450, + "width": 700 + } +} diff --git a/test/jasmine/tests/polar_test.js b/test/jasmine/tests/polar_test.js index f241d155088..84565b145d7 100644 --- a/test/jasmine/tests/polar_test.js +++ b/test/jasmine/tests/polar_test.js @@ -381,75 +381,62 @@ describe('Test relayout on polar subplots:', function() { } function toggle(astr, vals, exps, selector, fn) { - return Plotly.relayout(gd, astr, vals[0]).then(function() { - fn(selector, exps[0], astr + ' ' + vals[0]); - return Plotly.relayout(gd, astr, vals[1]); - }) - .then(function() { - fn(selector, exps[1], astr + ' ' + vals[1]); - return Plotly.relayout(gd, astr, vals[0]); - }) - .then(function() { - fn(selector, exps[0], astr + ' ' + vals[0]); - }); + return function() { + return Plotly.relayout(gd, astr, vals[0]).then(function() { + fn(selector, exps[0], astr + ' ' + vals[0]); + return Plotly.relayout(gd, astr, vals[1]); + }) + .then(function() { + fn(selector, exps[1], astr + ' ' + vals[1]); + return Plotly.relayout(gd, astr, vals[0]); + }) + .then(function() { + fn(selector, exps[0], astr + ' ' + vals[0]); + }); + }; } - Plotly.plot(gd, fig).then(function() { - return toggle( - 'polar.radialaxis.showline', - [true, false], [null, 'none'], - '.radial-line > line', assertDisplay - ); - }) - .then(function() { - return toggle( - 'polar.radialaxis.showgrid', - [true, false], [null, 'none'], - '.radial-grid', assertDisplay - ); - }) - .then(function() { - return toggle( - 'polar.radialaxis.showticklabels', - [true, false], [6, 0], - '.radial-axis > .xtick > text', assertCnt - ); - }) - .then(function() { - return toggle( - 'polar.radialaxis.ticks', - ['outside', ''], [6, 0], - '.radial-axis > path.xtick', assertCnt - ); - }) - .then(function() { - return toggle( - 'polar.angularaxis.showline', - [true, false], [null, 'none'], - '.angular-line > path', assertDisplay - ); - }) - .then(function() { - return toggle( - 'polar.angularaxis.showgrid', - [true, false], [8, 0], - '.angular-grid > .angularaxis > path', assertCnt - ); - }) - .then(function() { - return toggle( - 'polar.angularaxis.showticklabels', - [true, false], [8, 0], - '.angular-axis > .angularaxistick > text', assertCnt - ); - }) - .then(function() { - return toggle( - 'polar.angularaxis.ticks', - ['outside', ''], [8, 0], - '.angular-axis > path.angularaxistick', assertCnt - ); - }) + Plotly.plot(gd, fig) + .then(toggle( + 'polar.radialaxis.showline', + [true, false], [null, 'none'], + '.radial-line > line', assertDisplay + )) + .then(toggle( + 'polar.radialaxis.showgrid', + [true, false], [null, 'none'], + '.radial-grid', assertDisplay + )) + .then(toggle( + 'polar.radialaxis.showticklabels', + [true, false], [6, 0], + '.radial-axis > .xtick > text', assertCnt + )) + .then(toggle( + 'polar.radialaxis.ticks', + ['outside', ''], [6, 0], + '.radial-axis > path.xtick', assertCnt + )) + .then(toggle( + 'polar.angularaxis.showline', + [true, false], [null, 'none'], + '.angular-line > path', assertDisplay + )) + .then(toggle( + 'polar.angularaxis.showgrid', + [true, false], [8, 0], + '.angular-grid > .angularaxis > path', assertCnt + )) + .then(toggle( + 'polar.angularaxis.showticklabels', + [true, false], [8, 0], + '.angular-axis > .angularaxistick > text', assertCnt + )) + .then(toggle( + 'polar.angularaxis.ticks', + ['outside', ''], [8, 0], + '.angular-axis > path.angularaxistick', assertCnt + )) .catch(failTest) .then(done); }); diff --git a/test/jasmine/tests/ternary_test.js b/test/jasmine/tests/ternary_test.js index 8bd9847049a..f202749ed3b 100644 --- a/test/jasmine/tests/ternary_test.js +++ b/test/jasmine/tests/ternary_test.js @@ -1,7 +1,7 @@ var Plotly = require('@lib'); var Lib = require('@src/lib'); -var supplyLayoutDefaults = require('@src/plots/ternary/layout/defaults'); +var supplyLayoutDefaults = require('@src/plots/ternary/layout_defaults'); var d3 = require('d3'); var createGraphDiv = require('../assets/create_graph_div'); @@ -382,6 +382,60 @@ describe('ternary plots', function() { .then(done); }); + it('should be able to hide/show ticks and tick labels', function(done) { + var gd = createGraphDiv(); + var fig = Lib.extendDeep({}, require('@mocks/ternary_simple.json')); + + function assertCnt(selector, expected, msg) { + var sel = d3.select(gd).selectAll(selector); + expect(sel.size()).toBe(expected, msg); + } + + function toggle(selector, astr, vals, exps) { + return function() { + return Plotly.relayout(gd, astr, vals[0]).then(function() { + assertCnt(selector, exps[0], astr + ' ' + vals[0]); + return Plotly.relayout(gd, astr, vals[1]); + }) + .then(function() { + assertCnt(selector, exps[1], astr + ' ' + vals[1]); + return Plotly.relayout(gd, astr, vals[0]); + }) + .then(function() { + assertCnt(selector, exps[0], astr + ' ' + vals[0]); + }); + }; + } + + Plotly.plot(gd, fig) + .then(toggle( + '.aaxis > .ytick > text', 'ternary.aaxis.showticklabels', + [true, false], [4, 0] + )) + .then(toggle( + '.baxis > .xtick > text', 'ternary.baxis.showticklabels', + [true, false], [5, 0] + )) + .then(toggle( + '.caxis > .ytick > text', 'ternary.caxis.showticklabels', + [true, false], [4, 0] + )) + .then(toggle( + '.aaxis > path.ytick', 'ternary.aaxis.ticks', + ['outside', ''], [4, 0] + )) + .then(toggle( + '.baxis > path.xtick', 'ternary.baxis.ticks', + ['outside', ''], [5, 0] + )) + .then(toggle( + '.caxis > path.ytick', 'ternary.caxis.ticks', + ['outside', ''], [4, 0] + )) + .catch(failTest) + .then(done); + }); + it('should render a-axis and c-axis with negative offsets', function(done) { var gd = createGraphDiv();