Solved

Why does this function not work?

Posted on 2016-09-23
11
69 Views
Last Modified: 2016-09-28
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?
0
Comment
Question by:brucegust
  • 3
  • 3
  • 3
  • +2
11 Comments
 
LVL 42

Expert Comment

by:zephyr_hex
ID: 41813162
F12 developer tools are your friend!

On clicking submit, this error comes up in F12 developer tools console:
error
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.
scope
  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.
0
 
LVL 32

Assisted Solution

by:it_saige
it_saige earned 50 total points
ID: 41813169
Try this:
<!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" action="#target" onsubmit="return checkForm(this) && false;">
<input type="submit" name="myButton" value="Submit">
<input type="button" value="Reset Button" onclick="resetForm(this.form);">
</form>

Open in new window


But as Zephyr stated, these methods are outdated...  I would really use their final suggestion when they post it...

-saige-
0
 
LVL 42

Expert Comment

by:zephyr_hex
ID: 41813176
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

0
 
LVL 82

Assisted Solution

by:leakim971
leakim971 earned 50 total points
ID: 41814129
this is a very old style coding referencing object in a page :P

if you want to do a small update, just replace : form.myButton
by : form["myButton"]

else the best is to use an ID for each element you want to play with :
<input id="mySubmit" type="button" name="myButton" value="Submit">

<script type="text/javascript">

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

    document.getElementById("myButton").disabled = true; // document.getElementById("myButton").setAttribute("disabled","disabled");
    fdocument.getElementById("myButton").value = "Please wait...";
    return true;
  }

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

</script>

Open in new window

0
 

Author Comment

by:brucegust
ID: 41815123
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:

screenshot
I'm probably missing something very obvious, but I didn't see what.

Looking forward to seeing what you guys have to say.

Thanks!
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41815761
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

0
 

Author Comment

by:brucegust
ID: 41816342
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?
0
 
LVL 42

Assisted Solution

by:zephyr_hex
zephyr_hex earned 150 total points
ID: 41816393
BTW: Zephyr! When I tried your suggestion on JFiddle, I got this:
EE isn't loading the screenshot you posted, but when I go back and look at the link, I can see I re-posted the same link from #41813162, and not the updated one.

Here's the updated fiddle:  https://jsfiddle.net/zephyr_hex/zsjasekw/2/
0
 
LVL 51

Accepted Solution

by:
Julian Hansen earned 250 total points
ID: 41816485
"window.addEventListener('load', init);?" Is that similar to $('document').ready(function(){}); in JQuery?
Yes, both achieve the same thing - which is analogous to the window.onload function.
If you were using jQuery you would use the $(function() { ... }); to enclose all your on ready scripts. If you want to go plain JS then you would use the addeventlistener to attach event handlers to the load event.

And, just to check my understanding, since JavaScript / JQuery are both processing things in chronological order
Yes - but important to understand where the code is declared - inside or outside of a document ready block.
If the code is raw - just in the document it will be executed as it is encountered - if it is inside an onlaod / document ready event handler it will be executed only after the document has finished loading.

Consider this bit of code
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery.js"></script>
<script>
function checkHeading(cp)
{
  var h1 = document.getElementById('heading');
  if (h1) {
    console.log('   >>> Heading exists at ' + cp);
  }
  else {
    console.log('   >>> Heading DOES NOT exist at ' + cp);
  }
}
// Raw JavaScript: start of document
console.log('RAW: checkpoint 1');
checkHeading('checkpoint 1');

// JQuery Document Ready: start of document
$(function() {
  console.log('JQDR: checkpoint 2');
  checkHeading('checkpoint 2');
});

// JavaScript OnLoad: start of document
window.addEventListener('load', function() {
  console.log('WEL: checkpoint 3');
  checkHeading('checkpoint 3');
});
// Raw JavaScript after OnLoad: start of document
console.log('RAW: checkpoint 4');
checkHeading('checkpoint 4');
</script>
</head>
<body>
<h1 id="heading">I am the heading</h1>
<script>
// Raw JavaScript: end of document
console.log('RAW: checkpoint 5');
checkHeading('checkpoint 6');

// JavaScript OnLoad: end of document
window.addEventListener('load', function() {
  console.log('WEL: checkpoint 6');
  checkHeading('checkpoint 6');
});
// JQUERY Document Ready: end of document
$(function() {
  console.log('JQDR: checkpoint 7');
  checkHeading('checkpoint 7');
});
</script>
</body>
</html>

Open in new window

You can see it working here
Look at the console (F12) output from this code to see
a) The order in which statements are produced
b) Which ones are able to access the #heading element.
Each console.log is sequenced so you can see the order, and prefixed with either
RAW (raw JavaScript executed as encountered)
JQDR: JQuery Document Ready
WEL: Window Event Listener

The output should help to shed some light on how things happen with JavaScript when a page is loaded.
0
 

Author Closing Comment

by:brucegust
ID: 41820289
Thanks, guys! Very much appreciate the solution as well as the explanations!
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41820342
You are welcome.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

This article will give core knowledge of JavaScript and will head in to your first JavaScript program. I am Durvesh Naik and I am here to deal with this series of JavaScript. I will teach you JavaScript in part wise , as its quite boring to read big…
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now