I need some code to recurse through the entire form. This code needs to be generic enough to use for any form created by any template designer. I tried to create a recursive function but its not working correctly because I am not able to preserve parent node lists when traversing child nodes. The result is that I am able to traverse a form but my code stops executing when it hits the end of the first path it finds.Here is what I need to do.for each item in the form do something. If that item has children then get the children and do something to the children and so on. I am familiar with getChildren() method but can get the function to work recursivly.
If you post what you actually have done - I'm sure someone will be happy to point out where you went wrong.
Sure. Here it is. As I said it has to work with any structure. The functions goal is to start at the root node (xml dcr) and recursivly handle all the items it finds. The problem is that when the function finds children it calls itself to handle the children. When this happens the children array I'm using gets reset and the result is that the function recurses only within the path it finds.function init() { walkNodes(IWDatacapture.getRootItems()[0]);}function walkNodes(node) { /* will be doing something to each node I find. */ alert(node.getLabel()); alert(node.getDescription()); if(node.getChildren() != "") { children = node.getChildren(); for(i=0;i<=children.length;i++) { walkNodes(children); } }}// Call the initialization routine on load.IWEventRegistry.addFormHandler("onFormInit", init);
What is your dcr-type, iwov or xml? If the former, you may have multiple root nodes, not just 0.
checkAllLinks("/Root/");function checkAllLinks(Xpath){ alert ("got "+Xpath); var children = IWDatacapture.getItem(Xpath).getChildren(); if (children == null) { return; } for (var i = 0; i < children.length; i++) { checkAllLinks(children.getName()); } return true;}
Funny thing, I am working on the same thing. (XML style DCRs)This will traverse the DCR (I think, still doing dev and test): checkAllLinks("/Root/");function checkAllLinks(Xpath){ alert ("got "+Xpath); var children = IWDatacapture.getItem(Xpath).getChildren(); if (children == null) { return; } for (var i = 0; i < children.length; i++) { checkAllLinks(children.getName()); } return true;}
Go figure your code works.
At least in my tests the null never occurs?
Don't look so surprised, even a blind squirrel finds a nut once in a while. :-)Yea I just put an alert after the null check, that return never gets executed. The size of children is 0 however, so you can do children.length==0 or just let it fall through the for loop
One potential use for this sort of thing is dealing with labels. I find that getChildren() gets replicant instances not the container. So, my function gets a handle on the replicant instances but not the container. Working on the solution now. Any thoughts?
Hmm, what happens if you call getLabel on the child from the parent ? i..e for /Root/Replicantchildren = rootItem.GetChildren();for (i = 0; i < children.length, i++) {setLabel(test)}FYI, I use a Link object at many levels of many DCRs, so this allows me to, on formload of an existing DCR, set the appropriate files visible /not (whether it is a internal link, external, etc).
The first thing my function does is try to change the label. I think thats the same thing your asking. But when the function recuses its operating on what it gets passed which is a list of replicant instances in some cases which does not have the actual reference to the or|and replicant container only the [indexes]. I'm experimenting with looking for [1] and trimming it off to get at the container.function walkNodes(node) {if(node.getLabel() != "") {node.setLabel("test")}if(node.getChildren() != "") {var children = node.getChildren();for(var i=0;i walkNodes(children);}}}
function walkNodes(node) {if(node.getChildren() != "") {var children = node.getChildren();for(var i=0;i < children.length; I++){if(children.getLabel() != "") {children.setLabel("test")}walkNodes(children);}}}
No, I mean move the check to the children (and not after you call the children)something like; function walkNodes(node) {if(node.getChildren() != "") {var children = node.getChildren();for(var i=0;i < children.length; i++){if(children.getLabel() != "") {children.setLabel("test");}walkNodes(children);}}}
function walkNodes(node) {if(node.getChildren() != "") {var children = node.getChildren();for(var i=0;i < children.length; i++){if(children.getLabel() != "") {children.setLabel("test");}walkNodes(children);}}}
I did get that working but the results are the same because both still have the fundamental issue above children will never be a handle to the conatiner only
function traverse_node(item) { if (item.getType().match(/(container|replicant)/)) { var children = item.getChildren(); for (var c = 0; c < children.length; c++) { traverse_node(children); } } else { // now you have an actual item node // do what you want // You *might* have to make sure the 'type' is not "CDATA" handle_node(item); }}
I've used something like this in the past (not verified prior to posting):function traverse_node(item) { if (item.getType().match(/(container|replicant)/)) { var children = item.getChildren(); for (var c = 0; c < children.length; c++) { traverse_node(children); } } else { // now you have an actual item node // do what you want // You *might* have to make sure the 'type' is not "CDATA" handle_node(item); }}
Thanks that is similar to what we're working with and will not handle container labels which is my problem.This seems to work but I need to refine it to something more elegant.
How aboutHey ! Are you the guy who set items without labels ?Smack, Smack, SmackDon't do it againSmack
The label or no label rare occurance is not my motive for this code. I'm simply trying to gain access to all elements on the form. Unfortunately for me the way getChildren is implemented makes this a royal pain. Any suggestions to the above code. Is there a simpler way?