Skip to content

Commit fffddcb

Browse files
authored
Merge pull request #837 from plotly/decircular-a-few-things
Decircularise a few things
2 parents c0c0ad6 + 95e9259 commit fffddcb

27 files changed

+417
-384
lines changed

build/plotcss.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var Plotly = require('../src/plotly');
3+
var Lib = require('../src/lib');
44
var rules = {
55
"X,X div": "font-family:'Open Sans', verdana, arial, sans-serif;margin:0;padding:0;",
66
"X input,X button": "font-family:'Open Sans', verdana, arial, sans-serif;",
@@ -58,5 +58,5 @@ for(var selector in rules) {
5858
var fullSelector = selector.replace(/^,/,' ,')
5959
.replace(/X/g, '.js-plotly-plot .plotly')
6060
.replace(/Y/g, '.plotly-notifier');
61-
Plotly.Lib.addStyleRule(fullSelector, rules[selector]);
61+
Lib.addStyleRule(fullSelector, rules[selector]);
6262
}

src/components/legend/draw.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var Plots = require('../../plots/plots');
1717
var dragElement = require('../dragelement');
1818
var Drawing = require('../drawing');
1919
var Color = require('../color');
20+
var svgTextUtils = require('../../lib/svg_text_utils');
2021

2122
var constants = require('./constants');
2223
var getLegendData = require('./get_legend_data');
@@ -354,14 +355,14 @@ function drawTexts(g, gd) {
354355
.text(name);
355356

356357
function textLayout(s) {
357-
Plotly.util.convertToTspans(s, function() {
358+
svgTextUtils.convertToTspans(s, function() {
358359
s.selectAll('tspan.line').attr({x: s.attr('x')});
359360
g.call(computeTextDimensions, gd);
360361
});
361362
}
362363

363364
if(gd._context.editable && !isPie) {
364-
text.call(Plotly.util.makeEditable)
365+
text.call(svgTextUtils.makeEditable)
365366
.call(textLayout)
366367
.on('edit', function(text) {
367368
this.attr({'data-unformatted': text});

src/components/modebar/buttons.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
'use strict';
1111

1212
var Plotly = require('../../plotly');
13+
var Plots = require('../../plots/plots');
14+
var Axes = require('../../plots/cartesian/axes');
1315
var Lib = require('../../lib');
1416
var downloadImage = require('../../snapshot/download');
1517
var Icons = require('../../../build/ploticon');
@@ -72,7 +74,7 @@ modeBarButtons.sendDataToCloud = {
7274
title: 'Save and edit plot in cloud',
7375
icon: Icons.disk,
7476
click: function(gd) {
75-
Plotly.Plots.sendDataToCloud(gd);
77+
Plots.sendDataToCloud(gd);
7678
}
7779
};
7880

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

186188
var ax, axName;
187189

@@ -263,7 +265,7 @@ function handleDrag3d(gd, ev) {
263265
attr = button.getAttribute('data-attr'),
264266
val = button.getAttribute('data-val') || true,
265267
fullLayout = gd._fullLayout,
266-
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d'),
268+
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'),
267269
layoutUpdate = {};
268270

269271
var parts = attr.split('.');
@@ -295,7 +297,7 @@ function handleCamera3d(gd, ev) {
295297
var button = ev.currentTarget,
296298
attr = button.getAttribute('data-attr'),
297299
fullLayout = gd._fullLayout,
298-
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
300+
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');
299301

300302
for(var i = 0; i < sceneIds.length; i++) {
301303
var sceneId = sceneIds[i],
@@ -327,7 +329,7 @@ function handleHover3d(gd, ev) {
327329
val = button._previousVal || false,
328330
layout = gd.layout,
329331
fullLayout = gd._fullLayout,
330-
sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d');
332+
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');
331333

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

420422
for(var i = 0; i < geoIds.length; i++) {
421423
var geo = fullLayout[geoIds[i]]._geo;

src/components/modebar/index.js

+1-277
Original file line numberDiff line numberDiff line change
@@ -9,280 +9,4 @@
99

1010
'use strict';
1111

12-
var d3 = require('d3');
13-
14-
var Lib = require('../../lib');
15-
var Icons = require('../../../build/ploticon');
16-
17-
18-
/**
19-
* UI controller for interactive plots
20-
* @Class
21-
* @Param {object} opts
22-
* @Param {object} opts.buttons nested arrays of grouped buttons config objects
23-
* @Param {object} opts.container container div to append modeBar
24-
* @Param {object} opts.graphInfo primary plot object containing data and layout
25-
*/
26-
function ModeBar(opts) {
27-
this.container = opts.container;
28-
this.element = document.createElement('div');
29-
30-
this.update(opts.graphInfo, opts.buttons);
31-
32-
this.container.appendChild(this.element);
33-
}
34-
35-
var proto = ModeBar.prototype;
36-
37-
/**
38-
* Update modeBar (buttons and logo)
39-
*
40-
* @param {object} graphInfo primary plot object containing data and layout
41-
* @param {array of arrays} buttons nested arrays of grouped buttons to initialize
42-
*
43-
*/
44-
proto.update = function(graphInfo, buttons) {
45-
this.graphInfo = graphInfo;
46-
47-
var context = this.graphInfo._context;
48-
49-
if(context.displayModeBar === 'hover') {
50-
this.element.className = 'modebar modebar--hover';
51-
}
52-
else this.element.className = 'modebar';
53-
54-
// if buttons or logo have changed, redraw modebar interior
55-
var needsNewButtons = !this.hasButtons(buttons),
56-
needsNewLogo = (this.hasLogo !== context.displaylogo);
57-
58-
if(needsNewButtons || needsNewLogo) {
59-
this.removeAllButtons();
60-
61-
this.updateButtons(buttons);
62-
63-
if(context.displaylogo) {
64-
this.element.appendChild(this.getLogo());
65-
this.hasLogo = true;
66-
}
67-
}
68-
69-
this.updateActiveButton();
70-
};
71-
72-
proto.updateButtons = function(buttons) {
73-
var _this = this;
74-
75-
this.buttons = buttons;
76-
this.buttonElements = [];
77-
this.buttonsNames = [];
78-
79-
this.buttons.forEach(function(buttonGroup) {
80-
var group = _this.createGroup();
81-
82-
buttonGroup.forEach(function(buttonConfig) {
83-
var buttonName = buttonConfig.name;
84-
if(!buttonName) {
85-
throw new Error('must provide button \'name\' in button config');
86-
}
87-
if(_this.buttonsNames.indexOf(buttonName) !== -1) {
88-
throw new Error('button name \'' + buttonName + '\' is taken');
89-
}
90-
_this.buttonsNames.push(buttonName);
91-
92-
var button = _this.createButton(buttonConfig);
93-
_this.buttonElements.push(button);
94-
group.appendChild(button);
95-
});
96-
97-
_this.element.appendChild(group);
98-
});
99-
};
100-
101-
/**
102-
* Empty div for containing a group of buttons
103-
* @Return {HTMLelement}
104-
*/
105-
proto.createGroup = function() {
106-
var group = document.createElement('div');
107-
group.className = 'modebar-group';
108-
109-
return group;
110-
};
111-
112-
/**
113-
* Create a new button div and set constant and configurable attributes
114-
* @Param {object} config (see ./buttons.js for more info)
115-
* @Return {HTMLelement}
116-
*/
117-
proto.createButton = function(config) {
118-
var _this = this,
119-
button = document.createElement('a');
120-
121-
button.setAttribute('rel', 'tooltip');
122-
button.className = 'modebar-btn';
123-
124-
var title = config.title;
125-
if(title === undefined) title = config.name;
126-
if(title || title === 0) button.setAttribute('data-title', title);
127-
128-
if(config.attr !== undefined) button.setAttribute('data-attr', config.attr);
129-
130-
var val = config.val;
131-
if(val !== undefined) {
132-
if(typeof val === 'function') val = val(this.graphInfo);
133-
button.setAttribute('data-val', val);
134-
}
135-
136-
var click = config.click;
137-
if(typeof click !== 'function') {
138-
throw new Error('must provide button \'click\' function in button config');
139-
}
140-
else {
141-
button.addEventListener('click', function(ev) {
142-
config.click(_this.graphInfo, ev);
143-
144-
// only needed for 'hoverClosestGeo' which does not call relayout
145-
_this.updateActiveButton(ev.currentTarget);
146-
});
147-
}
148-
149-
button.setAttribute('data-toggle', config.toggle || false);
150-
if(config.toggle) button.classList.add('active');
151-
152-
button.appendChild(this.createIcon(config.icon || Icons.question));
153-
button.setAttribute('data-gravity', config.gravity || 'n');
154-
155-
return button;
156-
};
157-
158-
/**
159-
* Add an icon to a button
160-
* @Param {object} thisIcon
161-
* @Param {number} thisIcon.width
162-
* @Param {string} thisIcon.path
163-
* @Return {HTMLelement}
164-
*/
165-
proto.createIcon = function(thisIcon) {
166-
var iconHeight = thisIcon.ascent - thisIcon.descent,
167-
svgNS = 'http://www.w3.org/2000/svg',
168-
icon = document.createElementNS(svgNS, 'svg'),
169-
path = document.createElementNS(svgNS, 'path');
170-
171-
icon.setAttribute('height', '1em');
172-
icon.setAttribute('width', (thisIcon.width / iconHeight) + 'em');
173-
icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' '));
174-
175-
path.setAttribute('d', thisIcon.path);
176-
path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')');
177-
icon.appendChild(path);
178-
179-
return icon;
180-
};
181-
182-
/**
183-
* Updates active button with attribute specified in layout
184-
* @Param {object} graphInfo plot object containing data and layout
185-
* @Return {HTMLelement}
186-
*/
187-
proto.updateActiveButton = function(buttonClicked) {
188-
var fullLayout = this.graphInfo._fullLayout,
189-
dataAttrClicked = (buttonClicked !== undefined) ?
190-
buttonClicked.getAttribute('data-attr') :
191-
null;
192-
193-
this.buttonElements.forEach(function(button) {
194-
var thisval = button.getAttribute('data-val') || true,
195-
dataAttr = button.getAttribute('data-attr'),
196-
isToggleButton = (button.getAttribute('data-toggle') === 'true'),
197-
button3 = d3.select(button);
198-
199-
// Use 'data-toggle' and 'buttonClicked' to toggle buttons
200-
// that have no one-to-one equivalent in fullLayout
201-
if(isToggleButton) {
202-
if(dataAttr === dataAttrClicked) {
203-
button3.classed('active', !button3.classed('active'));
204-
}
205-
}
206-
else {
207-
var val = (dataAttr === null) ?
208-
dataAttr :
209-
Lib.nestedProperty(fullLayout, dataAttr).get();
210-
211-
button3.classed('active', val === thisval);
212-
}
213-
214-
});
215-
};
216-
217-
/**
218-
* Check if modeBar is configured as button configuration argument
219-
*
220-
* @Param {object} buttons 2d array of grouped button config objects
221-
* @Return {boolean}
222-
*/
223-
proto.hasButtons = function(buttons) {
224-
var currentButtons = this.buttons;
225-
226-
if(!currentButtons) return false;
227-
228-
if(buttons.length !== currentButtons.length) return false;
229-
230-
for(var i = 0; i < buttons.length; ++i) {
231-
if(buttons[i].length !== currentButtons[i].length) return false;
232-
for(var j = 0; j < buttons[i].length; j++) {
233-
if(buttons[i][j].name !== currentButtons[i][j].name) return false;
234-
}
235-
}
236-
237-
return true;
238-
};
239-
240-
/**
241-
* @return {HTMLDivElement} The logo image wrapped in a group
242-
*/
243-
proto.getLogo = function() {
244-
var group = this.createGroup(),
245-
a = document.createElement('a');
246-
247-
a.href = 'https://plot.ly/';
248-
a.target = '_blank';
249-
a.setAttribute('data-title', 'Produced with Plotly');
250-
a.className = 'modebar-btn plotlyjsicon modebar-btn--logo';
251-
252-
a.appendChild(this.createIcon(Icons.plotlylogo));
253-
254-
group.appendChild(a);
255-
return group;
256-
};
257-
258-
proto.removeAllButtons = function() {
259-
while(this.element.firstChild) {
260-
this.element.removeChild(this.element.firstChild);
261-
}
262-
263-
this.hasLogo = false;
264-
};
265-
266-
proto.destroy = function() {
267-
Lib.removeElement(this.container.querySelector('.modebar'));
268-
};
269-
270-
function createModeBar(gd, buttons) {
271-
var fullLayout = gd._fullLayout;
272-
273-
var modeBar = new ModeBar({
274-
graphInfo: gd,
275-
container: fullLayout._paperdiv.node(),
276-
buttons: buttons
277-
});
278-
279-
if(fullLayout._privateplot) {
280-
d3.select(modeBar.element).append('span')
281-
.classed('badge-private float--left', true)
282-
.text('PRIVATE');
283-
}
284-
285-
return modeBar;
286-
}
287-
288-
module.exports = createModeBar;
12+
exports.manage = require('./manage');

0 commit comments

Comments
 (0)