snap.svg.zpd icon indicating copy to clipboard operation
snap.svg.zpd copied to clipboard

Prevent click at end of drag

Open jlgrall opened this issue 10 years ago • 10 comments

Here is a quick workaround that should work in all browsers targeted by Snap.svg (IE 9+), though I cannot test it in IE. It is partly inspired by ThreeDubMedia's jquery.event.drag, which has a well though event code.

var zpdElement;
paper.zpd(function(err, _zpdElement) {
    zpdElement = _zpdElement;
});

/* Add the following instruction in snap.svg.zpd.js, line 264 (the mouseup handler):
     if(zpdElement.data.mouseupTime === -1) zpdElement.data.mouseupTime = Date.now();
   Add the following instruction in snap.svg.zpd.js, line 313 (the mousemove handler):
     if(zpdElement.data.state) zpdElement.data.mouseupTime = -1;
   The first records the time of the mouseup event, but only if the mouse has moved.
   The second uses -1 as a flag to tell that the mouse was moved during the "click".
*/

window.addEventListener("click", function(e) {
    // If mouseup just happened (within 5 ms), cancel the click event:
    if(e.timeStamp - zpdElement.data.mouseupTime < 5) {
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        return false;
    }
}, true);   // true makes the handler acts during the capture phase !

jlgrall avatar Nov 29 '14 15:11 jlgrall

Thanks for your help @jlgrall Would you mind help me by creating a PR on this issue?

hueitan avatar Dec 01 '14 01:12 hueitan

I have forked the repo and added a fix here: https://github.com/AdvancedClimateSystems/snap.svg.zpd Although this fix works, isn't there a better way of doing this? Checking the time at which the events happened can be a bit spotty and if there is a more reliable way, then I'd much rather use that.

jaapz avatar Sep 09 '15 08:09 jaapz

it seems this does not work in firefox, it returns timestamp not relative to epoch 0:0:0 UTC 1st January 1970.

minjas avatar Dec 07 '15 20:12 minjas

@minjas Are you mentioned @jaapz fix?

hueitan avatar Dec 09 '15 10:12 hueitan

I added this code by @jlgrall to snap.svg.zpd library in m project. It works inChrome and IE, but did not work on my version of firefox 42.0. timeStamp value is different in firefox as I could see in console.

minjas avatar Dec 09 '15 10:12 minjas

Im editing my answer. I removed some of my code used for fixing this issue and used only fork code to test. I can confirm that fork does not work on Firefox due to different value of timeStamp, explained bellow, and in Chrome and IE 100 is too big interval, sometimes it does not catch click event.

e.timeStamp - zpdElement.data.mouseupTime < 5 from @jlgrall and event.timeStamp - dragStartTime > 100 from @jaapz will not work because firefox returns this values for event.timeStamp and dragStartTime respectively:

image.

minjas avatar Dec 09 '15 10:12 minjas

Yeah I found out my solution is not consistent at all across browsers. It's also just a dirty hack to look at time stamps IMO. I am looking into alternatives but have not found a better way yet...

jaapz avatar Dec 09 '15 13:12 jaapz

Also checking timestamps is not only inconsistent across browsers, it's also inconsistent across computers. My linux laptop running chrome behaves slightly different than my coworkers windows desktop using chrome.

jaapz avatar Dec 09 '15 13:12 jaapz

Using Date.now() inside clickHandler instead timeStamp will solve issue with firefox on my desktop. Agree this hack is not the most elegent way to do this, will try to come up with better option.

Also condition (event.timeStamp - dragStartTime > 100) does not behave good, I used @jlgrall instructions to change code and it is more consistent, 100 is pretty large time offset, so it does not work sometimes.

minjas avatar Dec 09 '15 13:12 minjas

I don't know if you finally found a solution but since the issue is still opened I think it's a no. I had this same issue and found this solution on stackoverflow. The proposition is to use mousemove and mousedown event do know if it was a drag or a click :

var flag = 0;
var element = xxxx;
element.addEventListener("mousedown", function(){
    flag = 0;
}, false);
element.addEventListener("mousemove", function(){
    flag = 1;
}, false);
element.addEventListener("mouseup", function(){
    if(flag === 0){
        console.log("click");
    }
    else if(flag === 1){
        console.log("drag");
    }
}, false);

This solution launched the mouseup event twice for me so I added a comparison beetwen the current event and the last event fired

// outside of the handlers
var lastEvent = 0;
// in the mouseup handler
if (lastEvent === e.timeStamp) {return}
lastEvent = e.timeStamp

perhaps using Undescore's isEqual or an equivalent can make the comparison cleaner

jonatjano avatar Jul 05 '18 09:07 jonatjano