Forum Moderators: open

Message Too Old, No Replies

Javascript form submit

         

Readie

2:22 am on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



When I first started learning JavaScript there was no mention in the tutorial I used to get started of using form buttons to activate a JavaScript; only using links with the syntax
<a href="javascript:function_name()">Link</a>
, however intuition filled out using something like:

<form name="form" action="javascript:function_name()">
<input>
<input>
<input name="submit" type="submit" value="Submit">
</form>

Which is all well and good, never had any problems with it. However recently, just to clarify my memory, I needed to look up the phrasing of logic statements for a JavaScript if statement, and on the same page I noticed that the method for activating a JavaScript from a form was being suggested as:

<input type="button" onClick="javascript:function_name()">

After looking at a few more sites I found that all suggestions were for the second method of activating a JavaScript, and I was just curious as to whether or not there is any argument for using the second method over the first other than personal preference?

rocknbil

3:55 am on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, both of those methods fail to supply alternate content if Javascript is disabled. Which should be important to all of us, as this is exactly what a search engine is/doesn't do. There is a larger reason, one of accessibility, as well. So I say, javascript: is not a valid url. Nor is it a valid form action.

Input type="button" has no inherent action without javascript to activate them. Again, if JS is disabled, you have nothing.

You mind is probably going where most JS coders' go - thinking about percentages of who doesn't have Javascript disabled, does it really matter, it's such a small percentage we don't care - but there are two important points to consider about this.

Making your documents accessible without Javascript is so easy, there's no reason not to do so. You don't have to create two copies of your web site, you just have to code JS progressively.

Let's say your stats say ".001% of my visitors have JS disabled." How many of those visitors get past your first page, and what does that number reflect about potential users? .001% of billions . . . is still a lot of people to cut out.

Here's how to do an inline link that serves content if JS is disabled.

<a href="file.html" onlick="alert('boo'); return false;">link</a>

The return false is important. It's what stops the browser from navigating to "file.html", which is supposed to be alternate content for non-JS clients.

Here's a version using a function, except it's the function that returns false:

<a href="file.html" onlick="return some_function();">link</a>

<script type="text/javascript">
function some_function() {
alert('boo');
return false;
}
</script>

Forms are a little different. The return false still has the same effect, stops the form from performing it's "natural action", but there's a little catch, which I refer to as abuse. :-)

Often you will see the action attached to the button itself, but what happens if you press enter from one of the fields? You got it, your JS is bypassed and the form submits.

For this reason, it's always best to put the event handler on the form itself, and pass a reference of the form object to your function so that the function can manage the submit. Always use a submit button - see comment about button types above - so if JS is disabled, it still works.


<form method="post" action="some-script.cgi" onSubmit="return validateForm(this);">
<input type="submit" value="submit">
</form>
<script type="text/javascript">
function validate(form) {
var msg = '';
// do your form validation, if it doesn't validate,
// populate msg with the . . . message.
if (msg != '') { alert(msg); }
else { form.submit(); }
return false;
}
</script>

This also works inline . . .

<form method="post" action="some-script.cgi" onSubmit="alert('boo'); return false;">

. . . but is a little harder to maintain, less graceful, and less portable. For example, the function validate() can validate any form on your site, so is only needed once as a .js include.

Fotiman

3:01 pm on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I agree with what rocknbil said.

javascript:function_name()

There is no such thing as a "javascript:" protocol, so it's technically wrong to include this anywhere. It's also not needed at all. And as rocknbil pointed out, the correct place to attach form code is the onsubmit handler (note, I prefer to use all lowercase, which is valid in both HTML and XHTML, whereas onSubmit is not valid in XHTML).

A better alternative is to use unobtrusive JavaScript, which means you keep your HTML code free of all inline event handlers and JavaScript code, and you instead attach event listeners (or assign event handlers) in the JavaScript code.

Readie

10:04 pm on Dec 31, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It has always bothered me that my JavaScripts have always, to some extent, excluded a minority; even though I always made a useable alternative with some <noscript> tags.

With regards to pressing enter rather than clicking bypassing the script; that is what prompted me to use the form action= rather than a link in the first place, however I'd forgotten that until just a moment ago :)

Also I wasn't even aware that onSubmit= was a valid attribute on a form, so thanks for sharing that - and also thank you for the script suggestions.

I am curious though, say the form exists purely to provide values for a JavaScript that eventually ends up saying something like:

var page = window.document.form.input.value
this.location.href = page + ".html";

Is it possible to have this sort of functionality using your method?

Cgi scripts are something I always intended to learn, but never got around to (web making being something I've maintained an interest in but never pursued as a career) so I'm unaware if it's possible do something like this with a cgi script as an alternative.

rocknbil

8:25 pm on Jan 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I am curious though, say the form exists purely to provide values for a JavaScript that eventually ends up saying something like:
var page = window.document.form.input.value
this.location.href = page + ".html";

I used .cgi because I work in many languages (Perl, PHP, etc) doesn't matter what the server language is.

Since you refer to a form, as said - you start **without** the enhancement.


<form action="redirector.php" method="post">
<p><label for="url">Destination:</label>
<select name="url" id="url">
<option value="">Select Destination</option>
<option value="tos">TOS</option>
<option value="about">About Us</option>
<option value="contact">Contact</option>
</select>
<input type="submit" value="Submit">
</p>
</form>

Contents of redirector.php would be something like this (not working code, typed OTF, might have errors:)


<?php
if (isset($_POST['url']) and preg_match('/^[a-z0-9\-\_]+$/i',$_POST['url'])) {
$loc = $_POST['url'] . '.html';
header("location:$loc");
exit;
}
else {
header("content-type:text/html");
$form = '
<!-- use a full doctype, for ex. only -->
<html><head><title>Select Destination</title></head>
<body>
<form action="redirector.php" method="post">
<p><strong>Please select a destination.</strong></p>
<p><label for="url">Destination:</label>
<select name="url" id="url">
<option value="">Select Destination</option>
<option value="tos">TOS</option>
<option value="about">About Us</option>
<option value="contact">Contact</option>
</select>
<input type="submit" value="Submit">
</p>
</form>
</body>
</html>
';
echo $form;
}
?>

So if the URL is selected, it does the redirect, otherwise, it re-outputs the form with the bolded message.

So now it works without JS . . . enhance it. You'd apply this to both the original form and the form in the PHP script (and could/should make it unobtrusive as mentioned, just displaying the in-document approach.)


<form action="redirector.php" method="post" onsubmit="return chkForm(this);">
<p><label for="url">Destination:</label>
<select name="url" id="url">
<option value="">Select Destination</option>
<option value="tos">TOS</option>
<option value="about">About Us</option>
<option value="contact">Contact</option>
</select>
<input type="submit" value="Submit">
</p>
</form>
<script type="text/javascript">
function chkForm(form) {
msg = '';
if (form.url.selectedIndex==0) {
msg = 'Please select a url.';
}
if (msg != '') { alert(msg; }
else {
var ind = form.url.selectedIndex;
var loc = form.url.options[url].value+'.html';
window.location=loc;
}
return false;
}
</script>

So we've done two enhancements - validated that an item was selected, and now it goes directly to the URL instead of a redirector script first.

Let's add one more. On change of the select list, we can auto submit the form.

.....
<select name="url" id="url" onchange="this.form.submit();">
....

So now they don't even have to submit, we do it for them. You might ask, why the button then, and good question.

On load, let's hide it if JS is enabled. :-)


<form action="redirector.php" method="post" onsubmit="return chkForm(this);">
<p><label for="url">Destination:</label>
<select name="url" id="url" onchange="this.form.submit();">
<option value="">Select Destination</option>
<option value="tos">TOS</option>
<option value="about">About Us</option>
<option value="contact">Contact</option>
</select>
<input type="submit" id="submitButton" value="Submit">
<!-- never use reserved names like submit,
reset, etc. for ID'ed elements
-->
</p>
</form>
<script type="text/javascript">
function chkForm(form) {
msg = '';
if (form.url.selectedIndex==0) {
msg = 'Please select a url.';
}
if (msg != '') { alert(msg; }
else {
var ind = form.url.selectedIndex;
var loc = form.url.options[url].value+'.html';
window.location=loc;
}
return false;
}
window.onload=function() {
if (document.getElementById('submitButton')) {
document.getElementById('submitButton').style.display='none';
}
};

</script>

All of this works if JS is enabled, but if it isn't - it still works. True, the redirector.php will never get used for most of your clients, but it insures that everyone can access the content, and it's so easy to do, why wouldn't you?

daveVk

10:49 pm on Jan 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



if (msg != '') { alert(msg); }
else { form.submit(); }
return false;

If the form is OK, why not return true and let default submit occur ?

if (msg != '') { alert(msg); }
return (msg == '');

rocknbil

3:31 am on Jan 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



'Spoze you could, but it's just one more hit to the server (the script and redirect) you eliminate by using window.location.

daveVk

10:40 am on Jan 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



rocknbil

Sorry should have read your post in full, using using window.location is obviously better.

rocknbil

6:44 pm on Jan 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nah, raises a good question, in a regular form where it's just validation, say, to a contact processor where it will submit the form anyway, what's more "efficient" or "correct,", using the form.submit() method or returning true? Seems about the same, but don't know.

Readie

10:25 pm on Jan 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Right, I shall definatley have to try that now - thank you very much Rocknbil - I have somehow defied the laws of physics and sent you a hug through the internet :) Out of interest is onChange="this.form.submit();" a valid attribute for a form aswell as an input?

Although it's not quite related to the subject at hand, I do have yet another question :)

On one of my websites I have a very nice looking JavaScript powered multi-level navigation menu. I made sure that there was a useable alternative by wrapping the navigation space in a div, with a non-JS menu inside said div, and using innerHTML to overwrite that with the JS menu.

Problem is it's rather difficult to edit (being forced to put all the code on one line), and you can see the non-JS menu as the page is loading.

Is there a method of detecting whether JavaScript is enabled with a PhP if statement? So I could have something like:

if (JavaScript = enabled) {
echo 'JS menu code';
} else {
echo 'non-JS alternative';
}

And that would make me very happy :)

Readie

12:05 am on Jan 3, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I figured

$result = get_browser();
if ($result['javascript'] == 1) {
echo '';
} else {
echo '';
}

as a possibility, but I'm concerned over people having JavaScript disabled, rather than just a browser that doesn't support it.

rocknbil

6:05 am on Jan 3, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, PHP doesn't test for JS directly, you need JS (I think . . .) and if you test for Javascript with Javascript it's a bit like the chicken and the egg . . .

Second, browser testing is an endless chase as they are always changing. Besides, identifying the browser is no indicator if that user has JS enabled or not.

At any rate, the overall concept of the thread still applies:

1. Build your page WITHOUT the Javascript. That is, don't test for JS first, supply the alternate content. If this causes some "shift" in elements while the Javascript changes the document, the solution is to design it in such a way that it's not noticed - that is, have an element that is common to both, JS and non JS, that loads first. Example: regular image button (or something) then if JS is enabled, overwrite the contents of that container (which, in the case of a menu, should probably be an <li> . . .)

2. IF JS is enabled, then write the menu to the li. Or div. :-)

Out of interest is onChange="this.form.submit();" a valid attribute for a form as well as an input?

I really don't know, or know if the browser would recognize a form "changing." Would be an interesting experiment, though I can't think of a single reason why I'd apply onchange to a form. If you're thinking, "if anything changes in the form" I guess it might be worth exploring.

Readie

8:06 pm on Jan 3, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hmm, well, for the navigation menu I, on a whim, shifted the alternative version to actually look the same on the surface, with the 'links' that dropped down to show the menus actually being links to a page that is, in effect, the drop down menu.

Am dissapointed that PhP can't directly test for JS though - would of been very nice.

It should of occured to me to write to each li, rather than writing the whole thing to a div - would make it so much neater - and easier - in the function.

If you're thinking, "if anything changes in the form" I guess it might be worth exploring.

Is exactly what I was thinking - although the basis was more for some sort of calculation rather than a means of site navigation. I have tested it and it unfortunatley does not work.

rocknbil

8:17 pm on Jan 3, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Usually what I do in those situations is declare a global "formChanged=false;" variable. When the form loads, a function goes through all the form elements to determine their loaded state. OnSubmit, compare the current state of the form elements against the original, if anything's changed formChanged gets set to true.

This is of use if the user encounters something and has to navigate away from the form, which should be rare.