Some Insight Into The Document Object Model: How Forms Are Stored By JavaScript

Recently asked on Yahoo! Answers:

JavaScript Submit form?

Ok, I know of the function…

function submitform() {document.myform.submit();}

however, for this to work, I have to name my forms, also, if I want to use it multiple times on the same page, each funtion name must be unique.

Is there a way to replace a submit button with javascript without having to uniquely name each function, or name my forms? I’m just looking for a link replacement for the submit button. So, a submit button just sits at the end of the form and submits it’s data, can I just replace it with a link, no extra stuff except one function at the top of the screen?

Also, the form’s method is POST, not GET. Also, the action is $PHP_SELF; though, if you give me an ideal answer, the JavaScript won’t even worry about the action.

This is something I don’t see as often as I’d like: A question about how something works, and a question with a practical application.

In other words, the user wants to solve a particular problem, but the question is posed in a way that its answer can reveal a great deal about how the Document Object Model (DOM) works. And understanding how things work makes programming far easier, believe me.

I began answering the direct question of how to submit an unnamed form with JavaScript, but then decided that, because opportunities like this are so rare, I’d seize upon it and launch a full dissertation here.

Before we begin, I’m going to be tossing around some terms about how classes / objects work. If you’re new to programming, or at least object-oriented programming, and aren’t familiar with terms such as “property,” “method,” “event” or “namespace,” you’ll want to check out my earlier entry, titled “Objects (Classes) Explained In Very Simple Terms.”

In the HTML / XHTML Document Object Model (DOM), all form elements on the page are handled as an associative array, even if there is only one form on the page.

In other words, JavaScript holds all the forms on a page as an array of form objects, called document.forms. If there is only one form on the page, that form is the zero index of the document.forms array.

Aside: To be 100 percent accurate, JavaScript has a class, document, which refers to the current Web page. The document class has a property, forms, which contains a collection of all the form objects on the page. [In object-oriented programming, a collectionis an array of similar objects.]So, when you call document.forms, you are actually requesting the collection of form objects from the current document. And thus, you can work with the forms on the page as you would any one-dimensional array.

The document.forms array is ordered by the order of the forms on the page, with the topmost form being the first element of the array and the bottommost form, the last element.

As the questioner notes, it is most common in JavaScript to address forms by their DOM namespace (e.g., document.myform.submit()).

However, in most JavaScript implementations, you can address the same form via the document.forms array. And when that is the case, you can work with the document.forms array as you would any other associative array.

So, assuming the form named “myform” is the first form on your page, you can address it by document.myform (its namespace), document.forms[0] (its index in the array) or document.forms[‘myform’] (its key in the array).

(There are additional ways of referring to forms on a page, but I don’t want to bog down the point with arcana.)

Since the question is about working with unnamed forms, it makes the most sense to address the forms on a page by their index in the document.forms array.

So, if there is only one form on the page, you can submit it by:

document.forms[0].submit();

You can submit the third form on the page with:

document.forms[2].submit();

You can submit all forms on a page with:

for(var i = 0; i < document.forms.length; i++) {
     document.forms[i].submit();
}

As most people know, JavaScript is almost exclusively invoked by events.

Therefore, you can invoke the form object’s submit() method via any event in the DOM (onclick, onmouseover, onfocus, etc.). And any element that supports an event is capable of triggering the submit() method.

In other words, you can submit a form not only via a button click, but by clicking on a link or a div, placing your cursor in a text box, hovering over an image, changing the selected item in a select, clicking on a checkbox. … any legal event for any element that supports events can trigger form submission.

For example, the button below will submit the first form on a page when clicked:

<button id="mybutton" onclick="document.forms[0].submit()"></button>

The image below will submit the same form if the cursor is placed over it:

<img onmouseover="document.forms[0].submit()" src="myimg.jpf" alt="" />

Here is a text box that submits the 347th form on a page once the cursor is placed inside it:

<input name="mytext" size="30" type="text" value="foobar" />

And, as requested, a link that submits the first form on the page:

<a onclick="document.forms[0].submit()">Submit form</a>

Because the DOM treats all page elements as objects, and JavaScript is an object-oriented language (in most implementations), you don’t even need to use document.forms, if you use a button click to call the submit() method. Instead, you can use this.form.submit().

In object-oriented programming, the reserved word “this” is used to refer to an object when you’re not sure what it is named — or, as in the case here, when the object hasn’t been named yet, either because it’s not ready to be named or because it’s inconvenient to name it.

If you don’t want to name your forms, using a button with this.form.submit() as its onclick event handler to submit the form makes the most sense.

<button onclick="this.form.submit()"></button>

So what does this.form.submit() mean?

N00bs might think “this.form” refers to “this form,” but that’s not quite right. The button element, not the form, is the object referenced by “this.”

The button object has a property, “form”, which is a reference to the form containing the button. And the form object has a method, submit, which you already know about.

So, this.form.submit() literally says, “get this button, then find the form to which it belongs, then submit that form.” So “this.form” is effectively the same thing as “this form,” but it’s not exactly the same — and remember, computers are literal.

The difference between “this.form” and “this form” might seem trivial, but it’s actually significant.

In object-oriented programming, you quickly learn that “this” is very handy. You also quickly learn that not knowing what type of object you are referring to when you use “this” will cause major chaos with your code — chaos that is often difficult to track down and fix.

Finally, the method and action of a form are immaterial to the form object’s submit() method. Basically, the method simply indicates that whatever action is specified for the form should be invoked, with data sent via whatever method the form is told to use.

7 Comments

  1. You’re such a geek! Yes, you’re my brother and I still love ya. Thankfully, you’ve got an outlet for your vice! See you soon.

  2. As a side note (which I’ve just spent TOO long trying to figure out)…

    If any of the fields in the form have name of “submit” eg then, the submit() method is no longer usable… Continuing in the spirit of the article, I’ll give the why:

    Consider this form:

    <form action="script.php">
    <input type="text" name="username" />
    </form>
    

    If you want to access the input field with a name of “username” you can get to it with:

    document.forms[0].username

    So when you add,

    <input type="text" name="submit" />
    

    you end up with a conflict:

    document.forms[0].submit wants to access the object relating to the form field with a name of submit, while document.forms[0].submit() wants to access the form object and run its submit method

    Kiall

  3. What Kiall describes is the difference between accessing a namespace member and calling a class method. It’s an example of why you should never use reserved words as a variable name, too.

    In the case of his code example, document.forms[0].submit basically says, “in the current document, find the first form on the page, and give me the element in that form named “submit.” document.forms[0].submit() says, “in the current document, find the first form on the page, and invoke the submit method for that form.”

    Here’s a trick that draws it all together. Let’s start with his form:

    <form action="script.php">
    <input type="text" name="username" />
    <input type="text" name="submit" />
    </form>
    

    We can actually “double up”, as it were, on the namespaces, properties and methods, and call the following JavaScript, which would also submit the form:

    document.forms[0].submit.form.submit();
    

    What document.forms[0].submit.form.submit() says is, “In the current page, get the first form [“forms” is a property of the document class; specifically, it is a collection of all the form objects in the current Web page]. Then, find the element within that form named “submit” [“submit” is the namespace for a text-type input element named, not coincidentally, “submit”]. Find that element’s parent form [“form” is a property of the input class; it refers to the parent form which contains the input element]. Then, invoke the submit method for that form [“submit()” is a method of the form class; and again, we are calling that method via a reference to the form that contains the input element named “submit”].”

    Of course, for all that’s worth, we could remove the input named “submit” and simply use document.forms[0].username.form.submit(); or, for all that’s worth, simply call document.forms[0].submit().

    Elegance is always what we’re after, and namespaces are primarily intended to group together our objects in a way that makes them easier to address. But as the examples above show, sometimes it’s simpler and better to avoid using namespaces altogether and directly address collections as we would any array.

  4. Excellent article that really sheds light on the subject, thanks. Also, a big thanks to Kiall for his addendum, of which I would probably still be lost.

  5. Thanks for this post. Very helpful to understand the workings. I was actually having the problem with a button named submit and trying to call document.form[0].submit(); wouldn’t work until I renamed the button. Thanks!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!