When I want to prevent other event handlers from executing after a certain event is fired, I can use one of two techniques. I'll use jQuery in the examples, but this applies to plain-JS as well:
1. event.preventDefault()
$('a').click(function (e) {
// custom handling here
e.preventDefault();
});
2. return false
$('a').click(function () {
// custom handling here
return false;
});
Is there any significant difference between those two methods of stopping event propagation?
For me, return false; is simpler, shorter and probably less error prone than executing a method. With the method, you have to remember about correct casing, parenthesis, etc.
Also, I have to define the first parameter in callback to be able to call the method. Perhaps, there are some reasons why I should avoid doing it like this and use preventDefault instead? What's the better way?
return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object.
e.preventDefault() will prevent the default event from occuring, e.stopPropagation() will prevent the event from bubbling up and return false will do both. Note that this behaviour differs from normal (non-jQuery) event handlers, in which, notably, return false does not stop the event from bubbling up.
Source: John Resig
Any benefit to using event.preventDefault() over "return false" to cancel out an href click?
From my experience, there is at least one clear advantage when using event.preventDefault() over using return false. Suppose you are capturing the click event on an anchor tag, otherwise which it would be a big problem if the user were to be navigated away from the current page. If your click handler uses return false to prevent browser navigation, it opens the possibility that the interpreter will not reach the return statement and the browser will proceed to execute the anchor tag's default behavior.
$('a').click(function (e) {
// custom handling here
// oops...runtime error...where oh where will the href take me?
return false;
});
The benefit to using event.preventDefault() is that you can add this as the first line in the handler, thereby guaranteeing that the anchor's default behavior will not fire, regardless if the last line of the function is not reached (eg. runtime error).
$('a').click(function (e) {
e.preventDefault();
// custom handling here
// oops...runtime error, but at least the user isn't navigated away.
});
This is not, as you've titled it, a "JavaScript" question; it is a question regarding the design of jQuery.
jQuery and the previously linked citation from John Resig (in karim79's message) seem to be the source misunderstanding of how event handlers in general work.
Fact: An event handler that returns false prevents the default action for that event. It does not stop the event propagation. Event handlers have always worked this way, since the old days of Netscape Navigator.
Event handler content attributes and event handler IDL attributes that returns false prevents the default action for that event handler.
What happens in jQuery is not the same as what happens with event handlers. DOM event listeners and MSIE "attached" events are a different matter altogether.
For further reading, see the[ [W3C DOM 2 Events documentation]][1].
Generally, your first option (preventDefault()) is the one to take, but you have to know what context you're in and what your goals are.
Fuel Your Coding has a great article on return false; vs event.preventDefault() vs event.stopPropagation() vs event.stopImmediatePropagation().
When using jQuery, return false is doing 3 separate things when you call it:
event.preventDefault();
event.stopPropagation();
Stops callback execution and returns immediately when called.
See jQuery Events: Stop (Mis)Using Return False for more information and examples.
You can hang a lot of functions on the onClick event for one element. How can you be sure the false one will be the last one to fire? preventDefault on the other hand will definitely prevent only the default behavior of the element.
I think
event.preventDefault()
is the w3c specified way of canceling events.
You can read this in the W3C spec on Event cancelation.
Also you can't use return false in every situation. When giving a javascript function in the href attribute and if you return false then the user will be redirected to a page with false string written.
I think the best way to do this is to use event.preventDefault() because if some exception is raised in the handler, then the return false statement will be skipped and the behavior will be opposite to what you want.
But if you are sure that the code won't trigger any exceptions, then you can go with any of the method you wish.
If you still want to go with the return false, then you can put your entire handler code in a try catch block like below:
$('a').click(function (e) {
try{
your code here.........
}
catch(e){}
return false;
});
The main difference between return false and event.preventDefault() is that your code below return false will not be executed and in event.preventDefault() case your code will execute after this statement.
When you write return false it do the following things for you behind the scenes.
* Stops callback execution and returns immediately when called.
* event.stopPropagation();
* event.preventDefault();
e.preventDefault();
It simply stops the default action of an element.
Instance Ex.:-
prevents the hyperlink from following the URL, prevents the submit button to submit the form. When you have many event handlers and you just want to prevent default event from occuring, & occuring from many times,
for that we need to use in the top of the function().
Reason:-
The reason to use e.preventDefault(); is that in our code so something goes wrong in the code, then it will allow to execute the link or form to get submitted or allow to execute or allow whatever action you need to do. & link or submit button will get submitted & still allow further propagation of the event.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Preventsss page from redirect
<script type="text/javascript">
function doSomethingElse(){
console.log("This is Test...");
}
$("a").click(function(e){
e.preventDefault();
});
</script>
</body>
</html>
return False;
It simply stops the execution of the function().
"return false;" will end the whole execution of process.
Reason:-
The reason to use return false; is that you don't want to execute the function any more in strictly mode.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
Blah
<script type="text/javascript">
function returnFalse(){
console.log("returns false without location redirection....")
return false;
location.href = "http://www.google.com/";
}
</script>
</body>
</html>
Basically, this way you combine things because jQuery is a framework which mostly focuses on HTML elements, you basically preventing the default, but at the same time, you stop propagation to bubble up.
So we can simply say, return false in jQuery is equal to:
return false is e.preventDefault AND e.stopPropagation
But also don't forget it's all in jQuery or DOM related functions, when you run it on the element, basically, it prevents everything from firing including the default behaviour and propagation of the event.
Basically before starting using return false;, first understand what e.preventDefault(); and e.stopPropagation(); do, then if you think you need both at the same time, then simply use it.
So basically this code below:
$('div').click(function () {
return false;
});
is equal to this code:
$('div').click(function (event) {
event.preventDefault();
event.stopPropagation();
});
From my experience event.stopPropagation() is mostly used in CSS effect or animation works, for instance when you have hover effect for both card and button element, when you hover on the button both card and buttons hover effect will be triggered in this case, you can use event.stopPropagation() stop bubbling actions, and event.preventDefault() is for prevent default behaviour of browser actions. For instance, you have form but you only defined click event for the submit action, if the user submits the form by pressing enter, the browser triggered by keypress event, not your click event here you should use event.preventDefault() to avoid inappropriate behavior. I don't know what the hell is return false; sorry.For more clarification visit this link and play around with line #33 https://www.codecademy.com/courses/introduction-to-javascript/lessons/requests-i/exercises/xhr-get-request-iv
My opinion from my experience saying, that it is always better to use
event.preventDefault()
Practically
to stop or prevent submit event, whenever we required rather than return false
event.preventDefault() works fine.
preventDefault() and return false are different ways to prevent the default event from happening.
For example, when a user clicks on an external link, we should display a confirmation modal that asks the user for redirecting to the external website or not:
hyperlink.addEventListener('click', function (e) {
// Don't redirect the user to the link
e.preventDefault();
});
Or we don't want to submit the form when clicking its submit button. Instead, we want to validate the form first:
submitButton.addEventListener('click', function (e) {
// Don't submit the form when clicking a submit
e.preventDefault();
});
Differences
return false doesn't have any effect on the default behavior if you use the addEventListener method to handle an event. It only works when the event handler is declared as an element's attribute:
hyperlink.addEventListener('click', function (e) {
// Does NOT work
return false;
});
// Work
hyperlink.onclick = function (e) {
return false;
};
According to the HTML 5 specifications, return false will cancel the event except for the mouseover event.
Good practices
It's recommended to use the preventDefault method instead of return false inside an event handler. Because the latter only works with using the onclick attribute which will remove other handlers for the same event.
If you're using jQuery to manage the events, then you're able to use return false within the event handler:
$(element).on('click', function (e) {
return false;
});
Before returning the value of false, the handler would do something else. The problem is that if there's any runtime error occurring in the handler, we will not reach the return false statement at the end.
In that case, the default behavior will be taken:
$(element).on('click', function (e) {
// Do something here, but if there's an error at runtime
// ...
return false;
});
We can avoid this situation by using the preventDefault method before performing any custom handler:
$(element).on('click', function (e) {
e.preventDefault();
// Do something here
// The default behavior is prevented regardless of errors at runtime
// ...
});
Good to know
If you're using jQuery to manage the event, then return false will behave the same as the preventDefault() and stopPropagation() methods:
$(element).on('click', function (e) {
// Prevent the default event from happening and
// prevent the event from bubbling up to the parent element
return false;
});
Related
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)
I don't have an example at hand, but in some situations calling event.preventDefault() lets the original event through (navigating to page, submitting form etc) but returning false helps. What could cause this?
You don't have an example to hand? OK, let me invent one that may or may not be whatever it was you were thinking of.
Remember that return false; is the equivalent of calling both event.preventDefault(); and event.stopPropagation(). EDIT: This applies with jQuery, which explictly implements this behaviour and also normalises event.preventDefault() and event.stopPropagation() for use in all browsers. It doesn't work that way in all browsers with "plain" JS, in fact older IE versions don't support event.preventDefault() at all, they have their own equivalent event.returnValue = false;
If you have nested elements and you handle the same event in several levels then calling event.preventDefault() will not stop the outer elements' event handlers from running, but return false will because it stops propagation of the event.
An example that demonstrates it: http://jsfiddle.net/nnnnnn/KjLv3/
<span>Click me to see an alert</span>
// using jQuery for simplicity in the example:
$("a span").click(function(e){
e.preventDefault();
});
$("a").click(function() {
alert("Hello");
});
The alert will display. If you change the "a span" handler to return false the alert will not display.
event.preventDefault() prevents the browser from performing the default action ( if the event is cancelable ) without stopping further propagation of the event, whereas
return false prevents the event from propagating (or "bubbling up") the DOM, along with preventing the default action.
So,
function() {
return false;
}
// IS EQUAL TO
function(e) {
e.preventDefault();
e.stopPropagation();
}
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();
...
}
Before I start writing huge swathes of code that don't work I thought I'd ask this question.
event.preventDefault() only cancels the default action of the click event doesn't it?
Theoretically I should be able to bind mutiple click event handlers in jQuery to a given target to perform different actions like Ajax posts and Google tracking.
Am I wrong?
event.preventDefault() only cancels the default action of the click event doesn't it?
It cancels the browser's default action of the event (not just the click event) (W3C docs, jQuery docs). So for instance, in the form submit event, it prevents the form being submitted by the browser. It doesn't stop anything you're doing in code, and it doesn't stop bubbling; that's what stopPropagation is for (W3C docs, jQuery docs).
So say you have a link in a div, and you have the click event hooked on both the link and the div. If the link's event handler calls preventDefault, the browser won't do its default action (following the link), but the event continues to bubble up the DOM to the link's parent element, the div, and so you'll see the event on your click handler there, too. Any actions you're taking in code in either handler will be unaffected by your calling preventDefault.
In your comment below, you ask about multiple handlers on the same element. Neither preventDefault nor stopPropagation affects those, they'll still get fired...unless you use stopImmediatePropagation, which tells jQuery to stop the event dead in its tracks (but doesn't prevent the browser's default action).
I should probably round this out by saying that if you return false from your event handler, that tells jQuery to prevent the default and stop bubbling. It's just like calling preventDefault and stopPropagation. It's a handy shortcut form for when your event handler is taking full control of the event.
So, given this HTML:
<div id='foo'><a href='http://stackoverflow.com'>Q&A</a></div>
Example 1:
// Here we're preventing the default but not stopping bubbling,
// and so the browser won't follow the link, but the div will
// see the event and the alert will fire.
$("#foo").click(function() {
alert("foo clicked");
});
$("#foo a").click(function(event) {
event.preventDefault();
});
Example 2:
// Here we're stopping propagation and not preventing the default;
// the browser will follow the link and the div will not be given
// a chance to process the event (no alert, and more to the point,
// code in the div's handler can't prevent the default)
$("#foo").click(function() {
alert("foo clicked");
});
$("#foo a").click(function(event) {
event.stopPropagation();
});
Example 3 (you'll only rarely see this):
// Here we're doing both, and so the browser doesn't follow the
// link and the div doesn't see the event (no alert).
$("#foo").click(function() {
alert("foo clicked");
});
$("#foo a").click(function(event) {
event.preventDefault();
event.stopPropagation();
});
Example 4:
// Shorter version of Example 3, exactly the same effect
$("#foo").click(function() {
alert("foo clicked");
});
$("#foo a").click(function() {
return false;
});
It is said that when we handle a "click event", returning false or calling event.preventDefault() makes a difference, in which
the difference is that preventDefault
will only prevent the default event
action to occur, i.e. a page redirect
on a link click, a form submission,
etc. and return false will also stop
the event flow.
Does that mean, if the click event is registered several times for several actions, using
$('#clickme').click(function() { … })
returning false will stop the other handlers from running?
I am on a Mac now and so can only use Firefox and Chrome but not IE, which has a different event model, and tested it on Firefox and Chrome by adding 3 handlers, and all 3 handlers ran without any stopping…. so what is the real difference, or, is there a situation where "stopping the event flow" is not desirable?
This is related to
Using jQuery's animate(), if the clicked on element is "<a href="#" ...> </a>", the function should still return false?
and
What's the difference between e.preventDefault(); and return false?
hopes this code can explain it to you...
html
<div>
click me
click me
</div>
jquery
$('div').click(function(){
alert('I am from <div>');
});
$('a.a1').click(function(){
alert('I am from <a>');
return false; // this will produce one alert
});
$('a.a2').click(function(e){
alert('I am from <a>');
e.preventDefault(); // this will produce two alerts
});
demo
or
$('div').click(function(){
alert('I am from <div>');
});
$('a').click(function(){
alert('I am from <a>');
});
$('a.a1').click(function(){
alert('I am from <a class="a1">');
return false;
});
$('a.a2').click(function(e){
alert('I am from <a class="a2">');
e.preventDefault();
});
demo 2
Writing return false or e.preventDefault() will not prevent other handlers from running.
Rather, they will prevent the browser's default reaction, such as navigating to a link.
In jQuery, you can write e.stopImmediatePropagation() to prevent other handlers from running.
return false and preventDefault() are there to prevent the browser's default action associated with an event (for example, following a link when it's clicked). There is a different technique to achieve this for each of three different scenarios:
1. An event handler added using addEventListener() (non-IE browsers). In this case, use the preventDefault() method of the Event object. Other handlers for the event will still be called.
function handleEvent(evt) {
evt.preventDefault();
}
2. An event handler added using attachEvent() (IE). In this case, set the returnValue property of window.event to true. Other handlers for the event will still be called, and may also change this property.
function handleEvent() {
window.event.returnValue = false;
}
3. An event handler added using an attribute or event handler property.
<input type="button" value="Do stuff!" onclick="return handleEvent(event)">
or
button.onclick = handleEvent;
In this case, return false will do the job. Any other event handlers added via addEventListener() or attachEvent() will still be called.
function handleEvent() {
return false;
}
Sometimes an event listener wants to cancel the sideeffects of the event is is interested in. Imagine a textbox which you wish to only allow numbers. Because textboxes can accept anything it becomes necessary to tell the browser to ignore non numbers that are typed. This is achieved by listening the key events and returning false if the wrong key is typed.
This doesn't completely answer your question, but the other day I used YUI's e.preventDefault() on an <a> element to squash the href action, as I only wanted the JavaScript onclick event to have control (unless no JS detected). In this situation stopping the entire chain of events wouldn't effect me.
But a couple days before that, I had an <input type="checkbox"> nested inside a <label> element, and I had to use a conditional in the event handler to determine if the clicked target was a label, as neither e.preventDefault() nor e.stopEvent() stopped my 'click' event from (legitimately) triggering twice (except in IE6).
What would have been nice is the ability to squash an entire chain of related events, since I'd already tried propagation and return false ;, but I was always going to get a 2nd event fire thanks to my label element.
Edit: I wouldn't mind knowing how jQuery would've handled my double-event situation, if anyone's keen to comment on that.