Copy link to clipboard
Copied
I am working on a form that has a drop down box with over 75 selection/choices. Each selection has been given one of two possible export values. For example: "choice 1" has export value A, "choice 2" has export value A, "choice 3" has export value B, "choice 4" has export value A, "choice 5" has export value "B", and so on. I neeed to write a script that will spawn a page template based on the export value (i.e., all choices with export value "A" will spawn "page template 1" and all choices with export value "B" will spawn "page template 2".
I currently am able to do this based on the selection/choice name, but would like to simplify by using the export value. This is how I have done this using the selection/choice name:
Added JavaScript to Drop Down that triggers spawned template (Properties>Format>select Custom Keystroke Script and add)
if(event.willCommit)
{
switch(event.value)
{
case "Choice 1":
this.getTemplate("page template 1").spawn({bRename: false, bOverlay: true});
break;
case "Choice 2":
this.getTemplate(""page template 1").spawn({bRename: false, bOverlay: true});
break;
... and so on
I was hoping it would be simple to modify the script to look for the export value rather than the selection/choice item name, but have be unable to figure it out. Is there a way to do this? I would appreciate any help.
So is the template spawned if a selection from any of the 78 dropdowns is made?
What if they select options from different dropdowns that spawn different templates?
You can absolutley use the "Full" or "Simplified" values for the selection. It doesn't really matter what is used, as long as you know it will work and your methodology is consistent, and doesn't have any holes in it.
Use this code to get the export value, Note the is the Non-Commited keystroke (i.e., the real keystroke)
if
...
Copy link to clipboard
Copied
Get rid of the event.willCommit part and move the code to the field's Calculate event.
Also, change "Choice 1" to "A", and "Choice 2" to "B" in your code...
Copy link to clipboard
Copied
Do I start with:
switch(event.value)
{
case "A":
Copy link to clipboard
Copied
Yes.
Copy link to clipboard
Copied
When I do that I get reference errors:
ReferenceError: value is not defined
Copy link to clipboard
Copied
Post your full code, please.
Copy link to clipboard
Copied
I moved the script to the drop down field's calculation tab (Properties>Calculation>select Custom Calculation Script). Is that correct? Here's the script that I added:
if(event.value.willCommit)
{
switch(event.value)
{
case "Full":
this.getTemplate("1 Ind CIP Long").spawn({bRename: false, bOverlay: true});
break;
case "Simplified":
this.getTemplate("1 Ind CIP Short").spawn({bRename: false, bOverlay: true})
break;
}
} else if (this.numPages==2) {
this.deletePages(1);
}
Note that this shows the actual export values ("Full" and "Simplified") and the actual page templates I want to spawn ("1 Ind CIP Long" and "1 Ind CIP Short").
When I moved the code to the field's calculate event and removed the event will commit part, I get a syntax error 14, as well as the value is not defined errors
I really appreciate all your time and help.
Copy link to clipboard
Copied
I don't know if this is helpful, but here are the actual errors from the JavaScript debugger:
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
ReferenceError: value is not defined
1:Field:Keystroke
TypeError: getField(...) is null
4:Field:Mouse Up
ReferenceError: value is not defined
1:Field:Keystroke
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
SyntaxError: syntax error
14:
Copy link to clipboard
Copied
Like I said, remove this part (and the curly brackets associated with it):
if(event.value.willCommit)
Copy link to clipboard
Copied
This script cannot be used in a calculation as written.
There is no "event.value.willCommit", it doesn't exist.
The correct event property is "event.willCommit" ,but this value is only available in a keystroke script.
However, spawning a template from a calculation is not a good idea anyway. Calculation scripts are run anytime any value on the form is changed. Spawning templates is an activity that has to be carefully managed. You don't want the same template to be spawned multiple times, or different templates to be spawned on top of one another.
Also, there is no page number specified in the spawn function. Which page is supposed to be overlaid? And why the deletePages if the spawn is overlaying a page?
I would suggest that you test the single line of "spawn" code in the console window to make sure it does what you want before using it in any script. You also need a way to manage this process. You should figure that out and test it before spawning any pages.
You'll find a tutorial here on using the console window.
https://www.pdfscripting.com/public/Free_Videos.cfm#JSIntro
Copy link to clipboard
Copied
Thanks. Are you saying I should put it back under Format/Custom Keystroke? When I had it there before it worked exactly how I wanted it to, EXCEPT I had to put in each selection/item name (78) separately. I was hoping to just put in the corresponding event value (2 entries vs 78), but I could not get that to work. Would changing "event.value.willCommit" to "event.willCommit" make the event value option work?
Copy link to clipboard
Copied
Actually, I just looked at my original script and I had "event.willCommit" not "event.value.willCommit". This is the beginning of my original script that I had as a Custom keystroke script:
if(event.willCommit)
{
switch(event.value)
{
As I said earlier, this worked, except I had to include a separate entry for each of the drop down item names with the template page I wanted to be spawned for that item (in this case 78 items). Is there a way to write it so that the specified template page will be spawned based on the specified event value ?
Copy link to clipboard
Copied
The solution to the problem of handling 78 separate dropdowns, is to do this:
1) put the code into a document level function. This gives you a central location to make changes that are then applied to all the fields simultaneously.
2) write a console script to place the code to call this function into all of the dropdowns. The same script could even automatically set the entries for the dropdowns and/or any other properties that are shared. This saves an enormous amount of time, and potential entry errors. The trick to being successful at this sort of thing is field naming. The names control everything, and can make your live easy or impossible.
For example, say the dropdown fields are named "MyDropdown.Choice1", "MyDropdown.Choice2", etc. the document level function is named "MyChoiceFunction". This code will place the script in all fields.
this.getField("MyDropdown").getArray().forEach(function(a){a.setAction("Keystroke","MyChoiceFunction()"});
If you're names aren't suitable for this code and you don't want to rename them Another approach is to write a loop to go through all the fields on the form and use the field type to select for adding the script.
Copy link to clipboard
Copied
Thom is right that since this involves spawning pages the calculation event is not the best option. That's my bad. There are other ways to retrieve the export value, though. For example, you can use the getItemAt method in a loop, comparing event.value with each display item in the field, and then accessing the export value of that selected item. That might be a better option in this case.
Generally speaking, though, I don't think it's a good idea to have multiple items with the same export value.
An export value needs to be unique. I would change the export values to "Choice1-A", "Choice2-B", etc.
That would make them unique and still allow extraction of the template name to spawn.
Copy link to clipboard
Copied
I'm not sure this would make the script simpler than my original method of specifying each item name. I may not have explained what I am trying to accomplish very clearly. I hope you have the patience to let me try and clarify one more time.
The export value is only included for the purpose of determining which item/choice gets which template page spawned. There are only two possible options--a "full" or a "simplified" template page.
In this form, the drop down item selections would contain approximately 78 choices for the end user to choose from. Based on their choice, either the "full" or the "simplified" template page would be spawned.
Is there any way to use my original script, but have the extraction based on the export value ("full" or "simplified") instead of 78 different item names?
I hope this make sense--thanks again for all your help and patience.
Copy link to clipboard
Copied
So is the template spawned if a selection from any of the 78 dropdowns is made?
What if they select options from different dropdowns that spawn different templates?
You can absolutley use the "Full" or "Simplified" values for the selection. It doesn't really matter what is used, as long as you know it will work and your methodology is consistent, and doesn't have any holes in it.
Use this code to get the export value, Note the is the Non-Commited keystroke (i.e., the real keystroke)
if(!event.willCommit)
{
switch(event.changeEx)
{
case "Full":
this.getTemplate("1 Ind CIP Long").spawn({bRename: false, bOverlay: true});
break;
case "Simplified":
this.getTemplate("1 Ind CIP Short").spawn({bRename: false, bOverlay: true})
break;
}
}
You can learn everything you ever wanted to know about list fields in Acrobat scripting here:
https://www.pdfscripting.com/public/List-Field-Usage-and-Handling.cfm
Copy link to clipboard
Copied
That works! Thank you so much!!!! For future reference, what made it use the export value was: (event.changeEx) vs (event.value) for the item value. Correct?
Regarding the 78 drop downs--I was only trying to get this to work for one drop down with 78 selections. I will be adding additional drop downs, but they will be different.
An additional thing that I was trying to do is delete the spawned page if a person changes their selection.
The reason I want to do this is, if a person makes a selection and the page is spawned and then they realize they made a mistake/change their mind and choose another selection, another page will be spawned. This would be confusing for the person filling out the form. What I was using before (at the end of the script) was:
} else if (this.numPages==2) {
this.deletePages(1);
}
This no longer works properly. Any suggestions?
Copy link to clipboard
Copied
Yes, "event.changeEx" is the Export value of a selected list item in the uncommited Keystroke event script for a list field. Always check the Acrobat JavaScript reference when looking for information about object properties and functions in Acrobat JavaScript.
So how many of these 78 items in the dropdown have the same export value? It is not generally a good idea to have items in a list with the same export value, because the export value represents the value of the field. Export values should be unique so that each item represents a unique field value. This is not necessary, it's just a good practice.
For example, the "bOverlay" argument in the "template.spawn()" function causes the template to overlay an existing page when it is set to "true". So in your code, the template overlays Page 0, i.e. the first page of the document. So there are no new pages to be deleted.
But even if there were, when you changed the code to use "!event.willCommit", you changed the order in which the script processed the events. You see, the uncommited keystrok happens first. In your old code the test for the number of pages happened before the new page was spawned. That is no longer true. If you want to test for an extra page and delete it, then do it in the main code.
if(!event.willCommit)
{
if(this.numPages == 2)
this.deletePages(1);
switch(event.changeEx)
{
case "Full":
this.getTemplate("1 Ind CIP Long").spawn({bRename: false, bOverlay: true});
break;
case "Simplified":
this.getTemplate("1 Ind CIP Short").spawn({bRename: false, bOverlay: true})
break;
}
}
Copy link to clipboard
Copied
Thanks again--this works exactly as needed!
I do try to refer to the Acrobat JavaScript reference, but since I am not that familiar with JavaScript, I never know where to find what I am looking for. Your answers have been so helpful. In addition to providing the solution, you explain the reasons behind the solution which helps educate and give everyone in the community a better understanding of how Acrobat JavaScript works.
Regarding the export values on the 78 drop down items--appoximately 20 of the items/choices have one value ("Full") and 58 have the another value ("Simplified"). I usually don't use export values on drop down items, but used them here to identify which item/choice goes with which template. Are there any potential problems with this approach?
Copy link to clipboard
Copied
The only problem with using the same export for several items in a list, is that there is no way (from the field value) to distinguish which entry was actually selected. This is a probelm in a couple of situations. First, if the list value is set from a script or data import, then the first item with the export will be selected. Second, if data is exported from the PDF, then there is no way to know which specific selection is made. But if the form is only viewed interactively, there is no problem because the user is not seeing the value of the list selection, they are seeing the label attached to that value.
Copy link to clipboard
Copied
Thanks again, Thom. The explanation is very helpful and fortunately this form falls into the later category.
In the meantime, however, I did find another issue that I was able to solve. I needed the selected drop down item name (label) to populate a text field on the spawned template page. The original script (see below) , which I had added to the calculation tab for the text field, worked when there were no export values associated with the drop down items. After I added the export values to the items, the export value populated the text box instead of the label.
ORIGINAL (populates the text field with the selected drop down's export value if there is one):
event.value=this.getField("dropdownname").value;
REVISED (populates the text field with the selected drop down's label instead of export value):
var field = this.getField("dropdownname");
var selectedIndex = field.currentValueIndices;
var exportValue = field.getItemAt(selectedIndex); // The field value
var displayValue = field.getItemAt(selectedIndex, false); // Label shown in the UI
event.value=displayValue;
This seems to be working. I thought it might be helpful to others, as well. Let me know if you see any issues.
Copy link to clipboard
Copied
Another option is to populate this value at from the Keystroke script on the dropdown. This is much easier since you don't need all the code for geting the item index. And it doesn't yank the entire form around like calculations do.
Add this line after the code that spawns the template
this.getField("SpawnedTextFieldName").value = event.change;
Copy link to clipboard
Copied
Perfect. Thank you once again!
For future reference, does the addition of:
=event.change
to the code make the text field populate with the item name rather than the export value?
Copy link to clipboard
Copied
Yes, event.change is the value of the selection label/name.
Copy link to clipboard
Copied
Hi
Im very new to all this, could someone let me know if it is possible to split a PDF by the page templates?
Thanks