Home
eMail

If you're seeing something other than Verdana, the Font is Graublau Sans Web by FDI fonts.info

Working with Rich Media Annotations
Updated 11/16/2009

Self Connecting RMAs

Skills Required: Flex, ActionScript, Acrobat JavaScript

The Basics of SWF in PDF

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.


The floating window has certain advantages when you need the RMA to be present regardless of what page you are on in the PDF file.


When the RMA is played on the page, you are able to use the Acrobat commenting features to review and markup the interactive content.

Read “Add multimedia files to a PDF” to learn how to add RMAs to PDF files using the new Flash tool rather than the legacy multimedia object.

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.

Creating a Self Connecting RMA

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

  1. Identity: Your RMA may not be easily identifiable by the index number or internal PDF name. You'll want to create a method to identify your RMA by name.
  2. Editability: The PDF file that your RMA is in may not be editable. This could be because it is playing in the Adobe Reader or it could be playing in Acrobat but the file is secured to prevent editing. To avoid errors, you may want to modify your RMA's UI based on the editability of the PDF file.
  3. Location: Assuming the PDF file can be edited, you may want to add page elements to the PDF file. In the "Yahoo Map in a PDF File" example, new buttons are added to the bottom left of the RMA.
  4. Data: There are several ways that you can store data that your RMA may need in addition to the method discussed in Part 2: Enabling Review and Markup with State Save. 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.

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

Comments: