Skip to content

Instantly share code, notes, and snippets.

@couchand
Forked from tmcw/index.html
Created August 30, 2013 21:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save couchand/6394506 to your computer and use it in GitHub Desktop.
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
Copy link

jazeee commented Feb 25, 2015

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
Copy link

kashesandr commented Jul 28, 2016

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

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

@sardbaba
Copy link

sardbaba commented Dec 5, 2017

@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

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

@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