Skip to content

Instantly share code, notes, and snippets.

@couchand
Forked from tmcw/index.html
Created August 30, 2013 21:37
Show Gist options
  • Select an option

  • Save couchand/6394506 to your computer and use it in GitHub Desktop.

Select an option

Save couchand/6394506 to your computer and use it in GitHub Desktop.
Distinguishing click and double-click in D3.
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0; padding:0; }
#map { width:960px; height:500px; background:cyan; }
</style>
</head>
<body>
<div id='map'></div>
<script>
function clickcancel() {
var event = d3.dispatch('click', 'dblclick');
function cc(selection) {
var down,
tolerance = 5,
last,
wait = null;
// euclidean distance
function dist(a, b) {
return Math.sqrt(Math.pow(a[0] - b[0], 2), Math.pow(a[1] - b[1], 2));
}
selection.on('mousedown', function() {
down = d3.mouse(document.body);
last = +new Date();
});
selection.on('mouseup', function() {
if (dist(down, d3.mouse(document.body)) > tolerance) {
return;
} else {
if (wait) {
window.clearTimeout(wait);
wait = null;
event.dblclick(d3.event);
} else {
wait = window.setTimeout((function(e) {
return function() {
event.click(e);
wait = null;
};
})(d3.event), 300);
}
}
});
};
return d3.rebind(cc, event, 'on');
}
var cc = clickcancel();
d3.select('#map').call(cc);
cc.on('click', function() {
d3.select('#map').text(d3.select('#map').text() + 'click, ');
});
cc.on('dblclick', function() {
d3.select('#map').text(d3.select('#map').text() + 'dblclick, ');
});
</script>
</body>
</html>
@jazeee

jazeee commented Feb 25, 2015

Copy link
Copy Markdown

Thanks for this. It helped a lot.
Just a note: This mostly works, however it does not quite act the same way as a d3.select().on('click'...)
In particular, in cc.on('click', we cannot get the mouse position via d3.mouse(this).
In other words, using typical d3 mechanisms.
In order to get the mouse position, you'd have to capture the mouse position on the original click, then you can use it in cc.on('click')

@kashesandr

kashesandr commented Jul 28, 2016

Copy link
Copy Markdown

The bad thing here is that the arguments are replaced.
So when the selection is bundled with some data this variant you can use http://bl.ocks.org/kashesandr/0c9fee5edc8d78a32a10e7040822cd30.

@aalimovs

Copy link
Copy Markdown

d3.rebind() has been removed in v4. Does anyone have a v4 working example?

@sardbaba

sardbaba commented Dec 5, 2017

Copy link
Copy Markdown

@aalimovs http://bl.ocks.org/ropeladder/83915942ac42f17c087a82001418f2ee

In this example there is an error: Math.sqrt(Math.pow(a[0] - b[0], 2), Math.pow(a[1] - b[1], 2));
Math.sqrt takes exactly one argument: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt
So the correct code should be: Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));

@austince

Copy link
Copy Markdown

If anyone is using Observable, I've ported the v4 update (and verified for v5) over here: https://observablehq.com/@austince/cancelable-click

@sinamoeini

Copy link
Copy Markdown

@austince thanks that is exactly what I was looking for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment