diff --git a/src/components/modebar/buttons.js b/src/components/modebar/buttons.js index b545faff14b..25da2554b2a 100644 --- a/src/components/modebar/buttons.js +++ b/src/components/modebar/buttons.js @@ -256,7 +256,7 @@ function handleCartesian(gd, ev) { Plotly.relayout(gd, aobj).then(function() { if(astr === 'dragmode') { - if(fullLayout._hasCartesian) { + if(fullLayout._has('cartesian')) { setCursor( fullLayout._paper.select('.nsewdrag'), DRAGCURSORS[val] @@ -500,7 +500,7 @@ function toggleHover(gd) { var fullLayout = gd._fullLayout; var onHoverVal; - if(fullLayout._hasCartesian) { + if(fullLayout._has('cartesian')) { onHoverVal = fullLayout._isHoriz ? 'y' : 'x'; } else onHoverVal = 'closest'; diff --git a/src/components/modebar/manage.js b/src/components/modebar/manage.js index e0c6ba3f6bf..eacfabbfe3b 100644 --- a/src/components/modebar/manage.js +++ b/src/components/modebar/manage.js @@ -73,12 +73,12 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { var fullLayout = gd._fullLayout, fullData = gd._fullData; - var hasCartesian = !!fullLayout._hasCartesian, - hasGL3D = !!fullLayout._hasGL3D, - hasGeo = !!fullLayout._hasGeo, - hasPie = !!fullLayout._hasPie, - hasGL2D = !!fullLayout._hasGL2D, - hasTernary = !!fullLayout._hasTernary; + var hasCartesian = fullLayout._has('cartesian'), + hasGL3D = fullLayout._has('gl3d'), + hasGeo = fullLayout._has('geo'), + hasPie = fullLayout._has('pie'), + hasGL2D = fullLayout._has('gl2d'), + hasTernary = fullLayout._has('ternary'); var groups = []; diff --git a/src/components/rangeslider/index.js b/src/components/rangeslider/index.js index 31bd1175c8e..26ef6b1d069 100644 --- a/src/components/rangeslider/index.js +++ b/src/components/rangeslider/index.js @@ -41,7 +41,7 @@ function draw(gd) { var height = (fullLayout.height - fullLayout.margin.b - fullLayout.margin.t) * options.thickness, offsetShift = Math.floor(options.borderwidth / 2); - if(sliderContainer[0].length === 0 && !fullLayout._hasGL2D) createSlider(gd); + if(sliderContainer[0].length === 0 && !fullLayout._has('gl2d')) createSlider(gd); // Need to default to 0 for when making gl plots var bb = fullLayout.xaxis._boundingBox ? diff --git a/src/lib/index.js b/src/lib/index.js index 0a6b8f839bc..9f8d40b0928 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -335,6 +335,23 @@ lib.noneOrAll = function(containerIn, containerOut, attrList) { } }; +/** + * Push array with unique items + * + * @param {array} array + * array to be filled + * @param {any} item + * item to be or not to be inserted + * @return {array} + * ref to array (now possibly containing one more item) + * + */ +lib.pushUnique = function(array, item) { + if(item && array.indexOf(item) === -1) array.push(item); + + return array; +}; + lib.mergeArray = function(traceAttr, cd, cdAttr) { if(Array.isArray(traceAttr)) { var imax = Math.min(traceAttr.length, cd.length); diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 74e751b1030..30d7b13275c 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -205,7 +205,7 @@ Plotly.plot = function(gd, data, layout, config) { if(!recalc) return; var subplots = Plots.getSubplotIds(fullLayout, 'cartesian'), - modules = gd._modules; + modules = fullLayout._modules; // position and range calculations for traces that // depend on each other ie bars (stacked or grouped) @@ -250,11 +250,12 @@ Plotly.plot = function(gd, data, layout, config) { // Now plot the data function drawData() { - var calcdata = gd.calcdata; + var calcdata = gd.calcdata, + i; // in case of traces that were heatmaps or contour maps // previously, remove them and their colorbars explicitly - for(var i = 0; i < calcdata.length; i++) { + for(i = 0; i < calcdata.length; i++) { var trace = calcdata[i][0].trace, isVisible = (trace.visible === true), uid = trace.uid; @@ -272,18 +273,11 @@ Plotly.plot = function(gd, data, layout, config) { } } - var plotRegistry = Plots.subplotsRegistry; - - if(fullLayout._hasGL3D) plotRegistry.gl3d.plot(gd); - if(fullLayout._hasGeo) plotRegistry.geo.plot(gd); - if(fullLayout._hasGL2D) plotRegistry.gl2d.plot(gd); - if(fullLayout._hasCartesian || fullLayout._hasPie) { - plotRegistry.cartesian.plot(gd); + // loop over the base plot modules present on graph + var basePlotModules = fullLayout._basePlotModules; + for(i = 0; i < basePlotModules.length; i++) { + basePlotModules[i].plot(gd); } - if(fullLayout._hasTernary) plotRegistry.ternary.plot(gd); - - // clean up old scenes that no longer have associated data - // will this be a performance hit? // styling separate from drawing Plots.style(gd); @@ -1660,10 +1654,12 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { axlist, flagAxForDelete = {}; - // for now, if we detect gl or geo stuff, just re-do the plot - if(fullLayout._hasGL3D || fullLayout._hasGeo || fullLayout._hasGL2D) { - doplot = true; - } + // At the moment, only cartesian, pie and ternary plot types can afford + // to not go through a full replot + var doPlotWhiteList = ['cartesian', 'pie', 'ternary']; + fullLayout._basePlotModules.forEach(function(_module) { + if(doPlotWhiteList.indexOf(_module.name) === -1) doplot = true; + }); // make a new empty vals array for undoit function a0() { return traces.map(function() { return undefined; }); } @@ -2308,7 +2304,7 @@ Plotly.relayout = function relayout(gd, astr, val) { if(p.parts[0].indexOf('scene') === 0) doplot = true; else if(p.parts[0].indexOf('geo') === 0) doplot = true; else if(p.parts[0].indexOf('ternary') === 0) doplot = true; - else if(fullLayout._hasGL2D && + else if(fullLayout._has('gl2d') && (ai.indexOf('axis') !== -1 || p.parts[0] === 'plot_bgcolor') ) doplot = true; else if(ai === 'hiddenlabels') docalc = true; @@ -2581,9 +2577,6 @@ function makePlotFramework(gd) { var gd3 = d3.select(gd), fullLayout = gd._fullLayout; - // TODO - find a better place for 3D to initialize axes - if(fullLayout._hasGL3D) Plots.subplotsRegistry.gl3d.initAxes(gd); - // Plot container fullLayout._container = gd3.selectAll('.plot-container').data([0]); fullLayout._container.enter().insert('div', ':first-child') @@ -2658,7 +2651,7 @@ function makePlotFramework(gd) { makeSubplots(gd, subplots); } - if(fullLayout._hasCartesian) makeCartesianPlotFramwork(gd, subplots); + if(fullLayout._has('cartesian')) makeCartesianPlotFramwork(gd, subplots); // single ternary layer for the whole plot fullLayout._ternarylayer = fullLayout._paper.append('g').classed('ternarylayer', true); diff --git a/src/plot_api/plot_schema.js b/src/plot_api/plot_schema.js index c7a3c9b2f84..36d83861831 100644 --- a/src/plot_api/plot_schema.js +++ b/src/plot_api/plot_schema.js @@ -286,6 +286,8 @@ function handleSubplotObjs(layoutAttributes) { var subplotRegistry = subplotsRegistry[subplotType], isSubplotObj; + if(!subplotRegistry.attrRegex) return; + if(subplotType === 'cartesian' || subplotType === 'gl2d') { isSubplotObj = ( subplotRegistry.attrRegex.x.test(k) || diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 4440e2b54d6..42f898387e7 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -39,7 +39,7 @@ axes.getFromTrace = axisIds.getFromTrace; // find the list of possible axes to reference with an xref or yref attribute // and coerce it to that list axes.coerceRef = function(containerIn, containerOut, gd, axLetter) { - var axlist = gd._fullLayout._hasGL2D ? [] : axes.listIds(gd, axLetter), + var axlist = gd._fullLayout._has('gl2d') ? [] : axes.listIds(gd, axLetter), refAttr = axLetter + 'ref', attrDef = {}; @@ -1797,7 +1797,7 @@ axes.doTicks = function(gd, axid, skipTitle) { var alldone = axes.getSubplots(gd, ax).map(function(subplot) { var plotinfo = fullLayout._plots[subplot]; - if(!fullLayout._hasCartesian) return; + if(!fullLayout._has('cartesian')) return; var container = plotinfo[axletter + 'axislayer'], diff --git a/src/plots/cartesian/graph_interact.js b/src/plots/cartesian/graph_interact.js index a33ef57d124..9a997837a8c 100644 --- a/src/plots/cartesian/graph_interact.js +++ b/src/plots/cartesian/graph_interact.js @@ -60,7 +60,7 @@ fx.supplyLayoutDefaults = function(layoutIn, layoutOut, fullData) { coerce('dragmode'); var hovermodeDflt; - if(layoutOut._hasCartesian) { + if(layoutOut._has('cartesian')) { // flag for 'horizontal' plots: // determines the state of the mode bar 'compare' hovermode button var isHoriz = layoutOut._isHoriz = fx.isHoriz(fullData); @@ -89,7 +89,7 @@ fx.isHoriz = function(fullData) { fx.init = function(gd) { var fullLayout = gd._fullLayout; - if(!fullLayout._hasCartesian || gd._context.staticPlot) return; + if(!fullLayout._has('cartesian') || gd._context.staticPlot) return; var subplots = Object.keys(fullLayout._plots || {}).sort(function(a,b) { // sort overlays last, then by x axis number, then y axis number @@ -107,7 +107,7 @@ fx.init = function(gd) { subplots.forEach(function(subplot) { var plotinfo = fullLayout._plots[subplot]; - if(!fullLayout._hasCartesian) return; + if(!fullLayout._has('cartesian')) return; var xa = plotinfo.x(), ya = plotinfo.y(), diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 2e0ceebfe1b..56c1ac40946 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -30,7 +30,7 @@ exports.plot = function(gd) { var fullLayout = gd._fullLayout, subplots = Plots.getSubplotIds(fullLayout, 'cartesian'), calcdata = gd.calcdata, - modules = gd._modules; + modules = fullLayout._modules; function getCdSubplot(calcdata, subplot) { var cdSubplot = []; @@ -78,9 +78,6 @@ exports.plot = function(gd) { // skip over non-cartesian trace modules if(_module.basePlotModule.name !== 'cartesian') continue; - // skip over pies, there are drawn below - if(_module.name === 'pie') continue; - // plot all traces of this type on this subplot at once var cdModule = getCdModule(cdSubplot, _module); _module.plot(gd, subplotInfo, cdModule); @@ -88,18 +85,4 @@ exports.plot = function(gd) { Lib.markTime('done ' + (cdModule[0] && cdModule[0][0].trace.type)); } } - - // now draw stuff not on subplots (ie, only pies at the moment) - if(fullLayout._hasPie) { - var Pie = Plots.getModule('pie'); - var cdPie = getCdModule(calcdata, Pie); - - if(cdPie.length) Pie.plot(gd, cdPie); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - if(oldFullLayout._hasPie && !newFullLayout._hasPie) { - oldFullLayout._pielayer.selectAll('g.trace').remove(); - } }; diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index 2fae5aaace3..15273f50b33 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -71,7 +71,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { // if gl3d or geo is present on graph. This is retain backward compatible. // // TODO drop this in version 2.0 - var ignoreOrphan = (layoutOut._hasGL3D || layoutOut._hasGeo); + var ignoreOrphan = (layoutOut._has('gl3d') || layoutOut._has('geo')); if(!ignoreOrphan) { for(i = 0; i < layoutKeys.length; i++) { @@ -95,7 +95,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { // make sure that plots with orphan cartesian axes // are considered 'cartesian' if(xaListCartesian.length && yaListCartesian.length) { - layoutOut._hasCartesian = true; + Lib.pushUnique(layoutOut._basePlotModules, Plots.subplotsRegistry.cartesian); } function axSort(a, b) { diff --git a/src/plots/geo/layout/defaults.js b/src/plots/geo/layout/defaults.js index 5919cbfafcb..f149d6b1191 100644 --- a/src/plots/geo/layout/defaults.js +++ b/src/plots/geo/layout/defaults.js @@ -16,8 +16,6 @@ var supplyGeoAxisLayoutDefaults = require('./axis_defaults'); module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - if(!layoutOut._hasGeo) return; - handleSubplotDefaults(layoutIn, layoutOut, fullData, { type: 'geo', attributes: layoutAttributes, diff --git a/src/plots/gl3d/index.js b/src/plots/gl3d/index.js index d0286ee52c7..be90dab79d3 100644 --- a/src/plots/gl3d/index.js +++ b/src/plots/gl3d/index.js @@ -46,10 +46,13 @@ exports.plot = function plotGl3d(gd) { for(var i = 0; i < sceneIds.length; i++) { var sceneId = sceneIds[i], fullSceneData = Plots.getSubplotData(fullData, 'gl3d', sceneId), - scene = fullLayout[sceneId]._scene; // ref. to corresp. Scene instance + sceneLayout = fullLayout[sceneId], + scene = sceneLayout._scene; // If Scene is not instantiated, create one! if(scene === undefined) { + initAxes(gd, sceneLayout); + scene = new Scene({ id: sceneId, graphDiv: gd, @@ -60,10 +63,11 @@ exports.plot = function plotGl3d(gd) { fullLayout ); - fullLayout[sceneId]._scene = scene; // set ref to Scene instance + // set ref to Scene instance + sceneLayout._scene = scene; } - scene.plot(fullSceneData, fullLayout, gd.layout); // takes care of business + scene.plot(fullSceneData, fullLayout, gd.layout); } }; @@ -91,18 +95,10 @@ exports.cleanId = function cleanId(id) { exports.setConvert = require('./set_convert'); -exports.initAxes = function(gd) { - var fullLayout = gd._fullLayout; - var sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'); - - for(var i = 0; i < sceneIds.length; ++i) { - var sceneId = sceneIds[i]; - var sceneLayout = fullLayout[sceneId]; +function initAxes(gd, sceneLayout) { + for(var j = 0; j < 3; ++j) { + var axisName = axesNames[j]; - for(var j = 0; j < 3; ++j) { - var axisName = axesNames[j]; - var ax = sceneLayout[axisName]; - ax._gd = gd; - } + sceneLayout[axisName]._gd = gd; } -}; +} diff --git a/src/plots/gl3d/layout/defaults.js b/src/plots/gl3d/layout/defaults.js index 066f7ec2fa4..291d8dcd572 100644 --- a/src/plots/gl3d/layout/defaults.js +++ b/src/plots/gl3d/layout/defaults.js @@ -17,14 +17,12 @@ var supplyGl3dAxisLayoutDefaults = require('./axis_defaults'); module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - if(!layoutOut._hasGL3D) return; - var hasNon3D = ( - layoutOut._hasCartesian || - layoutOut._hasGeo || - layoutOut._hasGL2D || - layoutOut._hasPie || - layoutOut._hasTernary + layoutOut._has('cartesian') || + layoutOut._has('geo') || + layoutOut._has('gl2d') || + layoutOut._has('pie') || + layoutOut._has('ternary') ); // some layout-wide attribute are used in all scenes diff --git a/src/plots/layout_attributes.js b/src/plots/layout_attributes.js index 601251a1a8d..52f016e8af5 100644 --- a/src/plots/layout_attributes.js +++ b/src/plots/layout_attributes.js @@ -168,30 +168,7 @@ module.exports = { role: 'info', description: 'Determines whether or not a legend is drawn.' }, - _hasCartesian: { - valType: 'boolean', - dflt: false - }, - _hasGL3D: { - valType: 'boolean', - dflt: false - }, - _hasGeo: { - valType: 'boolean', - dflt: false - }, - _hasPie: { - valType: 'boolean', - dflt: false - }, - _hasGL2D: { - valType: 'boolean', - dflt: false - }, - _hasTernary: { - valType: 'boolean', - dflt: false - }, + _composedModules: { '*': 'Fx' }, diff --git a/src/plots/plots.js b/src/plots/plots.js index 271c18374cf..f71e4733d72 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -190,8 +190,8 @@ plots.getSubplotIds = function getSubplotIds(layout, type) { if(_module === undefined) return []; // layout must be 'fullLayout' here - if(type === 'cartesian' && !layout._hasCartesian) return []; - if(type === 'gl2d' && !layout._hasGL2D) return []; + if(type === 'cartesian' && (!layout._has || !layout._has('cartesian'))) return []; + if(type === 'gl2d' && (!layout._has || !layout._has('gl2d'))) return []; if(type === 'cartesian' || type === 'gl2d') { return Object.keys(layout._plots); } @@ -259,18 +259,18 @@ plots.getSubplotData = function getSubplotData(data, type, subplotId) { // then wait a little, then draw it again plots.redrawText = function(gd) { - // doesn't work presently (and not needed) for polar or 3d - if(gd._fullLayout._hasGL3D || (gd.data && gd.data[0] && gd.data[0].r)) { - return; - } + // do not work if polar is present + if((gd.data && gd.data[0] && gd.data[0].r)) return; return new Promise(function(resolve) { setTimeout(function() { Plotly.Annotations.drawAll(gd); Plotly.Legend.draw(gd); - (gd.calcdata||[]).forEach(function(d) { - if(d[0]&&d[0].t&&d[0].t.cb) d[0].t.cb(); + + (gd.calcdata || []).forEach(function(d) { + if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); }); + resolve(plots.previousPromises(gd)); },300); }); @@ -435,22 +435,36 @@ plots.sendDataToCloud = function(gd) { return false; }; +// Fill in default values: +// +// gd.data, gd.layout: +// are precisely what the user specified, +// these fields shouldn't be modified nor used directly +// after the supply defaults step. +// +// gd._fullData, gd._fullLayout: +// are complete descriptions of how to draw the plot, +// use these fields in all required computations. +// +// gd._fullLayout._modules +// is a list of all the trace modules required to draw the plot. +// +// gd._fullLayout._basePlotModules +// is a list of all the plot modules required to draw the plot. +// plots.supplyDefaults = function(gd) { - // fill in default values: - // gd.data, gd.layout: - // are precisely what the user specified - // gd._fullData, gd._fullLayout: - // are complete descriptions of how to draw the plot var oldFullLayout = gd._fullLayout || {}, newFullLayout = gd._fullLayout = {}, - newLayout = gd.layout || {}, - oldFullData = gd._fullData || [], + newLayout = gd.layout || {}; + + var oldFullData = gd._fullData || [], newFullData = gd._fullData = [], - newData = gd.data || [], - modules = gd._modules = []; + newData = gd.data || []; - var i, trace, fullTrace, _module, axList, ax; + var modules = newFullLayout._modules = [], + basePlotModules = newFullLayout._basePlotModules = []; + var i, _module; // first fill in what we can of layout without looking at data // because fullData needs a few things from layout @@ -461,24 +475,23 @@ plots.supplyDefaults = function(gd) { // then do the data for(i = 0; i < newData.length; i++) { - trace = newData[i]; - - fullTrace = plots.supplyDataDefaults(trace, i, newFullLayout); + var fullTrace = plots.supplyDataDefaults(newData[i], i, newFullLayout); newFullData.push(fullTrace); - // detect plot type - if(plots.traceIs(fullTrace, 'cartesian')) newFullLayout._hasCartesian = true; - else if(plots.traceIs(fullTrace, 'gl3d')) newFullLayout._hasGL3D = true; - else if(plots.traceIs(fullTrace, 'geo')) newFullLayout._hasGeo = true; - else if(plots.traceIs(fullTrace, 'pie')) newFullLayout._hasPie = true; - else if(plots.traceIs(fullTrace, 'gl2d')) newFullLayout._hasGL2D = true; - else if(plots.traceIs(fullTrace, 'ternary')) newFullLayout._hasTernary = true; - else if('r' in fullTrace) newFullLayout._hasPolar = true; + // detect polar + if('r' in newData[i]) continue; _module = fullTrace._module; - if(_module && modules.indexOf(_module)===-1) modules.push(_module); + if(!_module) continue; + + // fill in module lists + Lib.pushUnique(modules, _module); + Lib.pushUnique(basePlotModules, fullTrace._module.basePlotModule); } + // attach helper method to check whether a plot type is present on graph + newFullLayout._has = plots._hasPlotType.bind(newFullLayout); + // special cases that introduce interactions between traces for(i = 0; i < modules.length; i++) { _module = modules[i]; @@ -494,22 +507,28 @@ plots.supplyDefaults = function(gd) { // finally, fill in the pieces of layout that may need to look at data plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData); + // TODO remove in v2.0.0 + // add has-plot-type refs to fullLayout for backward compatibility + newFullLayout._hasCartesian = newFullLayout._has('cartesian'); + newFullLayout._hasGeo = newFullLayout._has('geo'); + newFullLayout._hasGL3D = newFullLayout._has('gl3d'); + newFullLayout._hasGL2D = newFullLayout._has('gl2d'); + newFullLayout._hasTernary = newFullLayout._has('ternary'); + newFullLayout._hasPie = newFullLayout._has('pie'); + // clean subplots and other artifacts from previous plot calls plots.cleanPlot(newFullData, newFullLayout, oldFullData, oldFullLayout); - /* - * Relink functions and underscore attributes to promote consistency between - * plots. - */ + // relink functions and _ attributes to promote consistency between plots relinkPrivateKeys(newFullLayout, oldFullLayout); plots.doAutoMargin(gd); // can't quite figure out how to get rid of this... each axis needs // a reference back to the DOM object for just a few purposes - axList = Plotly.Axes.list(gd); + var axList = Plotly.Axes.list(gd); for(i = 0; i < axList.length; i++) { - ax = axList[i]; + var ax = axList[i]; ax._gd = gd; ax.setScale(); } @@ -517,18 +536,32 @@ plots.supplyDefaults = function(gd) { // update object references in calcdata if((gd.calcdata || []).length === newFullData.length) { for(i = 0; i < newFullData.length; i++) { - trace = newFullData[i]; + var trace = newFullData[i]; (gd.calcdata[i][0] || {}).trace = trace; } } }; +// helper function to be bound to fullLayout to check +// whether a certain plot type is present on plot +plots._hasPlotType = function(category) { + var basePlotModules = this._basePlotModules || []; + + for(var i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.name === category) return true; + } + + return false; +}; + plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { var i, j; - var plotTypes = Object.keys(subplotsRegistry); - for(i = 0; i < plotTypes.length; i++) { - var _module = subplotsRegistry[plotTypes[i]]; + var basePlotModules = oldFullLayout._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; if(_module.clean) { _module.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); @@ -713,24 +746,22 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) { coerce('separators'); coerce('hidesources'); coerce('smith'); - coerce('_hasCartesian'); - coerce('_hasGL3D'); - coerce('_hasGeo'); - coerce('_hasPie'); - coerce('_hasGL2D'); - coerce('_hasTernary'); }; plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData) { var i, _module; - // TODO incorporate into subplotRegistry + // can't be be part of basePlotModules loop + // in order to handle the orphan axes case Plotly.Axes.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - // plot module layout defaults - var plotTypes = Object.keys(subplotsRegistry); - for(i = 0; i < plotTypes.length; i++) { - _module = subplotsRegistry[plotTypes[i]]; + // base plot module layout defaults + var basePlotModules = layoutOut._basePlotModules; + for(i = 0; i < basePlotModules.length; i++) { + _module = basePlotModules[i]; + + // done above already + if(_module.name === 'cartesian') continue; // e.g. gl2d does not have a layout-defaults step if(_module.supplyLayoutDefaults) { @@ -739,9 +770,9 @@ plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData) { } // trace module layout defaults - var traceTypes = Object.keys(modules); - for(i = 0; i < traceTypes.length; i++) { - _module = modules[allTypes[i]]._module; + var modules = layoutOut._modules; + for(i = 0; i < modules.length; i++) { + _module = modules[i]; if(_module.supplyLayoutDefaults) { _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); @@ -792,7 +823,6 @@ plots.purge = function(gd) { // these get recreated on Plotly.plot anyway, but just to be safe // (and to have a record of them...) - delete gd._modules; delete gd._tester; delete gd._testref; delete gd._promises; @@ -810,7 +840,7 @@ plots.purge = function(gd) { }; plots.style = function(gd) { - var _modules = gd._modules; + var _modules = gd._fullLayout._modules; for(var i = 0; i < _modules.length; i++) { var _module = _modules[i]; diff --git a/src/plots/ternary/layout/defaults.js b/src/plots/ternary/layout/defaults.js index 047208ec562..3564d84b812 100644 --- a/src/plots/ternary/layout/defaults.js +++ b/src/plots/ternary/layout/defaults.js @@ -18,8 +18,6 @@ var handleAxisDefaults = require('./axis_defaults'); var axesNames = ['aaxis', 'baxis', 'caxis']; module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - if(!layoutOut._hasTernary) return; - handleSubplotDefaults(layoutIn, layoutOut, fullData, { type: 'ternary', attributes: layoutAttributes, diff --git a/src/snapshot/index.js b/src/snapshot/index.js index 2b662846928..86d3dd104ca 100644 --- a/src/snapshot/index.js +++ b/src/snapshot/index.js @@ -10,18 +10,20 @@ 'use strict'; function getDelay(fullLayout) { - return (fullLayout._hasGL3D || fullLayout._hasGL2D) ? 500 : 0; + + // polar clears fullLayout._has for some reason + if(!fullLayout._has) return 0; + + // maybe we should add a 'gl' (and 'svg') layoutCategory ?? + return (fullLayout._has('gl3d')|| fullLayout._has('gl2d')) ? 500 : 0; } function getRedrawFunc(gd) { - return function() { - var fullLayout = gd._fullLayout; - // doesn't work presently (and not needed) for polar or gl - if(fullLayout._hasGL3D || fullLayout._hasGL2D || - (gd.data && gd.data[0] && gd.data[0].r) - ) return; + // do not work if polar is present + if((gd.data && gd.data[0] && gd.data[0].r)) return; + return function() { (gd.calcdata || []).forEach(function(d) { if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); }); diff --git a/src/traces/pie/base_plot.js b/src/traces/pie/base_plot.js new file mode 100644 index 00000000000..c53f3e8ae8f --- /dev/null +++ b/src/traces/pie/base_plot.js @@ -0,0 +1,45 @@ +/** +* Copyright 2012-2016, 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 Plots = require('../../plots/plots'); + + +exports.name = 'pie'; + +exports.plot = function(gd) { + var Pie = Plots.getModule('pie'); + var cdPie = getCdModule(gd.calcdata, Pie); + + if(cdPie.length) Pie.plot(gd, cdPie); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadPie = (oldFullLayout._has && oldFullLayout._has('pie')); + var hasPie = (newFullLayout._has && newFullLayout._has('pie')); + + if(hadPie && !hasPie) { + oldFullLayout._pielayer.selectAll('g.trace').remove(); + } +}; + +function getCdModule(calcdata, _module) { + var cdModule = []; + + for(var i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var trace = cd[0].trace; + + if((trace._module === _module) && (trace.visible === true)) { + cdModule.push(cd); + } + } + + return cdModule; +} diff --git a/src/traces/pie/index.js b/src/traces/pie/index.js index c5344071d8e..d71ae74207a 100644 --- a/src/traces/pie/index.js +++ b/src/traces/pie/index.js @@ -21,7 +21,7 @@ Pie.styleOne = require('./style_one'); Pie.moduleType = 'trace'; Pie.name = 'pie'; -Pie.basePlotModule = require('../../plots/cartesian'); +Pie.basePlotModule = require('./base_plot'); Pie.categories = ['pie', 'showLegend']; Pie.meta = { description: [ diff --git a/src/traces/scatterternary/style.js b/src/traces/scatterternary/style.js index 7b92f4d3200..25459e55e74 100644 --- a/src/traces/scatterternary/style.js +++ b/src/traces/scatterternary/style.js @@ -12,13 +12,16 @@ var scatterStyle = require('../scatter/style'); -module.exports = function style(graphDiv) { - for(var i = 0; i < graphDiv._modules.length; i++) { - // we're just going to call scatter style... if we already - // called it, don't need to redo. - // Later though we may want differences, or we may make style - // more specific in its scope, then we can remove this. - if(graphDiv._modules[i].name === 'scatter') return; +module.exports = function style(gd) { + var modules = gd._fullLayout._modules; + + // we're just going to call scatter style... if we already + // called it, don't need to redo. + // Later though we may want differences, or we may make style + // more specific in its scope, then we can remove this. + for(var i = 0; i < modules.length; i++) { + if(modules[i].name === 'scatter') return; } - scatterStyle(graphDiv); + + scatterStyle(gd); }; diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 8efbfad68fd..8b58b06ded4 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -171,7 +171,10 @@ describe('Test axes', function() { var layoutIn, layoutOut, fullData; beforeEach(function() { - layoutOut = {}; + layoutOut = { + _has: Plots._hasPlotType, + _basePlotModules: [] + }; fullData = []; }); @@ -267,7 +270,7 @@ describe('Test axes', function() { fullData = []; supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut._hasCartesian).toBe(true); + expect(layoutOut._basePlotModules[0].name).toEqual('cartesian'); }); it('should detect orphan axes (gl2d trace conflict case)', function() { @@ -282,7 +285,7 @@ describe('Test axes', function() { }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut._hasCartesian).toBe(undefined); + expect(layoutOut._basePlotModules).toEqual([]); }); it('should detect orphan axes (gl2d + cartesian case)', function() { @@ -297,7 +300,7 @@ describe('Test axes', function() { }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut._hasCartesian).toBe(true); + expect(layoutOut._basePlotModules[0].name).toEqual('cartesian'); }); it('should detect orphan axes (gl3d present case)', function() { @@ -305,21 +308,21 @@ describe('Test axes', function() { xaxis: {}, yaxis: {} }; - layoutOut._hasGL3D = true; + layoutOut._basePlotModules = [ { name: 'gl3d' }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut._hasCartesian).toBe(undefined); + expect(layoutOut._basePlotModules).toEqual([ { name: 'gl3d' }]); }); - it('should detect orphan axes (gl3d present case)', function() { + it('should detect orphan axes (geo present case)', function() { layoutIn = { xaxis: {}, yaxis: {} }; - layoutOut._hasGeo = true; + layoutOut._basePlotModules = [ { name: 'geo' }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); - expect(layoutOut._hasCartesian).toBe(undefined); + expect(layoutOut._basePlotModules).toEqual([ { name: 'geo' }]); }); it('should use \'axis.color\' as default for \'axis.titlefont.color\'', function() { diff --git a/test/jasmine/tests/fx_test.js b/test/jasmine/tests/fx_test.js index b4a27fadc17..59ac3a146fc 100644 --- a/test/jasmine/tests/fx_test.js +++ b/test/jasmine/tests/fx_test.js @@ -1,4 +1,5 @@ var Fx = require('@src/plots/cartesian/graph_interact'); +var Plots = require('@src/plots/plots'); describe('Test FX', function() { @@ -6,22 +7,24 @@ describe('Test FX', function() { describe('defaults', function() { - it('should default (blank version)', function() { - var layoutIn = {}; - var layoutOut = {}; - var fullData = [{}]; + var layoutIn, layoutOut, fullData; + beforeEach(function() { + layoutIn = {}; + layoutOut = { + _has: Plots._hasPlotType + }; + fullData = [{}]; + }); + + it('should default (blank version)', function() { Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom'); }); it('should default (cartesian version)', function() { - var layoutIn = {}; - var layoutOut = { - _hasCartesian: true - }; - var fullData = [{}]; + layoutOut._basePlotModules = [{ name: 'cartesian' }]; Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('x', 'hovermode to x'); @@ -30,13 +33,8 @@ describe('Test FX', function() { }); it('should default (cartesian horizontal version)', function() { - var layoutIn = {}; - var layoutOut = { - _hasCartesian: true - }; - var fullData = [{ - orientation: 'h' - }]; + layoutOut._basePlotModules = [{ name: 'cartesian' }]; + fullData[0] = { orientation: 'h' }; Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('y', 'hovermode to y'); @@ -45,11 +43,7 @@ describe('Test FX', function() { }); it('should default (gl3d version)', function() { - var layoutIn = {}; - var layoutOut = { - _hasGL3D: true - }; - var fullData = [{}]; + layoutOut._basePlotModules = [{ name: 'gl3d' }]; Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); @@ -57,11 +51,7 @@ describe('Test FX', function() { }); it('should default (geo version)', function() { - var layoutIn = {}; - var layoutOut = { - _hasGeo: true - }; - var fullData = [{}]; + layoutOut._basePlotModules = [{ name: 'geo' }]; Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest'); @@ -69,12 +59,7 @@ describe('Test FX', function() { }); it('should default (multi plot type version)', function() { - var layoutIn = {}; - var layoutOut = { - _hasCartesian: true, - _hasGL3D: true - }; - var fullData = [{}]; + layoutOut._basePlotModules = [{ name: 'cartesian' }, { name: 'gl3d' }]; Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.hovermode).toBe('x', 'hovermode to x'); diff --git a/test/jasmine/tests/geolayout_test.js b/test/jasmine/tests/geolayout_test.js index 057897cdd4d..2c22715a056 100644 --- a/test/jasmine/tests/geolayout_test.js +++ b/test/jasmine/tests/geolayout_test.js @@ -11,8 +11,7 @@ describe('Test Geo layout defaults', function() { var layoutIn, layoutOut, fullData; beforeEach(function() { - // if hasGeo is not at this stage, the default step is skipped - layoutOut = { _hasGeo: true }; + layoutOut = {}; // needs a geo-ref in a trace in order to be detected fullData = [{ type: 'scattergeo', geo: 'geo' }]; diff --git a/test/jasmine/tests/gl3dlayout_test.js b/test/jasmine/tests/gl3dlayout_test.js index 8a2f4f81cdc..f6e2fd24d07 100644 --- a/test/jasmine/tests/gl3dlayout_test.js +++ b/test/jasmine/tests/gl3dlayout_test.js @@ -1,4 +1,5 @@ var Gl3d = require('@src/plots/gl3d'); +var Plots = require('@src/plots/plots'); var tinycolor = require('tinycolor2'); var Color = require('@src/components/color'); @@ -13,8 +14,9 @@ describe('Test Gl3d layout defaults', function() { var supplyLayoutDefaults = Gl3d.supplyLayoutDefaults; beforeEach(function() { - // if hasGL3D is not at this stage, the default step is skipped - layoutOut = { _hasGL3D: true }; + layoutOut = { + _has: Plots._hasPlotType + }; // needs a scene-ref in a trace in order to be detected fullData = [ { type: 'scatter3d', scene: 'scene' }]; @@ -173,7 +175,7 @@ describe('Test Gl3d layout defaults', function() { .toBe('orbit', 'to user layout val if valid and 3d only'); layoutIn = { scene: {}, dragmode: 'orbit' }; - layoutOut._hasCartesian = true; + layoutOut._basePlotModules = [{ name: 'cartesian' }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.scene.dragmode) .toBe('turntable', 'to default if not 3d only'); @@ -201,7 +203,7 @@ describe('Test Gl3d layout defaults', function() { .toBe(false, 'to user layout val if valid and 3d only'); layoutIn = { scene: {}, hovermode: false }; - layoutOut._hasCartesian = true; + layoutOut._basePlotModules = [{ name: 'cartesian' }]; supplyLayoutDefaults(layoutIn, layoutOut, fullData); expect(layoutOut.scene.hovermode) .toBe('closest', 'to default if not 3d only'); diff --git a/test/jasmine/tests/gl_plot_interact_test.js b/test/jasmine/tests/gl_plot_interact_test.js index f59a84f3875..70ce1fe0cd3 100644 --- a/test/jasmine/tests/gl_plot_interact_test.js +++ b/test/jasmine/tests/gl_plot_interact_test.js @@ -159,7 +159,7 @@ describe('Test gl plot interactions', function() { expect(gd.layout.scene).toEqual(sceneLayout); expect(gd.layout.xaxis).toBeUndefined(); expect(gd.layout.yaxis).toBeUndefined(); - expect(gd._fullLayout._hasGL3D).toBe(true); + expect(gd._fullLayout._has('gl3d')).toBe(true); expect(gd._fullLayout.scene._scene).toBeDefined(); Plotly.restyle(gd, 'type', 'scatter').then(function() { @@ -167,7 +167,7 @@ describe('Test gl plot interactions', function() { expect(gd.layout.scene).toEqual(sceneLayout); expect(gd.layout.xaxis).toBeDefined(); expect(gd.layout.yaxis).toBeDefined(); - expect(gd._fullLayout._hasGL3D).toBe(false); + expect(gd._fullLayout._has('gl3d')).toBe(false); expect(gd._fullLayout.scene).toBeUndefined(); return Plotly.restyle(gd, 'type', 'scatter3d'); @@ -176,7 +176,7 @@ describe('Test gl plot interactions', function() { expect(gd.layout.scene).toEqual(sceneLayout); expect(gd.layout.xaxis).toBeDefined(); expect(gd.layout.yaxis).toBeDefined(); - expect(gd._fullLayout._hasGL3D).toBe(true); + expect(gd._fullLayout._has('gl3d')).toBe(true); expect(gd._fullLayout.scene._scene).toBeDefined(); done(); @@ -186,7 +186,7 @@ describe('Test gl plot interactions', function() { it('should be able to delete the last trace', function(done) { Plotly.deleteTraces(gd, [0]).then(function() { expect(countCanvases()).toEqual(0); - expect(gd._fullLayout._hasGL3D).toBe(false); + expect(gd._fullLayout._has('gl3d')).toBe(false); expect(gd._fullLayout.scene).toBeUndefined(); done(); diff --git a/test/jasmine/tests/lib_test.js b/test/jasmine/tests/lib_test.js index 110cc948b91..e30a7378e6f 100644 --- a/test/jasmine/tests/lib_test.js +++ b/test/jasmine/tests/lib_test.js @@ -857,4 +857,44 @@ describe('Test lib.js:', function() { }); }); + describe('pushUnique', function() { + + beforeEach(function() { + this.obj = { a: 'A' }; + this.array = ['a', 'b', 'c', this.obj]; + }); + + it('should fill new items in array', function() { + var out = Lib.pushUnique(this.array, 'd'); + + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }, 'd']); + expect(this.array).toBe(out); + }); + + it('should ignore falsy items', function() { + Lib.pushUnique(this.array, false); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + Lib.pushUnique(this.array, undefined); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + Lib.pushUnique(this.array, 0); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + Lib.pushUnique(this.array, null); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + Lib.pushUnique(this.array, ''); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + }); + + it('should ignore item already in array', function() { + Lib.pushUnique(this.array, 'a'); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + Lib.pushUnique(this.array, this.obj); + expect(this.array).toEqual(['a', 'b', 'c', { a: 'A' }]); + + }); + }); }); diff --git a/test/jasmine/tests/modebar_test.js b/test/jasmine/tests/modebar_test.js index 9931091d431..b8a5c460e12 100644 --- a/test/jasmine/tests/modebar_test.js +++ b/test/jasmine/tests/modebar_test.js @@ -4,6 +4,7 @@ var createModeBar = require('@src/components/modebar'); var manageModeBar = require('@src/components/modebar/manage'); var Plotly = require('@lib/index'); +var Plots = require('@src/plots/plots'); var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var selectButton = require('../assets/modebar_button'); @@ -28,7 +29,8 @@ describe('ModeBar', function() { return { _fullLayout: { dragmode: 'zoom', - _paperdiv: d3.select(getMockContainerTree()) + _paperdiv: d3.select(getMockContainerTree()), + _has: Plots._hasPlotType }, _fullData: [], _context: { @@ -186,7 +188,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }]; gd._fullLayout.xaxis = {fixedrange: false}; manageModeBar(gd); @@ -204,7 +206,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }]; gd._fullLayout.xaxis = {fixedrange: false}; gd._fullData = [{ type: 'scatter', @@ -226,7 +228,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -243,7 +245,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasGL3D = true; + gd._fullLayout._basePlotModules = [{ name: 'gl3d' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -259,7 +261,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasGeo = true; + gd._fullLayout._basePlotModules = [{ name: 'geo' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -276,7 +278,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasGL2D = true; + gd._fullLayout._basePlotModules = [{ name: 'gl2d' }]; gd._fullLayout.xaxis = {fixedrange: false}; manageModeBar(gd); @@ -292,7 +294,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasPie = true; + gd._fullLayout._basePlotModules = [{ name: 'pie' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -307,8 +309,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; - gd._fullLayout._hasGL3D = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }, { name: 'gl3d' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -323,8 +324,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; - gd._fullLayout._hasGeo = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }, { name: 'geo' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -341,7 +341,6 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; gd._fullData = [{ type: 'scatter', visible: true, @@ -349,7 +348,7 @@ describe('ModeBar', function() { _module: {selectPoints: true} }]; gd._fullLayout.xaxis = {fixedrange: false}; - gd._fullLayout._hasPie = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }, { name: 'pie' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -364,8 +363,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasGL3D = true; - gd._fullLayout._hasGeo = true; + gd._fullLayout._basePlotModules = [{ name: 'geo' }, { name: 'gl3d' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -380,7 +378,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasTernary = true; + gd._fullLayout._basePlotModules = [{ name: 'ternary' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -395,13 +393,13 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasTernary = true; gd._fullData = [{ type: 'scatterternary', visible: true, mode: 'markers', _module: {selectPoints: true} }]; + gd._fullLayout._basePlotModules = [{ name: 'ternary' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -417,8 +415,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasTernary = true; - gd._fullLayout._hasCartesian = true; + gd._fullLayout._basePlotModules = [{ name: 'ternary' }, { name: 'cartesian' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -433,8 +430,7 @@ describe('ModeBar', function() { ]); var gd = getMockGraphInfo(); - gd._fullLayout._hasTernary = true; - gd._fullLayout._hasGL3D = true; + gd._fullLayout._basePlotModules = [{ name: 'ternary' }, { name: 'gl3d' }]; manageModeBar(gd); var modeBar = gd._fullLayout._modeBar; @@ -487,7 +483,7 @@ describe('ModeBar', function() { // gives 11 buttons in 5 groups by default function setupGraphInfo() { var gd = getMockGraphInfo(); - gd._fullLayout._hasCartesian = true; + gd._fullLayout._basePlotModules = [{ name: 'cartesian' }]; gd._fullLayout.xaxis = {fixedrange: false}; return gd; } @@ -496,8 +492,7 @@ describe('ModeBar', function() { var gd = setupGraphInfo(); manageModeBar(gd); - gd._fullLayout._hasCartesian = false; - gd._fullLayout._hasGL3D = true; + gd._fullLayout._basePlotModules = [{ name: 'gl3d' }]; manageModeBar(gd); expect(countButtons(gd._fullLayout._modeBar)).toEqual(10); diff --git a/test/jasmine/tests/plots_test.js b/test/jasmine/tests/plots_test.js index 4646f760185..8b71a9c5455 100644 --- a/test/jasmine/tests/plots_test.js +++ b/test/jasmine/tests/plots_test.js @@ -140,20 +140,20 @@ describe('Test Plots', function() { it('returns cartesian ids', function() { var layout = { + _has: Plots._hasPlotType, _plots: { xy: {}, x2y2: {} } }; expect(getSubplotIds(layout, 'cartesian')) .toEqual([]); - layout._hasCartesian = true; + layout._basePlotModules = [{ name: 'cartesian' }]; expect(getSubplotIds(layout, 'cartesian')) .toEqual(['xy', 'x2y2']); expect(getSubplotIds(layout, 'gl2d')) .toEqual([]); - delete layout._hasCartesian; - layout._hasGL2D = true; + layout._basePlotModules = [{ name: 'gl2d' }]; expect(getSubplotIds(layout, 'gl2d')) .toEqual(['xy', 'x2y2']); expect(getSubplotIds(layout, 'cartesian')) @@ -395,7 +395,6 @@ describe('Test Plots', function() { expect(gd.undonum).toBeUndefined(); expect(gd.autoplay).toBeUndefined(); expect(gd.changed).toBeUndefined(); - expect(gd._modules).toBeUndefined(); expect(gd._tester).toBeUndefined(); expect(gd._testref).toBeUndefined(); expect(gd._promises).toBeUndefined(); diff --git a/test/jasmine/tests/ternary_test.js b/test/jasmine/tests/ternary_test.js index 167d46c4b54..b933dae528c 100644 --- a/test/jasmine/tests/ternary_test.js +++ b/test/jasmine/tests/ternary_test.js @@ -230,9 +230,7 @@ describe('ternary defaults', function() { var layoutIn, layoutOut, fullData; beforeEach(function() { - // if hasTernary is not at this stage, the default step is skipped layoutOut = { - _hasTernary: true, font: { color: 'red' } };