Javascript onchange event preventing onsubmit event in HTML form? - javascript

Consider an HTML form:
<form action="" method="POST" onsubmit="return checkValidArray()">
<input type="text" name="data" onchange="return validate(this);">
</form>
It appears (in both IE 6 and Firefox 3) that when you type some text into the input field and click submit that the onchange event fires for the input field, but the onsubmit event does not fire for the form until you click the submit button a second time (at which time the onchange does not fire, of course). In other words, the onchange seems to prevent the onsubmit from firing.
The desire is to check each field in the form when the user exits the field in order to provide them with immediate validation feedback, and also to prevent submission of the form if there is invalid data.
[EDIT: Note that both validation functions contain an alert().]
How does one get around this problem?

Solution (of a sort):
It turns out that it is only presence of an alert() - or a confirm() - during the input's onchange event that causes the form's onsubmit event to not fire. The JS thread appears to get blocked by the alert().
The workaround is to not include any alert() or confirm() in the input's onchange call.
Browsers known to be affected:
IE6 - Windows
IE8 - Win
FF3 - Win
Browsers known not to be affected:
Google Chrome - Win
Safari - Mac
FF - Mac

I tried with Firefox 3 (Mac) with the following code:
<html>
<head>
<script>
function validate(ele)
{
alert("vali");
return false;
}
function checkValidArray()
{
alert("checkValidArray");
}
</script>
</head>
<body>
<form action="" method="POST" onsubmit="return checkValidArray()">
<input type="text" name="data" onchange="return validate(this);">
<input type="submit" value="Ok">
</form>
</body>
</html>
It seems to work. When I click on the Ok button, both "Vali" and "Check Valid Array" pop up.
Initially I thought return false could be the reason why the form was not submitted, but it IS submitted (at least, checkValidArray() is called).
Now, what are you doing in your checkValidArray() and validate() methods? Something special? Can you post the code?
EDIT: I tested with IE8 and FF3 on windows, and here both events do not get fired. I have no idea why. Perhaps onblur IS a solution, but WHY does onchange not work? Is there a specific reason or is it just another inconsistency? (Works on both FF and Safari on Mac)

You could use the onblur event in your inputs instead of onchange.

It's quite interesting that the behaviour is different on the Mac, so it appears platform dependent and not browser dependent. Must be a clue there somewhere...
I tried onblur with Nivas' code but had the same result as with onchange (only the "Vali" alert).
What does make a difference is whether you do anything in validate(). Comment out the line alert("vali"); and it works! (The actual return value from validate() does not matter, although I wouldn't expect it to.)
EDIT:
A colleague just tried this in Google Chrome on Windows and it works there. This intuitively makes sense because of how Chrome separates JS threads.
Something about the first alert() blocking the thread causes the onsubmit event to get lost. Possible race condition?

Don't create ; submit button. Instead, create a normal button and write a function which can be called onClick with that button.
Function will do the validation on the form fields, and if everything is fine, it will submit the form. Otherwise it will not.
function validate
{
"Piece of code to Validate your form"
document.formName.action.value = "URL which you want to call"
document.propFile.submit(); // It will submit he page
}

Related

input `type=image` onclick solution works, but why?

I had a problem using input type=image tag with onclick to run some javascript. Works perfectly with input type=button but, when used on an image input, it would run the script which changed the DOM (added images to a div) but would clear back to the default page within fractions of a second, the added images showing as a brief flash then disappearing.
So, using google, I eventually found a solution. I changed:
<input type="image" id="greenGoButton" src="Images2/goButton.png" alt="Submit" onclick="loopForm(document.thisForm); getPlates(document.thisForm);">
to:
<input type="image" id="greenGoButton" src="Images2/goButton.png" alt="Submit" onclick="loopForm(document.thisForm); getPlates(document.thisForm); return false;">
So, adding a return false; statement fixed it.
But why? This is bugging me. Why does it work without return false on a button but not when an image is used instead? Surely the internet is full of buttons made of images.
By default, type='image' creates a button that submits the enclosing form and reloads the page, by adding return false at the end of the click handler, you are telling Javascript to prevent the default behavior which is submitting the form and reloading the page.
You can also access the event object inside the click handler and call preventDefault() on it without doing return false at the end; event.preventDefault() which also does the same thing.
In short, return false at the end of an event handler prevents the default behavior from happening

Physical mouse click vs simulated button click?

Hello Stackoverflow!
I am experimenting with getting a chrome extensions cript to click a page button to trigger an AJAX request, however it would seem that physically clicking said button is not the same as using the following:
document.getElementsByTagName('input')[10].click();
the results of the getElements line is this:
<input type="submit" value="Continue ...">
Using document.forms sort of works, but unfortunately reloads the page, which is not what happens when the Ajaxrequest is fired by the click event.
document.forms[1].submit();
Calling the form returns the following:
<form
action="/battle.php" method="post" name="2913" id="2913" onsubmit="get('/battle.php', '', this);
disableSubmitButton(this);
return false;">…</form>
Doesn't seem obvious to a beginner programmer like me, why using the .click(); in F12 console (chrome) would be any different from the physical click. Also i have verified (sorf of) that the button on the screen is in fact the one i'm calling with the getElementsByTagName('input').
The page reloads because the type of the button is "submit". You could attach an event handler to the "click" button that can submit the form without reloading the page. Your code will look something like this:
Using JQuery:
$('#submitButton').on('click', function(e){
e.preventDefault(); // stops default submit
$('#2913').submit(); // or the ID of your form
});
And your HTML will be :
<input type="button" value="Continue ..." id="submitButton">

Why submitting a form overrides setting location.href in a submit button click handler?

This question is inspired by this post.
In a nutshell: Why window.location.href is not redirecting to a new page (example.com) when executing the code below?
<form>
<input type="submit" id="submit" value="Submit">
</form>
<script>
document.getElementById('submit').addEventListener('click', function (e) {
window.location.href = "http://www.example.com";
});
</script>
I've always believed, that setting window.location.href immediately loads a new page, but in this case it doesn't. Submitting the form just reloads the page instead, and setting a new location seems to be totally ignored. Why? How? What I'm missing here?
Please notice, that I'm aware of several ways how to prevent form submitting in this case, rather I'd like to know, why setting location.href is ignored, what is the mechanism behind the behavior? I've tried to search explanation from the standard, but haven't found anything so far.
Additional information
This seems to happen in all major browsers (Chrome, Firefox, IE11, Edge ...), but not when the code is run in a Stack snippet (because it's sandboxed, and won't send forms anyway). A console.log put in the function shows, that the click handler is executed before the actual submission is executed.
A jsFiddle reproducing the issue.
You can see easier here what is happening step by step if you will try tu change location drunning form submission
JSFIDDLE
If you will check your browser network tab than you can see that the submit request is cancelled (but still sent) by redirect request. I believe that same situation occurs when you trying to do it onclick or onsubmit the first request just cancelling the next one and prevent window.location.href redirection.
I belive the key thing here is not to view the problem as 'form submission vs page redirect', but as an event-listeners issue.
What you are doing is to attach an event listener to an html element. And it seems that the policy of DOM elements is to execute all the event listeners first, and then the event itself . In your case, the page is redirected to the url you provided, because you set window.location inside the listener, then the submit event itself takes place, so the same blank page is reloaded
The fact that "event flow process will complete after all listeners have been triggered" is stated here: http://www.w3.org/TR/DOM-Level-2-Events/events.html
So far I haven't figgured out a way to execute the listeners after the event , but if that can be done, that is all you need to make this example work
The main issue is that there is nothing preventing the submit button from actually submitting the form. You would need a return false somewhere for that to happen. I'm not fully certain whether the Submit button logic or the click handler is happening first, but regardless, the form post is taking precedence.
I was able to get the following to work:
<html>
<head>
<script type="text/javascript">
function redirect() {
window.location.href = "http://www.example.com";
return false;
}
</script>
</head>
<body>
<form method="GET" action="">
<input type="submit" id="submitbtn" value="Submit" onclick="return redirect()" />
</form>
</body>
</html>
This example does remove the programmatic addition of the click event, but if that's a hard requirement it should be possible to add that back in.

Capturing jQuery form submit event

I don't know what is wrong with that, because I was following at every step the tutorial from jquery.com regarding the form submit event.
My Javascript:
[Ofc. latest jQuery library is included].
<script type="text/javascript">
$("form#addFav").submit(function(event) { event.preventDefault(); alert("hello"); });
</script>
Have also tried with the $(document).ready() event:
$(document).ready(function(){
$("form#addFav").submit(function(event) { event.preventDefault(); alert("hello"); });
});
Here is my HTML form code:
<form action="" id="addFav">
<input type="text" name="name" class="thin-d"/>
<input type="submit" value="Send"/>
</form>
So, regarding the above Javascript code, it is supposed to work (I mean it should prevent default action [submitting form] and send the alert then), but it all doesn't work - have tried with thousands of combinations, but I fail'd. So I'm waiting for your solutions. I'd appreciate every one.
You probably have some syntax error or somthing like that somewhere else, because what you have just works.
Are you sure there aren't any JS errors?
P.S. I would alwyas go for the latter code to ensure that the elements are in the DOM before trying to attach events.
For anyone else who has the same problem, and still struggling to solve this issue, try to see if you have illegally reused the id, and try changing the form id to something unique.
I had accidentally given the id to two different DOM elements and the event was being bound to the first element with the respective id and my form was the second one so it was never captured. This had me pulling my hairs for quiet a long.
I just recently ran into the same issue. Jquery on submit would not work on the form, however just changing it to click event worked fine. Still at a loss why .on(submit) or .submit() events will not recognize the form.
$("form#addFav").click(function (event) {
event.preventDefault(); alert("hello");
$(this).submit();
});
this question is old but.. you might have had another submit events firing before yours fired. If these other events contained "return false;" statement then the event execution got interrupted and your code never fired. To put your code BEFORE these events you might use ONSUBMIT form attribute where you can put code that will fire before or at the same time as other events.

Opera problem with javascript on submit

I have an input element with onchange="do_something()". When I am typing and hit the enter key it executes correctly (do_something first, submit then) on Firefox and Chromium (not tested in IE and Safari), however in Opera it doesn't (it submits immediately). I tried using a delay like this:
<form action="." method="POST" onsubmit="wait_using_a_big_loop()">
<input type="text" onchange="do_something()">
</form>
but it didn't work either.
Do you have some recommendations?
Edit:
Finally I used a mix of the solutions provided by iftrue and crescentfresh, just unfocus the field to fire do_something() method, I did this because some other input fields had others methods onchange.
$('#myForm').submit( function(){
$('#id_submit').focus();
} );
Thanks
You could use jquery and hijack the form.
http://docs.jquery.com/Events/submit
<form id = "myForm">
</form>
$('#myForm').submit( function(){
do_something();
} );
This should submit the form after calling that method. If you need more fine-grained control, throw a return false at the end of the submit event and make your own post request with $.post();
From http://cross-browser.com/forums/viewtopic.php?id=123:
Per the spec, pressing enter is not
supposed to fire the change event. The
change event occurs when a control
loses focus and its value has changed.
In IE pressing enter focuses the
submit button - so the text input
loses focus and this causes a change
event.
In FF pressing enter does not focus
the submit button, yet the change
event still occurs.
In Opera neither of the above occurs.
keydown is more consistent across browsers for detecting changes in a field.
I'm not great at Javascript, but could you do something like this?
<form name="myform" action="." method="POST">
<input type="text" onchange="do_something();document.myform.submit();">
</form>

Categories