views:

1205

answers:

7

How can I find out which FORM an HTML element is contained within, using a simple/small bit of JavaScript? In the example below, if I have already got hold of the SPAN called 'message', how can I easily get to the FORM element?

<form name="whatever">
    <div>
        <span id="message"></span>
    </div>
</form>

The SPAN might be nested within other tables or DIVs, but it seems too long-winded to iterate around .parentElement and work my way up the tree. Is there a simpler and shorter way?

If it wasn't a SPAN, but an INPUT element, would that be easier? Do they have a property which points back to the containing FORM? Google says no...

+8  A: 

The form a form element belongs to can be accessed through element.form.

When the element you are using as reference is not a form element, you'd still have to iterate through the parentElement or use some other kind of selector.

Using prototype, you could simplify this by using Element.up():

$(element).up('form');

Other answers to this question have pointed out how to do the same in jQuery.

Aron Rotteveel
Well I thought there ought to be a .form property...but I wasnt sure so I Googled and didn't see one. I must be blind.Thanks for pointing out the obvious!
Magnus Smith
A: 

You could backtrack in the DOM tree until you get to the right node:

node = document.getElementById("message");
while (node.nodeName != "FORM" && node.parentNode) {
    node = node.parentNode;
}
Gumbo
+4  A: 

Guess you have to iterate through all elements then. You can try using jQuery:

$("input").parent("form")

http://docs.jquery.com/Traversing/parent#expr

Deniss Kozlovs
+2  A: 

Or a small jQuery (ignoring jQuery itself):

$("#message").parents("form:first")
Allain Lalonde
A: 

Other than node.parentNode, I don't believe there is a way to find a specific ancestor of a given node. Most libraries usually do what you describe and iterate up through parentNode.

If you're not using a library like prototype, jquery or Ext, it would probably be a good idea. By now, they've resolved all the incompatibilities and quirks in the DOM to make most operations like this a trifle.

Kevin
+1  A: 

Regarding Gumbo's Post: As much as prototype and jQuery are useful, some people don't implement them into their projects.

Could someone please explain why Gumbo's solution was downgraded, other than the fact that he repeated what the OP was originally trying to avoid?

node = document.getElementById(this.id);
while (node.nodeName != "FORM" && node.parentNode) {
    node = node.parentNode;
}

 

To answer the OP's question: Traversing the DOM is the fastest way to achieve this effect - perceived speed is accomplished by 1) better written JS code, or 2) execution time (if you store the form on page load for that element, you'll still be traversing, but you'll have a quicker call to a stored variable when you need to retrieve that information).

There are no attributes nested in non-form elements that would associate it with the form (span.form does not exist).

If you are using a script (php/perl) to generate your page, and you're going to be making a lot of calls to the form, you could embed the form id in the HTML for that element. Still, a look up would need to occur.

I hope this helps,

vol7ron

vol7ron
A: 

node = document.getElementById("message"); while (node.nodeName != "FORM" && node.parentNode) { node = node.parentNode; }

This is the perfect solution! Thank you.

Tito