Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session
SOLVED

Targeting multiple subforms with a shared name throughout a form

Avatar

Level 2
Level 2

Hi

I've found a few hints at this online, but to date with little detail as to successful methods.

Has anyone had any success with targeting subforms that have the same name throughout a form? The intention is to hide or disable the contents of those subforms by using a script.

These subforms are numerous and at various locations throughout the form, so I'm trying to find a way to use the common name to target all of these at once, as opposed to specifying absolute locations for all of these subforms. By means of comparison, what comes to mind is how classes can be used in CSS to target multiple elements. My initial thought is something along the lines of getElements, although I've hit a bit of a brick wall so far!

Any thoughts would be greatly appreciated!

Thanks

1 Accepted Solution

Avatar

Correct answer by
Level 10

Cribbed this together from a simplified lock all fields script that Radzmar posted and it seems to work. I surprise myself sometimes (I'm not the greatest coder!).

function hideSubs(vNode) {

     if (vNode.className === "subform") {

          //name of subform you're targeting

          if (vNode.name === "targetSub") {

               vNode.presence = "hidden";

          }

     }

     for (var i = 0; i < vNode.nodes.length; i += 1) {

          hideSubs(vNode.nodes.item(i));

     }

}

hideSubs(xfa.form);

View solution in original post

13 Replies

Avatar

Level 10

Depending on your form structure it can be as easy as a line of FormCalc, or you may need to write a loop to go through the form.

If all the subforms you want to target are under one continuous subform then in FormCalc:

PathToSubform.Subform1[*].presence = "hidden"

will target all instances of Subform1.

If the target subforms are spread all over the place you would need a loop to go through the form and find them. I'll have to leave that to someone else, I know how to do the loop but I'm not sure how to access the subform names and I don't have the time to look it up right now.

Avatar

Level 2
Level 2

Hi Jono

Thanks for your thoughts, that's helpful.

You're latter comment applies in this case - the nature of the form requires that these subforms that need to be hidden/disabled are in various locations. I'm hoping to find a way to hit all of these at once by targeting the name that they have in common. The loop/accessing the subform names has well and truely got me stumped!

Has anyone any thoughts on this?

Thanks

Avatar

Correct answer by
Level 10

Cribbed this together from a simplified lock all fields script that Radzmar posted and it seems to work. I surprise myself sometimes (I'm not the greatest coder!).

function hideSubs(vNode) {

     if (vNode.className === "subform") {

          //name of subform you're targeting

          if (vNode.name === "targetSub") {

               vNode.presence = "hidden";

          }

     }

     for (var i = 0; i < vNode.nodes.length; i += 1) {

          hideSubs(vNode.nodes.item(i));

     }

}

hideSubs(xfa.form);

Avatar

Level 2
Level 2

Jono that's genius. Just had a chance to embed it into the form and works a treat. (Thanks to Radzmar too.)

Now here's another related thought that has me scratching my head: is there a way to use this as a basis to target all text fields/check boxes/radio buttons inside those subforms? So for instance to use something like fillColor to change the colour of these to grey.

This would be an alternative to hiding the content of the subforms - to have them visible but have a visual cue to signal that they are out of use. This could then be locked from the script too, perhaps making them read only.

What do you think?

Thanks again

Avatar

Level 10

It should work for anything like that, you'd have to find out the different class names.

Here's Radzmar's lock fields script:

function lockFields(vNode) {

    if (vNode.className === "field") {

        vNode.access = "protected";

    }

    for (var i = 0; i < vNode.nodes.length; i += 1) {

        lockFields(vNode.nodes.item(i));

    }

}

lockFields(xfa.form);

Here's a link that covers using class names (I haven't done a lot with them myself):

http://andrewalbrecht.com/content.php?pageID=76

Avatar

Level 2
Level 2

Hi Jono

Good call - it seems like quite a flexible method.

What I'm trying to do at the moment though is to rehash the script to (1) find all subforms with the shared name (as above) and then to (2) select all fields inside those subforms only (all types: text fields, radio buttons, check boxes, etc.).

I'll then lock them down and apply a colour change as a visual cue.

I have to admit it's got me stumped! Any thoughts?

Thanks

Avatar

Level 10

You could do it by nesting functions. I'd make a script object to store the functions and then call them from there.

So you'd have a function to find the subforms, a function to target the fields, etc. Then when you've found your subform you call another function to go through the subform and do what you need to the fields.

I haven't tested it but I'm pretty sure with Radzmar's function you can target individual subforms, etc. For example the line that calls the the function below, hideSubs(xfa.form), could target specific form like hideSubs(form1.subform1.subform2).

This is very pseudocode-y, I haven't bothered changing the name of the function. The colourFields function would look kinda like the hideSubs function but target fields instead of subforms. I don't have time to figure it out right now but might be able to take a look at it this weekend.

function hideSubs(vNode) {

     if (vNode.className === "subform") {

          //name of subform you're targeting

          if (vNode.name === "targetSub") {

              //call function colourFields

               colourFields(targetSub);

          }

     }

     for (var i = 0; i < vNode.nodes.length; i += 1) {

          hideSubs(vNode.nodes.item(i));

     }

}

hideSubs(xfa.form);

Avatar

Level 2
Level 2

That's a very good suggestion - I haven't really got into nested functions before.

Would calling the nested function work alongside the elements of the script that target the subforms first (such as access= "protected" to lock them down)?

What would your thoughts be on how to target all field types (such as text fields, date fields, radio buttons, check boxes, etc.) in a nested function?

Cheers for your help.

Avatar

Level 10

I'll try and take a look at it later this week if I get a chance.

Avatar

Level 2
Level 2

That'll be great, thanks Jono

Avatar

Level 10

Ok, finally had a chance to get to this...

function lockFields(vNode) {

          if (vNode.className === "field") {

                    vNode.access = "protected";

                    vNode.fillColor = "128,128,128";

          }

          for (var i = 0; i < vNode.nodes.length; i += 1) {

                    lockFields(vNode.nodes.item(i));

          }

}

function findSubs(vNode) {

    if (vNode.className === "subform") {

        if (vNode.name === "targetSub") {

                              lockFields(vNode);

                    }

    }

    for (var i = 0; i < vNode.nodes.length; i += 1) {

        findSubs(vNode.nodes.item(i));

    }

}

findSubs(xfa.form);

You could abstract this to a Script Object by creating a Script Object and then copying and pasting the code in except for the "findSubs(xfa.form);" line at the end. Less code to maintain if you're using this in a lot of places. And then call it with:

myscriptobject.findSubs(xfa.form);

Avatar

Level 2
Level 2

Hi Jono,

Genius, thanks for that. Works a treat as am able to target fields as opposed to the subform.

My only wonder is how to target the fillable area of the fields only - the current technique means that the overall background colour is changed as opposed to just the fillable area.

I've been trying to find an answer but it seems it may be a little tricky. Have been playing around with the code above and an old validation script (which used oUITypeNode.border.fill.color.value to target the fields) which on a validation fail, was somehow was able to change the fillable area colour only. But so far my efforts have been to no avail!

Any thoughts on how to use your script to target just the fillable areas?

Thanks again.

---

EDIT: Cancel that! oUITypeNode.ui.oneOfChild.border.fill.color.value did the trick.

Jono: thanks for all your help on this one.

Message was edited by: JdL

Avatar

Level 10

I'm not sure what the "oUITypeNode" is, it looks like a variable from a script, but yeah you want fieldName.ui.oneOfChild.border.fill.color.value.

If you want you can mix those two settings to change the background and the field fill.