I'm observing a behavior where onClick events cause a page to reload.
$('#target').click(function(){
$('#target').hide();
})
So the object is shown, it hides on click, but then page reloads and the object is shown again. I'm working on a website that was setup before me, so I'm not entirely aware of all its parts. Any idea what might cause this behavior and how to fix it?
You need to prevent the default event behavior with event.preventDefault:
$("#target").on("click", function (e) {
$(this).hide();
e.preventDefault();
});
Using return false will also work, but it does more than you may intend.
This is in line with the event cancellation standard
add a
return false;
as last statement so that the link is not called, only you function (onclick) is executed.
Related
I have two different event handlers in two different locations in my page. One is supposed to be a default handler that handles 99% of the events everywhere in the whole site. The second is used on a single page to override that default behavior.
$(function() {
// side-wide default action
$('#button').click(function() {
window.location.reload();
});
// handler used on a single page, somewhere else in the JS
$('#button').click(function() {
window.location.href = "/page2";
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="#button">Click</button>
No matter what I do, the first (i.e. reload()) operation is always called. I can put the reload in a setTimeout or I can completely refactor the JS so that it is either before or after the redirect assignment. It doesnt matter. The page is always reloaded and the URL never changes.
How can I get the redirect to work without gutting the default behavior? Can I set a priority? Can I halt execution after the assignment?
You could check whether you're on the page that needs the replacement click handler, and remove the old handler.
// handler used on a single page, somewhere else in the JS
if (this_is_the_special_page) {
$('#button').off("click").click(function() {
window.location.href = "/page2";
});
}
Since you are binding events to the same DOM element #button, both events will run one after the other and you can't even use e.preventDefault() or stop the event to bubble up as there is no event chain.
I'd suggest you then to find a way to identify the page some how (a cssClass in the body perhaps) and don't run the main function if you identify the page as a "don't reload page".
// side-wide default action
$('#button').click(function() {
// if body class="prevent-reload", don't run your default function
if (!$("body").hasClass("prevent-reload")) {
window.location.reload();
}
});
You then could add a css class prevent-reload on that single page.
The easy way to handle this would be to add something like data-skip-default="true" to your button that you don't want to trigger the default action.
Then update your default handler to check to see if this data-skip-default is present and skip the reload if so.
As many other threads and external forums suggest, I've tried placing e.preventDefault() (while passing e as parameter, not in code sample) in every place imaginable, but it doesn't prevent the anchor from reloading the page. When I step through the debugger, it will assign every div with scrollNav the click event, but when I click on the div-link it just reloads the page and the debugger does not stop on any lines in the highlightSelection function. Another method I've tried is to use an anonymous function inside this.click and place e.preventDefault() as the first line, but it does nothing.
I also don't really understand why you would want to place e.preventDefault() as so many others have suggested. Isn't it basically saying return false? That may stop a link from reloading the page, but won't it prevent the code in the method from executing?
jQuery(document).ready(function() {
jQuery('.scrollNav').each(initSideNavForSelection);
}); // end ready
function initSideNavForSelection() {
this.click(highlightSelection);
}
function highlightSelection() {
var selectedDataID = this.attr("data-id");
jQuery('.scrollNav').each(function() {
if (this.attr("data-id") === selectedDataID) {
this.addClass("selected");
} else {
this.removeClass("selected");
}
})
}
Add onclick="return false;" to the anchor.
OR change initSideNavForSelection function to
this.click(function(e) {
e.preventDefaults();
highlightSelection();
});
either works
There are a few things I had to do to get your codes to run. You can take a link at this fiddle here.
Here's the list:
Add JQuery as the framework to be used for your fiddle, under the Frameworks & Extensions section on the top left corner.
Remove the broken onclick="Event.stop(event)" inlined attribute as Event is undefined.
Replace the usage of this with $(this) in both your initSideNavForSelection() and highlightSelection() functions. this represents a DOM object and $(this) is a JQuery wrapper around this. The latter will respond to JQuery methods like .click(), but not the former.
So far, there is no page reload in your fiddle, with or without e.preventDefault().
Finally, in addition to event.preventDefault(), return false also calls event.stopProgagation() to prevent the event from bubbling up the DOM, before terminating the callback execution immediately. A call to event.preventDefault() doesn't terminate the function call immediately.
I'm newbie in jquery and saw a piece of code with something strange given the functionality of a method, the "preventDefault". Well, to test, i created a test page and made two functions with "preventDefault" inside of it.
I have two questions on the same subject, i hope you can answer me.
$(document).ready( function( ) {
$('a').click( function( event ) {//Func 1
event.preventDefault( );
});
$("#ok").click( function( event ) {//Func 2
event.preventDefault( );
alert("Wut");
//...
});
});
1- Why, in the second function, the "alert( )" runs even if i comment "event.preventDefault( );" and the first function does not happen the same? If i comment "event.preventDefault();" in the first function, the link doesn't work!
I found it strange because regardless of the method "event.preventDefault();" whether or not commented in the second function, the "alert" works the same way. I think even what comes after "alert" would run.
2- What is the real utility of this method, "event.preventDefault ();"? Why, in the second function, it seems to be useless. Can you give me some example of when it might be useful?
Thanks!
The purpose of preventDefault is to prevent the browser's default action related to the event. Your alert isn't the browser's default action, and is unaffected. Following a link is the browser's default action, and so preventing the default prevents following the link.
preventDefault is crucial in many situations. For instance, when handling a form's submit event, we need preventDefault (directly or indirectly) if we do client-side form validation and the form isn't valid; otherwise, the browser would submit the invalid form.
(I said "directly or indirectly" above because jQuery handles the return value of event handlers in a special way: If you return false, it calls preventDefault and stopPropagation for you.)
It prevents the default action of the control. If it a link, it stops the link being followed. If it is a form submission, it prevents the form from being submitted.
It doesn't interact with other JS event handlers on the same element.
Examples of situations where you might use it:
Stopping the browser following a link because you have used Ajax and pushState to load the content and update the URL
Stopping the browser from submitting a form because you have tested the data entered and found a problem with it
The .preventDefault() function prevents the browser from carrying out the normal implicit behavior of an interactive element. If you click on an <a> tag, then apart from anything your JavaScript does the browser will attempt to follow the "href" value and reload the page. That's the "default" behavior that the function name refers to.
Your alert() runs because .preventDefault() has nothing to do with the code in your event handler. If you want to "abort" an event handler, you'd just return from it.
Note that jQuery also gives you .stopPropagation() and .stopImmediatePropagation() to cancel the process of event bubbling. Those also have no direct effect on the code in your event handler.
event.preventDefault() disables the default behaviour of the event. In case of an link the redirect. It does not effect your own code, in this case the alert() call.
Here's a snippet of my code:
$(".item").click(function () {
alert("clicked!");
});
And I have (hypothetically; in actuality it's far more complicated) the following on my page:
<img src="1.jpg" />
However, when I click the image, I do not get an alert.
What is my mistake?
Is your selector actually matching anything? Try using the jQuery debug plugin (http://jquery.glyphix.com/) and doing this:
$(".item").debug().click(function() {
alert("clicked!");
});
.debug() will log whatever is matched to the Firebug console (you are using firebug, right? :-) ) without "breaking the chain" so you can use it inline like this.
If that turns out correctly, there may be some issue with the browser navigating to "#" before it can show your alert. Try using the .preventDefault() method on the event object to prevent this behavior:
$(".item").click(function(evt) {
evt.preventDefault();
alert("clicked!");
});
First question - are you adding the element to be clicked dynamically? If it is,
you should use the live event since that will take care dynamically created elements.
http://docs.jquery.com/Events/live#typefn
Use bind.
$(".item").bind("click", function(e) { ... });
modifying the selector?
$(".item > img")
I had this problem recently after adding a context menu jquery plugin. The pluging was binding to the click event of the body and then unbinding click event - it seemed to remove all bindings to click event for all elements. Maybe a suggestion to turn off plugins or check you're not unbinding click for a parent element yourself.
The code you have posted is correct, so I suspect there's something else going on that you haven't considered.
Firstly, if there was an error somewhere (even not in that exact bit of code) that might cause it to stop working. Put an alert just after this line to check that it runs.
Check that no other elements are catching the event and stopping it from propagating. This has bitten me before in the past... If there's anything else handling a click which has stopPropagation() or return false in it, that might be the problem.
One thing I've found (though only with links going elsewhere) is that adding return false; in may help, if it's just firing the anchor off instead of evaluating the alert. I can't really say why this would be the case, but that's a solution I found to a similar problem recently.
Many times I've seen links like these in HTML pages:
<a href='#' onclick='someFunc(3.1415926); return false;'>Click here !</a>
What's the effect of the return false in there?
Also, I don't usually see that in buttons.
Is this specified anywhere? In some spec in w3.org?
The return value of an event handler determines whether or not the default browser behaviour should take place as well. In the case of clicking on links, this would be following the link, but the difference is most noticeable in form submit handlers, where you can cancel a form submission if the user has made a mistake entering the information.
I don't believe there is a W3C specification for this. All the ancient JavaScript interfaces like this have been given the nickname "DOM 0", and are mostly unspecified. You may have some luck reading old Netscape 2 documentation.
The modern way of achieving this effect is to call event.preventDefault(), and this is specified in the DOM 2 Events specification.
You can see the difference with the following example:
Google
Clicking "Okay" returns true, and the link is followed. Clicking "Cancel" returns false and doesn't follow the link. If javascript is disabled the link is followed normally.
WHAT "return false" IS REALLY DOING?
return false is actually doing three very separate things when you call it:
event.preventDefault();
event.stopPropagation();
Stops callback execution and returns immediately when called.
See jquery-events-stop-misusing-return-false for more information.
For example :
while clicking this link, return false will cancel the default behaviour of the browser.
<a href='#' onclick='someFunc(3.1415926); return false;'>Click here !</a>
Here's a more robust routine to cancel default behavior and event bubbling in all browsers:
// Prevents event bubble up or any usage after this is called.
eventCancel = function (e)
{
if (!e)
if (window.event) e = window.event;
else return;
if (e.cancelBubble != null) e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
if (window.event) e.returnValue = false;
if (e.cancel != null) e.cancel = true;
}
An example of how this would be used in an event handler:
// Handles the click event for each tab
Tabstrip.tabstripLinkElement_click = function (evt, context)
{
// Find the tabStrip element (we know it's the parent element of this link)
var tabstripElement = this.parentNode;
Tabstrip.showTabByLink(tabstripElement, this);
return eventCancel(evt);
}
Retuning false from a JavaScript event usually cancels the "default" behavior - in the case of links, it tells the browser to not follow the link.
I believe it causes the standard event to not happen.
In your example the browser will not attempt to go to #.
Return false will stop the hyperlink being followed after the javascript has run. This is useful for unobtrusive javascript that degrades gracefully - for example, you could have a thumbnail image that uses javascript to open a pop-up of the full-sized image. When javascript is turned off or the image is middle-clicked (opened in a new tab) this ignores the onClick event and just opens the image as a full-sized image normally.
If return false were not specified, the image would both launch the pop-up and open the image normally. Some people instead of using return false use javascript as the href attribute, but this means that when javascript is disabled the link will do nothing.
using return false in an onclick event stops the browser from processing the rest of the execution stack, which includes following the link in the href attribute.
In other words, adding return false stops the href from working. In your example, this is exactly what you want.
In buttons, it's not necessary because onclick is all it will ever execute -- there is no href to process and go to.
The return false is saying not to take the default action, which in the case of an <a href> is to follow the link. When you return false to the onclick, then the href will be ignored.
Browser hack:
http://jszen.blogspot.com/2007/03/return-false-to-prevent-jumping.html
Return false will prevent navigation. Otherwise, the location would become the return value of someFunc
The return false prevents the page from being navigated and unwanted scrolling of a window to the top or bottom.
onclick="return false"
I am surprised that no one mentioned onmousedown instead of onclick. The
onclick='return false'
does not catch the browser's default behaviour resulting in (sometimes unwanted) text selection occurring for mousedown but
onmousedown='return false'
does.
In other words, when I click on a button, its text sometimes becomes accidentally selected changing the look of the button, that may be unwanted. That is the default behaviour that we are trying to prevent here. However, the mousedown event is registered before click, so if you only prevent that behaviour inside your click handler, it will not affect the unwanted selection arising from the mousedown event. So the text still gets selected. However, preventing default for the mousedown event will do the job.
See also event.preventDefault() vs. return false
I have this link on my HTML-page:
<a href = ""
onclick = "setBodyHtml ('new content'); return false; "
> click here </a>
The function setBodyHtml() is defined as:
function setBodyHtml (s)
{ document.body.innerHTML = s;
}
When I click the link the link disappears and the text shown in the browser
changes to "new content".
But if I remove the "false" from my link, clicking the link does (seemingly) nothing. Why is that?
It is because if I don't return false the default behavior of clicking the link and displaying its target-page happens, is not canceled. BUT, here the href of the hyperlink is "" so it links back to the SAME current page. So the page is effectively just refreshed and seemingly nothing happens.
In the background the function setBodyHtml() still does get executed. It assigns its argument to body.innerHTML. But because the page is immediately refreshed/reloaded the modified body-content does not stay visible for more than a few milliseconds perhaps, so I will not see it.
This example shows why it is sometimes USEFUL to use "return false".
I do want to assign SOME href to the link, so that it shows as a link, as underlined text. But I don't want the click to the link to effectively just reload the page. I want that default navigation=behavior to be canceled and whatever side-effects are caused by calling my function to take and stay in effect. Therefore I must "return false".
The example above is something you would quickly try out during development. For production you would more likely assign a click-handler in JavaScript and call preventDefault() instead. But for a quick try-it-out the "return false" above does the trick.
When using forms,we can use 'return false' to prevent submitting.
function checkForm() {
// return true to submit, return false to prevent submitting
}
<form onsubmit="return checkForm()">
...
</form>
By default, when you click on the button, the form would be sent to server no matter what value you have input.
However, this behavior is not quite appropriate for most cases because we may want to do some checking before sending it to server.
So, when the listener received "false", the submitting would be cancelled. Basically, it is for the purpose to do some checking on front end.