Skip to content

Instantly share code, notes, and snippets.

@tmcw
Created November 13, 2012 18:58
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save tmcw/4067674 to your computer and use it in GitHub Desktop.
Save tmcw/4067674 to your computer and use it in GitHub Desktop.
double click and single click separation
<!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>
@mercicle
Copy link

Very nice!

@bel1k0v
Copy link

bel1k0v commented Jan 16, 2014

Thanks a lot!

@lazybios
Copy link

Nice !

@wmayner
Copy link

wmayner commented Jan 14, 2015

Thanks, this is awesome. You might want to change +new Date() to new Date().getTime(), though; see http://jsperf.com/new-date-timing.

@prakashkolandaivelu
Copy link

selection.on("click", function(d, i) {
dispatch.custom.apply(this, arguments);
});

This way the argument can also be passed

@turquoiseowl
Copy link

It looks like the last variable is redundant?

@pkraker
Copy link

pkraker commented May 26, 2016

@pkolanda: At what line did you insert the snippet you posted? Thanks!

@nharrisanalyst
Copy link

I updated this snippet for d3v4 and v5
you first have to put the rebind function back into d3 which can be found here https://github.com/d3/d3/blob/v3.5.17/src/core/rebind.js

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.call('dblclick',d3.event)
//event.dblclick(d3.event);
} else {
wait = window.setTimeout((function(e) {
return function() {
event.call('click',e)
//event.click(e);
wait = null;
};
})(d3.event), 300);
}
}
});
};
return d3.rebind(cc, event, 'on');
}

@nharrisanalyst
Copy link

Also if you want the mouse event to go into both the double click and the single click you have to pass it down through the anonymous functions

@mnehrig
Copy link

mnehrig commented Sep 5, 2018

Hey!

I created a fork of your snippet to stretch your euclidean distance to another dimension, when I learned, that a comment might be a better way to fight against discrimination of the vertical movement.
Math.sqrt(Math.pow(...) + Math.pow(...))
Don't just drop her into the void, please.

Your snippet helped me so much. Thank you.

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