why js identify my input type for text box but not forcheckbox/radiobox

R

Randell_D

This is annoying me and taking me a few hours to resolve so all help
appreciated if you can direct me forward. I'm writing a dynamic
script that will retrieve the value of a form field (an html input
tag) regardless if its a text, password, hidden, select, radio or
checkbox.

I have got the script to work correctly for text/password/hidden and
select but fail when I get to radio/check boxes. Roughly summarised,
the following will correctly alert "text" or "select-one" depending on
the value of "myField". However "undefined" is reported when I ask it
to identify a radio/checkbox. Anyone tell me why and where I am going
wrong?

alert( document.forms['myForm'].elements['myField'].type );

I've written test code here... the code loads and correctly identifes
radiobox name 'a' as a radio but when I click on the hyperlink it
identifies the same input box as "undefined".

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<form name="form1" method="post" action="">
<p>test1:<input name="test1" type="text" id="test1"></p>
<p>radio1<input name="a" type="radio" value="1" checked>
radio2<input type="radio" name="a" value="2"></p>
</form>
<hr>
<a href="#" onClick="showValues();">Show Values</a>
<script language="JavaScript">
function readRadioButton(radioObj)
{
var counter=new Number(0);
var limit=radioObj.length;
for( counter=0; counter<limit; ++counter )
{ if( radioObj[counter].checked==true )
{ return radioObj[counter].value; }
}
return false;
}

function showValues()
{
radioObject=f1.a;
alert(radioObject.type);
return true;
}
var DOCUMENT=top.document;
var f1=DOCUMENT.forms['form1'];
var vartmp=new String("");
for(var counter=0; counter<2; ++counter)
{
vartmp+="\n"+f1.elements[counter].type
+"="+f1.elements[counter].name;
}
alert(vartmp);
</script>
</body>
</html>
 
T

Thomas 'PointedEars' Lahn

Randell_D said:
I have got the script to work correctly for text/password/hidden and
select but fail when I get to radio/check boxes. Roughly summarised,
the following will correctly alert "text" or "select-one" depending on
the value of "myField". However "undefined" is reported when I ask it
to identify a radio/checkbox. Anyone tell me why and where I am going
wrong?

alert( document.forms['myForm'].elements['myField'].type );

As you have been told already, controls with the same name are represented
by a NodeList in the DOM:

window.alert(document.forms['form1'].elements['a'][0].type);
[...]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

The system identifier is missing, this will force the UA into
Quirks/Compatibility Mode.
[...]
<form name="form1" method="post" action="">
<p>test1:<input name="test1" type="text" id="test1"></p>
<p>radio1<input name="a" type="radio" value="1" checked>
radio2<input type="radio" name="a" value="2"></p>
</form>
<hr>
<a href="#" onClick="showValues();">Show Values</a>

For several reasons, that is very bad style. Consider this instead:

<form action="" method="post">
<div>
test1: <input name="test1" type="text" id="test1">
</div>

<div>
<input name="a" type="radio" value="1" checked>&nbsp;radio1
<input type="radio" name="a" value="2">radio2
</div>

<script type="text/javascript">
document.write(
'<input type="button" onclick="showValues(this);"'
+ ' value="Show Values">'
);
</script>
</form>

The button is generated with script so that it becomes unavailable when its
functionality is unavailable.
<script language="JavaScript">

Invalid, replace with

function readRadioButton(radioObj)
{
var counter=new Number(0);

Completely pointless.

var counter = 0;
var limit=radioObj.length;
for( counter=0; counter<limit; ++counter )
{ if( radioObj[counter].checked==true )

Unnecessarily inefficient and not pretty-printed.

{
if (radioObj[counter].checked)
{ return radioObj[counter].value; }
}
return false;
}

function showValues()
{
radioObject=f1.a;

Undeclared identifier; assignment causes modification of a property of an
object in the scope chain. May as well cause a runtime error if that object
is a host object.
[...]
var DOCUMENT=top.document;

Completely pointless; you are using the `DOCUMENT' reference only once, and
you are not even feature-testing it. Furthermore, the case of the
identifier is not pretty-printed; all-caps indicate a constant.
var f1=DOCUMENT.forms['form1'];

var f1 = window.top.document.forms['form1'];

However, this could be omitted if you passed `this.form' for `f1' or it
could be simplified to

var f1 = o.form;

if you passed `this' for the named argument `o'.
var vartmp=new String("");

Completely pointless.

var vartmp = "";
for(var counter=0; counter<2; ++counter)
{
vartmp+="\n"+f1.elements[counter].type
+"="+f1.elements[counter].name;
}

Completely pointless `for' loop, for two iterations.

var tmp = new Array(
f1.elements[0].type, "=", f1.elements[0].name,
"\n",
f1.elements[1].type, "=", f1.elements[1].name
).join("");

However, if you were to employ a `for' loop, you should do it more efficient
as follows:

var tmp = new Array();

for (var counter = 0, es = f1.elements, len = es.length;
counter < len;
++counter)
{
tmp.push(es[counter].type + "=" + es[counter].name);
}

tmp = tmp.join("\n");
alert(vartmp);

alert() is a method of Window objects and should be called so:

window.alert(tmp);


PointedEars
 
R

Randell_D

Thomas,

Thanks - the code I supplied was not my original code hence some of
the declarations while only used once are used multiple times in my
working code. The code I included was "playful", my attempt to create
a small test to try and resolve the problem before posting here.

In addition - while I am grateful to your help I have not "already
been told once". My previous post told me how to read the from a
radio/checkbox that had been "ticked".

Now though, I want to run a for loop on my form and dynamically read
the values of each input tag regardless if the input tag is of type
text, hidden, password, select-one, select-multiple, radio, or
checkbox.

Thus using the following code, if "myField" was a text box or a hidden
box then I correctly get an alert popup box that says "text" or
"hidden".

alert( document.forms['myForm'].elements['myField'].type );

when i try using the above code and point it towards a checkbox the
alert returns "undefined". If I point it towards a radio, it returns
"undefined".

I can't use

alert( document.forms['myForm'].elements['myField'][0].type );

since i don't know its a checkbox beforehand and performing the above
test on a text box would likely result in some other error.

So... using a for loop I want to go through my entire form
(elements[0] to elements[20] for example) and take a different action
depending if the element[x] points to a text box or a check box. How
can I do this if i cannot correctly identify a check box or radio box?
 
T

Thomas 'PointedEars' Lahn

Randell_D said:

This is Usenet, an m:n communications medium; it is considered inappropriate
to address only one person as anyone is welcome to reply. If you want 1:1
communication, use private e-mail or instant messaging.

It is even more inappropriate not to quote anything from the precursor.

http://jibbering.com/faq/
[...]
In addition - while I am grateful to your help I have not "already
been told once". My previous post told me how to read the from a
radio/checkbox that had been "ticked".

Maybe you need (new) glasses:

[...]
I can't use

alert( document.forms['myForm'].elements['myField'][0].type );

since i don't know its a checkbox beforehand [...]

var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))
{
// NodeList
}
else
{
// single item
}

Your reference worms are error-prone and very inefficient anyway. Pass
`this' from event listener code to your method instead and observe both
becoming less.


HTH

PointedEars
 
R

Randell_D

Randell_D said:

This is Usenet, an m:n communications medium; it is considered inappropriate
to address only one person as anyone is welcome to reply. If you want 1:1
communication, use private e-mail or instant messaging.

It is even more inappropriate not to quote anything from the precursor.

http://jibbering.com/faq/
[...]
In addition - while I am grateful to your help I have not "already
been told once". My previous post told me how to read the from a
radio/checkbox that had been "ticked".

Maybe you need (new) glasses:

[...]
I can't use
alert( document.forms['myForm'].elements['myField'][0].type );
since i don't know its a checkbox beforehand [...]

var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))
{
// NodeList
}
else
{
// single item
}

Your reference worms are error-prone and very inefficient anyway. Pass
`this' from event listener code to your method instead and observe both
becoming less.

HTH

PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee


Good God man... you've told me something I didn't know I didn't know
but nothing I wanted to know...
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))

appears to be a very long winded and ugly approach to identify an
input tag. I'm surprised there is no other resource friendly method...
 
T

Thomas 'PointedEars' Lahn

Randell_D said:
[Full quote]

Good God man... you've told me something I didn't know I didn't know
but nothing I wanted to know...

So it would seem, and so you will have to go without at least my advice
until further notice.
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))

appears to be a very long winded and ugly approach to identify an
input tag.

It does not "identify an input tag", whatever you think that might be.
I'm surprised there is no other resource friendly method...

That is a very resource-friendly approach, you just do not recognize it.


PointedEars
 
P

pr

Randell_D said:
On Mar 25, 11:15 pm, Thomas 'PointedEars' Lahn <[email protected]>
Good God man... you've told me something I didn't know I didn't know
but nothing I wanted to know...
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))

appears to be a very long winded and ugly approach to identify an
input tag. I'm surprised there is no other resource friendly method...

That is an efficient way of telling a NodeList from a <select> element,
both of which have a length property that means something slightly
different in each case.

Form elements bearing the same name are returned as a NodeList and you
must access individual members of the list by index before you can read
the type (or any other) property from them. To be honest, I think we're
running out of permutations of words with which to say this.

See what happens when you run your test on a form having just _one_
checkbox and _one_ radio button, each named something different; see the
element's type correctly reported? Good. Then read again the responses
you have received and the FAQ <URL: http://jibbering.com/faq/>.
 
V

VK

This is annoying me and taking me a few hours to resolve so all help
appreciated if you can direct me forward. I'm writing a dynamic
script that will retrieve the value of a form field (an html input
tag) regardless if its a text, password, hidden, select, radio or
checkbox.

I have got the script to work correctly for text/password/hidden and
select but fail when I get to radio/check boxes. Roughly summarised,
the following will correctly alert "text" or "select-one" depending on
the value of "myField". However "undefined" is reported when I ask it
to identify a radio/checkbox. Anyone tell me why and where I am going
wrong?

alert( document.forms['myForm'].elements['myField'].type );

I've written test code here... the code loads and correctly identifes
radiobox name 'a' as a radio but when I click on the hyperlink it
identifies the same input box as "undefined".

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<form name="form1" method="post" action="">
<p>test1:<input name="test1" type="text" id="test1"></p>
<p>radio1<input name="a" type="radio" value="1" checked>
radio2<input type="radio" name="a" value="2"></p>
</form>
<hr>
<a href="#" onClick="showValues();">Show Values</a>
<script language="JavaScript">
function readRadioButton(radioObj)
{
var counter=new Number(0);
var limit=radioObj.length;
for( counter=0; counter<limit; ++counter )
{ if( radioObj[counter].checked==true )
{ return radioObj[counter].value; }
}
return false;

}

function showValues()
{
radioObject=f1.a;
alert(radioObject.type);
return true;}

var DOCUMENT=top.document;
var f1=DOCUMENT.forms['form1'];
var vartmp=new String("");
for(var counter=0; counter<2; ++counter)
{
vartmp+="\n"+f1.elements[counter].type
+"="+f1.elements[counter].name;
}
alert(vartmp);
</script>
</body>
</html>

It is because radio and checkbox collections are polymorphic. If there
is only one element with such name then that element is returned. If
there are more than one elements with such name then HTMLCollection of
such elements is returned. In your case you have two elements named
"a" so you are getting HTMLCollection back - and HTMLCollection
doesn't have property "type" so it is properly reported as undefined.
Instead you have to query the type of a particular elements in the
collection, say the first one:
window.alert(radioObject[0].type); // "radio"
 
T

Thomas 'PointedEars' Lahn

pr said:
Randell_D said:
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))
appears to be a very long winded and ugly approach to identify an
input tag. I'm surprised there is no other resource friendly method...

That is an efficient way of telling a NodeList from a <select> element,
both of which have a length property that means something slightly
different in each case.

Actually, after reviewing this I think

if (typeof e[0] != "undefined" && !/\s*select\s*/i.test(e.tagName))

or

if (typeof e[0] != "undefined" && !/\s*select(-one)?\s*/i.test(e.type))

or

if (typeof e[0] != "undefined" && typeof e.options == "undefined")

are even more efficient, whereas I would prefer the last because it cannot
cause any warnings. The most efficient, but least compatible is of course

if (e instanceof NodeList)

(works in Gecko-based UAs.)


PointedEars
 
T

Thomas 'PointedEars' Lahn

VK said:
[...]
It is because radio and checkbox collections are polymorphic.

Utter nonsense. Apparently you neither know what a collection is nor what
polymorphism is.

However, it is interesting to note that in MSHTML-DOM-, Opera-DOM- and
WebKit-based UAs there is apparently a collection (the objects have a
namedItem() method and bracket property accessor with ID or name as string
value works); in the Gecko DOM there is only a NodeList. Both if, and only
if, there is more than one control with the same name. For radio buttons
this can be assumed, although there is no requirement for it.
If there are more than one elements with such name then HTMLCollection of
such elements is returned.

First, nothing is returned as nothing is called; second, a reference to an
object that often (but not always) implements the HTMLCollection or NodeList
interface can be retrieved when accessing the item of the form object's
`elements' collection.

It is interesting to note that Safari 3.1 (WebCore) and IE 7.0 (MSHTML DOM)
apparently do not implement this for dynamically created controls with the
same name, but Firefox 2.0.0.13 (Gecko-1.8.1 DOM) does. This might be due
to the fact that AFAICS W3C DOM Level 2 HTML does not have anything to say
about controls with the same name.


PointedEars
 
P

pr

Thomas said:
pr said:
Randell_D said:
On Mar 25, 11:15 pm, Thomas 'PointedEars' Lahn <[email protected]>
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))
That is an efficient way of telling a NodeList from a <select> element,
both of which have a length property that means something slightly
different in each case.

Actually, after reviewing this I think

if (typeof e[0] != "undefined" && !/\s*select\s*/i.test(e.tagName))

or

if (typeof e[0] != "undefined" && !/\s*select(-one)?\s*/i.test(e.type))

The advantage of this RegExp is that the element name is there to show
what the code is for. I would suggest

/\bselect\b/i

as the pattern, however (covers 'select-one' and 'select-multiple' too).
or

if (typeof e[0] != "undefined" && typeof e.options == "undefined")

That should do it and is almost certainly faster, but I suspect you know
something I don't because you are avoiding e.length.

I assume that a UA somewhere uses length to denote text input length,
for example, but I can't find one. Otherwise couldn't you do:

if (e.length && typeof e.options == "undefined")

?
are even more efficient, whereas I would prefer the last because it cannot
cause any warnings. The most efficient, but least compatible is of course

if (e instanceof NodeList)

(works in Gecko-based UAs.)

Yes. It's instanceof HTMLCollection in Opera and a syntax error in
antiques, worse luck.
 
T

Thomas 'PointedEars' Lahn

pr said:
Thomas said:
pr said:
Randell_D wrote:
On Mar 25, 11:15 pm, Thomas 'PointedEars' Lahn <[email protected]>
var e = document.forms['myForm'].elements['myField'];
if (typeof e[0] != "undefined" && !/\s*option\s*/i.test(e[0].tagName))
That is an efficient way of telling a NodeList from a <select> element,
both of which have a length property that means something slightly
different in each case.
Actually, after reviewing this I think

if (typeof e[0] != "undefined" && !/\s*select\s*/i.test(e.tagName))

or

if (typeof e[0] != "undefined" && !/\s*select(-one)?\s*/i.test(e.type))

The advantage of this RegExp is that the element name is there to show
what the code is for. I would suggest

/\bselect\b/i

as the pattern, however (covers 'select-one' and 'select-multiple' too).

It also matches "äselectß" and the like, but not consistently among
implementations. Hence my matching the optional whitespace instead.
or

if (typeof e[0] != "undefined" && typeof e.options == "undefined")
^^^^^^^^^^^^^^^^
That should do it and is almost certainly faster, but I suspect you know
something I don't because you are avoiding e.length.

I have marked the important parts above and below. I used the original
expression in my quick-hacked form serializer and stumbled upon select
element _objects_ also having a `0' property (observed in the Gecko DOM).
I assume that a UA somewhere uses length to denote text input length,
for example, but I can't find one. Otherwise couldn't you do:

if (e.length && typeof e.options == "undefined") ^^^^^^^^
?

are even more efficient, whereas I would prefer the last because it cannot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cause any warnings. [...]
^^^^^^^^^^^^^^^^^^

HTH

PointedEars
 
P

pr

Thomas said:
pr said:
Thomas said:
Actually, after reviewing this I think

if (typeof e[0] != "undefined" && !/\s*select\s*/i.test(e.tagName))

or

if (typeof e[0] != "undefined" && !/\s*select(-one)?\s*/i.test(e.type))
The advantage of this RegExp is that the element name is there to show
what the code is for. I would suggest

/\bselect\b/i

as the pattern, however (covers 'select-one' and 'select-multiple' too).

It also matches "äselectß" and the like, but not consistently among
implementations. Hence my matching the optional whitespace instead.

"äselectß" would be an unlikely result for e.type and an illegal one for
e.tagName, at least in the HTML DOM and form.elements collection.
or

if (typeof e[0] != "undefined" && typeof e.options == "undefined")
^^^^^^^^^^^^^^^^
That should do it and is almost certainly faster, but I suspect you know
something I don't because you are avoiding e.length.

I have marked the important parts above and below. I used the original
expression in my quick-hacked form serializer and stumbled upon select
element _objects_ also having a `0' property (observed in the Gecko DOM).

Really not sure what you mean. Maybe I have to look in the archive.
I assume that a UA somewhere uses length to denote text input length,
for example, but I can't find one. Otherwise couldn't you do:

if (e.length && typeof e.options == "undefined") ^^^^^^^^
?

are even more efficient, whereas I would prefer the last because it cannot ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cause any warnings. [...]
^^^^^^^^^^^^^^^^^^
 
T

Thomas 'PointedEars' Lahn

pr said:
Thomas said:
pr said:
Thomas 'PointedEars' Lahn wrote:
Actually, after reviewing this I think

if (typeof e[0] != "undefined" && !/\s*select\s*/i.test(e.tagName))

or

if (typeof e[0] != "undefined" && !/\s*select(-one)?\s*/i.test(e.type))
The advantage of this RegExp is that the element name is there to show
what the code is for. I would suggest

/\bselect\b/i

as the pattern, however (covers 'select-one' and 'select-multiple' too).
It also matches "äselectß" and the like, but not consistently among
implementations. Hence my matching the optional whitespace instead.

"äselectß" would be an unlikely result for e.type and an illegal one for
e.tagName, at least in the HTML DOM and form.elements collection.

W3C DOM Level 2 HTML applies to XHTML 1.0 documents as well, but you should
see my point anyway:
or

if (typeof e[0] != "undefined" && typeof e.options == "undefined") ^^^^^^^^^^^^^^^^
That should do it and is almost certainly faster, but I suspect you know
something I don't because you are avoiding e.length.
I have marked the important parts above and below. I used the original
expression in my quick-hacked form serializer and stumbled upon select ^^^^^^^^^^^^^^^
element _objects_ also having a `0' property (observed in the Gecko DOM).

Really not sure what you mean. Maybe I have to look in the archive.

Directly accessing an undefined property causes a strict warning in Gecko; a
`typeof' operation does not. While some consider designing scripts to that
feature pointless, I consider it good style, especially as we are dealing
with host objects here.


PointedEars
 
R

Richard Cornford

Thomas 'PointedEars' Lahn wrote
... . I used the original expression in my quick-hacked form
serializer and stumbled upon select element _objects_ also having
a '0' property (observed in the Gecko DOM).
<snip>

The - options - collections of SELECT elements have historically (and
still commonly) been implemented by the SELECT elements themselves (that
is, if you compared the options collection with the SELECT element you
would find that they were 'equal', and so the same object. As a result -
options - collections will often be observed to have all the properties
of the SELECT element that contains them and if the options collection
is non-empty the SELECT element will have integer indexed properties
with object values.

There was even a time (probably driven by code examples provided by
Microsoft) when it was common for code to be posted here that treated
the SELECT elements as the options collection (directly indexing it, or
appending new Option objects). I have not seen that here in a couple of
years, but it probably will show up at least once more.

Richard.
 
P

pr

Thomas said:
W3C DOM Level 2 HTML applies to XHTML 1.0 documents as well, but you should
see my point anyway:

If there's a risk of non-form elements being in the mix, yes.

[...]
Directly accessing an undefined property causes a strict warning in Gecko; a
`typeof' operation does not. While some consider designing scripts to that
feature pointless, I consider it good style, especially as we are dealing
with host objects here.

I agree with you and only wish the likes of Google and Yahoo did too.
But the following script only triggers warnings for me at the places marked:

var b = document.body.length ? true : false; /* undefined,
therefore false */
var o = {};
if (o.length) b = true;
if (!o.length) b = true;
if (!!document.body.length) b = true;
if (typeof o.length == "undefined") b = true;
if (o.length == 0) b = true; // warning
if (document.body.length == 0) b = true; // warning

Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.8.1.12) Gecko/20060601
Firefox/2.0.0.12 (Ubuntu-edgy)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,811
Latest member
SaulFernan

Latest Threads

Top