Skip to content

Add config options to remove specific modebar buttons #23

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 37 commits into from
Nov 25, 2015

Conversation

etpinard
Copy link
Contributor

@alexcjohnson @bpostlethwaite

A lot of folks have asked for ways to remove specify modebar buttons.

This PR:

  • Refactors a good chunk of the modebar code. Modebar instances now have an update method able to update the buttons and logo based on the context.
  • Moves Modebar management out of Fx object and into its own file.
  • Adds a config options tentatively named modebarButtonsToRemove (suggestions are welcomed) which takes in an array of modebar buttons names to be removed.
  • Remove modebar buttons click handler away from Modebar constructor. The Modebar constructor now expects buttons config objects, fully describing them. This puts plotly.js default buttons on-par with custom modebar buttons.
  • Adds a bunch of modebar tests.

- 'click' keys are now linked to strings corresponding to
   the name of the Modebar prototype method instead of being
   linked to the prototype methods themselves.
- 'val' can be a function of graphInfo (e.g. for 'hoverCompare2d')
- rm !(this instanceof ModeBar) code path
- rename 'config' arg --> 'opts' to not be mistaken with the
  buttons config
  instead of relying on internal Plotly.
- manageModebar handles logic around which button should
  appear on the modebar and how to modebar buttons are
  grouped.
- use it in manageModebar to update buttons based on
  plot type and config arguments
- no need to remove entire modebar element when buttons need to
  be changed.
- remove only child elements
- adds ability to remove specific modebar buttons by listing
  their names upon plot configuration
- throw error if 'modebarButtonsToRemove' isn't an Array
- add filter step to choose button routine, removing buttons
  that are in 'modebarButtonsToRemove' list.
group: 'ext',
title: 'download plot as a png',
icon: 'camera',
click: 'toImage'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

i.e. the name of the associated Modebar method.

Copy link
Member

Choose a reason for hiding this comment

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

This seems overly declarative to me, almost like we intend to ship this config over the wire. Having the click handler attached to this structure was simpler. What are the benefits in associating a function to a button via a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What are the benefits in associating a function to a button via a string?

Putting the config in a separate file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i.e. readability.

Copy link
Member

Choose a reason for hiding this comment

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

I think separate files are less readable actually. If it was a 1000 line structure I would be open to breaking it up. But this seems to add more cognitive dissonance

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about dry-ness? The list of buttons groups was repeated in three places before. Now only once.

- click handler are function of (modabar, eventObject)
- each button's config is passed to the constructor on init.
- the manager main purpose now is to pass the appropriate
  button groups and configs to the modebar constructor depending
  on the plot type.
- throw error when name is not passed in
- throw error when name is not unique
- check for button 'name' is Modebar.hasButton method
- add fallbacks to 'title', and 'toggle' and 'icon'
- throw error when 'click' handler isn't given
var Snapshot = require('../../snapshot');


var modebarButtons = module.exports = {};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@bpostlethwaite default plotly.js modebar button config objects (that now include click handler definitions) are defined here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i.e the Modebar constructor expects the button config objects as input, but doesn't know anything about them a priori.

@alexcjohnson
Copy link
Collaborator

I'd vote for Modebar, modebar and modebarButtons (although displayModeBar will need to stay for backward compat.)

I suppose we could support both displayModeBar and displayModebar if we want to change to lowercase b, and warn devs about the deprecated uppercase B. But unless you think lowercase b is more intuitive (I don't, modebar isn't one word, it's two) I'd still vote for uppercase B.

@etpinard
Copy link
Contributor Author

(I don't, modebar isn't one word, it's two) I'd still vote for uppercase B

@alexcjohnson that convinces me, ModeBar and modeBar it is.

@etpinard
Copy link
Contributor Author

Their custom buttons would go at the end, after the built-in buttons. I don't think most users would mind this. That's a pretty normal pattern I think for extending built-in menu bars and the like.

That's a valid point. Users wanting to simply add a buttons would use modeBarButtonsToAdd and users wanting full control would use modeBarButtons. I don't see a problem with supporting both.

- modebar click handler are now functions of (gd, ev)
  the graph div and the event object only.
- remove all traces of modebar methods inside click handler
- call updateActiveButtons after click handler
- N.B. updateActiveButtons is also called in Plotly.relayout
  so that 'dragmode' update also go through the modebar manager
- don't show hover text when 'title' is set to null or false or ''
- if undefined, fall back to 'name'
@bpostlethwaite
Copy link
Member

@etpinard if we are not putting 'add button' functionality in this go around could you make an issue and reference it in this PR? That way we can review the discussions here to refresh ourselves once they do go in

  Plotly.Icons has the full set of icons, ready to
  be used by users in their custom modebar buttons
- takes an array of buttons config objects (as the
  defined for the default buttons in modebar/buttons.js)
- these 'buttons to add' get appended an additional group
  of buttons passed to the ModeBar constructor
- this allows for fully custom modebar buttons
- modeBarButtons is a nested array of button config objects
- support 'string' entries to reference default buttons
button.addEventListener('click', function () {
config.click.apply(_this, arguments);
var title = config.title;
if(title !== null && title !== false && title !== '') {
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 OK with this logic? It felt weird handling null and '' but not false.

Copy link
Collaborator

Choose a reason for hiding this comment

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

good point. Could also take anything falsey except undefined as "no title," ie if(title || title === undefined) - actually, what do we want to happen if title is 0? I can imagine people getting confused results from that, like if someone makes a set of buttons that they want to label 0, 1, 2, 3, but the first one comes out labeled "setParamCount0" or something... strange, but we might as well plan for it, something like:

var title = config.title;
if(title === undefined) title = config.name;
if(title || title === 0) button.setAttribute('data-title', title);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds good

@@ -25,8 +25,7 @@ exports.Lib = require('./lib');
exports.util = require('./lib/svg_text_utils');
exports.Queue = require('./lib/queue');

// plot icons svg and plot css
exports.Icons = require('../build/ploticon');
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if users want to use our icons for their custom buttons?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah right - I forgot we had both of these... 👍

@alexcjohnson
Copy link
Collaborator

just 2 non-blocking comments left from me - 💃

etpinard added a commit that referenced this pull request Nov 25, 2015
Add config options to remove specific modebar buttons
@etpinard etpinard merged commit 2165998 into master Nov 25, 2015
@etpinard etpinard deleted the custom-modebar branch November 25, 2015 14:57
@harish2rb
Copy link

To all the gurus here, is it possible to use 'modeBarButtonToAdd' in plotly R yet. I am not able to get it working in R. Any help is appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants