Skip to content

Introducing layout update menus (aka dropdowns) #770

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 17 commits into from
Aug 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/color/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ exports.lightLine = '#eee';

exports.background = '#fff';

exports.borderLine = '#BEC8D9';

// with axis.color and Color.interp we aren't using lightLine
// itself anymore, instead interpolating between axis.color
// and the background color using tinycolor.mix. lightFraction
Expand Down
133 changes: 133 additions & 0 deletions src/components/updatemenus/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* 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 fontAttrs = require('../../plots/font_attributes');
var colorAttrs = require('../color/attributes');
var extendFlat = require('../../lib/extend').extendFlat;

var buttonsAttrs = {
_isLinkedToArray: true,

method: {
valType: 'enumerated',
values: ['restyle', 'relayout'],
dflt: 'restyle',
role: 'info',
description: [
'Sets the Plotly method to be called on click.'
].join(' ')
},
args: {
valType: 'info_array',
role: 'info',
items: [
{ valType: 'any' },
{ valType: 'any' },
{ valType: 'any' }
],
description: [
'Sets the arguments values to be passed to the Plotly',
'method set in `method` on click.'
].join(' ')
},
label: {
valType: 'string',
role: 'info',
dflt: '',
description: 'Sets the text label to appear on the button.'
}
};

module.exports = {
_isLinkedToArray: true,

visible: {
valType: 'boolean',
role: 'info',
description: [
'Determines whether or not the update menu is visible.'
].join(' ')
},

active: {
valType: 'integer',
role: 'info',
min: -1,
dflt: 0,
description: [
'Determines which button (by index starting from 0) is',
'considered active.'
].join(' ')
},

buttons: buttonsAttrs,

x: {
valType: 'number',
min: -2,
max: 3,
dflt: -0.05,
role: 'style',
description: 'Sets the x position (in normalized coordinates) of the update menu.'
},
xanchor: {
valType: 'enumerated',
values: ['auto', 'left', 'center', 'right'],
dflt: 'right',
role: 'info',
description: [
'Sets the update menu\'s horizontal position anchor.',
'This anchor binds the `x` position to the *left*, *center*',
'or *right* of the range selector.'
].join(' ')
},
y: {
valType: 'number',
min: -2,
max: 3,
dflt: 1,
role: 'style',
description: 'Sets the y position (in normalized coordinates) of the update menu.'
},
yanchor: {
valType: 'enumerated',
values: ['auto', 'top', 'middle', 'bottom'],
dflt: 'bottom',
role: 'info',
description: [
'Sets the update menu\'s vertical position anchor',
'This anchor binds the `y` position to the *top*, *middle*',
'or *bottom* of the range selector.'
].join(' ')
},

font: extendFlat({}, fontAttrs, {
description: 'Sets the font of the update menu button text.'
}),

Copy link
Member

Choose a reason for hiding this comment

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

🐄 some of these attributes have a space between them some do not. Non blocking obviously.

Copy link
Contributor Author

@etpinard etpinard Aug 3, 2016

Choose a reason for hiding this comment

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

Correct. This is on purpose actually. I like to group e.g. position attributes and style attributes together.

bgcolor: {
valType: 'color',
role: 'style',
description: 'Sets the background color of the update menu buttons.'
},
bordercolor: {
valType: 'color',
dflt: colorAttrs.borderLine,
role: 'style',
description: 'Sets the color of the border enclosing the update menu.'
},
borderwidth: {
valType: 'number',
min: 0,
dflt: 1,
role: 'style',
description: 'Sets the width (in px) of the border enclosing the update menu.'
}
};
73 changes: 73 additions & 0 deletions src/components/updatemenus/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* 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';


module.exports = {

// layout attribute names
name: 'updatemenus',
itemName: 'updatemenu',

// class names
containerClassName: 'updatemenu-container',
headerGroupClassName: 'updatemenu-header-group',
headerClassName: 'updatemenu-header',
headerArrowClassName: 'updatemenu-header-arrow',
buttonGroupClassName: 'updatemenu-button-group',
buttonClassName: 'updatemenu-button',
itemRectClassName: 'updatemenu-item-rect',
itemTextClassName: 'updatemenu-item-text',

// DOM attribute name in button group keeping track
// of active update menu
menuIndexAttrName: 'updatemenu-active-index',

// id root pass to Plots.autoMargin
autoMarginIdRoot: 'updatemenu-',

// options when 'active: -1'
blankHeaderOpts: { label: ' ' },

// min item width / height
minWidth: 30,
minHeight: 30,

// padding around item text
textPadX: 40,

// font size to height scale
fontSizeToHeight: 1.3,

// item rect radii
rx: 2,
ry: 2,

// item text x offset off left edge
textOffsetX: 12,

// item text y offset (w.r.t. middle)
textOffsetY: 3,

// arrow offset off right edge
arrowOffsetX: 4,

// gap between header and buttons
gapButtonHeader: 5,

// gap between between buttons
gapButton: 2,

// color given to active buttons
activeColor: '#F4FAFF',

// color given to hovered buttons
hoverColor: '#F4FAFF'
};
93 changes: 93 additions & 0 deletions src/components/updatemenus/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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 Lib = require('../../lib');

var attributes = require('./attributes');
var contants = require('./constants');

var name = contants.name;
var buttonAttrs = attributes.buttons;


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

for(var i = 0; i < contIn.length; i++) {
var menuIn = contIn[i] || {},
menuOut = {};

menuDefaults(menuIn, menuOut, layoutOut);

// used on button click to update the 'active' field
menuOut._input = menuIn;

// used to determine object constancy
menuOut._index = i;

contOut.push(menuOut);
}
};

function menuDefaults(menuIn, menuOut, layoutOut) {

function coerce(attr, dflt) {
return Lib.coerce(menuIn, menuOut, attributes, attr, dflt);
}

var buttons = buttonsDefaults(menuIn, menuOut);

var visible = coerce('visible', buttons.length > 0);
if(!visible) return;

coerce('active');

coerce('x');
coerce('y');
Lib.noneOrAll(menuIn, menuOut, ['x', 'y']);

coerce('xanchor');
coerce('yanchor');

Lib.coerceFont(coerce, 'font', layoutOut.font);

coerce('bgcolor', layoutOut.paper_bgcolor);
coerce('bordercolor');
coerce('borderwidth');
}

function buttonsDefaults(menuIn, menuOut) {
var buttonsIn = menuIn.buttons || [],
buttonsOut = menuOut.buttons = [];

var buttonIn, buttonOut;

function coerce(attr, dflt) {
return Lib.coerce(buttonIn, buttonOut, buttonAttrs, attr, dflt);
}

for(var i = 0; i < buttonsIn.length; i++) {
buttonIn = buttonsIn[i];
buttonOut = {};

if(!Lib.isPlainObject(buttonIn) || !Array.isArray(buttonIn.args)) {
continue;
}

coerce('method');
coerce('args');
coerce('label');

buttonsOut.push(buttonOut);
}

return buttonsOut;
}
Loading