12

I have a draggable <div> with a click event and without any event for drag, but after I drag <div> the click event is apply to <div>.

How can prevent of click event after drag?

$(function(){
    $('div').bind('click', function(){
        $(this).toggleClass('orange');
    });

    $('div').draggable();
});

http://jsfiddle.net/prince4prodigy/aG72R/

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Sara Goodarzi
  • 227
  • 1
  • 3
  • 8
  • This could help: http://stackoverflow.com/questions/3486760/how-to-avoid-jquery-ui-draggable-from-also-triggering-click-event – Simon Steinberger Aug 03 '13 at 11:07
  • - notice the x and y postions of your div on load. - check if the div has beed moved - if yes,remove the style you have assigned – HIRA THAKUR Aug 03 '13 at 11:08
  • check out my solution (much easier than any in this thread) https://stackoverflow.com/a/58836706/5934567 – Andrey Nov 13 '19 at 12:03

8 Answers8

26

FIRST attach the draggable event, THEN the click event:

$(function(){
    $('div').draggable();
    $('div').click(function(){
        $(this).toggleClass('orange');
    });
});

Try it here: http://jsfiddle.net/aG72R/55/

Simon Steinberger
  • 6,605
  • 5
  • 55
  • 97
13

With an ES6 class (No jQuery)

To achieve this in javascript without the help of jQuery you can add and remove an event handler.

First create functions that will be added and removed form event listeners

flagged () {
    this.isScrolled = true;
}

and this to stop all events on an event

preventClick (event) {
    event.preventDefault();
    event.stopImmediatePropagation();
}

Then add the flag when the mousedown and mousemove events are triggered one after the other.

element.addEventListener('mousedown', () => {
    element.addEventListener('mousemove', flagged);
});

Remember to remove this on a mouse up so we don't get a huge stack of events repeated on this element.

element.addEventListener('mouseup', () => {
    element.removeEventListener('mousemove', flagged);
});

Finally inside the mouseup event on our element we can use the flag logic to add and remove the click.

element.addEventListener('mouseup', (e) => {
    if (this.isScrolled) {
        e.target.addEventListener('click', preventClick);
    } else {
        e.target.removeEventListener('click', preventClick);
    }
    this.isScrolled = false;
    element.removeEventListener('mousemove', flagged);
});

In the above example above I am targeting the real target that is clicked, so if this were a slider I would be targeting the image and not the main gallery element. to target the main element just change the add/remove event listeners like this.

element.addEventListener('mouseup', (e) => {
    if (this.isScrolled) {
        element.addEventListener('click', preventClick);
    } else {
        element.removeEventListener('click', preventClick);
    }
    this.isScrolled = false;
    element.removeEventListener('mousemove', flagged);
});

Conclusion

By setting anonymous functions to const we don't have to bind them. Also this way they kind of have a "handle" allowing s to remove the specific function from the event instead of the entire set of functions on the event.

Joe Lloyd
  • 19,471
  • 7
  • 53
  • 81
  • 1
    from all the 10 links i've searched on stackoverflow, and all the hours of testing. this was the single solution that worked..because IM NOT using jquery as everyone else...thanks a lot man! – João Vilaça Feb 23 '18 at 13:57
  • THANKS works great for me! I implemented it on my lightweight JS slider https://github.com/hrsetyono/hSlider – hrsetyono Jan 30 '19 at 13:47
5

I made a solution with data and setTimeout. Maybe better than helper classes.

<div id="dragbox"></div>

and

$(function(){
    $('#dragbox').bind('click', function(){
        if($(this).data('dragging')) return;
        $(this).toggleClass('orange');
    });

    $('#dragbox').draggable({
        start: function(event, ui){
            $(this).data('dragging', true);
        },
        stop: function(event, ui){
            setTimeout(function(){
                $(event.target).data('dragging', false);
            }, 1);
        }
    });
});

Check the fiddle.

MightyPork
  • 18,270
  • 10
  • 79
  • 133
2

This should work:

$(function(){

    $('div').draggable({
    start: function(event, ui) {
        $(this).addClass('noclick');
    }
});

$('div').click(function(event) {
    if ($(this).hasClass('noclick')) {
        $(this).removeClass('noclick');
    }
    else {
        $(this).toggleClass('orange');
    }
});
});

DEMO

Engineer
  • 5,911
  • 4
  • 31
  • 58
2

You can do it without jQuery UI draggable. Just using common 'click' and 'dragstart' events:

$('div').on('dragstart', function (e) {
  e.preventDefault();
  $(this).data('dragging', true);
}).on('click', function (e) {
  if ($(this).data('dragging')) {
    e.preventDefault();
    $(this).data('dragging', false);
  }
});
Anton Suslov
  • 103
  • 5
0

You can just check for jQuery UI's ui-draggable-dragging class on the draggable. If it's there, don't continue the click event, else, do. jQuery UI handles the setting and removal of this class, so you don't have to. :)

Code:

$(function(){
    $('div').bind('click', function(){
        if( $(this).hasClass('ui-draggable-dragging') ) { return false; }
        $(this).toggleClass('orange');
    });

    $('div').draggable();
});
Philip
  • 2,888
  • 2
  • 24
  • 36
0

With React

This code is for React users, checked the draggedRef when mouse up.

I didn`t use click event. The click event checked by the mouse up event.

const draggedRef = useRef(false);

...

<button
  type="button"
  onMouseDown={() => (draggedRef.current = false)}
  onMouseMove={() => (draggedRef.current = true)}
  onMouseUp={() => {
    if (draggedRef.current) return;

    setLayerOpened(!layerOpened);
  }}
>
  BTN
</button>

wantyouring
  • 187
  • 2
  • 13
0

I had the same problem (tho with p5.js) and I solved it by having a global lastDraggedAt variable, which was updated when the drag event ran. In the click event, I just checked if the last drag was less than 0.1 seconds ago.

function mouseDragged() {
    // other code
    lastDraggedAt = Date.now();
}

function mouseClicked() {
    if (Date.now() - lastDraggedAt < 100)
        return; // its just firing due to a drag so ignore
    // other code
}
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
xenon134
  • 28
  • 6