Copy link to clipboard
Copied
I need help making multiple layers visible based on selections from two different fields.
My form has five layers:
"Form" = Base layer (to be visibile at all times)
"A" = Layer to be visible if selection "a" is made from "drop down 1"
"B" = Layer to be visible if selection "b" is made from "drop down 1"
"1" = Layer to be visible if selection "1" is made from "dd 2"
"2" = Layer to be visible if selection "2" is made from "dd 2"
I'm using this Validation script for "drop down 1":
var layers = this.getOCGs();
var v = event.value;
for (var i = 0; i < this.layers.length; i++) {
if (layers[i].name == "A" && v == "a") {
layers[i].state = true;
}
else if (layers[i].name == "B" && v == "b") {
layers[i].state = true;
}
else if (layers[i].name != "Form"){
layers[i].state = false;
}
}
This works exactly how I need it to, but when a selection is made for "dd 2" (w/similar validation script substituting "A" and "a" with "1" and "1", etc.), the layer made visible based on "drop down 1" selection is now hidden. Is there a way to make whatever layer is made visible ("A" or "B") from "drop down 1" selection stay visible after the selection for "dd 2" is made and layer "1" or "2" is also visible?
I would greatly appreciate any help! Please let me know if you need any clarification.
You're doing really well. You changed the script in the correct way to show the selected layer. However, keystroke scripts require an additional component, because they are called twice. Once when the "Keystroke", or in this case the selection is made, and then again when the value is committed. It's the second call which is hiding the layer since "event.changeEx" is not valid durring the commit process.
You can read about it here:
https://www.pdfscripting.com/public/Formatting-Form-Fields.cfm#KeyStr
...There are a few ways to handle clearing a non-standard form element on reset. The first is to do what you are already doing. A variation on this is to use a script to reset the visibility. Much like you are already doing to for the select. Loop over the layers and hide any that match the prefixes. Another method is to put the clearing code onto the Validate Event. Use an "if" statement to test for the default value, then clear the layers associated with the dropdown when it is selected.
C
...Copy link to clipboard
Copied
Yes, you need to separate the actions for the letters and numbers. You can also simplify the logic.
First, you need a way to cleanly separate the which layers belong to which group. This is done with naming, and since one group is numbers and one is letters, we have an easy way to do it.
Here's the code for the letter named group
//Since the layer name is always upper case, just do the conversion.
var v = event.value.toUpperCase();
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^[A-Z]$/.test(layers[i].name))
{// Sort for a layer name that is a single letter
if (layers[i].name == v)
layers[i].state = true;
else
layers[i].state = false;
}
}
Here's the code for the number named group
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^\d$/.test(layers[i].name))
{// Sort for a layer name that is a single digit
if (layers[i].name == event.value)
layers[i].state = true;
else
layers[i].state = false;
}
}
Copy link to clipboard
Copied
Thanks for getting back so quickly. I do have 5 layers but the layer names and drop down selections names were just used to make the explanation simpler. I could rename the layers to be "A", "B", "1", and "2", but the first drop down has 16 selections with long, specific item names that can't be changed. 4 of the drop down choices would need to show layer "A" and 12 need layer "B" to display. For "dd 2" there are only two items ("Written" or "Verbal") that would trigger either layer "1" or "2" to display.
Is there any way to modify the script you suggested to use the export value (event.changeEx) rather than the item name? In that case I could use "A" as the export value for the the 12 options in the 1st drop down that need to display layer "A" and "B" as the export value for the remaining 4 options that would trigger layer "B" to display instead. Likewise, I could also change the export values for dd 2 to "1" and "2". Will that work? Also, will the "Form" layer always be visible?
Thanks again for all your help.
Copy link to clipboard
Copied
Yes, anything that provides a way to differentiate the group would work. But if you want to use the export value, then you'll need to put the script in a custom Keystroke event. And my first choice would not be numbers and letters. I just used that because you'd already done it. I would suggest prefixed names in the export. The exports from the dropdown must exactly match the layer names.
You will need to pick names that make sense for your project, but here's an example of what I mean: "GRP1.Sel1", "GRP1.Sel2", etc, These are the names of both the dropdown exports and the layer names, then the group is identified with this if.
if(/^GRP1/.test(layers[i].name))
Copy link to clipboard
Copied
I think I'm doing something wrong.
I renamed the layers and matched appropriate export value names:
For dd 1: "TYPE.Twelve" or "TYPE.Wire"
For dd2: "METH.Verbal" or "METH.Wire"
I used this keystroke script for dd 1:
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^TYPE/.test(layers[i].name))
layers[i].state = true;
else
layers[i].state = false;
}
When I made a selection, both layers "TYPE.Twelve" and "TYPE.Wire" became visible and "Form" layer became hidden. What did I do wrong?
Copy link to clipboard
Copied
I did fix the script a bit, the "Form" layer remains visible now, but neither "TYPE.Twelve" nor "TYPE.Wire" becomes visible when I make a selection from dd 1.
Here is the script I am using:
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^TYPE/.test(layers[i].name))
{ if (layers[i].name == event.changeEx)
layers[i].state = true;
else
layers[i].state = false;
}
}
Copy link to clipboard
Copied
With the above script, the correct layer flashes on the screen as I make the selection, but stays hidden after the selection is made. Is there something that I am missing?
Copy link to clipboard
Copied
Thanks Thom for all your help. Your original codes (using the letters/numbers) worked perfectly run as validation scripts. Your updated solution using group names (above) with the codes being run as a custom keystroke scripts (in order to use export values) is not working for some reason. The correct layer flashes on the screen as I make the selection, but stays hidden after the selection is made. I don't know if this is an issue with the script being run as a custom keystroke, or if I made a mistake altering the code.
Here is the code I entered as a custom keystroke for dd 1 (Layer names and export values are "TYPE.Twelve" or "TYPE.Wire"):
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^TYPE/.test(layers[i].name))
{ if (layers[i].name == event.changeEx)
layers[i].state = true;
else
layers[i].state = false;
}
}
Can you see what mistake(s) I made? Is: { if (layers[i].name == event.changeEx) the proper way to use the event value rather than the label/item name? Any help would be greatly appreciated!
Copy link to clipboard
Copied
You're doing really well. You changed the script in the correct way to show the selected layer. However, keystroke scripts require an additional component, because they are called twice. Once when the "Keystroke", or in this case the selection is made, and then again when the value is committed. It's the second call which is hiding the layer since "event.changeEx" is not valid durring the commit process.
You can read about it here:
https://www.pdfscripting.com/public/Formatting-Form-Fields.cfm#KeyStr
Here is the corrected code, with a small simplification.
if(!event.willCommit)
{
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^TYPE/.test(layers[i].name))
layers[i].state = (layers[i].name == event.changeEx);
}
}
Copy link to clipboard
Copied
That works. Thank you so much!!
A couple of additional questions, if you have the time:
Again thank you for all your help and sharing your knowlege.
Copy link to clipboard
Copied
There are a few ways to handle clearing a non-standard form element on reset. The first is to do what you are already doing. A variation on this is to use a script to reset the visibility. Much like you are already doing to for the select. Loop over the layers and hide any that match the prefixes. Another method is to put the clearing code onto the Validate Event. Use an "if" statement to test for the default value, then clear the layers associated with the dropdown when it is selected.
Changing to checkboxes changes the script completely. Sadly There is no easily accessible keystroke script for checkboxes, so it will have to go into the MouseUp. You could write an individual script for each checkbox that turns on the associaed layer and turns off the other one in the group. But I'd do a generic script that will work for all checkboxes.
Here's how. The check boxs that replace a dropdown need to have the same name, for example "METH" for the "METH" layer. Having the same name makes them mutually exclusive so that only one can be selected. Then make the export values "Verbal" and "Written". Now this Mouseup script can be used on any checkbox.
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if((new RegExp("^" + event.target.name)).test(layers[i].name))
layers[i].state = (layers[i].name == (event.target.name + "." + event.target.value));
}
Copy link to clipboard
Copied
Again, thank you so much!!
For the clearing of the layers on reset, I added this mouse up action script to my clear button:
var layers = this.getOCGs();
for (var i = 0; i < this.layers.length; i++) {
if(/^TYPE/.test(layers[i].name))
layers[i].state = false;
if(/^METH/.test(layers[i].name))
layers[i].state = false;
}
I thought I'd add it here for any newbies like me who might be looking for a solution to a similar problem. Not sure if this is the best script option, but it is working for me.