Reputation: 27114
I have a throbber that is to appear when a user clicks a link.
The problem is is that that same link can be clicked and dragged to be rearranged. In this case, I wouldn't need the throbber to appear. It only needs to appear if its actually waiting to go somewhere.
How can I, with jQuery, create an event listener that would only allow a throbber to appear if its a click through to a link, and not a click and drag?
Upvotes: 121
Views: 209901
Reputation: 2985
Late to the party, but this code also detects touch events (mobile, tablet).
$(".draggable").on('touchstart mousedown', function(ev) {
ev.preventDefault();
$(this).on("touchmove mousemove",function(e){
var x = e.pageX || e.changedTouches[0].pageX;
var y = e.pageY || e.changedTouches[0].pageY;
var p1 = { x: x, y: y };
var p0 = $(this).data("p0") || p1;
console.log("dragging from x:" + p0.x + " y:" + p0.y + "to x:" + p1.x + " y:" + p1.y);
$(this).data("p0", p0);
});
}).on('touchend mouseup', function(ev) {
ev.preventDefault();
$(this).off("touchmove mousemove");
});
Upvotes: 2
Reputation: 3396
I needed a function that always keeps track of mouse position and detect left-, right-, top-, bottom- dragging. It also does not trigger on click but needs a minimum of 15px move
/**
* Check for drag when moved minimum 15px
* Same time keep track of mouse position while dragging
*/
// Variables to be accessed outside in other functions
var dragMouseX;
var dragMouseY;
var myDragging = false; // true or false
var dragDirectionX = false; // left or right
var dragDirectionY = false; // top or bottom
$(document).on("mousedown", function(e) {
// Reset some variables on mousedown
var lastDirectionCheck = e.timeStamp;
var dragStartX = e.pageX;
var dragStartY = e.pageY;
dragMouseX = e.pageX;
dragMouseY = e.pageY;
myDragging = false;
dragDirectionX = false;
dragDirectionY = false;
// On the move
$(document).on("mousemove", function(e) {
dragMouseX = e.pageX;
dragMouseY = e.pageY;
// Recalculate drag direction every 200ms in case user changes his mind
if (e.timeStamp > (lastDirectionCheck + 200)) {
dragStartX = dragMouseX;
dragStartY = dragMouseY;
lastDirectionCheck = e.timeStamp;
}
// Check for drag when moved minimum 15px in any direction
if (!myDragging && Math.abs(dragStartX - dragMouseX) > 15 || Math.abs(dragStartY - dragMouseY) > 15) {
myDragging = true;
}
if (myDragging) {
// Check drag direction X
if (dragStartX > dragMouseX) dragDirectionX = 'left';
if (dragStartX < dragMouseX) dragDirectionX = 'right';
// Check drag direction Y
if (dragStartY > dragMouseY) dragDirectionY = 'top';
if (dragStartY < dragMouseY) dragDirectionY = 'bottom';
// console.log(dragDirectionX + ' ' + dragDirectionY);
}
});
});
// Reset some variables again on mouseup
$(document).on("mouseup", function() {
$(document).off("mousemove");
myDragging = false;
dragDirectionX = false;
dragDirectionY = false;
});
Upvotes: 0
Reputation: 3405
I branched off from the accepted answer to only run when the click is being HELD down and dragged.
My function was running when I wasn't holding the mouse down. Here's the updated code if you also want this functionality:
var isDragging = false;
var mouseDown = false;
$('.test_area')
.mousedown(function() {
isDragging = false;
mouseDown = true;
})
.mousemove(function(e) {
isDragging = true;
if (isDragging === true && mouseDown === true) {
my_special_function(e);
}
})
.mouseup(function(e) {
var wasDragging = isDragging;
isDragging = false;
mouseDown = false;
if ( ! wasDragging ) {
my_special_function(e);
}
}
);
Upvotes: 2
Reputation: 21
Make sure you set the element's draggable attribute to false so you don't have side effects when listening to mouseup events:
<div class="thing" draggable="false">text</div>
Then, you can use jQuery:
$(function() {
var pressed, pressX, pressY,
dragged,
offset = 3; // helps detect when the user really meant to drag
$(document)
.on('mousedown', '.thing', function(e) {
pressX = e.pageX;
pressY = e.pageY;
pressed = true;
})
.on('mousemove', '.thing', function(e) {
if (!pressed) return;
dragged = Math.abs(e.pageX - pressX) > offset ||
Math.abs(e.pageY - pressY) > offset;
})
.on('mouseup', function() {
dragged && console.log('Thing dragged');
pressed = dragged = false;
});
});
Upvotes: 2
Reputation: 373
With jQuery UI just do this!
$( "#draggable" ).draggable({
start: function() {
},
drag: function() {
},
stop: function() {
}
});
Upvotes: 27
Reputation: 9156
You don`t have to setup variable, you can just set if it is moving in data-attribute
$youtubeSlider.find('a')
.on('mousedown', function (e) {
$(this).data('moving', false);
})
.on('mousemove', function (e) {
$(this).data('moving', true);
})
.on('mouseup', function (e) {
if (!$(this).data('moving')) {
// Open link
}
});
Upvotes: 0
Reputation: 51
$(".draggable")
.mousedown(function(e){
$(this).on("mousemove",function(e){
var p1 = { x: e.pageX, y: e.pageY };
var p0 = $(this).data("p0") || p1;
console.log("dragging from x:" + p0.x + " y:" + p0.y + "to x:" + p1.x + " y:" + p1.y);
$(this).data("p0", p1);
});
})
.mouseup(function(){
$(this).off("mousemove");
});
This solution uses the "on" and "off" functions to bind an unbind a mousemove event (bind and unbind are deprecated). You can also detect the change in mouse x and y positions between two mousemove events.
Upvotes: 5
Reputation: 11293
On mousedown, start set the state, if the mousemove event is fired record it, finally on mouseup, check if the mouse moved. If it moved, we've been dragging. If we've not moved, it's a click.
var isDragging = false;
$("a")
.mousedown(function() {
isDragging = false;
})
.mousemove(function() {
isDragging = true;
})
.mouseup(function() {
var wasDragging = isDragging;
isDragging = false;
if (!wasDragging) {
$("#throbble").toggle();
}
});
Here's a demo: http://jsfiddle.net/W7tvD/1399/
Upvotes: 239
Reputation: 1536
// here is how you can detect dragging in all four directions
var isDragging = false;
$("some DOM element").mousedown(function(e) {
var previous_x_position = e.pageX;
var previous_y_position = e.pageY;
$(window).mousemove(function(event) {
isDragging = true;
var x_position = event.pageX;
var y_position = event.pageY;
if (previous_x_position < x_position) {
alert('moving right');
} else {
alert('moving left');
}
if (previous_y_position < y_position) {
alert('moving down');
} else {
alert('moving up');
}
$(window).unbind("mousemove");
});
}).mouseup(function() {
var wasDragging = isDragging;
isDragging = false;
$(window).unbind("mousemove");
});
Upvotes: 2
Reputation: 13
jQuery plugin based on Simen Echholt's answer. I called it single click.
/**
* jQuery plugin: Configure mouse click that is triggered only when no mouse move was detected in the action.
*
* @param callback
*/
jQuery.fn.singleclick = function(callback) {
return $(this).each(function() {
var singleClickIsDragging = false;
var element = $(this);
// Configure mouse down listener.
element.mousedown(function() {
$(window).mousemove(function() {
singleClickIsDragging = true;
$(window).unbind('mousemove');
});
});
// Configure mouse up listener.
element.mouseup(function(event) {
var wasDragging = singleClickIsDragging;
singleClickIsDragging = false;
$(window).unbind('mousemove');
if(wasDragging) {
return;
}
// Since no mouse move was detected then call callback function.
callback.call(element, event);
});
});
};
In use:
element.singleclick(function(event) {
alert('Single/simple click!');
});
^^
Upvotes: 1
Reputation: 31
Try this: it shows when is 'dragged' state. ;) fiddle link
$(function() {
var isDragging = false;
$("#status").html("status:");
$("a")
.mousedown(function() {
$("#status").html("status: DRAGGED");
})
.mouseup(function() {
$("#status").html("status: dropped");
});
$("ul").sortable();
});
Upvotes: 3
Reputation: 3353
For this simplest way is touch start, touch move and touch end. That is working for both PC and touch device just check it in jquery documentation and hope this is the best solution for you. good luck
Upvotes: 1
Reputation: 995
For some reason, the above solutions were not working for me. I went with the following:
$('#container').on('mousedown', function(e) {
$(this).data('p0', { x: e.pageX, y: e.pageY });
}).on('mouseup', function(e) {
var p0 = $(this).data('p0'),
p1 = { x: e.pageX, y: e.pageY },
d = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2));
if (d < 4) {
alert('clicked');
}
})
You can tweak the distance limit to whatever you please, or even take it all the way to zero.
Upvotes: 29
Reputation: 4498
If you're using jQueryUI - there is an onDrag event. If you're not, then attach your listener to mouseup(), not click().
Upvotes: -1
Reputation: 114347
You've need to set a timer. When the timer times out, start the throbber and register the click. When drag occurs, clear the timer so it never completes.
Upvotes: 0