A Dialog for User Input

When starting a new InDesign project, whether you are using a template or not, you may end up doing the “Open Dialogs Shuffle”:

  • Find a template and open it
  • Add metadata to the document
  • Save the template as a new document
  • Add a date stamp to the document name
  • And more (you have your own workflow)

If you think it would be nice to be able to do all of this automatically with one simple dialog, the following discussion is for you. We will be writing it in AppleScript, but you ExtendScript users can follow the same pattern.

Custom Dialogs

In order for a dialog to display, the user interaction level for InDesign needs to be set to interact with all. As with other application settings you want to put the current setting in a variable before changing and then restore the value when you are through. Our example will use a variable called origLevel.

   tell application "Adobe InDesign CC 2014"
      --capture the current settings
      set origLevel to user interaction level of script preferences
      --set the setting to what the script requires
      set user interaction level of script preferences to interact with all
      (*do whatever needs to be done using the new preferences *)
      --set user interaction level back to original
      set user interaction level of script preferences to origLevel
   end tell

To create a dialog, you simply tell InDesign to make a dialog. Set properties for the dialog as part of the make statement. The following puts a reference to the dialog into a variable (dlgRef) as part of its being created.

set dlgRef to make dialog with properties {name:"Name Here", can cancel:true, label:"Label name"

A dialog is created in memory and does not display until you tell the dialog to show. With can cancel set to true, the user can respond to the dialog or cancel it. The following places the result of the user’s response into a variable as part of the statement that displays the dialog. Notice how the variable used to create the dialog is used to reference the dialog..

      set userResponse to show dlgRef

When through with the dialog, you need to clear the dialog from memory.

      destroy dlgRef

A Dialog Template

With all of this in mind, the following can be used as a boilerplate template for creating a custom dialog.

   tell application "Adobe InDesign CC 2014"
	set origLevel to user interaction level of script preferences
	set user interaction level of script preferences to interact with all
	set user interaction level of script preferences to interact with all
	set dlgRef to make dialog with properties {name:"Dialog Name", can cancel:true, label:"Dialog Label"}
	(*put the dialog code here *)
	(*end of user interface*)
	set userResponse to show dlgRef
	if userResponse = true then
		set theResult to {name:edit contents of nameField}
	else
		set theResult to {}
	end if
	--destroy the dialog
	destroy dlgRef
	--reset user interaction level
	set user interaction level of script preferences to origLevel
end tell
theResult

At this point if you run the script, all you will have is a dialog with two buttons: OK and Cancel.

Creating the Information Fields

Now that you have the skeleton for a custom dialog, you need to add input items. There are a number of widgets provided by InDesign’s custom dialog for this purpose: text fields, dropdowns, radio buttons, and checkboxes are just a few.

When you build the user interface, there are a few things you need to keep in mind:

  • columns build horizontally
  • rows build vertically
  • columns and rows are containers that hold input items

Add Items for User Input

Easy enough. To demonstrate, the following creates a master column for the dialog. The master column then creates a dialog row.

(*put the dialog code here*)
--first create the master column for the dialog
tell dlgRef
   set masterColumn to make dialog column
   tell masterColumn
      tell (make dialog row)
         --create label
         make static text with properties {static label:"Document Name:"}
         --add a text field (text editbox)
         set nameField to make text editbox with properties {min width:200}
      end tell
   end tell
end tell
(*end of user interface*)

Add this code to the skeleton for the dialog and run. The result will look like the following.

Notice that a variable is created to hold a reference to the name field (nameField). This will be used to create a record or list to hold the result of the user’s actions. Replace the if userResponse…end if statement block that checks the user’s response with the following and run the script.

   if userResponse = true
      set theResult to {name: edit contents of nameField}
   else
      set wasCancelled to true
   end if 

If the user enters information in the text field and clicks the “OK” button, the result will be a record having the value for a single record item: name.

You can add any number of fields to your custom dialog using code similar to that for creating the text edit box.

Add a Dropdown

For a dropdown you need to supply it with a list of string (text) values. The value for the variable templateList below is the result of a handler (subroutine) that pulls the names of the files from the path to a fixed folder.

   tell (make dialog row)
      make static text with properties {static label:"Select template: "}
      set templateField to make dropdown with properties {string list:templateList, selected index:0}
   end tell

Notice that lists for a custom dialog start indexing at 0 instead of 1. In returning the value from the user’s selection, your script will need to add 1.

Replace code inside the if statement that checks the user’s response (userResponse) with the following:

   if userResponse = true then
      set tempIndex to selected index of templateField + 1
      set theResult to {name: edit contents of nameField, templateIndex:tempIndex}
      --etc.

To get the text editbox and the dropdown to line up, the example simply placed a space after the colon for the label. If you have a number of label/widget groups to place in a custom dialog, you may want to create a column for the labels and another column for the input items.

Checkboxes and Radio Buttons

Checkboxes include the label as part of creating the checkbox.

   set checkDate to make checkbox control with properties {static label:"Add date stamp to document name:", checked state:true}

Radio buttons are a little different in that you first create a radiobutton group and then tell the readiobutton group to make radiobutton controls.

  set radioGroup to make radiobutton group
  tell radioGroup
      make radiobutton control with properties {static label:"Option 1", checked state:true}
      make radiobutton control with properties {static label:"Option 2"}
      make radiobutton control with properties {static label:"Option 3"}
  end tell 

Place Code for Dialog In a Handler

As you can see, a custom dialog can take a hefty amount of code. While writing the code, it is easiest to write it as its own routine so the code can be tested as you work with it. Once you have the dialog working the way you want it, make it a subroutine (handler) for your script.

Because the user can take more than the default time alloted for a modal dialog, you will want to place the call to the routine inside of a with timeout statement.

   global fileTypeList

   set fileTypeList to {"IDm7", "ID7t", "ID8t", "ID9t", "IDXt"}
   set templateList to getTemplateList("Templates")
   --call the handler for creating custom dialog and pass values for dialog properties as part of the call:
   with timeout of 500 seconds
      set userResponse to customDialog (dialogName, canCancel, dialogLabel)
   end timeout
   if userResponse = {} then
      activate
      display alert "User Cancelled"
   else --go on to use the information to create the document
      createDocument (userResponse)
   end if

   on createDocument (userResponse)
      --code for creating the document using information from userResponse
   end createDocument

   (*the handler that creates the dialog*)
   on customDialog (dialogName, canCancel, dialogLabel)
      --place code for creating the dialog here
      --don't forget to return the result back to where it was called
      return theResult
   end customDialog 

Now all you need is the handler to get the list of templates and your script is ready to create a document from a template using a script to get all of the information needed. With our next script we will post a sample script that does this and more.

Looking Forward

Our next blog will look at adding metadata to a document. Of course, the information for the metadata will come from the user input in our custom dialog.