Skip to content

Decircularise a few things #837

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 10 commits into from
Aug 10, 2016
4 changes: 2 additions & 2 deletions build/plotcss.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

var Plotly = require('../src/plotly');
var Lib = require('../src/lib');
var rules = {
"X,X div": "font-family:'Open Sans', verdana, arial, sans-serif;margin:0;padding:0;",
"X input,X button": "font-family:'Open Sans', verdana, arial, sans-serif;",
Expand Down Expand Up @@ -58,5 +58,5 @@ for(var selector in rules) {
var fullSelector = selector.replace(/^,/,' ,')
.replace(/X/g, '.js-plotly-plot .plotly')
.replace(/Y/g, '.plotly-notifier');
Plotly.Lib.addStyleRule(fullSelector, rules[selector]);
Lib.addStyleRule(fullSelector, rules[selector]);
}
5 changes: 3 additions & 2 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var Plots = require('../../plots/plots');
var dragElement = require('../dragelement');
var Drawing = require('../drawing');
var Color = require('../color');
var svgTextUtils = require('../../lib/svg_text_utils');

var constants = require('./constants');
var getLegendData = require('./get_legend_data');
Expand Down Expand Up @@ -354,14 +355,14 @@ function drawTexts(g, gd) {
.text(name);

function textLayout(s) {
Plotly.util.convertToTspans(s, function() {
svgTextUtils.convertToTspans(s, function() {
s.selectAll('tspan.line').attr({x: s.attr('x')});
g.call(computeTextDimensions, gd);
});
}

if(gd._context.editable && !isPie) {
text.call(Plotly.util.makeEditable)
text.call(svgTextUtils.makeEditable)
.call(textLayout)
.on('edit', function(text) {
this.attr({'data-unformatted': text});
Expand Down
14 changes: 8 additions & 6 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
'use strict';

var Plotly = require('../../plotly');
var Plots = require('../../plots/plots');
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
var downloadImage = require('../../snapshot/download');
var Icons = require('../../../build/ploticon');
Expand Down Expand Up @@ -72,7 +74,7 @@ modeBarButtons.sendDataToCloud = {
title: 'Save and edit plot in cloud',
icon: Icons.disk,
click: function(gd) {
Plotly.Plots.sendDataToCloud(gd);
Plots.sendDataToCloud(gd);
}
};

Expand Down Expand Up @@ -181,7 +183,7 @@ function handleCartesian(gd, ev) {
var mag = (val === 'in') ? 0.5 : 2,
r0 = (1 + mag) / 2,
r1 = (1 - mag) / 2,
axList = Plotly.Axes.list(gd, null, true);
axList = Axes.list(gd, null, true);

var ax, axName;

Expand Down Expand Up @@ -263,7 +265,7 @@ function handleDrag3d(gd, ev) {
attr = button.getAttribute('data-attr'),
val = button.getAttribute('data-val') || true,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d'),
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'),
layoutUpdate = {};

var parts = attr.split('.');
Expand Down Expand Up @@ -295,7 +297,7 @@ function handleCamera3d(gd, ev) {
var button = ev.currentTarget,
attr = button.getAttribute('data-attr'),
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');

for(var i = 0; i < sceneIds.length; i++) {
var sceneId = sceneIds[i],
Expand Down Expand Up @@ -327,7 +329,7 @@ function handleHover3d(gd, ev) {
val = button._previousVal || false,
layout = gd.layout,
fullLayout = gd._fullLayout,
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');

var axes = ['xaxis', 'yaxis', 'zaxis'],
spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor'];
Expand Down Expand Up @@ -415,7 +417,7 @@ function handleGeo(gd, ev) {
attr = button.getAttribute('data-attr'),
val = button.getAttribute('data-val') || true,
fullLayout = gd._fullLayout,
geoIds = Plotly.Plots.getSubplotIds(fullLayout, 'geo');
geoIds = Plots.getSubplotIds(fullLayout, 'geo');

for(var i = 0; i < geoIds.length; i++) {
var geo = fullLayout[geoIds[i]]._geo;
Expand Down
278 changes: 1 addition & 277 deletions src/components/modebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,280 +9,4 @@

'use strict';

var d3 = require('d3');

var Lib = require('../../lib');
var Icons = require('../../../build/ploticon');


/**
* UI controller for interactive plots
* @Class
* @Param {object} opts
* @Param {object} opts.buttons nested arrays of grouped buttons config objects
* @Param {object} opts.container container div to append modeBar
* @Param {object} opts.graphInfo primary plot object containing data and layout
*/
function ModeBar(opts) {
this.container = opts.container;
this.element = document.createElement('div');

this.update(opts.graphInfo, opts.buttons);

this.container.appendChild(this.element);
}

var proto = ModeBar.prototype;

/**
* Update modeBar (buttons and logo)
*
* @param {object} graphInfo primary plot object containing data and layout
* @param {array of arrays} buttons nested arrays of grouped buttons to initialize
*
*/
proto.update = function(graphInfo, buttons) {
this.graphInfo = graphInfo;

var context = this.graphInfo._context;

if(context.displayModeBar === 'hover') {
this.element.className = 'modebar modebar--hover';
}
else this.element.className = 'modebar';

// if buttons or logo have changed, redraw modebar interior
var needsNewButtons = !this.hasButtons(buttons),
needsNewLogo = (this.hasLogo !== context.displaylogo);

if(needsNewButtons || needsNewLogo) {
this.removeAllButtons();

this.updateButtons(buttons);

if(context.displaylogo) {
this.element.appendChild(this.getLogo());
this.hasLogo = true;
}
}

this.updateActiveButton();
};

proto.updateButtons = function(buttons) {
var _this = this;

this.buttons = buttons;
this.buttonElements = [];
this.buttonsNames = [];

this.buttons.forEach(function(buttonGroup) {
var group = _this.createGroup();

buttonGroup.forEach(function(buttonConfig) {
var buttonName = buttonConfig.name;
if(!buttonName) {
throw new Error('must provide button \'name\' in button config');
}
if(_this.buttonsNames.indexOf(buttonName) !== -1) {
throw new Error('button name \'' + buttonName + '\' is taken');
}
_this.buttonsNames.push(buttonName);

var button = _this.createButton(buttonConfig);
_this.buttonElements.push(button);
group.appendChild(button);
});

_this.element.appendChild(group);
});
};

/**
* Empty div for containing a group of buttons
* @Return {HTMLelement}
*/
proto.createGroup = function() {
var group = document.createElement('div');
group.className = 'modebar-group';

return group;
};

/**
* Create a new button div and set constant and configurable attributes
* @Param {object} config (see ./buttons.js for more info)
* @Return {HTMLelement}
*/
proto.createButton = function(config) {
var _this = this,
button = document.createElement('a');

button.setAttribute('rel', 'tooltip');
button.className = 'modebar-btn';

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

if(config.attr !== undefined) button.setAttribute('data-attr', config.attr);

var val = config.val;
if(val !== undefined) {
if(typeof val === 'function') val = val(this.graphInfo);
button.setAttribute('data-val', val);
}

var click = config.click;
if(typeof click !== 'function') {
throw new Error('must provide button \'click\' function in button config');
}
else {
button.addEventListener('click', function(ev) {
config.click(_this.graphInfo, ev);

// only needed for 'hoverClosestGeo' which does not call relayout
_this.updateActiveButton(ev.currentTarget);
});
}

button.setAttribute('data-toggle', config.toggle || false);
if(config.toggle) button.classList.add('active');

button.appendChild(this.createIcon(config.icon || Icons.question));
button.setAttribute('data-gravity', config.gravity || 'n');

return button;
};

/**
* Add an icon to a button
* @Param {object} thisIcon
* @Param {number} thisIcon.width
* @Param {string} thisIcon.path
* @Return {HTMLelement}
*/
proto.createIcon = function(thisIcon) {
var iconHeight = thisIcon.ascent - thisIcon.descent,
svgNS = 'http://www.w3.org/2000/svg',
icon = document.createElementNS(svgNS, 'svg'),
path = document.createElementNS(svgNS, 'path');

icon.setAttribute('height', '1em');
icon.setAttribute('width', (thisIcon.width / iconHeight) + 'em');
icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' '));

path.setAttribute('d', thisIcon.path);
path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')');
icon.appendChild(path);

return icon;
};

/**
* Updates active button with attribute specified in layout
* @Param {object} graphInfo plot object containing data and layout
* @Return {HTMLelement}
*/
proto.updateActiveButton = function(buttonClicked) {
var fullLayout = this.graphInfo._fullLayout,
dataAttrClicked = (buttonClicked !== undefined) ?
buttonClicked.getAttribute('data-attr') :
null;

this.buttonElements.forEach(function(button) {
var thisval = button.getAttribute('data-val') || true,
dataAttr = button.getAttribute('data-attr'),
isToggleButton = (button.getAttribute('data-toggle') === 'true'),
button3 = d3.select(button);

// Use 'data-toggle' and 'buttonClicked' to toggle buttons
// that have no one-to-one equivalent in fullLayout
if(isToggleButton) {
if(dataAttr === dataAttrClicked) {
button3.classed('active', !button3.classed('active'));
}
}
else {
var val = (dataAttr === null) ?
dataAttr :
Lib.nestedProperty(fullLayout, dataAttr).get();

button3.classed('active', val === thisval);
}

});
};

/**
* Check if modeBar is configured as button configuration argument
*
* @Param {object} buttons 2d array of grouped button config objects
* @Return {boolean}
*/
proto.hasButtons = function(buttons) {
var currentButtons = this.buttons;

if(!currentButtons) return false;

if(buttons.length !== currentButtons.length) return false;

for(var i = 0; i < buttons.length; ++i) {
if(buttons[i].length !== currentButtons[i].length) return false;
for(var j = 0; j < buttons[i].length; j++) {
if(buttons[i][j].name !== currentButtons[i][j].name) return false;
}
}

return true;
};

/**
* @return {HTMLDivElement} The logo image wrapped in a group
*/
proto.getLogo = function() {
var group = this.createGroup(),
a = document.createElement('a');

a.href = 'https://plot.ly/';
a.target = '_blank';
a.setAttribute('data-title', 'Produced with Plotly');
a.className = 'modebar-btn plotlyjsicon modebar-btn--logo';

a.appendChild(this.createIcon(Icons.plotlylogo));

group.appendChild(a);
return group;
};

proto.removeAllButtons = function() {
while(this.element.firstChild) {
this.element.removeChild(this.element.firstChild);
}

this.hasLogo = false;
};

proto.destroy = function() {
Lib.removeElement(this.container.querySelector('.modebar'));
};

function createModeBar(gd, buttons) {
var fullLayout = gd._fullLayout;

var modeBar = new ModeBar({
graphInfo: gd,
container: fullLayout._paperdiv.node(),
buttons: buttons
});

if(fullLayout._privateplot) {
d3.select(modeBar.element).append('span')
.classed('badge-private float--left', true)
.text('PRIVATE');
}

return modeBar;
}

module.exports = createModeBar;
exports.manage = require('./manage');
Loading