getElementsByName undefined for dynamic elements (radio buttons)

S

Saul

I have a set of radio buttons that are created dynamically, after
rendered I try loop thru this set by getting the length of the set, but
I keep getting an error stating the element is undefined. I am using
getElelementsByName since these are radio buttons, but it seems that
the dynamic element is not seen!!!

This is my code... please let me know if there is anything that I am
doing wrong! - thanks
----
....
....
// this loops thru an ajax structure --- this is correct so I kow is
not an Ajax issue.

for(var i=0; i<ds.Tables[0].Rows.length; i++){
//creating nue input element
var r=document.createElement('<INPUT type=radio name=company >');
r.type="radio";
r.name ="company";
r.id ="myradiobutton" + i;
r.setAttribute("value",ds.Tables[0].Rows.roottype);
td_company.appendChild(r);
td_company.appendChild(document.createTextNode(ds.Tables[0].Rows.roottypedesc));
}

-----
My function trying to get the lenght of the set is called after the
radion buttons are rendered. If I find one that has an specific value,
I check it.

for(var n=0; n<document.getElementsByName("company").length; n++){
if (document.getElementsByName("company")[n].value == 'msde')
{
document.getElementsByName("country")[n].checked = "checked";
}
}
 
A

ASM

Saul a écrit :
I have a set of radio buttons that are created dynamically, after
rendered I try loop thru this set by getting the length of the set, but
I keep getting an error stating the element is undefined. I am using
getElelementsByName since these are radio buttons, but it seems that
the dynamic element is not seen!!!

This is my code... please let me know if there is anything that I am
doing wrong! - thanks
----
...
...
// this loops thru an ajax structure --- this is correct so I kow is
not an Ajax issue.

for(var i=0; i<ds.Tables[0].Rows.length; i++){
//creating nue input element
var r=document.createElement('<INPUT type=radio name=company >');

var r=document.createElement('INPUT');
r.type="radio";
r.name ="company";
r.id ="myradiobutton" + i;
r.setAttribute("value",ds.Tables[0].Rows.roottype);


roottype isn't it Java language ?
td_company.appendChild(r);

what is td_company ?
td_company.appendChild(document.createTextNode(ds.Tables[0].Rows.roottypedesc));
}

-----
My function trying to get the lenght of the set is called after the
radion buttons are rendered. If I find one that has an specific value,
I check it.

for(var n=0; n<document.getElementsByName("company").length; n++){
if (document.getElementsByName("company")[n].value == 'msde')
{
document.getElementsByName("country")[n].checked = "checked";
}
}


var R = document.getElementsByName("company");
var C = document.getElementsByName("country");
for(var n=0; n<R.length; n++)
if (R[n].value == 'msde') C[n].checked = "checked";

to avoid to re-built these two collections (R & C)
on each loop
 
R

RobG

Saul said on 05/05/2006 7:01 AM AEST:
I have a set of radio buttons that are created dynamically, after
rendered I try loop thru this set by getting the length of the set, but
I keep getting an error stating the element is undefined. I am using
getElelementsByName since these are radio buttons, but it seems that
the dynamic element is not seen!!!

This is my code... please let me know if there is anything that I am
doing wrong! - thanks
----
...
...
// this loops thru an ajax structure --- this is correct so I kow is
not an Ajax issue.

for(var i=0; i<ds.Tables[0].Rows.length; i++){

Is ds.Tables an array of table elements? If so, and item[0] is a table,
then it has a 'rows' collection, not 'Rows' (note capitalisation). But
maybe it is some part of your XML structure that is called 'Rows', I
don't know.

Since you sequentially access all rows, it is also better to get a
reference to the row once and go from there.

It is more efficient to get the length attribute once and store it (the
saving may be insignificant if the number of rows is small, but it's the
thought that counts :) ):

var row, rows = ds.Tables[0].rows;
for(var i=0, len=rows.length; i<len; i++){
row = rows;

//creating nue input element
var r=document.createElement('<INPUT type=radio name=company >');

That method of dynamically adding elements is IE specific and will fail
in most (possibly all) other browsers, the W3C DOM standard method is:

var r = document.createElement('input');
r.type = 'radio';
r.name = 'company';

However, if that method is used, IE doesn't recognise the name attribute
in script, though the form will submit correctly. There is a thread
about it here:

r.type="radio";
r.name ="company";
r.id ="myradiobutton" + i;
r.setAttribute("value",ds.Tables[0].Rows.roottype);


setAttribute is buggy in some browsers, it is better (though
non-standard) to access properties directly as you have above:

r.value = ds.Tables[0].Rows.roottype;

td_company.appendChild(r);
td_company.appendChild(document.createTextNode(ds.Tables[0].Rows.roottypedesc));


Using the suggested row & rows variables above, this becomes:

td_company.appendChild(document.createTextNode(row.roottypedesc));

}

-----
My function trying to get the lenght of the set is called after the
radion buttons are rendered. If I find one that has an specific value,
I check it.

for(var n=0; n<document.getElementsByName("company").length; n++){
if (document.getElementsByName("company")[n].value == 'msde')
{
document.getElementsByName("country")[n].checked = "checked";

Similarly here:

var el, els = document.getElementsByName("company");
for(var n=0, len=els.length; n<len; n++){
el = els;
if (el.value == 'msde') {
el.checked = true;
}
 
A

ASM

RobG a écrit :
Saul said on 05/05/2006 7:01 AM AEST: [...]
for(var n=0; n<document.getElementsByName("company").length; n++){
if (document.getElementsByName("company")[n].value == 'msde')
{
document.getElementsByName("country")[n].checked = "checked";


Similarly here:

Similarly but not duplicately ( "company" != "country" )
var el, els = document.getElementsByName("company");
for(var n=0, len=els.length; n<len; n++){
el = els;
if (el.value == 'msde') {
el.checked = true;
}


var el, els = document.getElementsByName("company");
var en, ens = document.getElementsByName("country");
for(var n=0, len=els.length; n<len; n++){
el = els[n]; // and not els
if (el.value == 'msde') {
en = ens[n];
en.checked = true;
}
}
 
R

RobG

ASM said on 05/05/2006 12:31 PM AEST:
RobG a écrit :
Saul said on 05/05/2006 7:01 AM AEST:
[...]
for(var n=0; n<document.getElementsByName("company").length; n++){
if (document.getElementsByName("company")[n].value == 'msde')
{
document.getElementsByName("country")[n].checked = "checked";



Similarly here:


Similarly but not duplicately ( "company" != "country" )

Yeah, well, depends on the country, doesn't it? ;-)

var el, els = document.getElementsByName("company");
for(var n=0, len=els.length; n<len; n++){
el = els;
if (el.value == 'msde') {
el.checked = true;
}



var el, els = document.getElementsByName("company");
var en, ens = document.getElementsByName("country");
for(var n=0, len=els.length; n<len; n++){
el = els[n]; // and not els
if (el.value == 'msde') {
en = ens[n];
en.checked = true;


If I'd seen company/country I'd likey have done:

var companys = document.getElementsByName("company");
var countries = document.getElementsByName("country");
var n = companys.length;
while (n--){
countries[n].checked = (companies[n].value == 'msde');
}

Of course it's not very tollerant of cases where companys.length is less
than countires.length, but neither was the OP. :)
 
R

RobG

RobG said on 05/05/2006 12:49 PM AEST:
[...]
var companys = document.getElementsByName("company");

var companies = ...
var countries = document.getElementsByName("country");
var n = companys.length;

var n = companies.length;
while (n--){
countries[n].checked = (companies[n].value == 'msde');
}

Of course it's not very tollerant of cases where companys.length is less

... companies.length ...
 
S

Saul

thanks for your replies...

ds is a dataset coming from an Ajax call and roottype is an element of
this set... I am sure the Ajax call is not the issue(since the data is
obtained and rendered correctly) and this is why I focused in the
javascript part to find the problem.

The elements are createed correctly when I loop thru the array. The
radio buttons are there and are visible inside the div tag "td_company"
The issue arises when trying to reference the element "company" which
is the name given to all the radio buttons created dynamically.

if I write an alert from inside the function creating the radio
buttons, to output the company.length ... I get the correct value.
If I write the alert outside the function I always get a zero. So
trying"

document.getElementsByName("company").length

in the caller function always returns zero and therefore i cannot loop.
- but the radio buttons are there, how can it be zero!
Also using document.getElementsByName("company")[0].value to find out
the value of the first element of the set of radio buttons returns
document.getElementsByName(...)[...].value is undefined.

I tried the different recommendations above, but still get the same
issue! - Any other suggestions
 
S

Saul

thanks for your replies...

ds is a dataset coming from an Ajax call and roottype is an element of
this set... I am sure the Ajax call is not the issue(since the data is
obtained and rendered correctly) and this is why I focused in the
javascript part to find the problem.

The elements are createed correctly when I loop thru the array. The
radio buttons are there and are visible inside the div tag "td_company"
The issue arises when trying to reference the element "company" which
is the name given to all the radio buttons created dynamically.

if I write an alert from inside the function creating the radio
buttons, to output the company.length ... I get the correct value.
If I write the alert outside the function I always get a zero. So
trying"

document.getElementsByName("company").length

in the caller function always returns zero and therefore i cannot loop.
- but the radio buttons are there, how can it be zero!
Also using document.getElementsByName("company")[0].value to find out
the value of the first element of the set of radio buttons returns
document.getElementsByName(...)[...].value is undefined.

I tried the different recommendations above, but still get the same
issue! - Any other suggestions

-thanks
 
R

RobG

Saul said:
thanks for your replies...

Please quote the relevant parts of what you are replying to.

ds is a dataset coming from an Ajax call and roottype is an element of
this set... I am sure the Ajax call is not the issue(since the data is
obtained and rendered correctly) and this is why I focused in the
javascript part to find the problem.

I'll guess that -ds.Tables[0].Rows- is referring to your XML structure,
not the HTMLElement structure suggested by the names you've used.

The elements are createed correctly when I loop thru the array. The
radio buttons are there and are visible inside the div tag "td_company"
The issue arises when trying to reference the element "company" which
is the name given to all the radio buttons created dynamically.

Exactly. IE has trouble with the name attribute of elements added
dynamically - from Microsoft's documentation:

"The NAME attribute cannot be set at run time on elements
dynamically created with the createElement method. To create
an element with a name attribute, include the attribute and
value when using the createElement method."

<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/...>


Read the thread I suggested provides 2 work-arounds, here it is again;

<URL:http://groups.google.co.uk/group/co...?q=name+createElement&rnum=2#a86500f9f5880246>


[...]
I tried the different recommendations above, but still get the same
issue! - Any other suggestions

Try one of the methods in the suggested thread. Here's mine, I'm sure
you can adapt it to your circumstance:


<script type="text/javascript">

function addRadios(form, grpName, num)
{
var oRadio, e;
var dom = true;
for (var i=0; i<num; ++i){
if (dom){

// Create radio button, give it a name and add to form
oRadio = document.createElement('input');
oRadio.name = grpName;
form.appendChild(oRadio);

// Test if can access radio button group
// If not, remove element and set dom
if ( 0 == i && !document.getElementsByName(grpName).length){
dom = false;
form.removeChild(oRadio);
}
}

// If dom set to false, use IE method to add element
if (!dom){
try {
oRadio = document.createElement('<input type="radio"'
+ ' name="' + grpName + '">');
form.appendChild(oRadio);
} catch (e){ e = true;}

// If got to here and no error, add attributes to element
// and element to document
}
if (!e){
oRadio.type = 'radio';
oRadio.onclick = rbClicked;
oRadio.value = grpName + ' ' + i;
form.appendChild(document.createTextNode('rad-' + i));
form.appendChild(document.createElement('br'));
}
}
}

// A play onclick function to show name is set
function rbClicked(){
alert('Clicked me!'
+ '\nName: ' + this.name
+ '\nValue: ' + this.value);
}
</script>

<form action="" name="aFrom"><div>
<input type="button" value="Add radios"
onclick="addRadios(this.form, 'rBtnGrp', 4);"><br>
<input type="button" value="Click second radio"
onclick="
alert('There are ' + document.getElementsByName('rBtnGrp').length
+ ' radio buttons');
this.form.rBtnGrp[1].click();
"><br>
</div></form>
 
R

RobG

RobG said:
Exactly. IE has trouble with the name attribute of elements added
dynamically - from Microsoft's documentation:

"The NAME attribute cannot be set at run time on elements
dynamically created with the createElement method. To create
an element with a name attribute, include the attribute and
value when using the createElement method."

<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/...>

Sorry, should be:

<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp>
 
A

ASM

RobG a écrit :
Try one of the methods in the suggested thread. Here's mine, I'm sure
you can adapt it to your circumstance:

splendid !
that would answer to my IE's bug : type is read only
i.e. when we do : oRadio.type = 'radio';
<script type="text/javascript">

function addRadios(form, grpName, num)
{
var oRadio, e;
var dom = true;
for (var i=0; i<num; ++i){
if (dom){

// Create radio button, give it a name and add to form
oRadio = document.createElement('input');
oRadio.name = grpName;
form.appendChild(oRadio);

// Test if can access radio button group

I'm not sure(*) my IE (Mac) won't acces this new collection
so I prefer to put away all IEs

ie=false; /*@cc_on ie=true; @*/
// If not, remove element and set dom
if ( 0 == i && !document.getElementsByName(grpName).length){

if ( !ie ||
(0==i && !document.getElementsByName(grpName).length)
){
dom = false;
form.removeChild(oRadio);
}
}

// If dom set to false, use IE method to add element
if (!dom){
try {
oRadio = document.createElement('<input type="radio"'
+ ' name="' + grpName + '">');
form.appendChild(oRadio);
} catch (e){ e = true;}

// If got to here and no error, add attributes to element
// and element to document
}
if (!e){
oRadio.type = 'radio';
oRadio.onclick = rbClicked;
oRadio.value = grpName + ' ' + i;
form.appendChild(document.createTextNode('rad-' + i));
form.appendChild(document.createElement('br'));
}
}
}
< + '\nValue: ' + this.value);
}
</script>


(*) I've tried your example in my IE : yes it knows the new collection
and stops on : oRadio.type = 'radio';
in your function
 
M

Michael Winter

On 05/05/2006 02:34, RobG wrote:

[snip]
setAttribute is buggy in some browsers, it is better (though ^^^^^^
non-standard) to access properties directly [...]
^^^^^^^^^^^^
Not at all. The short cut properties are specified in the W3C DOM HTML
module. Their use is entirely 'standard' within a HTML document.

[snip]

Mike
 
V

VK

Michael said:
On 05/05/2006 02:34, RobG wrote:

[snip]
setAttribute is buggy in some browsers, it is better (though ^^^^^^
non-standard) to access properties directly [...]
^^^^^^^^^^^^
Not at all. The short cut properties are specified in the W3C DOM HTML
module. Their use is entirely 'standard' within a HTML document.

AFAIK they are dealing with completely different domains. While
setAttribute sets *string* values of element attribute node,
element.something = something works with the provided DOM reference.
The first is respectively good only for string values, the second can
hold any data including references. In this aspect I'm aware of any
bugs in setAttribute (?)

But IE indeed has a number of bugs in handling dymanically created form
elements. The relevant bug in application to radio buttons is described
in the article I linked in my previous post.

Here is the bug in action (this is what OP is hitting) :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>$Template$</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<style type="text/css">
html {
margin: 0px 0px;
padding: 0px 0px}
body {
margin: 10px 10px;
padding: 0px 0px;
font: 1em serif;
color: #000000;
background-color: #FFFFFF}
</style>
<script type="text/javascript">

var fs = null;

function init() {
fs = document.getElementById('fs01');
var rb = null;
for (var i=0; i<10; i++) {
rb = document.createElement('INPUT');
rb.type = 'radio';
rb.name = 'company';
rb.value = i;
fs.appendChild(rb);
}
window.setTimeout('show()',1000);
}

function show() {
var rb = document.getElementsByName('company');
alert(rb.length);
// Firefox shows 10
// IE shows 0
}

window.onload = init;
</script>
</head>

<body
<form name="myForm" action=""
<fieldset id="fs01"
<legend>Test</legend
</fieldset
</form
</body>
</html>
 
A

ASM

ASM a écrit :
RobG a écrit :


splendid !

pfft ! unlovely, no it is not :-(

here is what I get with my IE :
http://cjoint.com/?ffp4aJKJf3
after my supposed corrections ...

It appears that :

try {
oRadio = document.createElement('<input type="radio"'
+ ' name="' + grpName + '">');
form.appendChild(oRadio);
}

won't work in my IE (try() works but no result)

I don't understand what is supposed to do :
catch (e){ e = true;}

Anyway in my IE !e is true
so, as oRadio was removed, I don't more have errors and only
form.appendChild(document.createTextNode('rad-' + i));
form.appendChild(document.createElement('br'));
do something


If I code :
try {
oRadio = document.createElement('p');
oRadio.innerHTML= '<input type="radio"' +
' name="' + grpName + '" onclick="rbClicked();">';
form.appendChild(oRadio);
} catch (e){ e = true;}

new radios are 8 ! ! (of course only 4 are visible)
and they have no name :-(
by the way
this.form.rBtnGrp[1].click();
can't reach second button ==> error 'rBtnGrp' unknown

ie=false; /*@cc_on ie=true; @*/

// correction : if( ie ...
 
A

ASM

VK a écrit :
But IE indeed has a number of bugs in handling dymanically created form
elements. The relevant bug in application to radio buttons is described
in the article I linked in my previous post.

and anyway, with IE Mac it's worst :-(

[...]
<script type="text/javascript">

var fs = null;

function init() {
fs = document.getElementById('fs01');
var rb = null;
for (var i=0; i<10; i++) {
rb = document.createElement('INPUT');
rb.type = 'radio';

here my IE stops : IE cry on this big error ( type is read only :-( )
 
V

VK

ASM said:
and anyway, with IE Mac it's worst :-(

[...]
<script type="text/javascript">

var fs = null;

function init() {
fs = document.getElementById('fs01');
var rb = null;
for (var i=0; i<10; i++) {
rb = document.createElement('INPUT');
rb.type = 'radio';

here my IE stops : IE cry on this big error ( type is read only :-( )

Who needs a IE Mac solution?? This browser is not supported anymore and
not available for download for a year at least.

If rb.type is read-only, then it's the end of the line I guess....
 
M

Michael Winter

On 05/05/2006 09:31, RobG wrote:


[snip]
// If dom set to false, use IE method to add element
if (!dom){
try {
oRadio = document.createElement('<input type="radio"'
+ ' name="' + grpName + '">');
form.appendChild(oRadio);
} catch (e){ e = true;}

[snip]

An alternative version that avoids exception handling could look
something like:

/* Takes three arguments and returns a boolean to indicate
* success (true) or failure (false).
*
* groupName - Name used for the new radio button group.
* quantity - Number of radio buttons to add.
* container - Reference to a block-level element, to
* which the new controls will be added.
*/
var addRadioButtons = function() {
function create(name) {
var element = document.createElement('input');

if (element) {
element.name = name;
element.type = 'radio';
}
return element;
}

/* If the host is IE, the function declaration below
* will override the one above.
*/
/*@cc_on @*/
/*@if (@_jscript)
function create(name) {
return document.createElement('<input type="radio" name="'
+ name + '">');
}
@end @*/

return document.createElement && document.createTextNode
? function(groupName, quantity, container) {
if (!container.appendChild) return false;
for (var i = 0; i < quantity; ++i) {
var element, label, text;

if (!(element = create(groupName))
|| !(label = document.createElement('label'))
|| !label.appendChild
|| !(text = document.createTextNode(' radio-' + i)))
return false;
element.value = groupName + '-' + i;
label.appendChild(element);
label.appendChild(text);
container.appendChild(label);
}
return true;
} : function() {
return false;
};
}();

Mike
 
M

Michael Winter

On 05/05/2006 15:02, VK wrote:

[setAttribute versus equivalent HTML short cut properties]
AFAIK they are dealing with completely different domains.

They are not.
While setAttribute sets *string* values of element attribute node,
element.something = something works with the provided DOM reference.

The defined short cut properties all have types. If the right-hand
operand is not of that type, it will be coerced upon assignment.

For a highly visible example, create a text input element and assign an
object reference to its value property.

[snip]

Mike
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top