Walk your users through the form-filling process.
Collecting information with online forms is an interactive process. We have discussed how to collect form data [Hack #2] and how to drive forms [Hack #75] . Now, let's use what we know to program an interactive, online form-filling session, such as the one in Figure 6-6 (visit http://www.pdfhacks.com/form_session/ to see this example and download PHP source code).
To submit data to your server, the PDF form must be displayed inside a web browser. I recommend displaying it inside an HTML frameset. This enables you to bracket the form with (HTML) instructions and a hyperlinked escape route, so the user won't feel abandoned or trapped. It also adjusts the user to the idea that this isn't any old PDF. Most people experience PDF as something to download and print out. Not only will this look different, but also the frameset conceals the PDF's URL and prevents reflexive downloading.
Here is the HTML frameset code used in our example at http://www.pdfhacks.com/form_session/. Note that it uses a PDF+FDF URL to reference the form in order to prevent the PDF from breaking out of the frameset [Hack #75] .
<?php // This is part of form_session // visit www.pdfhacks.com/form_session/ // $our_dir= 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']); // The PDF+FDF URL notation respects frames // and triggers the browser's 'PDF' association // instead of its 'FDF' association (some browsers // don't have an FDF association). // $form_frame_url= '"'. $our_dir.'/form_session.pdf#FDF='. $our_dir.'/update_state.php?reset=1"'; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"> <html> <head> <title>PDF Form Filling Session Demo</title> </head> <frameset cols="*,200"> <frame src=<?php echo $form_frame_url ?> name="form" scrolling="no" marginwidth=0 marginheight=0 frameborder=1> <frame src="sidebar_session.html" name="sidebar" scrolling="auto" marginwidth=5 marginheight=5 frameborder=1> </frameset> </html>
Here are some ideas for your interactive PDF form design. Keep in mind that a form can have any number of PDF fields, and you can hide fields from the user or set them as read-only at any time. Our forge_fdf script [Hack #77] enables you to set these flags as needed. Just add the field's name to the $fields_hidden or $fields_readonly arrays.
Use hidden text fields to store the form's session and state information.
If your form has multiple sections that require separate, server-side computation, add a Submit Form button for each section. Show only one button at a time by hiding all the others.
Don't forget to append an #FDF to form submission actions?e.g., update_state.php#FDF.
Highlight specific sections of your form with borders. Create a border using an empty, read-only text field that shows a colored border and a transparent background.
You must draw these decorative form fields first, so they won't interfere with other, interactive fields. Or, move a decorative field behind the others by giving it a lower tab order.
After the user completes a section, set that section's fields as read-only to lock the data in. Fields that hold the results of server-side calculations also should be read-only.
If a form's page gets cluttered with PDF fields, consider dividing fields across two or three copies of the same PDF page.
Consider splitting multiple-page forms into single-page PDFs.
Create text fields to serve as read-only messages to the user. If the user submits invalid field data, serve the form again and show a suitable message. When creating these message fields in Acrobat, color them so that they stand out from the data. You can change a message's text using FDF.
We employ some of these techniques in our online example at http://www.pdfhacks.com/form_session/.
A form-filling session has a beginning, a middle, and an end. The middle is the hard part because that is where your form logic is. The tricky parts are the beginning and the end. Here they are, in order:
Begin the session by using a PDF+FDF URL [Hack #75] to open the form. For example:
The FDF portion is a script that initializes the session state. It must also serve FDF that sets the form's initial appearance.
Store the session's ID and state information in hidden PDF text fields, if necessary.
With each form submission, update the session state and then respond by serving FDF. Use FDF to update the form's appearance. Use it to activate some fields and hide others, as needed. Also use FDF to update read-only field text with calculated data or messages to the user.
Omit the /F key ($pdf_form_url in forge_fdf) from the FDF you serve until you are ready to exit this session.
When the form session is done, break out by serving an FDF Forward. This is an FDF with no form data except the /F key ($pdf_form_url in forge_fdf). Set the /F key to the URL of an HTML page or script. This new address will replace the PDF form in the user's browser.
Visit http://www.pdfhacks.com/form_session/ to see a live example of this model. Download form_session-1.1.zip from this page to examine the PHP scripts and PDF forms. IndigoPerl [Hack #74] users can unpack form_session-1.1.zip into C:\indigoperl\apache\htdocs\pdf_hacks\form_session-1.1\ and then run the example locally by pointing their browsers at http://localhost/pdf_hacks/form_session-1.1/start.html.