I hope this might be a low-hanging fruit for all you web-dev experts out there:
I have implemented event delegation by attaching a mouse click handler to a parent element of an unordered list of anchor elements (classic navigation design). The document I am working on exists in an iFrame. The handler looks like this:
const handleMouseClick = function(evt) {
if (evt.target.matches('a')) {
evt.preventDefault();
evt.stopPropagation();
console.log('Clicked a tag....', event.target.href);
}
};
Just to provide a full context, I am clicking through an overlay element that takes no pointer events - so it should have no influence on click handling.
Anyway, when clicking on one of the anchor tags, I would like to prevent the iframe from loading the URL referenced in the anchor. The before mentioned click handler, which is attached to a parent, receives the click event just fine and I would have expected that calling event.preventDefault() would do the trick. However, I have to call both
event.preventDefault() and event.stopPropagation() to stop the iframe from loading the link. If I remove either one of them, the iframe loads the link?
My first thought on this is that this is unexpected, when looking at the literature on preventDefault and stopPropagation but I might be missing something. What am I missing - why is event.preventDefault() not sufficient in this case?
In JavaScript/jQuery, I am registering click and touchstart events on a button, with this:
$('#open-about-popup').on('touchstart click', openAboutPopup_eventHandler)
Then in the event-handler, I have this:
e.stopPropagation();
e.preventDefault();
This is causing the next button-click not to fire. Do I have something wrong?
Thanks.
e.stopPropagation() prevents the event from bubbling up the DOM tree, e.preventDefault() prevents the browser from doing whatever default behavior is associated with the event - e.g. a click event on an <a> tag will make the browser redirect to the href of the link, but if you use preventDefault, it won't do that.
I fund the problem. It is unrelated to the post. Thanks.
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)
When I use event.preventDefault() on a link it works, however when I use it on a button doesn't!
DEMO
My code:
<a id="link" href="http://www.google.com">link</a>
<button id="button" onclick="alert('an alert')">button</button>
$('#link').click(function(event){
event.preventDefault();
});
$('#button').click(function(event){
event.preventDefault();
});
Link action is cancelled, but when I click on the button, still executes the onClick action.
Any help? what I want to do is to prevent the button onClick action without changing the button html (I know how to do
$('#button').removeAttr('onclick');
You want event.stopImmediatePropagation(); if there are multiple event handlers on an element and you want to prevent the others to execute. preventDefault() just blocks the default action (such as submitting a form or navigating to another URL) while stopImmediatePropagation() prevents the event from bubbling up the DOM tree and prevents any other event handlers on the same element from being executed.
Here are some useful links explaining the various methods:
http://api.jquery.com/event.preventDefault/
http://api.jquery.com/event.stopPropagation/
http://api.jquery.com/event.stopImmediatePropagation/
However, since it still doesn't work it means that the onclick="" handler executes before the attached event handler. There's nothing you can do since when your code runs the onclick code has already been executed.
The easiest solution is completely removing that handler:
$('#button').removeAttr('onclick');
Even adding an event listener via plain javascript (addEventListener()) with useCapture=true doesn't help - apparently inline events trigger even before the event starts descending the DOM tree.
If you just do not want to remove the handler because you need it, simply convert it to a properly attached event:
var onclickFunc = new Function($('#button').attr('onclick'));
$('#button').click(function(event){
if(confirm('prevent onclick event?')) {
event.stopImmediatePropagation();
}
}).click(onclickFunc).removeAttr('onclick');
you need stopImmediatePropagation not preventDefault. preventDefault prevents default browser behavior, not method bubbling.
http://api.jquery.com/event.stopImmediatePropagation/
http://api.jquery.com/event.preventDefault/
The preventDefault function does not stop event handlers from being triggered, but rather stops the default action taking place. For links, it stops the navigation, for buttons, it stops the form from being submitted, etc.
What you are looking for is stopImmediatePropagation.
you can try this:
$('#button').show(function() {
var clickEvent = new Function($(this).attr('click')); // store it for future use
this.onclick = undefined;
});
DEMO
It have helped me
function goToAccessoriesPage(targert) {
targert.onclick.arguments[0].preventDefault();
...
}
I am using event.preventDefault() to prevent concatenation of # which is the href of an anchor to the URL. I am performing events on the mousedown() and mouseup() parts of the click which is why I can't use click. But event.preventDefault() is not preventing the concatenation of # to the URL when envoking mouseup() or mousedown() methods. How can I get around this?
If you're talking about clicking a link, it is probably because there isn't a default behavior to prevent for mousedown and mouseup.
The default behavior of clicking a link requires a combination of mousedown plus mouseup on the link. If you mousedown then drag off the link before you mouseup, the link is not followed. The same vice-versa.
Only when you mousedown then mouseup is the default behavior activated. That event is represented by the click event.
EDIT: I guess I forgot to answer the question.
How do you get around it? Add a click() event handler that does e.preventDefault().
$('a.myElement').click(function(e){e.preventDefault()});
If you also want to stop propagation of the event, and if you're using jQuery 1.4.3 or later, you can do this:
$('a.myElement').bind('click',false);
From the docs for the bind()(docs) method:
Setting the third argument to false will attach a function that prevents the default action from occurring and stops the event from bubbling.
Again, it requires jQuery 1.4.3 or later.