Your prescription for increased productivity and profitability
Taking a short detour from automating animations in InDesign to look at a subject that came up recently in the user forums: text on a path. In working with text on a path you may have come across some issues that were a little difficult. That’s probably the reason that there are so many YouTube videos “out there” focusing on the subject. So why write a script? If you find yourself creating badges or other circular logos that require text on a path, you may find the following discussion most beneficial. And, because we will discuss the creation of a script step by step, you may find some code that can be reused for other purposes.
The script will assume that the user has a document open with a circle (oval) selected. The first step of the script will place a reference to the oval selected into a variable selItem:
Inside a tell statement block to the application, get a selection and make sure it is an oval. Selection returns a list of items. To make sure an object is selected we test to see if the value returned is an empty list (no object is selected). Next, the script checks the class of the first item of the list. If selection is empty or the class of the first item in the script is not oval, the script needs to give the user a message and exit from the script. Since this functionality is something that could be used many times in other scripts, we will set this up as a handler (known also as a subroutine, or function). The try statement block will give the user a message and exit from the script if an error is encountered in the handler.
tell application "Adobe InDesign CC 2017" try set selItem to my getSelection (oval) on error errMsg display alert errMsg return end try end tell (*The handler. tests for selection and class. Throws error if no selection exists or first item of selection is mot of type passed to handler as its only argument *) on getSelection(classType) tell application "Adobe InDesign CC 2017" set selList to selection if length of selList > 0 and class of item 1 of selList is classType then return item 1 of selList else error "Requires oval selection" end if end tell end getSelection
Test It
Copy the above code to the script editor for AppleScript. With an InDesign document open and a circle selected, run the script. Next, run the script with nothing selected and then with an object other than a circle (oval) selected.
Not using version CC 2017 for InDesign? Change the designation for the application in the above accordingly.
Define the text that will be placed on the text path. For now, you can just define it at the top of the script.
set textStr to "This is text on a path"
Define a paragraph style that will be used to style the text once it is placed on the text path. Here, again is functionality that could be used in any number of scripts. We will create another handler just for this purpose. It will test to see if a paragraph style as named in the handler’s argument list exists. If not a paragraph style will be created. For our purpose, only the name, font size, and justification will be defined for the style. All other properties will be inherited from the document’s text defaults. We can place the call to the handler just before the end tell statement in the top portion of the script above.
set styleProps to {point size: 24, justification: center align} set parastyleRef to my makeParagraphStyle (document 1, "pathStyle", styleProps)
Test It
Add the call to the handler to the top portion of the script above (just before the on error statement.
Add the following handler to the bottom of the script.
(*Checks if paragraph style as named in argument list exists. If not, a paragraph style is created with the name, point size, and justification; otherwise, reference to existing style is returned*) on makeParagraphStyle (docRef, styleName, styleProps) tell application "Adobe InDesign CC 2017" tell docRef if not (exists paragraph style styleName) then set parastyleRef to make paragraph style with properties {name:styleName} & styleProps else set parastyleRef to paragraph style styleName end if end tell end tell return parastyleRef end makeParagraphStyle
With the above in place and working, we are now ready to create the text path and set its styling. Immediately after the end try statement in the above, add the following:
tell selItem set textPathRef to make text path end tell tell textPathRef set contents to textStr set path effect to rainbow path effect set path alignment to top path alignment set text alignment to center text alignment set flip path effect to not flipped tell paragraph 1 of parent story to apply paragraph style using parastyleRef end tell
Test It
Compile the script (hammer button). Select a circle in the active document and run the script (Command+R). If all goes right, your text path should look similar to the screen capture below.
…Text placed on text path
You may want to open InDesign’s AppleScript scripting dictionary to view the properties and settings that can be used with a text path. (With Script Editor active, select Open Dictionary… from the File menu. Select the version of InDesign you are using from the list presented.) You will find the entry for Text Path in the Text suite.
Depending on the version of InDesign you are using, you may want to do some experimenting to make sure some of the properties listed actually work. For instance, path alignment has the following options: top path alignment, bottom path alignment, center path alignment. With this, one would assume changing path alignment to bottom path alignment in the script above would cause the text to align at the bottom of the circle. This may or may not work. What does work in CC 2017 is start bracket and end bracket.
The text path brackets start bracket and end bracket indicate the portion of the path that will be used for the text. The real value (number with decimals) used for this setting is based on the circumference of the circle (length of the path). This starts with 0 at bottom center and increases in value counter-clockwise. Fortunately for us, measurement units are in points and InDesign calculates the start bracket and end bracket for us. We can use the start bracket from the script above to calculate brackets to be used for text on the path bottom.
Change the text inside the tell textPathRef block above to read:
tell textPathRef set contents to textStr set path effect to rainbow path effect set path alignment to bottom path alignment set text alignment to center text alignment set flip path effect to flipped tell paragraph 1 of parent story to apply paragraph style using parastyleRef set a to start bracket set end bracket to a/4 set start bracket to (a/4)*3 end tell
Test It
Compose the script and correct any typing errors. Select another circle on the page and run the script with the changes. The path should look similar to the screen capture below.
Now that you are successful in creating text at the top and bottom of a text path, let’s modify the script so that one script can offer both options. We can do this by moving the styling for the text path to a handler and defining the text for the paths in a list. For now, the list will allow two items (1) text for the top of the path; (2) text for the bottom of the path. Change the textStr variable at the top of the script to read:
set textList to {"Text for top of text path", ""}
To create the handler, at the bottom of your script start with on and end statements:
on stylePath (textPathRef, textItem, textIndex, parastyleRef) tell application "Adobe InDesign CC 2017" --place code here end tell end stylePath
Cut all of the code from tell textPathRef block in the script above (Command+X) and paste it (Command+V) inside the on/end statements you just added. Change the code inside the tell block so the handler reads as follows:
on stylePath(textPathRef, textItem, textIndex, parastyleRef) tell application "Adobe InDesign CC 2017" tell textPathRef set path effect to rainbow path effect set text alignment to center text alignment set contents to textItem tell paragraph 1 of parent story to apply paragraph style using parastyleRef --for bottom if textIndex = 2 then set a to start bracket set flip path effect to flipped set end bracket to a / 4 set start bracket to (a / 4) * 3 else --for top set flip path effect to not flipped end if end tell end tell end stylePath
All you need now is the call to the handler. We can place the call just before the last tell statement in the top portion of the script. The top portion should now read as follows:
set textList to {"Text for top of text path", ""} tell application "Adobe InDesign CC 2017" try set selItem to my getSelection(oval) set styleProps to {point size:24, justification:center align} set parastyleRef to my makeParagraphStyle(document 1, "pathStyle", styleProps) on error errMsg display alert errMsg return end try tell selItem set textPathRef to make text path end tell my stylePath(textPathRef, item 1 of textList, 1, parastyleRef) end tell
If you start a new script with this for the top portion, don’t forget to include the following handlers: makeParagraphStyle, stylePath, and getSelection
Test It
When you run the script with a circle selected, your text should be placed on the top of the path. Note that you cannot use the same circle to create text for the bottom of the path simply because a single page item can only have one text path. But you can use another circle. Change the textList at the top of the script to read:
set textList to {"","text for bottom of text path"}
Change the call to the handler to read:
my stylePath(textPathRef, item 2 of textList, 2, parastyleRef)
Test It
Run the script again, with another circle selected.
For a badge (having both top and bottom text on s path) you could create two circles and physically move the two on top of one another. Or, you could make a few changes to the script to duplicate the first circle for a second text path. Let’s see how this latter option would work.
Right after the end try statement, have the script test to see if the second item in the textList is not empty. If not, the first circle is duplicated and the text path for the bottom text is created. The script assumes that the top portion of the path will have text. Replace the four lines of code after the end try statement (up to end tell), and replace with the following:
if item 2 of textList is not "" then set dupItem to duplicate selItem tell dupItem set pathList to text paths if pathList is {} then set dupPathRef to make text path else set dupPathRef to text path 1 end if end tell my stylePath(dupPathRef, item 2 of textList, 2, parastyleRef) end if tell selItem set pathList to text paths if pathList is {} then set textPathRef to make text path else set textPathRef to item 1 of pathList end if end tell my stylePath(textPathRef, item 1 of textList, 1, parastyleRef)
Finally, change the list at the top of the script to read:
set textList to {"Text for top of text path", "Text for bottom of text path"}
Select a new circle and run the script. When it completes successfully, congratulate yourself for a job well done.
…Badge created with script
Add more property definitions for the paragraph style created. Perhaps you may add user-defined choices for color fill and/or stroke. Change the settings for the text path so the text aligns on the inside of the circle. Try other text path options.
To make the script user-friendly, you will want to add a custom user dialog for entering text for top and bottom of the text path. Perhaps, the dialog can also allow the user to choose a paragraph style and color swatch from two drop downs. We will show you how to create the user dialog for your TextOnAPath script in our next blog post.
Disclaimer: Scripts are presented for demonstration only. No representation as to completeness or accuracy is implied. Use at your own risk.