I just helped a coworker diagnose this issue and it can be incredibly subtle if you aren't paying attention. Consider the following simple form:
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#myButton").click(function() {
$.post("test.cfc?method=whatever&returnformat=json", {}, function(res) {
console.log('back from cfc');
},"json");
});
}); </script>
</head> <body> <form method="post">
<input type="button" id="myButton" value="Click me like you mean it.">
</form> </body>
</html>
<html>
I've got a button that - when clicked - will fire off an event jQuery is listening to. This event handler fires off a post to a CFC with the result then logged to the console. Works perfectly. Now let's tweak it just a tiny bit...
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#myButton").click(function() {
$.post("test.cfc?method=whatever&returnformat=json", {}, function(res) {
console.log('back from cfc');
},"json");
});
}); </script>
</head> <body> <form method="post">
<input type="image" src="meatwork.jpg" id="myButton" value="Click me like you mean it." >
</form> </body>
</html>
<html>
Can you guess what happened here? Try to before scrolling down...
So - when clicked - if you had your network tools open in Chrome or Firefox, you would see a quick glimpse of a request and then it would go away. Why? The image input type is actually like a submit button. Unlike type=button that does - well - nothing - the image type actually works much like a submit button. What happened was that the entire form posted. Easy to miss especially if you are testing locally. A quick fix is to just prevent the default behavior:
$("#myButton").click(function(e) {
e.preventDefault();
$.post("test.cfc?method=whatever&returnformat=json", {}, function(res) {
console.log('back from cfc');
},"json");
});
Anyone else ever get bitten by this?
Archived Comments
Wow - I'd have never spotted that. I mean, I noticed the src attribute, but I'd not have known it submits the form.
Side note - instead of e.preventDefault() could you not just return false in the click handler?
I guessed right!
@todd - I think the general reason to e.preventDefault(); instead of return false; is that e.preventDefault() will not stop event propagation where as returning false will.
I might be wrong, but that is my understanding. In this situation though returning false would work just the same (no other events to propagate)
@Jeremy - that's my understanding too.
Ahh... fantastic - did not know that. Thanks guys.
I've had something that's a bit like this. I was firing a .click() function on a check box and it was conflicting with the native click event in the browser. Had a bit of a headache before figuring it out.
There's another similar problem, if you use the button tag.
Change this code:
<input type="button" id="myButton" value="Click me like you mean it.">
To this:
<button id="myButton">Click me like you mean it.</button>
And you have the same issue.
For some stupid reason, the idiots at the W3C defined the default type for button tag as submit, so to get a non-submitting button you need to specify the type:
<button type="button" id="myButton">Click me like you mean it.</button>
Which is annoyingly repetitive.
Couldn't you also just remove the input type and just have an image with that ID, of course you would have to style it for the pointer but I think it would work the same wouldn't it ?
It wont work if JS is disabled, whereas with input type=image you can put fallback functionality behind the form submission.
Interesting what statistic there is on 'JS disabled'. To me it has no sense in year 201x. I also agree on simpler <img onclick=""> solution.
Just to be clear - it wasn't so much that there was an easy work around - but that the initial issue was easy to miss. :)
Here's an apropos link to a great post on event.preventDefault() vs return false ... it simply supports what Jeremy stated and even goes a bit further to show how return false actually fires three bubbling events in it's wake ...
1. event.preventDefault();
2. event.stopPropagation();
3. Stops callback execution and returns immediately when called.
Here's the link for more FYI ...
http://fuelyourcoding.com/j...