How to get mouseup event after native drag event? - javascript

The implementation of the WHATWG drag and drop supports dragstart, drag and dragend events.
The dragend event fires when the draggable object returns to the original position, e.g. try dragging the red box as far as you can and release it. The dragend (and "END!" console.log message) will not fire until the draggable element returns to the original position (this is most visible in the Safari browser).
var handle = document.querySelector('#handle');
handle.addEventListener('dragend', function () {
console.log('END!');
});
#handle {
background: #f00; width: 100px; height: 100px;
}
<div id="handle" draggable="true"></div>
How do I capture the mouseup or whatever else event that would indicate the release of the drag handle without a delay?
I have tried variations of:
var handle = document.querySelector('#handle');
handle.addEventListener('dragend', function () {
console.log('END!');
});
handle.addEventListener('mouseup', function () {
console.log('Mouseup');
});
#handle {
background: #f00; width: 100px; height: 100px;
}
<div id="handle" draggable="true"></div>
Though, "mouseup" does not fire after dragstart.
The closest I got to finding an event that would fire instantly after the release of the handle is mousemove:
var handle = document.querySelector('#handle');
handle.addEventListener('dragend', function () {
console.log('END!');
});
window.addEventListener('mousemove', function () {
console.log('I will not fire during the drag event. I will fire after handle has been released and mouse is moved.');
});
#handle {
background: #f00; width: 100px; height: 100px;
}
<div id="handle" draggable="true"></div>
The problem is that this approach requires user to move the mouse.

The workaround is to enable drop on the document.body:
// #see https://developer.mozilla.org/en-US/docs/Web/Events/dragover
document.body.addEventListener('dragover', function (e) {
// Prevent default to allow drop.
e.preventDefault();
});
document.body.addEventListener('drop', function (e) {
// Prevent open as a link for some elements.
e.preventDefault();
});
Making document.body to listen for the drop event results in dragend thinking that you will move the element to the new position upon releasing the handle. Therefore, there is no delay between handle release and dragend.

Related

Javascript mousemove event not triggered when in object

I hope your doing fine.
Here's my problem :
This code works fine :
var imageMover = {
mouseDown: function(e) {
e.target.addEventListener("mousemove", mouseMoved, false);
console.log('mouseDown');
},
mouseUp: function(e) {
e.target.removeEventListener("mousemove", mouseMoved, false);
console.log('mouseUp');
}
};
function mouseMoved(e) {
console.log("mouseMoved");
}
While this one is not :
var imageMover = {
mouseDown: function(e) {
e.target.addEventListener("mousemove", this.mouseMoved, false);
console.log('mouseDown');
},
mouseUp: function(e) {
e.target.removeEventListener("mousemove", this.mouseMoved, false);
console.log('mouseUp');
},
mouseMoved: function(e) {
console.log("mouseMoved");
}
};
To give a little more context: There are thumbnails you can click on.
When you click on it, the image is added to a container, and the events mouseUp and mouseDown are added to the image.
When someone click on the image, i'd like the event mouseMouve to be attached so I can follow the image position.
mouseUp and mouseDown are well attached, and well triggered, but mouseMouve only works when it is not inside my imageMover object.
It seems to be a scope problem, but I can't figure why it acts like that.
In advance, many thanks !
The this from this.mouseMoved is refering to the event target, which is the DOM element not the object storing the methods.
var imageMover = {
mouseDown: function(e) {
console.log( 'this is refering to => ', this );
e.target.addEventListener("mousemove", this.mouseMoved, false);
}
};
document.querySelector( '.container' ).addEventListener( 'mousedown', imageMover.mouseDown );
.container
{
width: 500px;
height: 100px;
border: 1px solid #000;
}
<div class="container"></div>

jquery and hammer.js ghost click when panning

I'm using jQuery 191 and Hammer JS 204. I have the following example scenario
<div> class="myDiv">
<div class="content">
<img>
</div>
</div>
Example JS
$('.myDiv').hammer({}).bind("pan", function(h) {
h.gesture.srcEvent.preventDefault();
});
$('.content img').on('click', function(){
console.log('i was clicked');
});
When I click on the image to start panning myDiv, Right after panend, the myDiv img click event gets fired.
I've tried to stopPropagation and stopImmediatePropagation but still couldn't get it to stop firing the click after i finish panning.
var hammering = false;
$('.myDiv').hammer({}).bind("pan", function(h) {
h.gesture.srcEvent.preventDefault();
}).bind("panstart", function(h) {
hammering = true;
}).bind("panend", function(h) {
setTimeout(function(){
hammering = false;
}, 300);
});
$('.content img').on('click', function(){
if(hammering) return false;
console.log('i was clicked');
});
Another way to avoid this ghost click is to create a pseudo class over the hammer target.
for example you can add class and the style something like
`.block:after {
content: " ";
background: transparent;
top: 0;
left: 0;
width: 250px;
height: 100%;
z-index: 2;
display: block;
position: absolute;
}`
when panstart and remove it when panend.
hope this trick will help others.
I find out a easy way could prevent click event while hammer.js panning:
disable div pointer-events while pan start, then enable it while pan end.
...
myPanGesture.on("panstart", function(ev) {
$(".tab-pane.active").css({'pointer-events':'none'});
});
...
myPanGesture.on("panend", function(ev) {
$(".tab-pane.active").css({'pointer-events':'auto'});
});
...

Adding New Element during `mousedown` event prevent triggering `click` event?

I am working with jquery events and I am adding a new element at the time of mousedown at the position of the mouse pointer and after adding the element the binded click event is not triggered.
Any suggestion is appreciable.
Thanks in advance.
Madhu
Code:
<div style="border:1px solid">Click</div>
<span></span>
<div class="vis" style="display:none">Hello</div>
<script>
var visualEle = $('div.vis');
visualEle.css({border:"1px solid"});
$('a').on("click", function (e) { e.preventDefault();});
$('div').on("mousedown", mDown);
$('div').on("mouseup",mUp);
function mDown(e) {
e.preventDefault();
visualEle.css({ left: 100, top: 0, display: "block" });
}
function mUp(e) {
e.preventDefault();
$('span').append('mouse up triggerd<br/>');
return false;
}
$('p').on("click",dClick);
function dClick(e) {
$('span').append('double click triggerd<br/>');
}
</script>
In the above code the click event is not triggered after the mousedown is completed.
according to this document
The click event is sent to an element when the mouse pointer is over the element, and the mouse button is pressed and released
in your case mouse point is over when mousedown happen but after that visualDiv moves under and mouse is released on this element.
possible solution I can think of thanks to #ArunPJohny is use $(this).trigger("click");
$('p').on("mousedown", function (e) {
_x = e.pageX;
_y = e.pageY;
visualDiv.css({
left: _x,
top: _y
});
$(this).trigger("click");
});
$('p').on("click", function (e) {
console.log(e.target)
});
Demo: http://jsfiddle.net/c5CRd/

toggle- hide item when click outside of the div

I am using jquery's slidetoggle, want to learn how to make the showup class hide when click anywhere outside of the DIV.
thanks!
Online SAMPLE: http://jsfiddle.net/evGd6/
<div class="click">click me</div>
<div class="showup">something I want to show</div>​
$(document).ready(function(){
$('.click').click(function(){
$(".showup").slideToggle("fast");
});
});​
.showup {
width: 100px;
height: 100px;
background: red;
display:none;
}
.click {
cursor: pointer;
}
​
Stop event propagation from within the .showup area:
$(document).on("click", function () {
$(".showup").hide();
});
Then prevent those clicks on .showup from bubbling up to the document:
$(".showup").on("click", function (event) {
event.stopPropagation();
});
Any click event that reaches the document will result in the .showup element being hidden. Any click events that start from within .showup will be prevented from proceeding any further up the DOM tree, and thus will never reach the document.
You will also need to stop any clicks on your button from traveling up to the document as well:
$(".click").on("click", function (event) {
event.stopPropagation();
$(".showup").slideToggle("fast");
});
Otherwise that click event will bubble up to the document and result in the hiding of .showup immediately.
Demo: http://jsfiddle.net/evGd6/2/
If you still want to record clicks on .showup panel (lets say you want it to be more then a simple informative panel), calling event.stopPropagation() on clicking it will make that panel untouchable/useless. Use event.cancelBubble = true instead and will let the event occur on .showup childs.
$('.click').click(function(){
$(".showup").toggle();
});
$(".showup").on("click", function (/*nothing here*/) {
event.cancelBubble = true
});
$(document).on("click", function () {
$(".showup").hide();
});

Stopping propagation of mousedown/mouseup from a click handler

Here's a DEMO.
I have two divs, an inner and an outer:
<div id="outer">
<div id="inner"></div>
</div>
With some CSS so you can see which is which:
#outer {
width: 250px;
height: 250px;
padding: 50px;
background: yellow;
}
#inner {
width: 250px;
height: 250px;
background: blue;
}
I try to stop propagation of mousedown and mouseup events from within a click handler like so:
$('#inner').on('click', function(e) {
e.stopPropagation();
$(this).css({'background': 'green'});
return false;
});
$('#outer').on('mousedown', function(e) {
$(this).css({'background': 'green'});
});
$('#outer').on('mouseup', function(e) {
$(this).css({'background': 'yellow'});
});
This doesn't seem possible. What does work is calling .stopPropagation from within other mousedown and mouseup calls, as shown here (another DEMO):
$('#inner').on('mousedown', function(e) {
e.stopPropagation();
return false;
});
$('#inner').on('mouseup', function(e) {
e.stopPropagation();
return false;
});
I may have already answered my own question, but I'm not sure if my approach is the best or most reasonable. Is this the right way to stop an event bubbling up to a mousedown and mouseup?
Yes. Since mouseclick and mousedown/mouseup are different events, you can't get at one from the other at all - you have to do it from within your own mousedown/mouseup handlers. What you can do is refactor that into a generic method to use in both places:
stopPropagation('#inner', 'mousedown');
stopPropagation('#inner', 'mouseup');
function stopPropagation(id, event) {
$(id).on(event, function(e) {
e.stopPropagation();
return false;
});
}

Categories

Resources