• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Working with Visibility Layers

Explorer ,
Jun 11, 2021 Jun 11, 2021

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. 

 

TOPICS
How to , JavaScript , PDF forms

Views

2.3K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Jun 13, 2021 Jun 13, 2021

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

...

Votes

Translate

Translate
Community Expert , Jun 13, 2021 Jun 13, 2021

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

...

Votes

Translate

Translate
Community Expert ,
Jun 11, 2021 Jun 11, 2021

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;
   } 
}

 

 

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 11, 2021 Jun 11, 2021

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 11, 2021 Jun 11, 2021

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))

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 11, 2021 Jun 11, 2021

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?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 11, 2021 Jun 11, 2021

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;
}
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 11, 2021 Jun 11, 2021

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?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 12, 2021 Jun 12, 2021

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!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 13, 2021 Jun 13, 2021

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);
   }
}

 

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 13, 2021 Jun 13, 2021

Copy link to clipboard

Copied

That works. Thank you so much!! 

 

A couple of additional questions, if you have the time:

  1. Is it possible to make the additional layers (layers other than "Form") automically hide when the form is cleared? Currently, the additional layers will go away if  the dd(s) are deselected, which is great, but if the form is cleared while there is a selection made, only the selection is cleared--the dd selection's triggered layer remains visible.  I can work around this using the mouse up action "Set Visibility Layer" of my "Clear" button, but every time I replace the page (because of edits being made) I need to edit/update the "Set Visibility Layer" of the button. Not a huge problem, but was wondering if there is a simple workaround.
  2. Can I use checkboxes (vs a drop down) using a similar script?
    I'm was hoping to replace dd2 with checkboxes, since there are only two options. I could set the each checkbox with the export value matching the layer name ( "METH.Verbal" or "METH.Written" ). If this is possible, how would the script need to be altered and where should it be placed?  Using check boxes instead of a drop down is not vital, but slightly preferrable.

 

Again thank you for all your help and sharing your knowlege.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 13, 2021 Jun 13, 2021

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));
   }

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 14, 2021 Jun 14, 2021

Copy link to clipboard

Copied

LATEST

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines