Multi-state Objects

If you have walked through the steps required to create a multi-state object in InDesign, you must have thought to yourself “There must be a better way.” Since you already know how to work with scripts, your thoughts may have matured to the point of wondering how you would go about writing a script to automate the process.

The problem with automating a multi-state object is that there are so many design criterias for creating for the object. This could translate into the script needing to provide the user with a number of options:

  • Where the assets (images) will be located
  • Will a caption be needed for the individual states (images)
  • If a caption is needed, how will it be styled, and what will be its text source?
  • Will buttons need to be added?
  • If buttons are to be added, how will this be done.
  • If created as part of the script, what size will the buttons be, how will they be styled, and where in relation to the object will they be placed?

As you can see, this could require a custom dialog that might become prohibitively complex.

For this reason, you might want to start small. Pick your most widely-used multi-state object requirement and automate it. As long as your script is written modularly, you should be able to modify it to meet other requirements without much hassle. The biggest task might end up being in creating the user interface.

Starting Small

In this demonstration we will start small with a number of dependencies assumed. We will write the code in AppleScript but ExtendScript users can follow along.

  • The script will assume the user has a document open with measurements in either points or pixels.
  • The position and size for the multi-state object will be indicated by a selected rectangle on the active page
  • The multi-state object will be comprised of a folder of images located in the same folder as the active document
  • All of the image files have been cropped to fit within the space indicated by the selected page item

With these dependencies taken care of, the following will return the bounds to the page item selected.

   set selBounds to getSelectionBounds()
   on getSelectionBounds()
	tell application "Adobe InDesign CC 2014"
		set selList to selection
                if length of selList is greater than 0 then
		   set selItem to item 1 of selList
                   if class of selItem is in {rectangle, polygon, text frame} then
		      return geometric bounds of selItem
                   end if
                end if
                error "Requires page item selection"
	end tell
   end getSelectionBounds 

The reference to the selected item will be used later in the script to create the multi-state object.

If the active document is saved in the same folder as the folder with the images, the following will return the path to the image folder. This will be used for placing the images for the multi-state object. Notice the call to the handler passes the name of the images folder as part of the call.

   set imagePath to getImagePath("Images")
   on getImagePath(folderName)
	tell application "Adobe InDesign CC 2014"
	   tell document 1
              set docPath to file path as string
	   end tell
	end tell
	return (docPath & folderName)
   end getImagePath

With the path to the Images folder, list folder will return a list of the names for the files. For our purpose we will assume all of the files in the folder are valid files.

   set fileList to getFileList (imagePath)
   on getFileList (imagePath)
      set fileList to list folder imagePath without invisibles
      if length of fileList is less than 3 then
         error "Requires at least 3 items for multi-state object"
      end if
      return fileList
   end getFileList

It would be better to add code to the getFileList handler to validate that each item in the list returned is a file (not a folder) with either a “.jpg” or “.png” extension. We will leave this up to the reader.

Creating the Multi-state Object

With the above routines in place, the script can create the multi-state object.

   set MSObject to makeMSO (selBounds, imagePath, fileList, "MultiImages")
   on makeMSO (imageBounds, imagePath, fileNames, MSOName)
      set statesToAdd to (length of fileNames) - 2
	 tell application "Adobe InDesign CC 2014"
	   tell document 1
	      set layerRef to layer 1
	      set MSORef to make multi state object with properties{name:MSOName, geometric bounds:imageBounds, item layer:layerRef}
	      repeat with i from 1 to statesToAdd
		tell MSORef to make state
	      end repeat
	   end tell
	   repeat with i from 1 to length of fileNames
	      set nameStr to item i of fileNames
	      set fileAlias to (imagePath & ":" & nameStr) as alias
	      tell state i of MSORef
	         set rectRef to make rectangle with properties {geometric bounds:imageBounds, name:("State" & i), fill color:"None", stroke weight:0}
		 end tell
		 tell rectRef to place fileAlias
	   end repeat
	end tell
	return MSORef
   end makeMSO 

You will also need to add error handling at the top of the script. When the modules for the script are combined, the top portion of the script should read similar to the following:

	set selBounds to getSelectionBounds()
	set imagePath to getImagePath("Images")
	set fileList to getFileList (imagePath)
	set MSObject to makeMSO(selBounds, imagePath, fileList, "MultiImages")
   on error errStr
	display alert errStr
   end try

To make the script more robust, you could present the user with a list of layers from which to choose for placing the multi-state object. The reference to this layer would be used in the above in place of layer 1 for the layer reference (layerRef).

Add Buttons

All that is needed now are the buttons. You can create the buttons manually and set their behavior in InDesign’s Buttons and Forms panel. Or, if you are ambitious, you can let the script create the buttons for you. This would be a little more challenging, and something that we will reserve for a future demonstration.

About File Types

You can use either jpeg or png files for this multi-state object script. If using jpeg, InDesign will give you an alert when you go to export your document to fixed layout EPUB. You may decide to use jpeg anyway as the problem reported does not seem to affect the outcome of the final product, and you save more than one-half as far as total file size is concerned.

Onward and Upward

Now that your have a script to automate the basics for a multi-state object, add the ability to display a caption with each image. You might decide to have the captions stored as part of the metadata for the image. Alternatively, you could have text files named to correspond to their image file. For styling the text, you might designate an object style that defines the paragraph styles for its contents. As you can see, this script could get fairly complex.