'use strict'; var perStackAttrs = ['orientation', 'groupnorm', 'stackgaps']; module.exports = function handleStackDefaults(traceIn, traceOut, layout, coerce) { var stackOpts = layout._scatterStackOpts; var stackGroup = coerce('stackgroup'); if(stackGroup) { // use independent stacking options per subplot var subplot = traceOut.xaxis + traceOut.yaxis; var subplotStackOpts = stackOpts[subplot]; if(!subplotStackOpts) subplotStackOpts = stackOpts[subplot] = {}; var groupOpts = subplotStackOpts[stackGroup]; var firstTrace = false; if(groupOpts) { groupOpts.traces.push(traceOut); } else { groupOpts = subplotStackOpts[stackGroup] = { // keep track of trace indices for use during stacking calculations // this will be filled in during `calc` and used during `crossTraceCalc` // so it's OK if we don't recreate it during a non-calc edit traceIndices: [], // Hold on to the whole set of prior traces // First one is most important, so we can clear defaults // there if we find explicit values only in later traces. // We're only going to *use* the values stored in groupOpts, // but for the editor and validate we want things self-consistent // The full set of traces is used only to fix `fill` default if // we find `orientation: 'h'` beyond the first trace traces: [traceOut] }; firstTrace = true; } // TODO: how is this going to work with groupby transforms? // in principle it should be OK I guess, as long as explicit group styles // don't override explicit base-trace styles? var dflts = { orientation: (traceOut.x && !traceOut.y) ? 'h' : 'v' }; for(var i = 0; i < perStackAttrs.length; i++) { var attr = perStackAttrs[i]; var attrFound = attr + 'Found'; if(!groupOpts[attrFound]) { var traceHasAttr = traceIn[attr] !== undefined; var isOrientation = attr === 'orientation'; if(traceHasAttr || firstTrace) { groupOpts[attr] = coerce(attr, dflts[attr]); if(isOrientation) { groupOpts.fillDflt = groupOpts[attr] === 'h' ? 'tonextx' : 'tonexty'; } if(traceHasAttr) { // Note: this will show a value here even if it's invalid // in which case it will revert to default. groupOpts[attrFound] = true; // Note: only one trace in the stack will get a _fullData // entry for a given stack-wide attribute. If no traces // (or the first trace) specify that attribute, the // first trace will get it. If the first trace does NOT // specify it but some later trace does, then it gets // removed from the first trace and only included in the // one that specified it. This is mostly important for // editors (that want to see the full values to know // what settings are available) and Plotly.react diffing. // Editors may want to use fullLayout._scatterStackOpts // directly and make these settings available from all // traces in the stack... then set the new value into // the first trace, and clear all later traces. if(!firstTrace) { delete groupOpts.traces[0][attr]; // orientation can affect default fill of previous traces if(isOrientation) { for(var j = 0; j < groupOpts.traces.length - 1; j++) { var trace2 = groupOpts.traces[j]; if(trace2._input.fill !== trace2.fill) { trace2.fill = groupOpts.fillDflt; } } } } } } } } return groupOpts; } };