Buttons for InDesign Fixed Layout

This week we will delve into the world of buttons for InDesign fixed layout animation. For this we will add some new handlers to our scripting library.

MakeTextFrame

This handler will require the following arguments:

  • parentObj – the parent object for the text frame
  • itemName – a name for the object to be used for reference
  • gBounds – list of four page coordinates (top, left, bottom, right) for geometric bounds
  • textStr – text to be displayed in text frame
  • textProps – a record of any properties to be applied to the text
   on makeTextFrame(parentObj, itemName, gBounds, textStr, textProps)
      tell application "Adobe InDesign CC 2014"
	 tell parentObj
		set frameRef to make text frame with properties {name:itemName, geometric bounds:gBounds, contents:textStr}
		set paraRef to object reference of paragraph 1 of frameRef
		set properties of paraRef to textProps
	 end tell
      end tell
      return frameRef
   end makeTextFrame

Test the handler using the following code for the top part of the script. (Assumes an InDesign document is open.):

   tell application "Adobe InDesign CC 2014"
        set docRef to document 1
        set spreadRef to spread 1 of docRef
        set gBounds to {"100 pt", "100 pt", "300 pt", "300 pt"}
	set textStr to "Hello World"
	set textProps to {point size:24, leading:24, justification:center align}
        my makeTextFrame (spreadRef, "testing", gBounds, textStr, textProps)
   end tell

Create Button

The handler to create a simple button (SimpleButton) is a little more complicated than makeTextFrame. This handler allows the button created to optionally have a title. If the value for the variable itemLabel is not an empty string, the button title is created. The handler takes advantage of the fact that there will be a makeTextFrame handler in the script. Its arguments are similar to that of makeTextFrame in that it requires the parent object (parentObj), item name (itemName), and geometric bounds (gBounds). It also requires:

  • itemLabel – may be an empty string
  • buttonProps – properties for the button
  • textProps – required properties for label text if itemLabel is not an empty string

SimpleButton

   (*If itemLabel is not an empty string, button is created with Title*)
   on simpleButton(parentObj, itemName, gBounds, itemLabel, buttonProps, textProps)
	tell application "Adobe InDesign CC 2014"
	    tell parentObj
		set buttonRef to make button with properties {name:itemName, geometric bounds:gBounds}
		tell buttonRef
		    set properties to buttonProps
		    convert shape given convert to rounded rectangle corner radius 12
		    if itemLabel is not "" then
			 set labelRef to my makeTextFrame(buttonRef, "ButtonLabel", gBounds, itemLabel, textProps)
			 set fill color of labelRef to "None"
			 set properties of text frame preferences of labelRef to {vertical justification:center align}
		    end if
		end tell
	    end tell
	end tell
	return buttonRef
    end simpleButton

Notice that the handler calls the makeTextFrame handler and passes a reference to the button as the parent. You will need to make sure that the fill color specified for the buttonProps variable (“Orange”) exists in your document.

 

Animation Behavior

Of interest in working with buttons is animation behavior. This object is an element of a button and has a number of properties you need to be aware of:

  • animated page item – the page item that will animate when the user interacts with the button
  • behavior event – the event that will trigger the animation; can be mouse upmouse downmouse entermouse exiton focus, or on blur
  • enable behavior – true or false; if true, the behavior is enabled
  • operation – the playback mode; can be playstoppauseresumereverse playback, or stop all

With this in mind, we can create and set the animation for our page items. We will do this using the following script:

Example Script

Start a new script in AppleScript Editor. Copy the two handlers (makeTextFrame and simpleButton) to the script. The top part of the script that calls the handlers and sets animation properties is as follows. Add this to the script:

   tell application "Adobe InDesign CC 2014"
	set docRef to document 1
	set spreadRef to spread 1 of docRef
	--create a page item that will be invisible
	tell spreadRef
		--create text frame to make visible when button is pushed
		set gBounds to {"100 pt", "60 pt", "200 pt", "250 pt"}
		set textStr to "You pushed the button"
		set textProps to {point size:24, leading:26, justification:center align}
		set invisibleObj to my makeTextFrame(spreadRef, "invisible", gBounds, textStr, textProps)
		set properties of animation settings of invisibleObj to {initially hidden:true, hidden after:false}
		--create button
		set buttonProps to {fill color:"Orange", stroke weight:2, stroke color:"Black"}
		set gBounds to {"110 pt", "300 pt", "146 pt", "400 pt"}
		set button1Ref to my simpleButton(spreadRef, "button1", gBounds, "Push Me", buttonProps, textProps)
		tell button1Ref 
                    make animation behavior with properties {behavior event:mouse down, enable behavior:true, animated page item:invisibleObj, auto reverse on roll off:false, operation:play}
	        end tell --button1Ref
	end tell--spreadRef
	--timing settings
	tell timing settings of spreadRef
		delete timing list 1
		set pageClickTimingList to make timing list with properties {trigger event:on page click}
	end tell
   end tell

To test, start a new InDesign document set up for web intent. Make sure the document has a color swatch established that you can use for the value of the fill color property in the buttonProps property record. With the two handlers added below the top portion of the code for the Example Script above, compile the script. Run the script. Notice that when you preview the animation (in InDesign’s EPUB Interactivity Preview panel) the button is visible when the page opens, but the text frame is not. When the button is pushed, the text frame becomes visible.

Button States

You can give your custom buttons up/rollover/down state behavior. It takes a little doing, but the process is spelled out for you in the handler below. The handler is almost the same as the SimpleButton handler but with properties for the different button states added.

   on makeStateButton(parentObj, itemName, gBounds, itemLabel, buttonProps, ROProps, clkProps, textProps)
       tell application "Adobe InDesign CC 2014"
	   --create the button
           tell parentObj
		set buttonRef to make button with properties {name:itemName, geometric bounds:gBounds}
	   end tell
	   tell buttonRef
               --create up state
	       set myUpState to make state with properties {statetype:up}
	       tell myUpState
		   set upRect to make rectangle with properties {geometric bounds:gBounds} & buttonProps
		   tell upRect to convert shape given convert to rounded rectangle corner radius 10
	       end tell
               --create rollover state
	       set myROState to make state with properties {statetype:rollover}
	       tell myROState
		    set RORect to make rectangle with properties {geometric bounds:gBounds} & ROProps
		    tell RORect to convert shape given convert to rounded rectangle corner radius 10
		end tell
                --create down state
		set myDownState to make state with properties {statetype:down}
	        tell myDownState
		    set downRect to make rectangle with properties {geometric bounds:gBounds} & clkProps
		    tell downRect to convert shape given convert to rounded rectangle corner radius 10
		end tell
                --add label to button
		if itemLabel is not "" then
		    set labelRef to my makeTextFrame(buttonRef, "ButtonLabel", gBounds, itemLabel, textProps)
		    set fill color of labelRef to "None"
		    set properties of text frame preferences of labelRef to {vertical justification:center align}
		end if
	    end tell --buttonRef
	end tell --application
	return buttonRef
   end makeStateButton

To test this handler, copy the Example Script from above to a new script. Add the makeStateButton handler. Make the following changes to the top portion of the script:

    1. After the line that sets the property list for buttonProps, add:
   set ROProps to {fill color:"Green", stroke color:"None", stroke weight:0}
   set clkProps to {fill color:"Green", fill tint:50, stroke color:"Green", stroke weight:0}
    1. Instead of calling the simpleButton handler, call the new makeStateButton handler. Replace the line that calls the simpleButton handler with the following:
   set button1Ref to my makeStateButton(spreadRef, "button1", gBounds, "Push Me", buttonProps, ROProps, clkProps, textProps)
  1. Open a new document in InDesign. Make sure the document has color swatches establish for the colors referenced. (The code above uses Orange and Green for contrast. Use your own choice of colors.)
  2. Compile the script and run. Preview the animation for the button.

When previewed in InDesign’s EPUB Interactivity Preview panel, the button performs as anticipated. However, when exported to fixed layout EPUB, Adobe’s Digital Editions 4.0 does not work as well. The good news is that iBooks on the Mac and on the iPad works flawlessly.

Invisible Buttons

One trick that animators use quite often is to create invisible buttons over page items. This is used when the item to be animated is not the item itself that is clicked. Creating an invisible button is the same as creating the Simple Button, just set the fill and stroke colors to “None” and the stroke weight to zero (0).

   set buttonProps to {fill color:"None", stroke weight:0, stroke color:"None"}

On Your Own

To the Example Script above, see if you can add a hexagon (polygon page item) with an invisible button over. When the invisible button is clicked, a text frame becomes visible with the definition for the item clicked: (“A hexagon is a polygon with six equal sides.”).

Hint: To create the hexagon, you will need to set polygon preferences at the application level:

   tell application "Adobe InDesign CC 2014"
	set properties of polygon preferences to {number of sides:6, inset percentage:0}

With the polygon preferences set as above, the script can create the polygon using the following inside the tell spreadRef block:

        --create hexagon that will have invisible button over
	set hexBounds to {"300 pt", "300 pt", "400 pt", "400 pt"}
	set myHex to make polygon with properties {geometric bounds:hexBounds, fill color:"Dark Red"}

Make sure you use a color that is in your document for the value of the fill color property above.

All the rest of the code you will add is pretty much the same as the code in the Example Script above. Copy and paste code; change variables and values for properties as needed.

Create a new document in InDesign. When you run your script, your InDesign page should look somewhat similar to the screen capture below.

Screen capture of page setup created using modified Example Script