Javascript to turn off ocg / layers beginning with a text string

New Here ,
Jan 31, 2020 Jan 31, 2020

Copy link to clipboard

Copied

Hi, I'm trying to turn off all layers that begin with a text string.

So far I have:

var l = this.getField("SELECT.Language").valueAsString;

var n = this.getField("SELECT.Number").valueAsString;

for (var x=0; x < ResetOCGs.length; x++)

{ ResetOCGs[x].state = false; }

for (var x=0; x < docOCGs.length; x++)

{

if(docOCGs[x].name == "Logo" ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l + ".1" ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l + ".2" ) { docOCGs[x].state = false; }

if(docOCGs[x].name == l + ".3" ) { docOCGs[x].state = false; }

if(docOCGs[x].name == l + ".4" ) { docOCGs[x].state = false; }

}

I'd ideally like to get rid of Reset OCGs a turn off layers that begin with l + ".3".

I was thinking something like l + ".3*", with the asterisk acting as a wildcard but it doesn't seem to work.

Can anyone help please?

This is a form created in Acrobat, with all fields created in Acrobat.

TOPICS
Acrobat SDK and JavaScript, General troubleshooting

Views

147

Likes

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

Adobe Community Professional , Jan 31, 2020 Jan 31, 2020
You can use something like this: if (docOCGs[x].name.indexOf(l)==0) { docOCGs[x].state = true; } This will match all the OCGs whose name begin with the value of that variable.

Likes

Translate

Translate
Adobe Community Professional , Feb 07, 2020 Feb 07, 2020
Same as you did before, in the first post. Put this at the top: for (var x=0; x < docOCGs.length; x++) { docOCGs[x].state = false; } You are a good ways along in your process, don't loose hope. This is complex, and you're having exactly the same difficulties every programmer has when they are starting out. Your thinking in a straight line about how you want it to work, but you also have to think about how you don't want it to work. You're strategy has to take "all" scenerios into account. Co...

Likes

Translate

Translate
Adobe Community Professional ,
Jan 31, 2020 Jan 31, 2020

Copy link to clipboard

Copied

You can use something like this:

 

if (docOCGs[x].name.indexOf(l)==0) { docOCGs[x].state = true; }

 

This will match all the OCGs whose name begin with the value of that variable.

Likes

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
New Here ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

Thanks try67 for your reply, I will give it a go & reply back.

Likes

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
Adobe Community Professional ,
Jan 31, 2020 Jan 31, 2020

Copy link to clipboard

Copied

Where do "docOCG" and "resetOCG" come from ? 

 

If you want to do pattern matching you need to use a Regular Expression.

https://acrobatusers.com/tutorials/text-matching-regular-expressions/

 

 

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

Likes

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
New Here ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

Thanks for your reply Thom, I have earlier in the workflow of the form:

var ResetOCGs = this.getOCGs();

var docOCGs = this.getOCGs();

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < ResetOCGs.length; x++)

{

ResetOCGs[x].state = false;

}

for (var x=0; x < docOCGs.length; x++)

{

if(docOCGs[x].name == "Logo" ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l ) { docOCGs[x].state = true; }

}

The reset is to turn all OCGs off but it takes a few seconds for the reset to run for some reason, so I'd like to not use it more than I have to.

If I can use some pattern matching to turn some of the OCGs off rather than using the reset, it will make the form quicker.

Thanks for the link, I will have a look.

Likes

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
New Here ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

ok, so thanks to a combination of advice from try67 & Thom_Parker, I have made some progress.

The form is for different languages (var l) & for a different number of groups (var n).

The following works for group 1 in that it doesn't use the resetOCGs var & is quicker but it's not quite there:

 

var l = this.getField("SELECT.Language").valueAsString;

var n = this.getField("SELECT.Number").value;

for (var x=0; x < docOCGs.length; x++)

{ if(docOCGs[x].name.indexOf(l + ".") == 0 ){ docOCGs[x].state = false; }

if(docOCGs[x].name == l + "." + n) { docOCGs[x].state = true; } }

 

This shows OCGs that begin with language.number.

However I need it to show the levels before.

So if the group is 1, it shows OCGs that are language.1

But if the group is 2, it needs to show language.1 & language.2

For group 3, it shows language.1, language.2 & language.3 & so on.

I have tried:

 

for (var x=0; x < docOCGs.length; x++)

{ if(docOCGs[x].name.indexOf(l + ".") == 0 ) { docOCGs[x].state = false; }

if(docOCGs[x].name == l + "." + <n) { docOCGs[x].state = true; }

if(docOCGs[x].name == l + "." + n) { docOCGs[x].state = true; }

if(docOCGs[x].name == l + "." + >n) { docOCGs[x].state = false; }}

 

But the greater or less than indicator throws up a syntax error, I can't seem to find anything on if value is less than or greater than a var.

It feels so close, can you help please?

Likes

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
Adobe Community Professional ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

You haven't actually explained your naming convention for the layers and explicitly layed out the rules for the languange and group selections.

It also seems like there are two completely different things going on, i.e. language and group. 

 

If you can give a clear and short explanation I can provide a method for diplaying the correct layers.

 

 

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

Likes

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
New Here ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

Ah sorry Thom, I thought it was going to be a simple tweak, here goes:

So we have different languages using a venue, with a number of different groups in the venue each night.

The form is to provide a timetable showing what groups meet & when, & this is to be provided in each language.

So layers are named as just "language" or "language.number" or "language.number.other", e.g.

English or Spanish.2 or Polish.4.time

The language radio selector is the first selection made in the form, so I need the language radio selector to turn off all layers, other than those that have the selected language in the name of the layer.

Once the language is selected another radio selector selects how many groups are using the venue that will be shown on the page, this is currently 4 possible groups but could expand up to 10. I need this selector to turn off the layers with numbers that are greater than the radio selection & to turn on layers with numbers that are equal to or less than the radio selection.

For the language selector I currently have:

var ResetOCGs = this.getOCGs();

var docOCGs = this.getOCGs();

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < ResetOCGs.length; x++)

{ ResetOCGs[x].state = false; }

for (var x=0; x < docOCGs.length; x++)

{ if(docOCGs[x].name == "Logo" ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l ) { docOCGs[x].state = true; } }

 

I'd like to get rid ResetOCGs as it is very slow & have something like (the bits I'm struggling with are in red):

var docOCGs = this.getOCGs();

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < docOCGs.length; x++)

if(docOCGs[x].name == "all layers" ) { docOCGs[x].state = false; } (I tried Try67's solution for this but couldn't select all layers) This could be all layers other than one layer called just "Logo"

if(docOCGs[x].name == "Logo" ) { docOCGs[x].state = true; }

if(docOCGs[x].name == l ) { docOCGs[x].state = true; } }

 

Then for the number of groups I would need something like:

var n = this.getField("SELECT.Number").value;

for (var x=0; x < docOCGs.length; x++)

{ if(docOCGs[x].name.indexOf(l + ".") == 0 ) { docOCGs[x].state = false; }

if(docOCGs[x].name.indexOf(l + "." + (<=n)) == 0 ) { docOCGs[x].state = true; }

if(docOCGs[x].name.indexOf(l + "." + (>n)) == 0 ) { docOCGs[x].state = false; } }

So if the group number selector was 1 only layers that were language.1 would be on.

For 2, layers with language.1 & language.2 would be on

For 3, layers with language.1 & language.2 & language.3 would be on.

 

I hope that makes more sense, the form has kind of expanded over time & is getting unwieldy.

Please let me know if I haven't been clear enough, I really do appreciate your help.

 

Likes

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
Adobe Community Professional ,
Feb 03, 2020 Feb 03, 2020

Copy link to clipboard

Copied

Ok, so forget what you've done already,

 

What you need to do is extract the language name and group number from each OCG. You also need to filter out those layers that are not language layers so they are not affected. Do this by prefixing all the language layers with something like "Lg."  This makes it explicit and you are not mucking about with looking for specfic names like "Logo".

 

// First, a helper regular expression, assuming the previouly mentioned prefix.

var rgLangGrp = /Lg\.(\w+)(?:\.(\d+))?/;

var n = Number(this.getField("SELECT.Number").value);

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < docOCGs.length; x++)

{

      if(rgLangGrp.test(docOCGs[i].name))

      {// Matches a language layer. Test for lang and group

           bOn = (RegExp.$1 == l)  && ((RegExp.$2=="") || (Number(RegExp.$2) <= n));

           docOCG[i].state = bOn;

       }

}

 

 

 

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

Likes

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
New Here ,
Feb 04, 2020 Feb 04, 2020

Copy link to clipboard

Copied

Hi Thom,

Thanks very much for your in depth reply.

Could you help me understand how this would work please?

As mentioned, I need the language radio selector to be a seperate operation. This is to turn off all layers, then turn on the single layer for the language selected, this is currently named as the language, so just English or Spanish etc. So would this layer get renamed to Lg.English, Lg. Spanish etc?

The language selector needs to be a seperate control from the number selector, as it shows other fields that are specific to each language group. The language selector will need to turn off layers that are not named with the specific language, so that changing the language will effectively reset the form.

The number radio selector gets the language to turn on layers named English.1 or English.2, which would presumably become Lg.English.1 or English.2 & also to turn off any layers with numbers in that are higher than the number selected. Is this where your code comes in, is it for the number controller rather than the language?

 

 

Likes

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
Adobe Community Professional ,
Feb 04, 2020 Feb 04, 2020

Copy link to clipboard

Copied

Ok that is much clearer. So there are two separate operations. You'll need two separate regular expressions.

For performance reasons you might consider qualifiying the separate parts of the script with the triggering field, i.e. event.source.

 

var rgLangOnly = /Lg\.(\w+)$/;

var rgLangGrp = /Lg\.(\w+)\.(\d+)/;

 

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < docOCGs.length; x++)

{

      if(rgLangOnly.test(docOCGs[i].name))

      {// Matches a language only layer

           docOCG[i].state = (RegExp.$1 == l);

       }

}

 

var n = Number(this.getField("SELECT.Number").value);

for (var x=0; x < docOCGs.length; x++)

{

      if(rgLangGrp.test(docOCGs[i].name))

      {// Matches a language with group only. Test for lang and group

           bOn = (RegExp.$1 == l)  && (Number(RegExp.$2) <= n));

           docOCG[i].state = bOn;

       }

}

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

Likes

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
New Here ,
Feb 07, 2020 Feb 07, 2020

Copy link to clipboard

Copied

Hi Thom, Thanks again for coming back to me.

So I put the first half of the code i.e.:

var rgLangOnly = /Lg\.(\w+)$/;

var rgLangGrp = /Lg\.(\w+)\.(\d+)/;

 

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < docOCGs.length; x++)

{

      if(rgLangOnly.test(docOCGs[i].name))

      {// Matches a language only layer

           docOCG[i].state = (RegExp.$1 == l);

       }

}

into the language selector & I get this error message:

Exception in line 15 of function top_level, script AcroForm:SELECT.Language:Annot1:MouseUp:Action2 ReferenceError: docOCGs is not defined 15:AcroForm:SELECT.Language:Annot1:MouseUp:Action2 (for the English option)

Exception in line 18 of function top_level, script AcroForm:SELECT.Language:Annot2:MouseUp:Action2 ReferenceError: docOCGs is not defined 18:AcroForm:SELECT.Language:Annot2:MouseUp:Action2 (for the French option)

I tried to patch what I thought might have been typos, where docOCGs[i] when. think the rest of the code is referring to [x] or where the code says docOCG rather than docOCGs but to no avail.

Likes

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
New Here ,
Feb 07, 2020 Feb 07, 2020

Copy link to clipboard

Copied

AH, was perhaps a little hasty, this works now for the language selector:

var docOCGs = this.getOCGs();

var rgLangOnly = /Lg\.(\w+)$/;

var rgLangGrp = /Lg\.(\w+)\.(\d+)/;

var l = this.getField("SELECT.Language").valueAsString;

for (var x=0; x < docOCGs.length; x++)

{ if(rgLangOnly.test(docOCGs[x].name)) {// Matches a language only layer docOCGs[x].state = (RegExp.$1 == l); } }

I was missing the docOCGs var, replaced [i] with [x] & replaced docOCG with docOCGs.

Onto the number selector now!

Likes

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
New Here ,
Feb 07, 2020 Feb 07, 2020

Copy link to clipboard

Copied

Hmm sorry Thom, I'm beginning to think I'm expecting too much of acrobat & asking too much of your time that you've already given me. The language selector works but it doesn't turn off every OCG. So if I have got halfway through filling out English for example, then realise that I should've been filling out French, the language selector needs to basically reset the form. I have done this with a form reset to reset the fields but it doesn't turn off any of the english OCGs that might have been turned on. Is there some simple way of turning off all the OCGs, then running the code you've provided to turn the correct language OCGs on?

Likes

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
Adobe Community Professional ,
Feb 07, 2020 Feb 07, 2020

Copy link to clipboard

Copied

LATEST

Same as you did before, in the first post.

Put this at the top:

 

for (var x=0; x < docOCGs.length; x++)

{ docOCGs[x].state = false; }

 

You are a good ways along in your process, don't loose hope. This is complex, and you're having exactly the same difficulties every programmer has when they are starting out. Your thinking in a straight line about how you want it to work, but you also have to think about how you don't want it to work. You're strategy has to take "all" scenerios into account. Cover all the possibilities. Think about this first, before committing to a specific methodology. 

 

Also, when you asking for help, remember that we don't know anything about your setup and goals. So unless it's real simple, we're not going to understand the total complexity and are not going to be able to help with figuring out all the possible scenerios. We can only help with the mechanics of a specific issue, unless of course you hire me 😉

 

 

 

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

Likes

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