Skip to content

Add visible attribute to layout container items. #1110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Nov 7, 2016
4 changes: 4 additions & 0 deletions src/components/annotations/annotation_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ module.exports = function handleAnnotationDefaults(annIn, fullLayout) {
return Lib.coerce(annIn, annOut, attributes, attr, dflt);
}

var visible = coerce('visible');

if(!visible) return annOut;

coerce('opacity');
coerce('align');
coerce('bgcolor');
Expand Down
9 changes: 9 additions & 0 deletions src/components/annotations/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ var extendFlat = require('../../lib/extend').extendFlat;
module.exports = {
_isLinkedToArray: true,

visible: {
valType: 'boolean',
role: 'info',
dflt: true,
description: [
'Determines whether or not this annotation is visible.'
].join(' ')
},

text: {
valType: 'string',
role: 'info',
Expand Down
2 changes: 1 addition & 1 deletion src/components/annotations/calc_autorange.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var draw = require('./draw').draw;

module.exports = function calcAutorange(gd) {
var fullLayout = gd._fullLayout,
annotationList = fullLayout.annotations;
annotationList = Lib.filterVisible(fullLayout.annotations);

if(!annotationList.length || !gd._fullData.length) return;

Expand Down
10 changes: 7 additions & 3 deletions src/components/annotations/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ function draw(gd) {
fullLayout._infolayer.selectAll('.annotation').remove();

for(var i = 0; i < fullLayout.annotations.length; i++) {
drawOne(gd, i);
if(fullLayout.annotations[i].visible) {
drawOne(gd, i);
}
}

return Plots.previousPromises(gd);
Expand Down Expand Up @@ -140,8 +142,6 @@ function drawOne(gd, index, opt, value) {
// where we fail here when they add/remove annotations
if(!optionsIn) return;

var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref};

// alter the input annotation as requested
var optionsEdit = {};
if(typeof opt === 'string' && opt) optionsEdit[opt] = value;
Expand All @@ -153,7 +153,11 @@ function drawOne(gd, index, opt, value) {
Lib.nestedProperty(optionsIn, k).set(optionsEdit[k]);
}

// return early in visible: false updates
if(optionsIn.visible === false) return;

var gs = fullLayout._size;
var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref};

var axLetters = ['x', 'y'];
for(i = 0; i < 2; i++) {
Expand Down
9 changes: 9 additions & 0 deletions src/components/images/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ var cartesianConstants = require('../../plots/cartesian/constants');
module.exports = {
_isLinkedToArray: true,

visible: {
valType: 'boolean',
role: 'info',
dflt: true,
description: [
'Determines whether or not this annotation is visible.'
].join(' ')
},

source: {
valType: 'string',
role: 'info',
Expand Down
36 changes: 17 additions & 19 deletions src/components/images/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,34 @@ var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
var attributes = require('./attributes');

var name = 'images';

module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
var contIn = Array.isArray(layoutIn[name]) ? layoutIn[name] : [],
contOut = layoutOut[name] = [];

if(!layoutIn.images || !Array.isArray(layoutIn.images)) return;
for(var i = 0; i < contIn.length; i++) {
var itemIn = contIn[i] || {},
itemOut = {};

imageDefaults(itemIn, itemOut, layoutOut);

var containerIn = layoutIn.images,
containerOut = layoutOut.images = [];


for(var i = 0; i < containerIn.length; i++) {
var image = containerIn[i];

if(!image.source) continue;

var defaulted = imageDefaults(containerIn[i] || {}, containerOut[i] || {}, layoutOut);
containerOut.push(defaulted);
contOut.push(itemOut);
}
};


function imageDefaults(imageIn, imageOut, fullLayout) {

imageOut = imageOut || {};

function coerce(attr, dflt) {
return Lib.coerce(imageIn, imageOut, attributes, attr, dflt);
}

coerce('source');
var source = coerce('source');
var visible = coerce('visible', !!source);

if(!visible) return imageOut;

coerce('layer');
coerce('x');
coerce('y');
Expand All @@ -52,12 +50,12 @@ function imageDefaults(imageIn, imageOut, fullLayout) {
coerce('sizing');
coerce('opacity');

for(var i = 0; i < 2; i++) {
var tdMock = { _fullLayout: fullLayout },
axLetter = ['x', 'y'][i];
var gdMock = { _fullLayout: fullLayout },
axLetters = ['x', 'y'];

for(var i = 0; i < 2; i++) {
// 'paper' is the fallback axref
Axes.coerceRef(imageIn, imageOut, tdMock, axLetter, 'paper');
Axes.coerceRef(imageIn, imageOut, gdMock, axLetters[i], 'paper');
}

return imageOut;
Expand Down
18 changes: 8 additions & 10 deletions src/components/images/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,23 @@ var Axes = require('../../plots/cartesian/axes');
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');

module.exports = function draw(gd) {

var fullLayout = gd._fullLayout,
imageDataAbove = [],
imageDataSubplot = [],
imageDataBelow = [];

if(!fullLayout.images) return;


// Sort into top, subplot, and bottom layers
for(var i = 0; i < fullLayout.images.length; i++) {
var img = fullLayout.images[i];

if(img.layer === 'below' && img.xref !== 'paper' && img.yref !== 'paper') {
imageDataSubplot.push(img);
} else if(img.layer === 'above') {
imageDataAbove.push(img);
} else {
imageDataBelow.push(img);
if(img.visible) {
if(img.layer === 'below' && img.xref !== 'paper' && img.yref !== 'paper') {
imageDataSubplot.push(img);
} else if(img.layer === 'above') {
imageDataAbove.push(img);
} else {
imageDataBelow.push(img);
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/components/shapes/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ var scatterLineAttrs = scatterAttrs.line;
module.exports = {
_isLinkedToArray: true,

visible: {
valType: 'boolean',
role: 'info',
dflt: true,
description: [
'Determines whether or not this shape is visible.'
].join(' ')
},

type: {
valType: 'enumerated',
values: ['circle', 'rect', 'path', 'line'],
Expand Down
3 changes: 2 additions & 1 deletion src/components/shapes/calc_autorange.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

'use strict';

var Lib = require('../../lib');
var Axes = require('../../plots/cartesian/axes');

var constants = require('./constants');
Expand All @@ -17,7 +18,7 @@ var helpers = require('./helpers');

module.exports = function calcAutorange(gd) {
var fullLayout = gd._fullLayout,
shapeList = fullLayout.shapes;
shapeList = Lib.filterVisible(fullLayout.shapes);

if(!shapeList.length || !gd._fullData.length) return;

Expand Down
13 changes: 9 additions & 4 deletions src/components/shapes/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ function draw(gd) {
fullLayout._shapeSubplotLayer.selectAll('path').remove();

for(var i = 0; i < fullLayout.shapes.length; i++) {
drawOne(gd, i);
if(fullLayout.shapes[i].visible) {
drawOne(gd, i);
}
}

// may need to resurrect this if we put text (LaTeX) in shapes
Expand Down Expand Up @@ -169,8 +171,6 @@ function updateShape(gd, index, opt, value) {
// TODO: clean this up and remove it.
if(!optionsIn) return;

var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref};

// alter the input shape as requested
var optionsEdit = {};
if(typeof opt === 'string' && opt) optionsEdit[opt] = value;
Expand All @@ -182,7 +182,12 @@ function updateShape(gd, index, opt, value) {
Lib.nestedProperty(optionsIn, k).set(optionsEdit[k]);
}

var posAttrs = ['x0', 'x1', 'y0', 'y1'];
// return early in visible: false updates
if(optionsIn.visible === false) return;

var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref},
posAttrs = ['x0', 'x1', 'y0', 'y1'];

for(i = 0; i < 4; i++) {
var posAttr = posAttrs[i];
// if we don't have an explicit position already,
Expand Down
4 changes: 4 additions & 0 deletions src/components/shapes/shape_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ module.exports = function handleShapeDefaults(shapeIn, fullLayout) {
return Lib.coerce(shapeIn, shapeOut, attributes, attr, dflt);
}

var visible = coerce('visible');

if(!visible) return shapeOut;

coerce('layer');
coerce('opacity');
coerce('fillcolor');
Expand Down
19 changes: 13 additions & 6 deletions src/lib/filter_visible.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@

'use strict';

module.exports = function filterVisible(dataIn) {
var dataOut = [];
/** Filter out object items with visible !== true
* insider array container.
*
* @param {array of objects} container
* @return {array of objects} of length <= container
*
*/
module.exports = function filterVisible(container) {
var out = [];

for(var i = 0; i < dataIn.length; i++) {
var trace = dataIn[i];
for(var i = 0; i < container.length; i++) {
var item = container[i];

if(trace.visible === true) dataOut.push(trace);
if(item.visible === true) out.push(item);
}

return dataOut;
return out;
};
2 changes: 2 additions & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ lib.error = loggersModule.error;
lib.notifier = require('./notifier');

lib.filterUnique = require('./filter_unique');
lib.filterVisible = require('./filter_visible');


/**
* swap x and y of the same attribute in container cont
Expand Down
7 changes: 4 additions & 3 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1917,13 +1917,14 @@ function _relayout(gd, aobj) {
objList = layout[objType] || [],
obji = objList[objNum] || {};

// new API, remove annotation / shape with `null`
if(vi === null) aobj[ai] = 'remove';

// if p.parts is just an annotation number, and val is either
// 'add' or an entire annotation to add, the undo is 'remove'
// if val is 'remove' then undo is the whole annotation object
if(p.parts.length === 2) {

// new API, remove annotation / shape with `null`
if(vi === null) aobj[ai] = 'remove';

if(aobj[ai] === 'add' || Lib.isPlainObject(aobj[ai])) {
undoit[ai] = 'remove';
}
Expand Down
3 changes: 1 addition & 2 deletions src/plots/ternary/ternary.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ var Drawing = require('../../components/drawing');
var setConvert = require('../cartesian/set_convert');
var extendFlat = require('../../lib/extend').extendFlat;
var Axes = require('../cartesian/axes');
var filterVisible = require('../../lib/filter_visible');
var dragElement = require('../../components/dragelement');
var Titles = require('../../components/titles');
var prepSelect = require('../cartesian/select');
Expand Down Expand Up @@ -94,7 +93,7 @@ proto.plot = function(ternaryData, fullLayout) {
var moduleData = traceHash[moduleNames[i]];
var _module = moduleData[0]._module;

_module.plot(_this, filterVisible(moduleData), ternaryLayout);
_module.plot(_this, Lib.filterVisible(moduleData), ternaryLayout);
}

_this.traceHash = traceHash;
Expand Down
1 change: 1 addition & 0 deletions test/image/mocks/annotations.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
{"text":"right bottom","showarrow":false,"xref":"paper","yref":"paper","xanchor":"right","yanchor":"bottom","x":0.5,"y":1},
{"text":"move with page","xref":"paper","yref":"paper","x":0.75,"y":1},
{"text":"opacity","opacity":0.5,"x":5,"y":5},
{"text":"not-visible", "visible": false},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mock is not autoranged... do you want to also include an invisible annotation in annotations-autorange.json, positioned to verify that it doesn't contribute? Same for shapes.

I guess images currently don't contribute to autorange at all - is that on purpose or should I consider it a bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to also include an invisible annotation in annotations-autorange.json

done in a2dd634

Same for shapes.

the shape_below_traces is autoranged, so that's a ✅ already

I guess images currently don't contribute to autorange at all - is that on purpose or should I consider it a bug?

I'd say that's a 🐛

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the shape_below_traces is autoranged, so that's a ✅ already

but the shape you added there just says {visible: false} so it will get auto coordinates too, which are going to be within the range chosen by autorange anyway, ie including it in autorange wouldn't make any difference.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(actually that's true of a2dd634 too right?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson good 👁️

I chose to revert a2dd634 and test annotations and shapes autorange using jasmine tests in 5e62c08

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, the new tests look great. Definitely better to do this with jasmine and relayout.

{"text":"left<br>justified","showarrow":false,"align":"left","x":1,"y":4},
{"text":"center<br>justified","showarrow":false,"x":2,"y":4},
{"text":"right<br>justified","showarrow":false,"align":"right","x":3,"y":4},
Expand Down
13 changes: 13 additions & 0 deletions test/image/mocks/layout_image.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@
"opacity": 0.4,
"layer": "below"
},
{
"visible": false,
"source": "https://images.plot.ly/language-icons/api-home/python-logo.png",
"xref": "x",
"yref": "y",
"x": 1,
"y": 3,
"sizex": 2,
"sizey": 2,
"sizing": "stretch",
"opacity": 0.4,
"layer": "below"
},
{
"source": "https://images.plot.ly/language-icons/api-home/matlab-logo.png",
"xref": "x",
Expand Down
1 change: 1 addition & 0 deletions test/image/mocks/shapes_below_traces.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"y1": 1,
"yref": "paper"
},
{ "visible": false },
{
"fillcolor": "#f6e8c3",
"layer": "below",
Expand Down
Loading