views:

157

answers:

4

I need to be able to iterate through all the form fields within a specified DIV tag. Basically, any given DIV tag can have multiple form fields (which is easy enough to parse through), but it can also any number of tables or even additional DIV tags (adding additional levels of hierarchical layering).

I've written a basic function that goes through each of the direct descendants of the parent node (in this case, the DIV tag) and it clears out its value. This part works fine. The problem is getting it to parse children when children (grandchildren) of their own. It winds up getting caught up in an infinite loop.

In this case, I need be able to find all the form fields within DIV tag "panSomePanel", which will include some direct children (txtTextField1), but also some grandchildren who are within nested TABLE objects and/or nested DIV tags (radRadioButton, DESC_txtTextArea).

Here is a sample DIV and its contents:

<DIV id="panSomePanel">

    <INPUT name="txtTextField1" type="text" id="txtTextField1" size="10"/><BR><BR>
    <TABLE id="tblRadioButtons"  border="0">
        <TR>
            <TD>                    
                <INPUT id="radRadioButton_0" type="radio" name="radRadioButton" value="1" /><LABEL for="radRadioButton_0">Value 1</LABEL>
            </TD>
            <TD>                    
                <INPUT id="radRadioButton_5" type="radio" name="radRadioButton" value="23" /><LABEL for="radRadioButton_5">Value 23</LABEL>
            </TD>
        </TR>
        <TR>
            <TD>                    
                <INPUT id="radRadioButton_1" type="radio" name="radRadioButton" value="2" /><LABEL for="radRadioButton_1">Value 2</LABEL>
            </TD>
            <TD>                    
                <INPUT id="radRadioButton_6" type="radio" name="radRadioButton" value="24" /><LABEL for="radRadioButton_6">Value 24</LABEL>
            </TD>
        </TR>
        <TR>
            <TD>                    
                <INPUT id="radRadioButton_2" type="radio" name="radRadioButton" value="3" /><LABEL for="radRadioButton_2">Value 3</LABEL>
            </TD>
            <TD>                    
                <INPUT id="radRadioButton_7" type="radio" name="radRadioButton" value="25" /><LABEL for="radRadioButton_7">Value 25</LABEL>
            </TD>
        </TR>
        <TR>
            <TD>                    
                <INPUT id="radRadioButton_3" type="radio" name="radRadioButton" value="21" /><LABEL for="radRadioButton_3">Value 21</LABEL>
            </TD>
            <TD>                    
                <INPUT id="radRadioButton_8" type="radio" name="radRadioButton" value="4" /><LABEL for="radRadioButton_8">Value 4</LABEL>
            </TD>
        </TR>
        <TR>
            <TD>                    
                <INPUT id="radRadioButton_4" type="radio" name="radRadioButton" value="22" /><LABEL for="radRadioButton_4">Value 22</LABEL>
            </TD>
        </TR>
    </TABLE>
    <DIV id="panAnotherPanel"><BR>
        <TABLE cellpadding="0" cellspacing="0" border="0" style="display:inline;vertical-align:top;">
            <TR>
                <TD valign="top">
                    <TEXTAREA name="DESC:txtTextArea" rows="3" cols="48" id="DESC_txtTextArea"></TEXTAREA>&nbsp;
                </TD>
                <TD valign="top"><SPAN id="DESC_lblCharCount" style="font-size:8pt;"></SPAN>
                </TD>
            </TR>
        </TABLE>
    </DIV>
</DIV>

Here is the function I've written:

function clearChildren(node) {

var child;
if (node.childNodes.length > 0) {
    child= node.firstChild;
}

while(child) {
    if (child.type == "text") {
        alert(child.id);
        child.value = "";
    }
    else if (child.type == "checkbox") {
        child.checked = false;
    }
    else if (child.type == "radio") {
        alert(child.id);
        child.checked = false;
    }
    else if (child.type == "textarea") {
        child.innerText = "";
    }

    //alert(child.childNodes.length);

    if (child.childNodes.length > 0) {
        var grandchild = child.firstChild;

        while (grandchild) {
            clearChildren(grandchild);
        }
        grandchild = grandchild.nextSibling;
    }

    child = child.nextSibling;
}

}
A: 

You can replace the child = child.getNextSibling line with child = getNext(child), where getNext has this implementation:

function getNext(node) {
  if (node.nextSibling) {
    return node.nextSibling;
  }
  var parent = node.parentNode;
  do {
    if (parent && parent.nextSibling) {
      return parent.nextSibling;
    }
    parent = parent.parentNode;
  } while (parent);
  return null;
}

(and delete the loop over child.childNodes)

Annie
+1  A: 
function clearChildren(node){

    if(node.childNodes.length >0){
        for(var index=0;index<node.childNodes.length;index++){
            clearChildren(node.childNodes[index]);
        }
    }

    if(node.localName == "input"){
        if (node.type == "text") {
            alert(node.id);
            node.value = "";
        }
        else if (node.type == "checkbox") {
            node.checked = false;
        }
        else if (node.type == "radio") {
            alert(node.id);
            node.checked = false;
        }
        else if (node.type == "textarea") {
            node.innerText = "";
       }
    }
}

clearChildren(document.getElementById("panSomePanel"));
Gregoire
This answer came in handy :-)
Erik
Although I should note that .localName is an XML property only that happens to work in firefox on html. Use .nodeName instead (and then know that tags are all caps)
Erik
A: 

I think you are overcomplicating the search a little bit. I found this snippet, which parses through all the children of a table and sets the colors.

function setColors(tbody, color1, color2){
var colors  = [color1, color2];
var counter = 0;
var tr      = tbody.firstChild;

while(tr){
    tr.style.backgroundColor = colors[counter++ % 2];
    tr = tr.nextSibling;
}
} 

I got this from: http://www.htmlgoodies.com/primers/jsp/article.php/3594621/Javascript-Basics-Part-6.htm

Try putting your clearing switches within the while loop - you'd just have to set the tr var to be the div ID and then check for your input types within the while loop. Hope this helps somewhat.

liquidleaf
A: 

You'll want to approach this problem with a recursive method like so:

function clearChildren(node) {

    var child = null;
    if (node.childNodes.length > 0) {
        child = node.firstChild;
    }

    while (child) {
        if (child.type == "text") {
            alert(child.id);
            child.value = "";
        }
        else if (child.type == "checkbox") {
            child.checked = false;
        }
        else if (child.type == "radio") {
            alert(child.id);
            child.checked = false;
        }
        else if (child.type == "textarea") {
            child.innerText = "";
        }

        //alert(child.childNodes.length);
        // here is the recursive method call
        clearChildren(child);

        child = child.nextSibling;
    }

}
Josh the Goods