Skip to content

Commit afcf4f4

Browse files
author
Robert Paskowitz
committed
Sort out interaction between drag/edit and legend toggles.
Introduces a global _editing flag to be able to block other interactions while edit is in progress. Could be one solution for plotly#1437. This makes it more clear that there should be some refactor to consolidate the double click behavior, since when the drag layer is on, that code path's click detection is used. The other path needs to remain since the drag layer doesn't exist when editable: false, but it's now easier to picture a world where these two paths converge.
1 parent 895ba89 commit afcf4f4

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

src/components/dragelement/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ dragElement.unhoverRaw = unhover.raw;
3737
* dx and dy are the net pixel offset of the drag,
3838
* dragged is true/false, has the mouse moved enough to
3939
* constitute a drag
40-
* doneFn (optional) function(dragged, numClicks)
40+
* doneFn (optional) function(dragged, numClicks, e)
4141
* executed on mouseup, or mouseout of window since
4242
* we don't get events after that
4343
* dragged is as in moveFn
4444
* numClicks is how many clicks we've registered within
4545
* a doubleclick time
46+
* e is the original event
4647
* setCursor (optional) function(event)
4748
* executed on mousemove before mousedown
4849
* the purpose of this callback is to update the mouse cursor before
@@ -136,7 +137,7 @@ dragElement.init = function init(options) {
136137
numClicks = Math.max(numClicks - 1, 1);
137138
}
138139

139-
if(options.doneFn) options.doneFn(gd._dragged, numClicks);
140+
if(options.doneFn) options.doneFn(gd._dragged, numClicks, e);
140141

141142
if(!gd._dragged) {
142143
var e2 = document.createEvent('MouseEvents');

src/components/legend/draw.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,31 @@ module.exports = function draw(gd) {
329329
xf = dragElement.align(newX, 0, gs.l, gs.l + gs.w, opts.xanchor);
330330
yf = dragElement.align(newY, 0, gs.t + gs.h, gs.t, opts.yanchor);
331331
},
332-
doneFn: function(dragged) {
332+
doneFn: function(dragged, numClicks, e) {
333333
if(dragged && xf !== undefined && yf !== undefined) {
334334
Plotly.relayout(gd, {'legend.x': xf, 'legend.y': yf});
335+
} else {
336+
var traces = [],
337+
clickedTrace;
338+
fullLayout._infolayer.selectAll('g.traces').each(function() { d3.select(this).call(function() { traces.push(this); }); });
339+
for(var i = 0; i < traces.length; i++) {
340+
var tracei = traces[i];
341+
var p = tracei[0][0].getBoundingClientRect();
342+
if(e.clientX >= p.left && e.clientX <= p.right && e.clientY >= p.top && e.clientY <= p.bottom) {
343+
clickedTrace = tracei;
344+
break;
345+
}
346+
}
347+
if(clickedTrace) {
348+
if(numClicks === 1) {
349+
legend._clickTimeout = setTimeout(function() { handleClick(clickedTrace, gd, numClicks); }, 300);
350+
} else if(numClicks === 2) {
351+
if(legend._clickTimeout) {
352+
clearTimeout(legend._clickTimeout);
353+
}
354+
handleClick(clickedTrace, gd, numClicks);
355+
}
356+
}
335357
}
336358
}
337359
});
@@ -426,7 +448,7 @@ function setupTraceToggle(g, gd) {
426448
}
427449
});
428450
traceToggle.on('mouseup', function() {
429-
if(gd._dragged) return;
451+
if(gd._dragged || gd._editing) return;
430452
var legend = gd._fullLayout.legend;
431453

432454
if((new Date()).getTime() - gd._legendMouseDownTime > DBLCLICKDELAY) {
@@ -445,6 +467,7 @@ function setupTraceToggle(g, gd) {
445467
}
446468

447469
function handleClick(g, gd, numClicks) {
470+
if(gd._dragged || gd._editing) return;
448471
var hiddenSlices = gd._fullLayout.hiddenlabels ?
449472
gd._fullLayout.hiddenlabels.slice() :
450473
[];

src/lib/svg_text_utils.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ exports.makeEditable = function(context, _delegate, options) {
467467
}
468468

469469
function appendEditable() {
470-
var plotDiv = d3.select(Lib.getPlotDiv(that.node())),
470+
var gd = Lib.getPlotDiv(that.node()),
471+
plotDiv = d3.select(gd),
471472
container = plotDiv.select('.svg-container'),
472473
div = container.append('div');
473474
div.classed('plugin-editable editable', true)
@@ -487,6 +488,7 @@ exports.makeEditable = function(context, _delegate, options) {
487488
.text(options.text || that.attr('data-unformatted'))
488489
.call(alignHTMLWith(that, container, options))
489490
.on('blur', function() {
491+
gd._editing = false;
490492
that.text(this.textContent)
491493
.style({opacity: 1});
492494
var svgClass = d3.select(this).attr('class'),
@@ -503,13 +505,15 @@ exports.makeEditable = function(context, _delegate, options) {
503505
})
504506
.on('focus', function() {
505507
var context = this;
508+
gd._editing = true;
506509
d3.select(document).on('mouseup', function() {
507510
if(d3.event.target === context) return false;
508511
if(document.activeElement === div.node()) div.node().blur();
509512
});
510513
})
511514
.on('keyup', function() {
512515
if(d3.event.which === 27) {
516+
gd._editing = false;
513517
that.style({opacity: 1});
514518
d3.select(this)
515519
.style({opacity: 0})

0 commit comments

Comments
 (0)