If you're seeing something other than Verdana, the Font is Graublau Sans Web by FDI fonts.info
Skills Required: Flex, ActionScript, Acrobat JavaScript
One of the great new features of Adobe Acrobat 9 Pro and Pro Extended is the ability to add SFW based Rich Media Annotations (RMAs) developed in Flash or Flex. These SWF files can be placed in a PDF file using the new Flash Tool in Acrobat 9 and play using the built-in Flash Player. The built-in player provides greater security and consistency for Flash playback inside any PDF file. For those of you that attempted to use Flash in a PDF with earlier versions of Acrobat, you'll remember that the user experience wasn'tât all that great. Acrobat 9 provides tight integration between the PDF document and the RMAs well as other content types that run in the Flash Player such as FLV and H.264 encoded video.
There are two ways to play the RMA in a PDF file, on the page or in a floating window.
|
![]() When the RMA is played on the page, you are able to use the Acrobat commenting features to review and markup the interactive content. |
In the "Yahoo Map in a PDF File" example, there is some fairly intricate connections between the map RMA and the PDF file. The RMA even has the ability to add buttons to the PDF file that are already instrumented to communicate with the RMA and trigger ActionScript events. After reading the article about the map, come back here and read about how it's done.
The "Yahoo Map in a PDF File" example doesn't use any techniques more advanced than what you've already seen in parts one through four of this series, the only difference is that I use more advanced Acrobat JavaScript to do more interesting things to the PDF file. From the ActionScript side, you won't need to know more that what has already been discussed.
4 Steps to Creating a Self Connecting RMA
Step 1: Identity
Creating a custom identity for your RMA, is pretty simple. It begins with adding a method to the RMA that simply returns a string and then adding a callback for that method.
ExternalInterface.addCallback("swfIdentity", swfIdentity);
private function swfIdentity():String
{
return "yahooMap";
}
Then in the JavaScript that you send to Acrobat during the RMA's creationComplete event, you run something that looks like the code below. For each page in the document, on each RMA, the "swfIdentity" ActionScript is called. If the return value is "yahooMap" then you know you've got the right one and you can set some variables based on where you are in the loop. This gives you a way to interact withthe RMA
for (p=0; p < this.numPages; p++){
RMAs = this.getAnnotsRichMedia(p)
for each (RMA in RMAs){
if (RMA.callAS("swfIdentity") == "yahooMap"){
yahooMapRMA = RMA.name;
yahooMapPage = p;
}
}
}
This gives you a way to interact with the RMA by page number and name regardless of where it is in the document with something that looks like this.
RMA = getAnnotRichMedia(yahooMapPage, yahooMapRMA)
Step 2: Editability
To determine if you can add page elements to the PDF, you need to know three things.
Is the file being displayed in a browser?
If it is, you probably don't want to modify it. The ActionScript/JavaScript combination below will return true if the file is running in a browser.var external:Boolean = Boolean(ExternalInterface.call("eval", "this.external"));Is the file being displayed in the Adobe Reader?
If it is, there is only a limited set of JavaScript that can change the file. Adding buttons isn't in that set. The ActionScript/JavaScript combination below will return the viewerVariation which you can use to determine if you are running in Reader or a version of Acrobat.var viewerVariation:String = ExternalInterface.call("eval", "app.viewerVariation");Is the file secured to prevent editing?
The ActionScript/JavaScript combination below will tell you if the file has been secured in some way though it won't tell you the specifics. If it returns null, then the file can be modified. If there is a securityHandler (this.securityHandler returns an object rather than null), then you know that some sort of security has been placed on the file. It is certainly possible that the file can still be modified but you just can't tell, so in my example, I assume you can't.var securityHandler:String = ExternalInterface.call("eval", "this.securityHandler");
Step 3: Location
Once you've done step one, this one is pretty easy. The "rect" property of the RMA, returns an array of four numbers [xll, yll, xur, yur] specifying the lower-left x, lower-left y, upper-right x and upper-right y coordinates, of the rectangle defining the location of the RMA on the page. This information can then be used elsewhere to place other PDF page elements relative to the location of the RMA.
Note: The online documentation describes the rect property as read/write. It isn't.
function rmaRect()
{
RMA = getAnnotRichMedia(yahooMapPage, yahooMapRMA)
return = RMA.rect.toString();
}
Step 4: Data
As I discussed in Part 2: Enabling Review and Markup with State Save, the built-in Flash player in Acrobat and Reader can store state information inside the RMA. However, what is described in that article is not the only way. In the "Yahoo Map in a PDF File" example, I use the name and userName properties of a field to store the information that I need for each button to interact with the RMA.
In the map's creationComplete event handler, addMarkersFromPDF() gets called. The first thing it does is retrieve a list of the field names from the PDF file. The Acrobat JavaScript getMapButtons() function iterates through each of the fields in the PDF file looking for field names that begin with "yahooMap." and adds that field name to an array that gets returned to the RMA. The buttons were previously created by the RMA. The line in red below adds a marker based on the userName property of each field in the PDF file that begins with "yahooMap.".
private function addMarkersFromPDF():void
{
var mapButtonsString:String = ExternalInterface.call("eval", "getMapButtons()");
if (mapButtonsString.length > 0)
{
var mapButtonArray:Array = mapButtonsString.split(",")
var marker:Marker;
var button:String
for each (button in mapButtonArray)
{
marker = new CustomImageMarker();
marker.address = new Address(ExternalInterface.call("eval", "this.getField('"+button+"').userName"));
_yahooMap.markerManager.addMarker(marker);
}
}
}
The Acrobat JavaScript to retrieve the field names.
function getMapButtons()
{
buttons = [];
for ( var i = 0; i < this.numFields; i++)
{
var fname = this.getNthFieldName(i);
f = this.getField(fname);
if ( f.type == "button" && fname.substr(0,9) == "yahooMap.")
{
buttons.push(fname);
}
}
return buttons.toString();
}
Using a combination of Acrobat JavaScript and ActionScript can create very tight integrations between the RMA and the PDF file container.
You can download the Flex project for the Yahoo Map example below. Get your own application id from the Yahoo! Developer Network at http://developer.yahoo.com/wsregapp/ in order to compile the project.
Open the Example PDF file
Download the Flex Project for the RMA in the example