kbirk kbirk - 1 month ago 14
CSS Question

Cancel incoming jQuery click event if mouse is moved after mousedown

I'm trying to prevent a click event from firing if the mouse is moved after the 'mousedown' event. Currently I'm doing everything manually via conditionals and booleans. I still don't have it working how I want, and I feel it's just a poor approach to accomplishing this.

var mousemove = false;
var mousedown = false;
var cancelClick = false;

$('.example').click( function() {
if (!cancelClick) {
if ( $(this).attr('id') === 'example-green') {
$(this).attr('id', 'example-blue');
} else {
$(this).attr('id', 'example-green');
}
}
cancelClick = false;
});

$('.example').mousedown( function() {
mousedown = true;
});

$('.example').mouseup( function() {
if (mousemove) {
cancelClick = true;
}
mousedown = false;
mousemove = false;
});

$('.example').mousemove( function() {
if (mousedown) {
mousemove = true;
}
});


http://jsfiddle.net/aGf6G/4/

Is there is a simpler way to achieve this? Preferably one that prevents the click events from being processed, or removes them from the pending event queue (I'm not sure if they are queued until after you release the mouse). That way the callbacks themselves aren't coupled with the implementation of this.

Answer

I would just store the x/y coordinates of the mouse on mousedown and compare it to the current coordinates in click.

$('.example')
   .on('mousedown', function() {
        $(this).data("initcoords", { x: event.clientX, y: event.clientY });
    })
   .on('click', function() {
        var initCoords = $(this).data("initcoords") || { x: 0, y: 0 };

        if (event.clientX === initCoords.x && event.clientY === initCoords.y) {
            if ( $(this).attr('id') === 'example-green') {
                $(this).attr('id', 'example-blue');
            } else {
                $(this).attr('id', 'example-green');
            }  
            $(this).data('initcoords', {x:-1, y:-1});
        }
    });

http://jsfiddle.net/zp2y2/8/


You could also toggle the click event on and off. It is a little more concise but I wonder about the overhead of setting up event handlers compared to the method above.

$('.example')
    .on('mousedown', function() { $(this).one("click", handleClick); })
    .on('mousemove mouseout', function() { $(this).off('click'); });

function handleClick(){
    var $el = $('.example');
    if ( $el.attr('id') === 'example-green') {
        $el.attr('id', 'example-blue');
    } else {
        $el.attr('id', 'example-green');
    }  
}

http://jsfiddle.net/du7ZX/