Check Boxes That Show and Hide PDF Pages
Here's the scenario. You need to assemble a document from a list of pages. The selection is dependent upon different criteria. You would like to create one master document, but only show the pages
that are relevant to the specific criteria, which would be listed on a cover page next to check box fields. An example is a new employee onboarding package with different positions, departments, and responsibilities. Here's an outline of the project:
The document must function with Adobe Reader.
Before any selections are made, the document will appear as a 1-page PDF cover page with check boxes for different pages.
As the user selects different check boxes, the relevant pages will appear.
As the user unselects different check boxes, the pages connected to those check boxes will disappear.
Regardless of the order in which the check boxes are selected and unselected the pages displayed will maintain the same order as the check box list.
Each page will have a page number at the bottom of the page. As pages are added and deleted the page numbers will be automatically updated to reflect their position in the pages that are displayed.
Here's a working example. For simplicity the optional pages are visually labelled as Black, Blue, Green, and Red.
Page templates were used. Here are some of the challenges:
Maintaining the page order when adding and deleting pages.
Updating the page numbers when adding and deleting pages.
Adobe Reader does not have the functionality to hide and show template pages, so they must be "spawned".
Adobe Reader can only delete pages if they were spawned from template pages in the same session.
David’s Scripting Tips
Since I taught myself JavaScript, I write my scripts a little differently than what you might be used to seeing. One of the first steps for me is thinking ahead through the other steps and trying to make the scripts as short and concise as possible. I copy and paste a lot with my left pinky finger on the Ctrl  key, and my left index finger smashing the a (select all), z (reverse), x (cut), c (copy), or v (paste), while controlling the mouse with my right hand.Â
While I don't mind copying and pasting, I try not to repeat what I don't have to. And I only define variables when I'm going to use the object of that variable more than once. This cuts down on redundant (in my opinion) typing. Naming is very important. I use the same name for different objects that will be connected in the scripts. You will see it in this project. The check box fields have the same names as their corresponding page templates, which also happen to be the page headings (Black, Blue, Green, and Red). This allows me to use the same script, with only minor modifications, for each check box, and to write a document level function that is easy to apply to each check box by simply changing the input variable.
Take the Acrobat Pro/JavaScript eLearning Course Acrobat Like a Pro
Here are the steps in creating this project:
1)Â Â Create the cover page and the four optional pages.
2)  Create text fields centered at the bottom of all pages, except the cover page. The cover page does not need a field as it will always read Page 1 so this text can be static.
3)  Name these fields Page Black, Page Blue, etc. where Black and Blue are the page template names. These fields will contain two scripts: A custom validation script and a custom format script.
4)  The reason for the custom format script is to prefix the field value, which will be a page number, with "Page: ". This script is optional. Without it the field will display the page number only, not "Page: " plus the page number. Here is the custom format script:
event.value = "Page: " + event.value;
5)  The custom validation script will extract the page number property from the field that contains the script, and then add one. One is added because page numbers are zero-based. One of the parameters for the spawn method is bRename, which determines whether the fields in the spawned pages will be renamed. In this project bRename is false so the fields will not be renamed. Because the fields will not be renamed, when the pages are spawned the document will end up with two page number fields for each spawned page (the one on the original template page and the one on the spawned page). When there is more than one field of the same name and the field page number property is called, it returns an array of page numbers (one for each field of that name). Hidden template page numbers are page number -1 (negative 1). The original template page will be the first page number in the array and the actual zero-based page number of the spawned page will be the second page number in the array. Here is the validation script.
event.value=Number(event.target.page[1])+1;
If this field is validated before the page is spawned there will be an error because there won't be an array of page numbers for that field. In this script [1] represents the page number of the second field of that name, or the page number of the field on the spawned page.
6)  Create templates of all pages except the cover page and name the templates. In this example the names are "Black", "Blue","Green", and "Red".
7)Â Â Hide the templates.
8)Â Â Create the following document level script:
function tmpl(pg)
{
var tmps=this.templates;
for(var i=0; i<tmps.length;i++)
{
if(tmps[i].name==pg)
{
tmps[i].spawn(this.numPages,false,false);break;
}
}
}
The script above creates a function called tmpl with an input variable pg, that loops through the templates and tests each template name. If the template name is equal to pg (which will be the template name), the page is spawned. When testing for a result that will only be found once, I always break the loop when the result is found, to stop the script from continuing to run. In this example it probably won't make much of a difference in performance, but in other loops that might run thousands of times after the result is found, breaking the loop will speed up the process by immediately stopping the script once the result is found. The three parameters of the spawn method in use are:
a)   nPage: The 0-based index of the page number after which, or on which the new page will be created. this.numPages is the last page of the document plus 1, which means the page will be created at the end of the document.
b)  bRename: Specifies whether the form fields on the spawned page will be renamed. It is set to false, so they won't be renamed.
c)   bOverlay: If true, the template will be overlaid on a specific page. It is set to false so the spawned page will be inserted as a new page.
9)Â Â Create four check box fields on the cover page and name them to match the template names ("Black", "Blue", "Green", and "Red").
10) Enter the following script as a mouse up action in the first check box field (Black):
if(this.numPages>1)//line 1
{this.deletePages(1,this.numPages-1);}//line 2
if(event.target.value!="Off")//line 3
{tmpl("Black");}//line 4
if(this.getField("Blue").value!="Off")//line 5
{tmpl("Blue");}//line 6
if(this.getField("Green").value!="Off")//line 7
{tmpl("Green");}//line 8
if(this.getField("Red").value!="Off")//line 9
{tmpl("Red");}//line 10
var ray=["Black","Blue","Green","Red"];//line 11
for(var i=0;i<ray.length;i++)//line 12
{this.getField("Page "+ray[i]).value="z";}//line 13
this.pageNum=0; //line 14
Here is a line-by-line explanation of the script:
Line 1:Â Test whether the number of pages in the document is greater than 1 (we only want the next line of the script to run if there are any pages besides the cover page).
Line 2:Â If the statement in line 1 is true, delete all pages except the cover page (0-based index for page 2 through the last page of the document).
Line 3:Â Test whether the check box that was clicked is not equal to "Off".
Line 4: If the statement in line 3 is true, run the tmpl function with the check box name as the input. This will spawn the template named with the same name as the check box ("Black").
Lines 5 through 10: Tests the other check boxes and if they are not equal to "Off", the corresponding templates are spawned. Since the script runs in order, and the pages are spawned as the last page in the document, the order is maintained. The script always deletes any spawned pages to start with and spawns them again if their corresponding check boxes are checked. This keeps the pages in order.
Line 11:Â Create an array of template names.
Line 12:Â Loop through the array.
Line 13: Set the page number fields in each template to a random text string. Because validation scripts only run when their field values change, this will trigger the custom validation script in each page number field.
Line 14:  Set the focus to the first page in the document (the cover page). Some versions of Acrobat will set the focus to the spawned page, so this line of code keeps the focus on the cover page.
11) Copy the mouse up action script from the first check box and paste it as a mouse up action script into all the other check boxes while making one slight modification. When calling a check box field from a script in the same check box you must use event.target instead of this.getField(<the field name>). event.target must be replaced with this.getField("Black") for all other check boxes. And the this.getField(<the field name>) must be replaced with event.target for each field that calls itself in the script.
For example, here is the script for the "Blue" check box field:
if(this.numPages>1)//line 1
{this.deletePages(1,this.numPages-1);}//line 2
if(this.getField("Black").value!="Off")//line 3
{tmpl("Black");}//line 4
if(event.target.value!="Off")//line 5
{tmpl("Blue");}//line 6
if(this.getField("Green").value!="Off")//line 7
{tmpl("Green");}//line 8
if(this.getField("Red").value!="Off")//line 9
{tmpl("Red");}//line 10
var ray=["Black","Blue","Green","Red"];//line 11
for(var i=0;i<ray.length;i++)//line 12
{this.getField("Page "+ray[i]).value="z";}//line 13
this.pageNum=0; //line 14
Notice the changes in lines 3 and 5. Here's a video of the entire project:
If you want to try this out you can download the file, create the templates, hide the templates, and add the scripts.
Happy testing. Next week I’ll show you how to hide and show PDF layers with check boxes. See you soon…