Connecting Tech Pros Worldwide Help | Site Map

newb: recurse over elements children and disable all form elements

SteveKlett@gmail.com
Guest
 
Posts: n/a
#1: Sep 18 '06
I have a subset of form items that I need to perform different
operations on (enable/disable, clear values, change style, etc)

rather than hard code the IDs or names I would like to recursively
search a parent element(in my case a <table>) and search for elements
of a certain type (<input>, <textarea>, etc) and perform operations on
them.

I've done some initial googling and found PLENTY of samples of
disabling all form items, but I need to work on a subset.

I'm also very new to the DOM and am not sure how to do type checking (
IE: if(item is type(input)) )

Any suggestions or tips welcome.

Thanks,
Steve

Tom Cole
Guest
 
Posts: n/a
#2: Sep 19 '06

re: newb: recurse over elements children and disable all form elements



SteveKlett@gmail.com wrote:
Quote:
I have a subset of form items that I need to perform different
operations on (enable/disable, clear values, change style, etc)
>
rather than hard code the IDs or names I would like to recursively
search a parent element(in my case a <table>) and search for elements
of a certain type (<input>, <textarea>, etc) and perform operations on
them.
>
I've done some initial googling and found PLENTY of samples of
disabling all form items, but I need to work on a subset.
>
I'm also very new to the DOM and am not sure how to do type checking (
IE: if(item is type(input)) )
I don't know that the W3C includes it, but most all browsers with any
DOM support includes the getElementsByTagName() method where you can
look for input tags (getElementsByTagName("input");). This method can
be called against any element, therefore if you had just a region of a
form you wanted checked you could (experts please help me here) wrap
that section in a particular div (i.e. with id="check"). You could then
obtain a handle to the check element and call getElementsById on it.

if (document.getElementById("check")) {
var nodes =
document.getElementById("check").getElementsByTagN ame("input");
//do stuff
}

HTH.
Quote:
>
Any suggestions or tips welcome.
>
Thanks,
Steve
RobG
Guest
 
Posts: n/a
#3: Sep 19 '06

re: newb: recurse over elements children and disable all form elements


SteveKlett@gmail.com wrote:
Quote:
I have a subset of form items that I need to perform different
operations on (enable/disable, clear values, change style, etc)
>
rather than hard code the IDs or names I would like to recursively
search a parent element(in my case a <table>) and search for elements
of a certain type (<input>, <textarea>, etc) and perform operations on
them.
>
I've done some initial googling and found PLENTY of samples of
disabling all form items, but I need to work on a subset.
>
I'm also very new to the DOM and am not sure how to do type checking (
IE: if(item is type(input)) )
The best way of course depends on what you are actually trying to to.
You can use a reference to the table (say by document.getElementById()
) then use the getElementsByTagName method of the table element, but
you'd have to get all the tags with names that might be form controls,
such as: button, input, textarea, select and object. Something like
(untested):

var table = document.getElementById('tableID');
var tagNames = ['button', 'input', 'textarea', 'select', 'object'];
var i = tagNames.length
var j, tagCollection;
var elementArray = [];
while (i--){
tagCollection = table.getElementsByTagName(tagNames[i]);
j = tagCollection.length;
while (j--){
elementArray.push(tagCollection[j]);
}
}
/* elementArray is all the elements that are descendents of the
table element and that can be form controls, but there is no
guarantee that they actually belong to the form
*/


Another way is to give each control of a certain group a class name
that you can filter on, then use the form's elements collection to
iterate over all the form controls and do stuff only to those with a
certain class name.

var el, els = document.forms['formName'].elements;
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (el.className && 'someClass' == el.className){
/* do something with el */
}
}


You could also create a 'testIsChildOf' function that checks to see if
a particular element is a child of the table element previously noted:

function testIsChildOf(el, parent){
while (el.parentNode){
if (el.parentNode == parent) {
return true;
}
el = el.parentNode;
}
return false;
}

var table = document.getElementById('tableID');
var el, els = document.forms['formName'].elements;
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (testIsChildOf(el, table)){
/* do something with el */
}
}


Lastly, you could get all the elements in the table and see which ones
belong to the form:

var table = document.getElementById('tableID');
var form = document.forms('formName');
var el, els = table.getElementsByTagName('*');
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (el.form && form == el.form){
/* do something with el */
}
}

Note that getElementsByTagName('*') is not supported in IE 5 and
earlier I think, you may have to use feature detection and document.all
for older IE. All untested of course, but it should give you some
ideas - the class filter and testIsChildOf methods seem best to me as
they (probably) iterate over the fewest number of elements. :-)


--
Rob

SteveKlett@gmail.com
Guest
 
Posts: n/a
#4: Sep 19 '06

re: newb: recurse over elements children and disable all form elements


Guys, thanks for the great responses!
I started coding a solution before I saw your post Rob, so I will need
to review your options in detail.

In the meantime I thought I would post what I'm using in case I'm doing
something really stupid (this code works fine)
Expand|Select|Wrap|Line Numbers
  1. function disableSectionFormItems(sectionID, disabled)
  2. {
  3. var section = document.getElementById(sectionID);
  4. if(section == null)
  5. {
  6. return;
  7. }
  8.  
  9. var controlCollections = new Array();
  10. controlCollections[0] = section.getElementsByTagName('input');
  11. controlCollections[1] = section.getElementsByTagName('textarea');
  12. controlCollections[2] = section.getElementsByTagName('select');
  13.  
  14. for(i = 0; i < controlCollections.length; i++)
  15. {
  16. for(j = 0; j < controlCollections[i].length; j++)
  17. {
  18. controlCollections[i][j].disabled = disabled;
  19. controlCollections[i][j].style.border = (disabled) ? '1px
  20. solid gainsboro' : '1px solid black';
  21. };
  22. };
  23. }
  24.  
This seems run real fast on my machine, but I have a really fast
machine so I don't know if I'm the best judge. Like I said, I will
look over your examples and mess around with some other options.

This stuff is addictive! I don't know why, but once I started working
with JavaScript and making the UI of my web app better I just can't
stop now :0)



RobG wrote:
Quote:
SteveKlett@gmail.com wrote:
Quote:
I have a subset of form items that I need to perform different
operations on (enable/disable, clear values, change style, etc)

rather than hard code the IDs or names I would like to recursively
search a parent element(in my case a <table>) and search for elements
of a certain type (<input>, <textarea>, etc) and perform operations on
them.

I've done some initial googling and found PLENTY of samples of
disabling all form items, but I need to work on a subset.

I'm also very new to the DOM and am not sure how to do type checking (
IE: if(item is type(input)) )
>
The best way of course depends on what you are actually trying to to.
You can use a reference to the table (say by document.getElementById()
) then use the getElementsByTagName method of the table element, but
you'd have to get all the tags with names that might be form controls,
such as: button, input, textarea, select and object. Something like
(untested):
>
var table = document.getElementById('tableID');
var tagNames = ['button', 'input', 'textarea', 'select', 'object'];
var i = tagNames.length
var j, tagCollection;
var elementArray = [];
while (i--){
tagCollection = table.getElementsByTagName(tagNames[i]);
j = tagCollection.length;
while (j--){
elementArray.push(tagCollection[j]);
}
}
/* elementArray is all the elements that are descendents of the
table element and that can be form controls, but there is no
guarantee that they actually belong to the form
*/
>
>
Another way is to give each control of a certain group a class name
that you can filter on, then use the form's elements collection to
iterate over all the form controls and do stuff only to those with a
certain class name.
>
var el, els = document.forms['formName'].elements;
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (el.className && 'someClass' == el.className){
/* do something with el */
}
}
>
>
You could also create a 'testIsChildOf' function that checks to see if
a particular element is a child of the table element previously noted:
>
function testIsChildOf(el, parent){
while (el.parentNode){
if (el.parentNode == parent) {
return true;
}
el = el.parentNode;
}
return false;
}
>
var table = document.getElementById('tableID');
var el, els = document.forms['formName'].elements;
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (testIsChildOf(el, table)){
/* do something with el */
}
}
>
>
Lastly, you could get all the elements in the table and see which ones
belong to the form:
>
var table = document.getElementById('tableID');
var form = document.forms('formName');
var el, els = table.getElementsByTagName('*');
for (var i=0, len=els.length; i<len; i++){
el = els[i];
if (el.form && form == el.form){
/* do something with el */
}
}
>
Note that getElementsByTagName('*') is not supported in IE 5 and
earlier I think, you may have to use feature detection and document.all
for older IE. All untested of course, but it should give you some
ideas - the class filter and testIsChildOf methods seem best to me as
they (probably) iterate over the fewest number of elements. :-)
>
>
--
Rob
RobG
Guest
 
Posts: n/a
#5: Sep 20 '06

re: newb: recurse over elements children and disable all form elements



SteveKlett@gmail.com wrote:
Quote:
Guys, thanks for the great responses!
Please don't top-post here, reply below trimmed quotes.

Quote:
I started coding a solution before I saw your post Rob, so I will need
to review your options in detail.
You have essentially implemented the getElementsById method, which I
guess is fine. The main idea is to get as close to the right number of
elements as you can first off.

Quote:
In the meantime I thought I would post what I'm using in case I'm doing
something really stupid (this code works fine)
Expand|Select|Wrap|Line Numbers
  1. function disableSectionFormItems(sectionID, disabled)
  2. {
  3.     var section = document.getElementById(sectionID);
  4.     if(section == null)
  5.     {
  6.         return;
  7.     }
Expand|Select|Wrap|Line Numbers
  1.  
  2. Support for getElementById is generally assumed these days, but I guess
  3. you really should test for it:
  4.  
  5. var section;
  6. if (document.getElementById
  7. && (section = document.getElementById(sectionID)) )
  8. {
  9.  
  10.     Quote:
  •  
  •                     var controlCollections = new Array();
  •  
  • Initialisers are often recommended instead of constructors:
  •  
  • var controlCollections = [];
  •  
  •     Quote:
  •  
  •                     controlCollections[0] = section.getElementsByTagName('input');
  •     controlCollections[1] = section.getElementsByTagName('textarea');
  •     controlCollections[2] = section.getElementsByTagName('select');
  •  
  • There are also buttons and objects, but you may not be interested in
  • those.  Also, the above elements don't have to be in a form (again,
  • might be totally irrelevant in your case  but just to cover all bases
  • :-)  )
  •  
  •     Quote:
  •  
  •                     for(i = 0; i < controlCollections.length; i++)
  •     {
  •         for(j = 0; j < controlCollections[i].length; j++)
  •  
  • You should keep counters local, getting the length property once is
  • more efficient than getting it on every loop, and consider using a
  • while statement:
  •  
  • var i = controlCollections.length;
  • var j;
  • while (i--) {
  • j = controlCollections[i].length;
  • while (j--) {
  •  
  • That goes backwards through all the elements but it shouldn't be an
  • issue here - order seems unimportant.
  •  
  •     Quote:
  •  
  •                         {
  •             controlCollections[i][j].disabled = disabled;
  •             controlCollections[i][j].style.border = (disabled) ? '1px
  • solid gainsboro' : '1px solid black';
  •  
  • gainsboro?  That is one of IE's extensions to the W3C named colour set.
  • If you want to see something in browsers that don't support IE's
  • extensions, use an rgb or hex value.
  •  
  •     Quote:
  •  
  •                         };
  •     };
  •  
  • There is no need for a semi-colon after an if block, it is effectively
  • an empty statement between the "}" and ";"
  •  
  •     Quote:
  •  
  •                 }
  •  
  • [...]
    Quote:
    This stuff is addictive! I don't know why, but once I started working
    with JavaScript and making the UI of my web app better I just can't
    stop now :0)
    Just don't overdo it: remember that some of your visitors will not have
    JavaScript available or turned off, and your scripts will likely not
    work for everyone (or may not be appreciated by everyone ;-) ). Your
    pages should work for everyone, even if they are less pretty for a few.


    --
    Rob

    Closed Thread