Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

Why does this function not work?

Here's my code:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Form Test</title>
<script type="text/javascript">

  function checkForm(form) // Submit button clicked
  {
    //
    // check form input values
    //

    form.myButton.disabled = true;
    form.myButton.value = "Please wait...";
    return true;
  }

  function resetForm(form) // Reset button clicked
  {
    form.myButton.disabled = false;
    form.myButton.value = "Submit";
  }

</script>
</head>

<body>

<form method="POST"  onsubmit="return checkForm(this);">
<input type="submit" name="myButton" value="Submit">
<input type="button" value="Reset Button" onclick="resetForm(this.form);">
</form>


</body>

</html>

Open in new window


This should be a slam dunk in that I'm simply copying and pasting from this site: http://www.the-art-of-web.com/javascript/doublesubmit/

But what you see above doesn't work and I don't know why. Can you help a brother out? What am I missing?
Avatar of zephyr_hex (Megan)
zephyr_hex (Megan)
Flag of United States of America image

F12 developer tools are your friend!

On clicking submit, this error comes up in F12 developer tools console:
User generated image
This tells me that the function is not in the right scope.  Move it outside of document ready, and it works.

Here is a JS Fiddle Demo.  Pay attention to the Load Type setting I have in the demo.
User generated image
  I changed it from OnLoad to No Wrap, which is the same thing as moving it outside of document ready.  In other words, these functions need global scope.

That being said, this structure of calling JavaScript functions inline is ... outdated.  More recent thought is to keep "separation of concerns".  I will post a followup answer with some suggestions.
SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'd recommend a structure like what I have below, where the event binding is done in the JavaScript instead of inline with the HTML.  Note:  I changed the submit button to just a button.  This way, you don't have to interrupt the default action of the submit.  You can just bind a click event to the button, and if your conditional checks have been met, you can then submit the form using form.submit();

Here is a JS Fiddle Demo

HTML
<form id="myForm" method="POST">
  <input id="mySubmit" type="button" name="myButton" value="Submit">
  <input id="myReset" type="button" value="Reset Button">
</form>

Open in new window


JS
var form = document.getElementById("myForm");
var btnSubmit = document.getElementById("mySubmit");
btnSubmit.addEventListener('click', checkForm);

function checkForm() {
  //
  // check form input values
  //
  console.log('here');
  form.myButton.disabled = true;
  form.myButton.value = "Please wait...";
  //form.submit();  //use this to submit the form
}

var btnReset = document.getElementById("myReset");
btnReset.addEventListener('click', resetForm);
function resetForm() 
{
  console.log('here 1');
  form.myButton.disabled = false;
  form.myButton.value = "Submit";
}

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruce Gust

ASKER

Alright, guys!

Thanks for your input! A couple of questions:

This works:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Form Test</title>
<script type="text/javascript">

  function checkForm(form) // Submit button clicked
  {
    //
    // check form input values
    //
    form.myButton.disabled = true;
    form.myButton.value = "Please wait...";
    return true;
  }

  function resetForm(form) // Reset button clicked
  {
    form.myButton.disabled = false;
    form.myButton.value = "Submit";
  }
  


</script>
</head>

<body>

<!--<form method="POST"  onsubmit="return checkForm(this);">-->
<form method="POST" name="myForm"  onsubmit="return checkForm(this) && false;">
<input type="submit"  id="theButton" name="myButton" value="Submit">
<input type="button" value="Reset Button" onclick="resetForm(this.form);">
</form>


</body>

</html>

Open in new window


One of the reasons I was at a loss is because the code didn't look familiar. After hearing your counsel it makes sense, given the fact that y'all were in agreement as far as the code being antiquated.

So, while this does work, I would much rather just the document.getElementById dynamic. Yet, this...

<!DOCTYPE html>
<html lang="en">
<head>
<title>Form Test</title>
<script type="text/javascript">
var form = document.getElementById("myForm");
var btnSubmit = document.getElementById("mySubmit");
btnSubmit.addEventListener('click', checkForm);

function checkForm() {
  //
  // check form input values
  //
  console.log('here');
  form.myButton.disabled = true;
  form.myButton.value = "Please wait...";
  //form.submit();  //use this to submit the form
}

var btnReset = document.getElementById("myReset");
btnReset.addEventListener('click', resetForm);
function resetForm() 
{
  console.log('here 1');
  form.myButton.disabled = false;
  form.myButton.value = "Submit";
}

</script>
</head>

<body>

<form id="myForm" method="POST">
  <input id="mySubmit" type="button" name="myButton" value="Submit">
  <input id="myReset" type="button" value="Reset Button">
</form>

</body>

</html>

Open in new window


...doesn't work and I don't know why.

Thoughts?

BTW: Zephyr! When I tried your suggestion on JFiddle, I got this:

User generated image
I'm probably missing something very obvious, but I didn't see what.

Looking forward to seeing what you guys have to say.

Thanks!
Not sure if I missed the point here but your original code would "work" if you replaced the return true on line 15 with return false - if by work you mean you want the button to change its text and stay on the same page.

When you return true from an event handler it proceeds with the default action - in this case a submit so the page posts to itself (as there is no action attribute) and the effect of changing the button is lost.

When you return false it cancels the default behaviour of submitting the form.

In your second example there are a couple of things that went wrong.

Firstly, JavaScript runs as it is loaded. If you have this line
	var btnSubmit = document.getElementById("mySubmit");

Open in new window

Then mySubmit needs to exist before this line runs. As this line appears before the markup for mySubmit an error is generated because the JavaScript code cannot find an element with that ID.

Two options
1. Move the code to after the html for mySubmit (before the closing </body> tag)
2. Put the code inside a window onload
window.onload = function() {
   // initialisation here
}

Open in new window

The above is provided for reference - unless you know what you are doing with chaining and preserving existing onload code this might have side effects down the line. The preferred method is to use addEventListener
var form, btnSubmit, btnReset;
window.addEventListener('load', init);
function init() {
	form = document.getElementById("myForm");
	btnSubmit = document.getElementById("mySubmit");
	btnSubmit.addEventListener('click', checkForm);
	btnReset = document.getElementById("myReset");
	btnReset.addEventListener('click', resetForm);
}

Open in new window

Note the declaration of form, btnReset and btnSubmit outside of init() - if you do it inside then it's scope is local to the init function and references to these var's in other functions will fail.

Having said that none of the globals are required - you could achieve the same result with this code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Form Test</title>
<script type="text/javascript">
window.addEventListener('load', init);
function init() {
	form = document.getElementById("myForm");
	document.getElementById("mySubmit")
		.addEventListener('click', checkForm);
	document.getElementById("myReset")
		.addEventListener('click', resetForm);
}
function checkForm(evt) {
  //
  // check form input values
  //
  console.log('here');
  myForm.myButton.disabled = true;
  myForm.myButton.value = "Please wait...";
  // if fail then prevent form submit
  evt.preventDefault();
  //form.submit();  //use this to submit the form
}

function resetForm() 
{
  console.log('here 1');
  myForm.myButton.disabled = false;
  myForm.myButton.value = "Submit";
}

</script>
</head>

<body>

<form id="myForm" method="POST">
  <input id="mySubmit" type="button" name="myButton" value="Submit">
  <input id="myReset" type="button" value="Reset Button">
</form>

</body>
</html>

Open in new window

Note the chaining of the getElementById to addEventListener and the use of myForm (id of your form) directly to reference the form.
Also, changing the submit button to type submit so we can bind to the submit event on the form.
(Above should be good back to IE9 - if you want to support ancient history then post back for the remedy)
There is also a jQuery solution which is provided for reference
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(function() {
  $('form').submit(function(e) {
    $('#mySubmit').val('Please wait ...').prop({disabled: true});
    // return true if good
    return false;
  });
  $('#myReset').click(function() {
    $('#mySubmit').val('Submit').prop({disabled: false});
  });
});
</script>

Open in new window

Julian! Thank you! I'm going through your code and google-ing things to better understand not just what you're doing, but why it works. With that in mind, one question: What's the significance / role of  "window.addEventListener('load', init);?" Is that similar to $('document').ready(function(){}); in JQuery?

And, just to check my understanding, since JavaScript / JQuery are both processing things in chronological order (going back to what you said earlier, as far as       var btnSubmit = document.getElementById("mySubmit"); not going to work if the button hasn't loaded yet), the "window.addEventListener" is a workaround or a "safety feature," in that it prevents the function from attempting to work prior to the page being fully loaded.

Yes?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks, guys! Very much appreciate the solution as well as the explanations!
You are welcome.