I am trying to attach a drop event to an HTML div:
document.getElementById('sub-main').addEventListener("drop",
() => {console.log('DROP')});
but it does not fire. Adding a click event for test purposes worked - this click event fires:
document.getElementById('sub-main').addEventListener("click",
() => {console.log('Click')});
I have read that returning false from ondragover will help:
document.getElementById('sub-main').addEventListener("ondragover",
() => {return false});
document.getElementById('sub-main').addEventListener("drop",
() => {console.log('Drop')});
But this does not work either. I tried setting draggable to true:
document.body.setAttribute('draggable', true);
But also no luck!
Logging the event listeners to the console with getEventListeners() shows all the events, even any random event name I chose:
getEventListeners(document.getElementById('sub-main'));
But the drop event still does not fire. Any ideas?
To enable dragging you should first of all disable the default behavior of the browser using the dragover event.
add this piece of code and it will work.
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
I did some trial and error in plunker and came to the conclusion that you first need to set the eventListener on the document(dont use.getElementById('sub-main') gives error in plunker at least) and then specify in the eventlistener on which target to fire on. And for it to detect that it can be dropped you need to have other eventListeners like: drag, dragstart, dragover, dragleave and dragenter. Just follow what they did here on MDN.
Related
I'm trying to handle touch/mouse events. So, I created this code:
myObject.addEventListener("touchstart", function(e){
e.stopPropagation();
e.preventDefault();
console.log("Touched");
mouseTouchDown(e);
});
myObject.addEventListener("mousedown", function(e){
console.log("Clicked");
mouseTouchDown(e);
});
function mouseTouchDown(e){
console.log("Some function.");};
I want to stop bubbling of touch event, so click won't be fired afterwards. It works on Chrome, but on Firefox I get in console:
Touched
Clicked
How can I stop mouse click firing after touch event?
I tried returning false, but it doesn't work.
This looks like a bug in the browser, your code looks fine.
See: https://bugzilla.mozilla.org/show_bug.cgi?id=977226.
What OS/version of Firefox are you testing this with?
Have u attached both events with same element?
If that is the case the error is not because of bubbling happening.while mouse click several events will happen like mousedown, touchstart ..etc.so if you want to avoid mouse click event occuring add preventDefault() in the mouse down.This will disable default mouse click event happening on that element.
I have the below JQuery eventhandler. I want to stop all navigations on a web page.
$(document).click(function(event) {
event.stopPropagation();
event.preventDefault();
event.cancelBubble = true;
event.stopImmediatePropagation();
$(document).css('border-color','');
$(document).css('background-color','');
$(event.target).css('border-color','yellow');
$(event.target).css('background-color','#6BFF70');
return false;
});
When I use this on Facebook Login page, it stops all navigations. But in Google home page, "I'm Feeling Lucky" button still navigates to next page. How do I avoid it?
I'm using JavaFX browser by the way. It is similar to Safari browser.
If I load the Google search page, and execute this at the console:
document.body.addEventListener(
"click",
function (ev) { ev.stopPropagation(); ev.preventDefault(); },
true);
then I cannot click the "I'm Feeling Lucky" button anymore. The key is to use the third parameter and set it to true. Here is what MDN [says] about it:
useCapture Optional
If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
(Emphasis added.)
What you tried to do does not work because your event handler is on document, and thus will be called after any event handlers on the children of the document. So your handler cannot prevent anything.
With useCapture set to true, you can operate on the event before it gets a chance to be passed to the child element. I do not know of a way to have jQuery's event handlers work in the way you get with useCapture. Barmar's answer here says you can't use jQuery to set such handler. I'm inclined to believe him.
99.99% of webpages won't be able to have their navigation stopped by stopping event propagation for the reason I commented (you can't stop the event before it triggers all handlers for the initial target of the event). If preventing navigation is all you are interested in, I recommend using the window.onbeforeunload event, which is made for this exact situation.
Here is an example: http://jsfiddle.net/ejreseuu/
HTML:
google
JS:
window.onbeforeunload = function() {
return "Are you sure?"
}
There is no way to not have a confirmation box that I know of, as code that locks the user out of navigating away no matter what they do is generally malicious.
preventDefault() should not work in this case, cause Google relied on custom event listeners to handle click events on this button. While preventDefault()
prevents browser's default behavior.
For example, if this button was of type="submit", preventing default on click event would prevent browser's default behavior, which is submitting a form. But in this case click is handled by eventListeners added to the button itself. preventDefault() won't affect catching an event by them. Nor stopPropagation(), because it stops propagation of event to higher levels of DOM, while other eventListeners on the same level (button in our case) still get the event. stopImmediatePropagation() could work in theory, but only if your eventListener was added before google's.
So the easiest way to stop propagation is to stop an event before it reaches button node, and that's on capture phase, because button is the lowest element in the hierarchy. This can be done by passing true argument while adding eventListener
document.body.addEventListener("click", function (event) {
event.stopPropagation();
}, true);
This way event will be stopped before bubble phase, and so before it reaches eventListeners added to the button. More on capture and bubble phases here
Note that preventDefault() is not needed in this case. Actually, this button's event listeners are to prevent default themselves. Here are those eventListeners, for click and keyup respectively:
d = function(a) {
c.Xa.search(c.yc(), b);
return s_1vb(a)
}
function(a) {
13 != a.keyCode && 32 != a.keyCode || d(a)
}
note call to s_1vb, here is its sourse:
s_1vb.toString();
/*"function (a){
a&&(a.preventDefault&&a.preventDefault(),a.returnValue=!1);
return!1
}"*/
Basically its a function that take an event and do everything possible to prevent browser's default behavior
By the way, default behavior can be canceled on any stage of event flow (se Events Specification), including the very last stage, when it reached document. Only after it passed "through" all eventListeners uncanceled, browser should execute its default behavior. So attaching your listener to document was not the reason preventDefault() didn't work, it was because it was the wrong guy for the job :)
Try this:
$('body').click(function(event) {
event.stopPropagation();
event.preventDefault();
event.cancelBubble = true;
event.stopImmediatePropagation();
$(document).css('border-color','');
$(document).css('background-color','');
$(event.target).css('border-color','yellow');
$(event.target).css('background-color','#6BFF70');
return false;
});
Try to bind not only to click event, but as well on mousedown event.
Try this css:
body * {
pointer-events: none;
}
or in jQuery:
$("body *").css("pointer-events", "none");
Try declaring a new window event and then stopping the propagation from there:
var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation)
{
e.stopPropagation();
}
Note that Google uses jsaction="..." instead of onclick="...". Try to use it's unbind method on the specified button.
Also you can use dynamic attachment, like:
$(document).on('click', '*', function
Or throw new Error()(just as a dirty hack)
It seems the drop event is not triggering when I would expect.
I assume that the drop event fires when an element that is being dragged is releases above the target element, but this doesn't seem to the the case.
What am I misunderstanding?
http://jsfiddle.net/LntTL/
$('.drop').on('drop dragdrop',function(){
alert('dropped');
});
$('.drop').on('dragenter',function(){
$(this).html('drop now').css('background','blue');
})
$('.drop').on('dragleave',function(){
$(this).html('drop here').css('background','red');
})
In order to have the drop event occur on a div element, you must cancel the ondragenter and ondragover events. Using jquery and your code provided...
$('.drop').on('drop dragdrop',function(){
alert('dropped');
});
$('.drop').on('dragenter',function(event){
event.preventDefault();
$(this).html('drop now').css('background','blue');
})
$('.drop').on('dragleave',function(){
$(this).html('drop here').css('background','red');
})
$('.drop').on('dragover',function(event){
event.preventDefault();
})
For more information, check out the MDN page.
You can get away with just doing an event.preventDefault() on the dragover event. Doing this will fire the drop event.
In order for the drop event to fire, you need to assign a dropEffect during the over event, otherwise the ondrop event will never get triggered:
$('.drop').on('dragover',function(event){
event.preventDefault();
event.dataTransfer.dropEffect = 'copy'; // required to enable drop on DIV
})
// Value for dropEffect can be one of: move, copy, link or none
// The mouse icon + behavior will change accordingly.
This isn't an actual answer but for some people like me who lack the discipline for consistency. Drop didn't fire for me in chrome when the effectAllowed wasnt the effect I had set for dropEffect. It did however work for me in Safari. This should be set like below:
ev.dataTransfer.effectAllowed = 'move';
Alternatively, effectAllowed can be set as all, but I would prefer to keep specificity where I can.
for a case when drop effect is move:
ev.dataTransfer.dropEffect = 'move';
I have tree structure in which mouse over on node name displays (UL) list. Each item in the list has a click event attached to it. The issue Im facing is when I click on any child item in list, it fires the mouseover event attached to parent span. Can you guys please help how to solve this issue?
<span id="treeNodeText">
<ul><li id="firstItem">First Item</li></ul>
</span>
My code is like this:
I have conman event attach method:
attachEvents(domId,eventType,callBackFunction,otherParams)
In attachEvent function I attach events to dom ids and assign appropriate call back functions
The mouseover event is fired before you click. So, apart with a delay, you can't prevent its handling.
Here's one way to deal with that :
var timer;
document.getElementById("treeNodeText").addEventListener('mouseover', function(){
clearTimeout(timer);
timer = setTimeout(function(){
// handle mouseover
}, 400); // tune that delay (depending on the sizes of elements, for example)
});
document.getElementById("firstItem").addEventListener('click', function(){
clearTimeout(timer); // prevents the mouseover event from being handled
// handle click
};
In JavaScript, events bubble up the DOM. Please read more about it: event order and propagation or preventDefault/stopPropagation.
In short, you can pervent event bubbling by
function callBackFunction(event){
event.stopPropagation()
}
or
function callBackFunction(event){
return false
}
return false also has the effect of preventing the default behavior, so it's technically equivalent to:
function callBackFunction(event){
event.stopPropagation()
event.preventDefault()
}
function myfunction(e){
e.stopPropagation()
e.preventDefault()
}
this will Help
jsfiddle
<div class='wrapper'>
<button class='child'>Click me</button>
</div>
function h(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
alert(e.type);
return false;
}
document.querySelector('.wrapper').addEventListener('mouseup', h, false);
document.querySelector('.child').addEventListener('click', h, false);
I expect this to prevent the 'click' event from firing, but it doesn't. However, changing mouseup to mousedown does in fact prevent the click event.
I've also tried setting the useCapture argument to true, and that also doesn't produce the desired behavior with mouseup. I've tested this on Chrome and Firefox. Before I file bugs, I figured I'd ask here.
Is this a bug in current browsers, or is it documented behavior?
I've reviewed the W3C standard (DOM level 2), and I wasn't able to find anything that could explain this behavior, but I could have missed something.
In my particular case, I'm trying to decouple two pieces of code that listen to events on the same element, and I figured using capture events on the part that has priority would be the most elegant way to solve this, but then I ran into this problem. FWIW, I only have to support officially supported versions of FF and Chrome (includes ESR for FF).
Check out this quirksmode article
The click event:
Fires when a mousedown and mouseup event occur on the same element.
So when the mouse click is released, both the mouseup and click events are fired, click doesn't wait for the mouseup callback to finish. Almost always, mouseup and click can be used synonymously.
In order to cancel the click, like you demonstrated, you can return false in the mousedown event callback which prevents the click event from ever completing.
I just want to provide my work around for this issue:
let click_works = true
this.addEventListener('mousedown', e => {
click_works = // condition why the click may work or not
})
this.addEventListener('click', e => {
if (click_works) // Do your stuff
})
Hopefully, it will help someone.
Finally found a way to prevent click event from firing. Tested on latest Chromium and Firefox. It may be some bug or implementation details.
Solution
Handle onpointerdown or onpointerup event, remove the element and insert it in the same position.
<span>
<button onpointerdown="let parent = this.parentElement; this.remove(); parent.appendChild(this);" onclick="alert();">TEST</button>
</span>
Result
onpointerdown
onmousedown
onpointerup
onmouseup
<-- no click event occures